[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.
- [Bug ld/27119] New: ld improperly relocates function address, creating an invalid pointer,
me at rhysre dot net <=
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, me at rhysre dot net, 2020/12/28
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, hjl.tools at gmail dot com, 2020/12/28
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, me at rhysre dot net, 2020/12/28
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, hjl.tools at gmail dot com, 2020/12/28
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, amonakov at gmail dot com, 2020/12/29
- [Bug ld/27119] ld improperly relocates function address, creating an invalid pointer, hjl.tools at gmail dot com, 2020/12/29