bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/27119] New: ld improperly relocates function address, creating a


From: me at rhysre dot net
Subject: [Bug ld/27119] New: ld improperly relocates function address, creating an invalid pointer
Date: Mon, 28 Dec 2020 06:11:33 +0000

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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]