lief-project / LIEF

LIEF - Library to Instrument Executable Formats
https://lief.re
Apache License 2.0
4.4k stars 611 forks source link

.tdata section allocated in weird place when writing binaries #662

Closed dktapps closed 2 years ago

dktapps commented 2 years ago

Describe the bug I'm using lief to rewrite the Linux version of Minecraft Bedrock Dedicated Server, in order to convert the provided debugging symbols into linkable dynamic symbols for modding.

I use the following script to do it:

import lief

lib_symbols = lief.parse("bedrock_server_symbols.debug")
for s in lib_symbols.exported_symbols:
#    print(s)
    lib_symbols.add_dynamic_symbol(s)
lib_symbols.write("bedrock_server_symbols_test.debug")

and then strip --strip-debug bedrock_server_symbols_test.debug (otherwise it will segfault; not sure if that's my fault or not). strip, gdb and other tools report that .tdata is allocated in a weird place after the modification; I haven't noticed this causing any issues yet, but no doubt it will crop up at some point.

strip output:

strip --strip-debug bedrock_server_symbols_test.debug
strip: st5VQNfj: section `.tdata' can't be allocated in segment 1
LOAD: .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .tdata .tbss .bss

To Reproduce Run the above Python script on the Minecraft Bedrock Dedicated Server bedrock_server_symbols.debug, and then run strip on the output (or gdb).

Expected behavior No error should be produced: all the sections should be allocated in suitable places.

Environment (please complete the following information):

romainthomas commented 2 years ago

Could you try with the master branch? (it fixes some ELF modification issues)

dktapps commented 2 years ago

Hi, with the master branch the modified binary immediately segfaults. It does this with two different binaries I tried.

https://minecraft.azureedge.net/bin-linux/bedrock-server-1.18.11.01.zip

make output:

strip --strip-debug bedrock_server_symbols.debug
python3 export-symbols.py
strip --strip-debug bedrock_server_symbols_test.debug
strip: stomyHgV: section .interp lma 0x400270 adjusted to 0x4002a8
strip: stomyHgV: section .note.ABI-tag lma 0x40028c adjusted to 0x4002c4

gdb

(gdb) run
Starting program: /home/user/bds-test/mapping/bedrock_server_symbols_test.debug

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fee60a in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0  0x00007ffff7fee60a in ?? () from /lib64/ld-linux-x86-64.so.2
#1  0x00007ffff7fd1ebf in ?? () from /lib64/ld-linux-x86-64.so.2
#2  0x00007ffff7febc3b in ?? () from /lib64/ld-linux-x86-64.so.2
#3  0x00007ffff7fd104c in ?? () from /lib64/ld-linux-x86-64.so.2
#4  0x00007ffff7fd0108 in ?? () from /lib64/ld-linux-x86-64.so.2
#5  0x0000000000000001 in ?? ()
#6  0x00007fffffffe4bf in ?? ()
#7  0x0000000000000000 in ?? ()
(gdb)
romainthomas commented 2 years ago

Ack I'll check

romainthomas commented 2 years ago

Ok got it. Strip does not work very well with a binary built by LIEF as strip removes the content that has been added by LIEF (at the end of the binary).

First I would suggest you to perform add_dynamic_symbol only on the debug symbols that are exported:

 lib_symbols = lief.parse("bedrock_server_symbols.debug")
for s in filter(lambda e: e.exported, lib_symbols.static_symbols):
    lib_symbols.add_dynamic_symbol(s)

As a workaround for the non-working strip, I would suggest to use the LIEF's builtin strip()[^1]

In the end, this modification should not segfault the binary:

import lief
lib_symbols = lief.parse("bedrock_server_symbols.debug")
for s in filter(lambda e: e.exported, lib_symbols.static_symbols):
    lib_symbols.add_dynamic_symbol(s)
lib_symbols.strip()
lib_symbols.write("foo.debug")

You can also observe that the binary is correctly stripped with file

file ./foo.debug
./foo.debug: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped

[^1]: Working well on the master branch. The version 0.11.5 misses to correctly handle this modification

dktapps commented 2 years ago

Thanks. The reason I was using strip is because the output binary produced would segfault immediately. Stripping it made it work as expected. I'll try your suggested code.

dktapps commented 2 years ago

The suggested code appears to work flawlessly. Thank you!