使用gcc为32位架构编译的C程序的意外退出代码 [英] Unexpected exit code for a C program compiled for 32 bit architecture using gcc

查看:111
本文介绍了使用gcc为32位架构编译的C程序的意外退出代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的C程序,并将其编译为32位体系结构.

I wrote a simple C program and compiled it for 32 bit architecture.

但是当我运行它时,我发现了意外的结果.

But when I ran it, I found unexpected results.

#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是返回值,由主函数打印出来.

I'm expecting 20100 to be the return value, as printed by the main function.

但是,我得到132作为退出代码.

But, I'm getting 132 as the exit code.

我使用GDB验证了当main将要返回时,20100eax寄存器中的值.

I verified using GDB that 20100 is the value in the eax register when main is about to return.

➜  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()的参数推入了.

I even verified that when control is transferred back to __libc_start_main and exit function is being called, 20100 is being pushed as argument to 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

这可能是什么原因?

我认为这里的退出代码132SIGILL没有任何关系,因为当我将硬编码参数从200更改为2时,退出代码更改为172,其中预期的退出代码为26796.

I don't think the exit code 132 here has got anything to do with SIGILL because when I changed the hardcoded argument to foo() from 200 to 2 , the exit code changed to 172 where the expected exit code is 26796.

推荐答案

您正在执行的操作似乎无效,因为您只有8位可以返回操作系统.

It looks like what you're doing is invalid, as you only have 8 bits to return to the OS.

假设您要链接到libc:

程序退出时,可以使用退出状态将少量有关终止原因的信息返回给父进程.这是一个介于0到255之间的值,退出进程将其作为要退出的参数传递.

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.

如其文档中此处所示.此行也与此相关:

As indicated in its documentation here. Also relevant is this line:

警告:请勿尝试将错误数量用作退出状态.实际上这不是很有用.父进程通常不会在意发生了多少错误.更糟糕的是,它不起作用,因为状态值被截断为八位.因此,如果程序尝试报告256个错误,则父级将收到0个错误的报告,即成功.

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.

这篇关于使用gcc为32位架构编译的C程序的意外退出代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆