我写了一个简单的C程序并将其编译为32位架构。
但是当我跑步时,我发现了意想不到的结果。
#include <stdio.h>
int foo(int n) {
int sum=0;
int i;
if (n <= 1 || n >= 0x1000)
return n;
for (i=0; i<= n; i++) {
sum = sum + i;
}
return foo(sum);
}
int main(int argc, char** argv) {
int n;
n = foo(200);
printf("\n\n main about to return %d \n\n", n);
return n;
}
➜ wbench gcc -o test.elf test.c -m32 -fno-stack-protector -mpreferred-stack-boundary=2 -Wall
➜ wbench ./test.elf
main about to return 20100
➜ wbench echo $?
132
我希望20100
成为主函数打印的返回值。
但是,我将132
作为退出代码。
我使用GDB验证,当main即将返回时,20100
是eax
寄存器中的值。
➜ wbench gdb -q test.elf
gdb-peda$ b *main+44
Breakpoint 1 at 0x8048492
gdb-peda$ r
main about to return 20100
Breakpoint 1, 0x08048492 in main ()
0x8048489 <main+35>: call 0x80482f0 <printf@plt>
0x804848e <main+40>: mov eax,DWORD PTR [ebp-0x4]
0x8048491 <main+43>: leave
=> 0x8048492 <main+44>: ret
0x8048493: xchg ax,ax
gdb-peda$ p/d $eax
$1 = 20100
gdb-peda$ c
[Inferior 1 (process 32172) exited with code 0204]
Warning: not running or target is remote
gdb-peda$ p/d 0204
$2 = 132
我甚至验证过,当控件转回__libc_start_main
并且正在调用exit
函数时,20100
被作为参数推送到exit()
。
gdb-peda$ r
main returning 20100
Breakpoint 1, 0x08048492 in main ()
gdb-peda$ finish
=> 0xf7e1ca83 <__libc_start_main+243>: mov DWORD PTR [esp],eax
0xf7e1ca86 <__libc_start_main+246>: call 0xf7e361e0 <exit>
0xf7e1ca8b <__libc_start_main+251>: xor ecx,ecx
gdb-peda$ si
=> 0xf7e1ca86 <__libc_start_main+246>: call 0xf7e361e0 <exit>
0xf7e1ca8b <__libc_start_main+251>: xor ecx,ecx
gdb-peda$ x/wd $esp
0xffffd5c0: 20100
这可能是什么原因?
我不认为此处的退出代码132
与SIGILL
有任何关系,因为当我将foo()
的硬编码参数从200
更改为2
,退出代码已更改为172
,其中预期退出代码为26796
。
答案 0 :(得分:3)
看起来你正在做的事情是无效的,因为你只有8位才能返回操作系统。
假设您要关联$.trim()
:
当程序退出时,它可以使用退出状态向父进程返回有关终止原因的少量信息。这是一个0到255之间的值,退出进程将作为参数传递给exit。
如文档here所示。这条线也是相关的:
警告:请勿尝试使用错误数作为退出状态。这实际上不是很有用;父进程通常不关心发生了多少错误。更糟糕的是,它不起作用,因为状态值被截断为8位。因此,如果程序试图报告256个错误,则父级将收到0错误的报告 - 即成功。
答案 1 :(得分:2)
20100
十进制为4E84
十六进制
132
十进制为84
十六进制
你的shell只接收8位返回值。
答案 2 :(得分:1)
当您的程序可能返回20100时,系统只会获取最低字节,例如return % 256
所以20100 % 256 = 132