使用 gcc 为 32 位体系结构编译的 C 程序的意外退出代码
Unexpected exit code for a C program compiled for 32 bit architecture using gcc
我写了一个简单的 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
是 return 值,如 main 函数所打印的那样。
但是,我得到 132
作为退出代码。
我使用 GDB 验证 20100
是当 main 即将 return.
时 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
= 20100
gdb-peda$ c
[Inferior 1 (process 32172) exited with code 0204]
Warning: not running or target is remote
gdb-peda$ p/d 0204
= 132
我什至验证了当控制权 t运行 返回给 __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
.
20100
十进制是 4E84
十六进制。
132
十进制是 84
十六进制。
您的 shell 收到的 return 值仅为 8 位。
看起来你所做的是无效的,因为你只有 8 位到 return 到 OS。
假设您链接到 libc
:
When a program exits, it can return to the parent process a small amount of information about the cause of termination, using the exit status. This is a value between 0 and 255 that the exiting process passes as an argument to exit.
如其文档中所述here。同样相关的是这一行:
Warning: Don’t try to use the number of errors as the exit status. This is actually not very useful; a parent process would generally not care how many errors occurred. Worse than that, it does not work, because the status value is truncated to eight bits. Thus, if the program tried to report 256 errors, the parent would receive a report of 0 errors—that is, success.
虽然您的程序可能会返回 20100,但系统只会获取最低字节,例如 return % 256
所以20100 % 256 = 132
我写了一个简单的 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
是 return 值,如 main 函数所打印的那样。
但是,我得到 132
作为退出代码。
我使用 GDB 验证 20100
是当 main 即将 return.
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
= 20100
gdb-peda$ c
[Inferior 1 (process 32172) exited with code 0204]
Warning: not running or target is remote
gdb-peda$ p/d 0204
= 132
我什至验证了当控制权 t运行 返回给 __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
.
20100
十进制是 4E84
十六进制。
132
十进制是 84
十六进制。
您的 shell 收到的 return 值仅为 8 位。
看起来你所做的是无效的,因为你只有 8 位到 return 到 OS。
假设您链接到 libc
:
When a program exits, it can return to the parent process a small amount of information about the cause of termination, using the exit status. This is a value between 0 and 255 that the exiting process passes as an argument to exit.
如其文档中所述here。同样相关的是这一行:
Warning: Don’t try to use the number of errors as the exit status. This is actually not very useful; a parent process would generally not care how many errors occurred. Worse than that, it does not work, because the status value is truncated to eight bits. Thus, if the program tried to report 256 errors, the parent would receive a report of 0 errors—that is, success.
虽然您的程序可能会返回 20100,但系统只会获取最低字节,例如 return % 256
所以20100 % 256 = 132