https://sourceware.org/bugzilla/show_bug.cgi?id=27119
Bug ID: 27119 Summary: ld improperly relocates function address, creating an invalid pointer Product: binutils Version: 2.31 Status: UNCONFIRMED Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: me at rhysre dot net Target Milestone: --- Originally brought up this here: https://gcc.gnu.org/pipermail/gcc/2020-December/234571.html, was told to file it here. Overview: When compiling C code to a position independent flat binary using the OUTPUT_FORMAT("binary") directive in a linker script, &func (where func is some function residing in another translation unit) will evaluate to the first sizeof(void *) bytes of func instead of the address of func. System Info: $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-6' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 8.3.0 (Debian 8.3.0-6) $ ld -v GNU ld (GNU Binutils for Debian) 2.31.1 $ head -1 /etc/os-release PRETTY_NAME="Debian GNU/Linux 10 (buster)" $ uname -a Linux desktop 5.9.0-0.bpo.2-amd64 #1 SMP Debian 5.9.6-1~bpo10+1 (2020-11-19) x86_64 GNU/Linux Steps to reproduce: 1) Create the following files: $ ls func.c link.lds Makefile prog.c $ cat prog.c extern void func(); void _start() { void *ptr = (void *) func; } $ cat func.c void func() { } $ cat link.lds OUTPUT_FORMAT("binary") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) SECTIONS { . = 0x0000000001000000; .text : { *(.text) } .data : { *(.data) } } $ cat Makefile CFLAGS = -fpie -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -c -I .. LDFLAGS = -pie OBJS = prog.o func.o BIN = prog all: $(OBJS) $(LD) $(LDFLAGS) $(OBJS) -T link.lds -o $(BIN) %.o: %.c $(CC) $(CFLAGS) $< -o $@ %.o: %.S $(AS) $< -o $@ clean: rm -f $(OBJS) $(BIN) 2) Run make and view the produced flat binary prod in any disassembler (eg. radare2), you should see something like the following: ┌ 18: fcn.00000000 (); │ ; var int64_t var_8h @ rbp-0x8 │ 0x00000000 55 push rbp │ 0x00000001 4889e5 mov rbp, rsp │ 0x00000004 488b05070000. mov rax, qword [0x00000012] ; fcn.00000012 │ ; [0x12:8]=0xc35d90e5894855 │ 0x0000000b 488945f8 mov qword [var_8h], rax │ 0x0000000f 90 nop │ 0x00000010 5d pop rbp └ 0x00000011 c3 ret ┌ 7: fcn.00000012 (); │ 0x00000012 55 push rbp │ 0x00000013 4889e5 mov rbp, rsp │ 0x00000016 90 nop │ 0x00000017 5d pop rbp └ 0x00000018 c3 ret 3) Note that fcn.00000000 corresponds to _start and fcn.00000012 corresponds to func. Now note the instructions at 0x00000004 and 0x0000000b. They should be loading the _address_ 0x00000012 into rax and then onto the stack, but instead load the eightbyte _at_ the address 0x00000012 into rax and then onto the stack (so we get 0xc35d90e5894855 instead of 0x00000012). Additional Information: Looking at the relocations in prog.o, it seems like this is due to ld improperly processing the R_X86_64_GOTPCRELX relocation for func: $ readelf --relocs prog.o | grep func 000000000007 000a0000002a R_X86_64_REX_GOTP 0000000000000000 func - 4 Alexander Monakov commented further on this in my original email to the gcc list here: https://gcc.gnu.org/pipermail/gcc/2020-December/234573.html. The linker should probably be emitting a diagnostic indicating that what the user is trying to do (link object files with GOT relative relocations into a flat binary with no GOT) is impossible, or work around that somehow, rather than producing nonsensical code. -- You are receiving this mail because: You are on the CC list for the bug.