Bug 25527 - [RISC-V] -static-pie not producing relocations
Summary: [RISC-V] -static-pie not producing relocations
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.32
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-02-10 11:09 UTC by Sergi Granell
Modified: 2024-04-10 14:31 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2020-02-11 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sergi Granell 2020-02-10 11:09:58 UTC
Trying to compile with -static-pie for a bare-metal target: no dynamic linker and therefore the relocations have to be resolved by the ELF loader when it establishes a load address or the executable itself at init by iterating over the relocatable sections.
The problem is that after linking, the output ELF doesn't contain relocations.
Also attached the output when compiling for aarch64.

$ cat simple.c
typedef void (*fptr)(void);

void func1(void) {}
void func2(void) {}

const fptr table[] = {
	func1,
	func2,
};

int _start(int i)
{
	table[i]();
}

$ cat linker.ld
ENTRY(_start)

SECTIONS
{
	. = 0x00001000;
}

---------------------------------------------------------------------------------------------------------------
RISC-V:
- GCC: riscv64-unknown-elf-gcc (GCC) 9.2.0
- binutils: GNU ld (GNU Binutils) 2.32

$ riscv64-unknown-elf-gcc -fPIE -c simple.c -o simple.riscv.o
$ riscv64-unknown-elf-readelf -r simple.riscv.o

Relocation section '.rela.text' at offset 0x278 contains 4 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000050  000b00000017 R_RISCV_PCREL_HI2 0000000000000000 table + 0
000000000050  000000000033 R_RISCV_RELAX                        0
000000000054  000600000018 R_RISCV_PCREL_LO1 0000000000000050 .L0  + 0
000000000054  000000000033 R_RISCV_RELAX                        0

Relocation section '.rela.data.rel.ro.local' at offset 0x2d8 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000000  000900000002 R_RISCV_64        0000000000000000 func1 + 0
000000000008  000a00000002 R_RISCV_64        000000000000001c func2 + 0

$ riscv64-unknown-elf-gcc -nostdlib -nostartfiles -T linker.ld -static-pie simple.riscv.o -o simple.riscv.elf
$ riscv64-unknown-elf-readelf -r simple.riscv.elf

There are no relocations in this file.

simple.riscv.elf is "Type: EXEC (Executable file)"

---------------------------------------------------------------------------------------------------------------
aarch64:
- GCC: aarch64-linux-gcc.br_real (Buildroot 2018.11-rc2-00003-ga0787e9) 8.2.0
- binutils: GNU ld (GNU Binutils) 2.31.1

$ aarch64-linux-gcc -fPIE -c simple.c -o simple.aarch64.o
$ aarch64-linux-readelf -r simple.aarch64.o 

Relocation section '.rela.text' at offset 0x2d8 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000001c  000e00000113 R_AARCH64_ADR_PRE 0000000000000000 table + 0
000000000020  000e00000115 R_AARCH64_ADD_ABS 0000000000000000 table + 0

Relocation section '.rela.data.rel.ro.local' at offset 0x308 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000000  000c00000101 R_AARCH64_ABS64   0000000000000000 func1 + 0
000000000008  000d00000101 R_AARCH64_ABS64   0000000000000008 func2 + 0

Relocation section '.rela.eh_frame' at offset 0x338 contains 3 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000001c  000200000105 R_AARCH64_PREL32  0000000000000000 .text + 0
000000000030  000200000105 R_AARCH64_PREL32  0000000000000000 .text + 8
000000000044  000200000105 R_AARCH64_PREL32  0000000000000000 .text + 10

$ aarch64-linux-gcc -nostdlib -nostartfiles -T linker.ld -static-pie simple.aarch64.o -o simple.aarch64.elf
$ aarch64-linux-readelf -r simple.aarch64.elf 

Relocation section '.rela.dyn' at offset 0x1148 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000001178  000000000403 R_AARCH64_RELATIV                    1000
000000001180  000000000403 R_AARCH64_RELATIV                    1008

simple.aarch64.elf is "Type: DYN (Shared object file)"
Comment 1 Jim Wilson 2020-02-11 01:21:40 UTC
I see two problems here.

The first problem is that the RISC-V GCC port isn't handling the --static-pie option.  For targets that support it, --static-pie should be translated to the linker options "--static --pie --no-dynamic-linker -z text".  This doesn't happen for RISC-V as the gcc support is missing.

The second problem is that if I manually specify the missing linker options then I get a linker error "-pie is not supported".  We do not have support for shared libraries in our embedded toolchain because no one has done a RISC-V shared library port of newlib yet.  I get binutils testsuite errors if I enable shared library support, which makes it harder to spot testsuite regressions.  Also, I used to get bug reports from users asking why the shared library support was broken because they couldn't get it working.  It isn't broken, it is because the newlib support is missing.

If I use a linux toolchain, and manually specify the missing linker options, then it works correctly.  But the linux toolchain isn't designed for bare metal targets so that probably isn't usable as a workaround.

The GCC bug should be fixed and looks easy enough.

You could hack around the binutils problem by reverting the patch that disabled shared library support in the embedded elf toolchain.  Or maybe I should consider re-enabling the support and find some other way to handle the newlib and testsuite problems.  You don't need shared libraries to make static pie work.  And the boot loader folks would also like to be able to use static pie or something similar.
Comment 2 Sergi Granell 2020-04-29 16:49:57 UTC
Hi Jim,
Are there any news/updates regarding this?
Seems like there were 2 problems:
1) GCC doesn't propagate "--static-pie" as "--static --pie --no-dynamic-linker -z text" to the linker
2) Newlib doesn't support building as a shared library (required by --pie), which shouldn't be needed for either bare-metal or static-pie

Have those been fixed? If not, do you have patches, that maybe are not ready yet for upstreaming, but that fix those issues?

Thanks!
Comment 3 Jim Wilson 2020-04-30 21:19:13 UTC
I don't know of anyone working on any of these problems.  So no progress.
Comment 4 Andreas Schwab 2024-04-10 14:31:23 UTC
gcc 14 will support -static-pie for linux configurations.