I have an ARM-based device running Embedded Linux and I have observed that when I use the C library's system() call, the return code is incorrect. Here is a test program that demonstrates the behavior:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int ret = system("exit 42");
printf("Should return 42 for system() call: %d\n", ret);
printf("Returning 43 to shell..\n");
exit(43);
};
And here is the program output on the device:
# returnCodeTest
Should return 42 for system() call: 10752
Returning 43 to shell..
The value "10752" is returned by system() instead of "42". 10752 is 42 when left-shifted by 8:
Python 2.7.3 (default, Feb 27 2014, 20:00:17)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 42<<8
10752
So is suspect one of the following is going on somewhere:
- The byte order is getting swapped
- The value is getting shifted by 8 bits
- Incompatible struct definitions are being used
When I run strace I see the following:
# strace /usr/bin/returnCodeTest
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x4001e308) = 977
wait4(977, [{WIFEXITED(s) && WEXITSTATUS(s) == 42}], 0, NULL) = 977
rt_sigaction(SIGINT, {SIG_DFL, [], 0x4000000 /* SA_??? */}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], 0x4000000 /* SA_??? */}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=977, si_status=42, si_utime=0, si_stime=0} ---
fstat64(1, {st_mode=S_IFCHR|0622, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4001f000
write(1, "Should return 42 for system() ca"..., 42Should return 42 for system() call: 10752
) = 42
write(1, "Returning 43 to shell..\n", 24Returning 43 to shell..
) = 24
exit_group(43) = ?
+++ exited with 43 +++
wait4() returns with the correct status (si_status=42), but when it gets printed to standard output the value is shifted by 8 bits, and it looks like it is happening in a library. Interestingly the write returns a value of 42. I wonder if this is a hint as to what is going on...
Unfortunately I cannot get ltrace to compile and run on the device. Has anyone seen this type of behavior before or have any ideas (possibly architecture-specific) on where to look?