Неожиданный код выхода для программы C, скомпилированной для 32-битной архитектуры с использованием 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 будет возвращаемым значением, напечатанным основной функцией.

Но я получаю 132 в качестве кода выхода.

Я проверил с помощью GDB, что 20100 является значением в регистре eax, когда main вот-вот вернется.

➜  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.


person Akshay Krishnan R    schedule 04.08.2015    source источник
comment
Также обратите внимание, что стандарт C поддерживает только 0 (синоним EXIT_SUCCESS) и EXIT_FAILURE в качестве возвращаемых значений из main.   -  person jxh    schedule 04.08.2015


Ответы (3)


Похоже, то, что вы делаете, неверно, так как у вас есть только 8 бит для возврата в ОС.

Предполагая, что вы ссылаетесь на libc:

Когда программа завершается, она может вернуть родительскому процессу небольшое количество информации о причине завершения, используя статус выхода. Это значение от 0 до 255, которое завершающийся процесс передает в качестве аргумента для выхода.

Как указано в его документации здесь. Также актуальна эта строка:

Предупреждение: не пытайтесь использовать количество ошибок в качестве статуса выхода. На самом деле это не очень полезно; родительский процесс, как правило, не заботится о том, сколько ошибок произошло. Хуже того, это не работает, потому что значение состояния усекается до восьми бит. Таким образом, если программа попытается сообщить о 256 ошибках, родитель получит отчет об 0 ошибках, то есть успех.

person dsolimano    schedule 04.08.2015
comment
Причина, по которой для кода выхода используется только 8 бит, заключается в том, что другие биты в status, которые вы получаете от waitpid, используются для другой информации: являются ли младшие 8 бит действительным статусом выхода или происходит что-то еще. И какой сигнал вызвал его выход, и какие-то другие флаги. - person Peter Cordes; 04.08.2015

20100 десятичное число равно 4E84 шестнадцатеричному.
132 десятичное число равно 84 шестнадцатеричному.
Ваша оболочка получает возвращаемое значение только в виде 8 бит.

person mah    schedule 04.08.2015

Хотя ваша программа может возвращать 20100, система извлекает только младший байт, например return % 256

So 20100 % 256 = 132

person Glenn Teitelbaum    schedule 04.08.2015