A little question about function address with no-pie on RISCV

ywgrit wangxin03@loongson.cn
Thu Nov 28 02:18:42 GMT 2024


Thank you very much.

在 2024/11/27 下午7:21, Xi Ruoyao 写道:
> Fangrui has left Google.
>
> On Wed, 2024-11-27 at 18:00 +0800, ywgrit wrote:
>> 1) The program tested on both riscv and x86_64.
>>
>> // foo.c
>>
>> void foo() {}
>>
>>
>> // main.c
>>
>> #include <stdio.h>
>> void foo();
>>
>> int main() {
>>           foo();
>>           printf("%p\n", foo);
>>           return 0;
>> }
>>
>> 2) The commands executed.
>>
>> gcc -fpic -shared -g -o libfoo.so foo.c
>>
>> gcc -c main.c -o main.o
>>
>> gcc main.o -o main -lfoo -L. -no-pie
>>
>> 3) The result.
>>
>> // riscv
>>
>> ./main
>>
>> 0x120000530
>>
>> // x86_64
>>
>> ./main
>>
>> 0x7ffff3ea05a0
>>
>> 4) The question
>>
>> With no-pie, riscv print the address of foo@plt which is in main, x86_64
>> print the address of foo which is in libfoo.so.
> On x86_64 if you use
>
> gcc main.o -o main -lfoo -L. -no-pie -fno-pie
>
> you get the address of the PLT entry too.  -fno-pie controls GCC code
> generation, while -no-pie is directly passed to the linker and mostly
> ignored by GCC.
>
> Traditionally, in a PDE the relocation for addressing *external* symbols
> was resolved at link time.  For example, when t.so provides data symbol
> dat and function symbol func, and pde.c is:
>
> int printf(const char *, ...);
> extern int dat;
> extern int func();
>
> int main() {
> 	printf("%p\n", &dat);
> 	printf("%p\n", &func);
> }
>
> On x86_64 "gcc pde.c -fno-pie -no-pie t.so -O2" gives;
>
> 0000000000401060 <main>:
>    401060:	48 83 ec 08          	sub    $0x8,%rsp
>    401064:	be 20 40 40 00       	mov    $0x404020,%esi
>    401069:	bf 04 20 40 00       	mov    $0x402004,%edi
>    40106e:	31 c0                	xor    %eax,%eax
>    401070:	e8 bb ff ff ff       	call   401030 <printf@plt>
>    401075:	be 40 10 40 00       	mov    $0x401040,%esi
>    40107a:	bf 04 20 40 00       	mov    $0x402004,%edi
>    40107f:	31 c0                	xor    %eax,%eax
>    401081:	e8 aa ff ff ff       	call   401030 <printf@plt>
>    401086:	31 c0                	xor    %eax,%eax
>    401088:	48 83 c4 08          	add    $0x8,%rsp
>    40108c:	c3                   	ret
>    40108d:	66 2e 0f 1f 84 00 00 	cs nopw 0x0(%rax,%rax,1)
>    401094:	00 00 00
>    401097:	66 0f 1f 84 00 00 00 	nopw   0x0(%rax,%rax,1)
>    40109e:	00 00
>
> So the address of dat is "fixed" at 0x404020, the address of func is
> "fixed" at 0x401040, etc.  But dat and func are actually in t.so which
> is loaded elsewhere, so for the data symbol dat, there's a "copy
> relocation" in the PDE:
>
> 000000404020  000400000005 R_X86_64_COPY     0000000000404020 dat + 0
>
> which instructs ld.so to copy dat to 0x404020 before running the code in
> the PDE.
>
> For the function symbol func, the solution should be obvious: the
> "fixed" address 0x401040 is just the address of the PLT entry for func.

Is it reasonable to access the address of a function and get the address 
of the plt of the function?

> This scheme had seemed useful even for PIE so it had been used for PIE
> for a while.  But it has some drawbacks, read
> https://maskray.me/blog/2021-01-09-copy-relocations-canonical-plt-entries-and-protected
> for details.  So nowadays (with a recent toolchain) this scheme is no
> longer used for PIE by default.
>
> When LoongArch supported was added, due to all the drawbacks
> "R_LARCH_COPY" was NACK'ed very early, thus on LoongArch this scheme
> isn't used at all, even for PDE.

When compiling ghc e70d41406b5d5638b42c4d8222cd03e76bbfeb86 on 
LoongArch, because of the -no-pie. The generated ghc runs with an error 
because when ghc accessing the address of the function, it gets the 
address of the plt.

Therefore it is necessary to link ghc with lld.


> So both x86_64 and RISC-V still use this scheme for PDE but not PIE, the
> difference seems for x86_64 it's decided at the compile time (i.e.
> depending on the GCC option -fno-pie), and for RISC-V it's decided at
> the link time (i.e depending on the ld option -no-pie).
>



More information about the Binutils mailing list