upx / upx

UPX - the Ultimate Packer for eXecutables
https://upx.github.io
Other
14.23k stars 1.34k forks source link

CantPackException: need DT_INIT on Rust executable for MIPS #200

Closed sticnarf closed 6 years ago

sticnarf commented 6 years ago

What's the problem (or question)?

UPX refuses to compress a Rust executable cross-compiled for MIPS (using LEDE's toolchain)

Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2017
UPX git-b711d2  Markus Oberhumer, Laszlo Molnar & John Reiser   May 13th 2017

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
upx.out: openwrt-test: CantPackException: need DT_INIT; try "void _init(void){}"

Packed 0 files.

WARNING: this is an unstable beta version - use for testing only! Really.

What should have happened?

It should compress the binary.

Do you have an idea for a solution?

I tried to add _init function manually, but got multiple definition of `_init'.

UPX works on the i386 binary compiled in the same way, so the issue might be specific to MIPS.

How can we reproduce the issue?

  1. Create a "Hello world" Rust project
    $ cargo new openwrt-test
  2. Configure the toolchain in cargo's config
    [target.mips-unknown-linux-musl]
    linker = "mips-openwrt-linux-musl-gcc"
  3. Compile the project
    $ cargo build --release --target=mips-unknown-linux-musl
  4. upx the binary
    $ upx target/mips-unknown-linux-musl/release/openwrt-test

Here is the binary.

openwrt-test.tar.gz

Please tell us details about your environment.

jreiser commented 6 years ago

Works for me after fix above.

sticnarf commented 6 years ago

After the fix, it accepts the executable. However, the compressed binary is neither unpackable nor actually executable.

When I tried to test the compressed binary, it says bad e_shoff:

upx -t target/mips-unknown-linux-musl/release/openwrt-test

                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2017
UPX git-774c8c  Markus Oberhumer, Laszlo Molnar & John Reiser   May 13th 2017

upx.out: target/mips-unknown-linux-musl/release/openwrt-test: CantUnpackException: bad e_shoff

Tested 0 files.

WARNING: this is an unstable beta version - use for testing only! Really.

And also, when I tried to execute it, a segmentation fault occured.

jreiser commented 6 years ago

Thank you for attaching the test case in the original Description. After compression I can now test (-t) and unpack (-d) it.

upx has trouble deciding whether openwrt-test is a shared library or a position-independent executable main program. Both are ET_DYN, but the compression and decompression protocols are different because the code is invoked differently (execve or dlopen.) Currently upx looks for the flag bit DF_1_PIE in the DT_FLAGS_1 word in the PT_DYNAMIC segment, or for a relocation that refers to libc_start_main or libc_init (or their uClibc equivalents). The file openwrt-test has none of those, so upx believes that openwrt-test is a shared library, and this causes SIGSEGV when compressed and invoked as a main program. openwrt-test does have the undefined symbol __libc_start_main, but there is no corresponding Elf32_Rel relocation entry. The preferred solution is to use DF_1_PIE.

p_elf_enum.h:        DT_FLAGS_1  = 0x6ffffffb,       /* DF_1_* */
p_elf_enum.h:        DF_1_PIE    = 0x08000000   // Position-Independent Executable (main program)
jreiser commented 6 years ago

New command-line option --force-pie works around un-cooperative 'rust'.

sticnarf commented 6 years ago

Decompression seems to work now. However, the packed binary is stilled not working for me.

First, I did not add --force-pie option when compressing.

Running the compressed binary on my machine results in Illegal instruction. This is weird because the original binary just works and when I tried to use upx to compress a simple "Hello world" program which is written in C and compiled using the same gcc, it works as well. (I tried to add --lzma option in both case, but nothing changes) I learn little about upx, so I have no idea what leads to this.

Below is the cpu info of my device:

root@LEDE:~# cat /proc/cpuinfo 
system type             : Atheros AR9344 rev 2
machine                 : NETGEAR WNDR3700v4
processor               : 0
cpu model               : MIPS 74Kc V4.12
BogoMIPS                : 278.93
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : yes
hardware watchpoint     : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa                     : mips1 mips2 mips32r1 mips32r2
ASEs implemented        : mips16 dsp dsp2
shadow register sets    : 1
kscratch registers      : 0
package                 : 0
core                    : 0
VCED exceptions         : not available
VCEI exceptions         : not available

But I found something maybe interesting when I tried to gdb the binary:

root@LEDE:~# gdb openwrt-test 
GNU gdb (GDB) 7.11.1
......
This GDB was configured as "mips-openwrt-linux".
......
Type "apropos word" to search for commands related to "word"...
"/root/openwrt-test": not in executable format: File truncated
(gdb)

It must be a problem that gdb complains the binary is not in executable format.



Then, I added --force-pie option. Again, the binary did not work. A Bus error occured.

Seemingly not much useful information from gdb:

Reading symbols from openwrt-test...(no debugging symbols found)...done.
(gdb) r
Starting program: /root/openwrt-test 
warning: GDB can't find the start of the function at 0x77f79370.

    GDB is unable to find the start of the function at 0x77f79370
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
    This problem is most likely caused by an invalid program counter or
stack pointer.
    However, if you think GDB should simply search farther back
from 0x77f79370 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.

Program received signal SIGBUS, Bus error.
0x77f79370 in ?? ()
(gdb)
jreiser commented 6 years ago

Without --force-pie then "It must be a problem that gdb complains the binary is not in executable format" can be ignored. upx has compressed for use as a shared library, and in that case .e_shoff usually points beyond the end of the file. e_shoff is not relevant to execution, only to debugging and linking.

With --force-pie then we need more information. Please run under strace, both before and after compression, and report the output until a few syscalls after the divergence.

$ strace ./openwrt-test   ## before compression
$ upx --force-pie openwrt-test   # compress
$ strace ./openwrt-test   ## after compression

Then get more information from gdb:

$ gdb ./openwrt-test
(gdb) run
   <<SIGBUS>>
(gdb) x/i $pc   ## current instruction
(gdb) x/9i $pc-4*4   ## surrounding instructions
(gdb) info reg   ## all registers
(gdb) x/8xw $sp   ## 32 bytes of stack frame
(gdb) bt   ## backtrace (probably garbage, but perhaps not)
(gdb) info proc   ## process ID, etc.
(gdb) shell cat /proc/PID/maps   ## PID is process ID from "info proc"

The --force-pie case worked for me until it tried to load the PT_INTERP /lib/ld-musl-mips-sf.so.1. I use qemu-mips emulator:

$ qemu-mips -strace -g 1234 ./foo   ## foo is the compressed openwrt-test
16763 open("/proc/self/exe",O_RDONLY) = 5
16763 mmap(NULL,92660,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x76795000
16763 mmap(0x76795000,91900,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,5,0) = 0x76795000
16763 cacheflush(1987752036,2448,3,1996144448,0,0) = 0
16763 mprotect(0x767aa000,6644,PROT_EXEC|PROT_READ) = 0
16763 readlink("/proc/self/exe",0x76fab0fc,4095) = 42
16763 cacheflush(1996139856,404,3,1996139752,0,0) = 0
16763 mmap(0x76fad000,339968,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fad000
16763 mmap(0x76fad000,260280,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fad000
16763 cacheflush(1996148736,404,3,1996139664,0,0) = 0
16763 cacheflush(1996149140,259876,3,1996139664,0,0) = 0
16763 mprotect(0x76fad000,260280,PROT_EXEC|PROT_READ) = 0
16763 mmap(0x76ffd000,8100,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76ffd000
16763 cacheflush(1996476496,8020,3,1996139664,0,0) = 0
16763 mprotect(0x76ffd000,8100,PROT_READ|PROT_WRITE) = 0
16763 mmap(0x76fff000,120,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fff000
16763 open("/lib/ld-musl-mips-sf.so.1",O_RDONLY) = -1 errno=2 (No such file or directory)
16763 exit(127)

I tried to find that file by searching the 'net. I found https://downloads.lede-project.org/snapshots/targets/adm5120/rb1xx/lede-sdk-adm5120-rb1xx_gcc-5.4.0_musl-1.1.15.Linux-x86_64.tar.xz but that archive contains onlyld-musl-mipsel-sf.so.1 which is the little-endian version, and we need the big-endian version. Please upload (attach) or point to the big-endian version.

sticnarf commented 6 years ago

Thank you for your kind explanation.

Here are the strace results.

Before compression:

root@LEDE:~# strace ./openwrt-test 
execve("./openwrt-test", ["./openwrt-test"], [/* 12 vars */]) = 0
set_thread_area(0x77539d48)             = 0
set_tid_address(0x77532cac)             = 1314
open("/etc/ld-musl-mips-sf.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=77040, ...}) = 0
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0(\20\0\0\0004"..., 936) = 936
mmap2(NULL, 143360, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7746a000
mmap2(0x7748c000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12000) = 0x7748c000
close(3)                                = 0
mprotect(0x5656a000, 4096, PROT_READ)   = 0
set_thread_area(0x77539e98)             = 0
set_tid_address(0x77532dfc)             = 1314
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[RT_68 RT_69 RT_73 RT_74 RT_75 RT_76 RT_79 RT_80 RT_81 RT_84 RT_87 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=NULL}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 16) = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 16) = 0
rt_sigaction(SIGSEGV, {sa_handler=0x565384ec, sa_mask=[RT_69 RT_73 RT_74 RT_75 RT_76 RT_79 RT_80 RT_81 RT_84 RT_87 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_SIGINFO|SA_ONSTACK, sa_restorer=NULL}, NULL, 16) = 0
rt_sigaction(SIGBUS, {sa_handler=0x565384ec, sa_mask=[RT_69 RT_73 RT_74 RT_75 RT_76 RT_79 RT_80 RT_81 RT_84 RT_87 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_SIGINFO|SA_ONSTACK, sa_restorer=NULL}, NULL, 16) = 0
sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7752b000
sigaltstack({ss_sp=0x7752b000, ss_flags=0, ss_size=8192}, NULL) = 0
write(1, "Hello, world!\n", 14Hello, world!
)         = 14
sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
munmap(0x7752b000, 8192)                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

After compression with --force-pie option:

root@LEDE:~# strace ./openwrt-test 
execve("./openwrt-test", ["./openwrt-test"], [/* 12 vars */]) = 0
open("/proc/self/exe", O_RDONLY)        = 3
mmap(NULL, 92660, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77f77000
mmap(0x77f77000, 91900, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x77f77000
cacheflush(0x77f8d064, 0x990, 0x3)      = 0
mprotect(0x77f8c000, 6644, PROT_READ|PROT_EXEC) = 0
readlink("/proc/self/exe", "/root/openwrt-test", 4095) = 18
cacheflush(0x7f89ae20, 0x194, 0x3)      = 0
mmap(0x77f8e000, 339968, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77f8e000
mmap(0x77f8e000, 260280, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77f8e000
cacheflush(0x77f8e000, 0x194, 0x3)      = 0
cacheflush(0x77f8e194, 0x3f724, 0x3)    = 0
mprotect(0x77f8e000, 260280, PROT_READ|PROT_EXEC) = 0
mmap(0x77fde000, 8100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77fde000
cacheflush(0x77fde050, 0x1f54, 0x3)     = 0
mprotect(0x77fde000, 8100, PROT_READ|PROT_WRITE) = 0
mmap(0x77fe0000, 120, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77fe0000
open("/lib/ld-musl-mips-sf.so.1", O_RDONLY) = 4
read(4, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\360\320\0\0\0004"..., 512) = 512
mmap(NULL, 675840, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77ed2000
mmap(0x77ed2000, 595008, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x77ed2000
mmap(0x77f73000, 8048, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x91000) = 0x77f73000
mmap(0x77f75000, 7628, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77f75000
close(4)                                = 0
mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x77ed0000
close(3)                                = 0
munmap(0x77f77000, 92660)               = 0
set_thread_area(0x77f7dd48)             = 0
set_tid_address(0x77f76cac)             = 1323
--- SIGBUS {si_signo=SIGBUS, si_code=SI_KERNEL, si_addr=NULL} ---
+++ killed by SIGBUS +++
Bus error

And information from gdb:

root@LEDE:~# gdb ./openwrt-test 
GNU gdb (GDB) 7.11.1
...
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./openwrt-test...(no debugging symbols found)...done.
(gdb) r
Starting program: /root/openwrt-test 
warning: GDB can't find the start of the function at 0x77f74370.

    GDB is unable to find the start of the function at 0x77f74370
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
    This problem is most likely caused by an invalid program counter or
stack pointer.
    However, if you think GDB should simply search farther back
from 0x77f74370 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.

Program received signal SIGBUS, Bus error.
0x77f74370 in ?? ()
(gdb) x/i $pc
=> 0x77f74370:  lw      t2,0(v0)
(gdb) x/9i $pc-4*4
   0x77f74360:  li      t4,2
   0x77f74364:  li      t5,1
   0x77f74368:  beqz    a1,0x77f743b4
   0x77f7436c:  nop
=> 0x77f74370:  lw      t2,0(v0)
   0x77f74374:  bne     t2,t4,0x77f7438c
   0x77f74378:  nop
   0x77f7437c:  lw      a3,4(v0)
   0x77f74380:  li      t1,1
(gdb) info reg
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 fffffff8 8a9cb018 77fcb000 00000000 00000320 77f90000 00000000 
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   00000000 00000000 6474e552 00002025 00000002 00000001 00000fb0 00000001 
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  7fffedf4 77f93460 77f729b0 77f90000 77f933b0 77f90000 77f93518 77f94d8c 
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000020 77f729b0 00000000 00000000 77f9a2c0 7fffec18 00000000 77f74318 
        status       lo       hi badvaddr    cause       pc
      0100dc13 000192ac 000000af 8a9cb018 00800010 77f74370 
          fcsr      fir      hi1      lo1      hi2      lo2      hi3      lo3
      00000000 00730000 00000000 00000000 00000000 00000000 00000000 00000000 
        dspctl  restart
      00000000 00000000 
(gdb) x/8xw $sp
0x7fffec18:     0x77f810c4      0x77f81098      0x77f93518      0x77f71730
0x7fffec28:     0x77efa70c      0x77f71040      0x77f9a2c0      0x77f70000
(gdb) bt
#0  0x77f74370 in ?? ()
(gdb) info proc
process 1327
cmdline = '/root/openwrt-test'
cwd = '/root'
exe = '/root/openwrt-test'
(gdb) shell cat /proc/1327/maps
77eee000-77eef000 r--p 00000000 00:0e 172        /root/openwrt-test
77ef0000-77f82000 r-xp 00000000 fe:00 673        /lib/libc.so
77f82000-77f91000 ---p 00000000 00:00 0 
77f91000-77f93000 rw-p 00091000 fe:00 673        /lib/libc.so
77f93000-77f95000 rw-p 00000000 00:00 0 
77fac000-77fec000 r-xp 00000000 00:00 0 
77fec000-77ffc000 ---p 00000000 00:00 0 
77ffc000-77fff000 rw-p 00000000 00:00 0          [heap]
7ffdf000-80000000 rwxp 00000000 00:00 0          [stack]

Ar71xx is a big-endian architecture. This is the corresponding SDK.

ld-musl-mips-sf.so.1 is linked to libc.so. This is the libc.so in the SDK: libc.tar.gz

And this is the actual libc.so inside my device: libc.tar.gz

jreiser commented 6 years ago

When I use the libc.so from inside your device and the libgcc_s.so.1 from the SDK, then it works for me running under qemu-mips on my x86_64 box.

Using a hex editor, I changed the DT_NEEDED entries in openwrt-test to start with 'M' instead of 'l', then copied the MIPS files into /lib on my x86_64 system:

 0x00000001 (NEEDED)                     Shared library: [Mibgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [Mibc.so]

-rwxr-xr-x. 1 root root 601968 Apr 28 15:03 /lib/Mibc.so
-rw-r--r--. 1 root root 366116 Apr 28 15:09 /lib/Mibgcc_s.so.1

and of course i re-compressed openwrt-test using --force-pie. Then:

$ qemu-mips -strace -g 1234 ./foo
3980 open("/proc/self/exe",O_RDONLY) = 5
3980 mmap(NULL,92660,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x76795000
3980 mmap(0x76795000,91900,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,5,0) = 0x76795000
3980 cacheflush(1987752036,2448,3,1996144448,0,0) = 0
3980 mprotect(0x767aa000,6644,PROT_EXEC|PROT_READ) = 0
3980 readlink("/proc/self/exe",0x76fab0fc,4095) = 42
3980 cacheflush(1996139856,404,3,1996139752,0,0) = 0
3980 mmap(0x76fad000,339968,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fad000
3980 mmap(0x76fad000,260280,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fad000
3980 cacheflush(1996148736,404,3,1996139664,0,0) = 0
3980 cacheflush(1996149140,259876,3,1996139664,0,0) = 0
3980 mprotect(0x76fad000,260280,PROT_EXEC|PROT_READ) = 0
3980 mmap(0x76ffd000,8100,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76ffd000
3980 cacheflush(1996476496,8020,3,1996139664,0,0) = 0
3980 mprotect(0x76ffd000,8100,PROT_READ|PROT_WRITE) = 0
3980 mmap(0x76fff000,120,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76fff000
3980 open("/lib/ld-musl-mips-sf.so.1",O_RDONLY) = 6
3980 read(6,0x76faad50,512) = 512
3980 mmap(NULL,675840,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x766f0000
3980 mmap(0x766f0000,595008,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_FIXED,6,0) = 0x766f0000
3980 mmap(0x76791000,8048,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,6,0x91000) = 0x76791000
3980 mmap(0x76793000,7628,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x76793000
3980 close(6) = 0
3980 mmap(NULL,4096,PROT_READ,MAP_PRIVATE,5,0) = 0x766ef000
3980 close(5) = 0
3980 munmap(0x76795000,92660) = 0
3980 set_thread_area(0x7679bd48) = 0
3980 set_tid_address(1987660972,1987661196,1,0,0,0) = 3980
3980 open("/etc/ld-musl-mips-sf.path",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 errno=2 (No such file or directory)
3980 open("/lib/Mibgcc_s.so.1",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 5
3980 fcntl64(5,F_SETFD,1) = 0
3980 fstat64(5,0x76faac58) = 0
3980 read(5,0x76faa590,936) = 936
3980 mmap2(NULL,143360,PROT_EXEC|PROT_READ,MAP_PRIVATE,5,0) = 0x766cc000
3980 mmap2(0x766ee000,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,5,0x12) = 0x766ee000
3980 close(5) = 0
3980 open("/lib/Mibc.so",O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 5
3980 fcntl64(5,F_SETFD,1) = 0
3980 fstat64(5,0x76faac58) = 0
3980 read(5,0x76faa590,936) = 936
3980 mmap2(NULL,675840,PROT_EXEC|PROT_READ,MAP_PRIVATE,5,0) = 0x76627000
3980 mmap2(0x766c8000,16384,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,5,0x91) = 0x766c8000
3980 mmap2(0x766ca000,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x766ca000
3980 close(5) = 0
3980 mprotect(0x766c8000,4096,PROT_READ) = 0
3980 mprotect(0x76ffd000,4096,PROT_READ) = 0
3980 set_thread_area(0x7679bf68) = 0
3980 set_tid_address(1987661516,1987661196,0,0,0,0) = 3980
3980 rt_sigaction(SIGPIPE,0x76faad18,0x76faad34) = 0
3980 rt_sigprocmask(SIG_UNBLOCK,0x76faad78,NULL) = 0
3980 rt_sigaction(SIGSEGV,0x76faad88,NULL) = 0
3980 rt_sigaction(10,0x76faad88,NULL) = 0
3980 sigaltstack((nil),0x76faae80) = 0
3980 mmap2(NULL,8192,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x76625000
3980 sigaltstack(0x76faae80,(nil)) = 0
3980 brk(NULL) = 0x77000000
3980 brk(0x77001000) = 0x77000000
3980 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x76624000
3980 write(1,0x76624170,14)Hello, world!
 = 14
3980 sigaltstack(0x76faae20,(nil)) = 0
3980 munmap(0x76625000,8192) = 0
3980 exit_group(0)

The only strangeness that I can see is my lack of /etc/ld-musl-mips-sf.path. I use mips-linux-gnu-gdb built from https://sourcery.mentor.com/GNUToolchain/release3217 ; see my comment of 2017-12-13 on https://github.com/upx/upx/issues/139 .

sticnarf commented 6 years ago

I retried in a QEMU environment which is similar to my MIPS device. A bus error occurred, but it is sligthly different in detailed debug information.

Maybe it is an easy way for you to reproduce this issue at your place.

  1. Download openwrt malta(built for mips qemu) initramfs: https://downloads.lede-project.org/snapshots/targets/malta/be/openwrt-malta-be-vmlinux-initramfs.elf

  2. Then, launch the system:

    $ qemu-system-mips -kernel openwrt-malta-be-vmlinux-initramfs.elf -nographic -m 256
  3. Put the binary into QEMU and run it.

You can install gdb and strace with opkg. (The packages are provided here ipk.tar.gz) (Perhaps you need to mount a disk to /overlay first)

jreiser commented 6 years ago

So I don't forget:


dd if=/dev/zero of=image100M bs=1M count=100
mkfs -t ext2 image100M
mount -t ext2 -o loop image100M /mnt
(cd /mnt; tar xvfz ipk.tar.gz)
upx -f -o /mnt/foo --force-pie openwrt-test
sync

qemu-system-mips -kernel openwrt-malta-be-vmlinux-initramfs.elf -nographic -m 256 -hda image100M
<Enter>
mount -t ext2 /dev/sda /mnt
cd /mnt
opkg install *.ipk
gdb foo
halt
jreiser commented 6 years ago

Fixed on devel branch.