Thanks for your response ! Ok, it makes sense in the context of dynamic libraries.But in the case of embedded code, not running on a OS like linux (which is the case of Cortex-Mx and a lot of xtensa devices), the definition of Position Independant Code is quite different, and in this case, only relative jumps/calls and relative access to constants should be allowed.
I have the feeling that because some xtensa chips are able to run linux, there may be some confusion there.
Regards, Vincent. Le 03/05/2022 à 12:24, Xi Ruoyao a écrit :
On Tue, 2022-05-03 at 10:26 +0200, vincent Dupaquis wrote:- Is there somewhere a common definition of what mean PIC for the different architectures ?Generally -fpic/-fPIC does not means only position-independant code, but position-independant code **suitable for dynamic linking**. Consider the code: void callee(void) { /* ... */ } void caller(void) { callee(); } Without -fPIC caller may call callee with a PC-relative call instruction. But with -fPIC it's not allowed because the symbol callee may be interposed. For more info: https://maskray.me/blog/2021-05-16-elf-interposition-and-bsymbolic (You may argue that the ELF interposition rule is strange and known to slow down programs, but there are still many programs depending on the rule in 2022.) So my guess is w/o -fPIC the compiler just calls callee with a PC-rel call, but with -fPIC it needs to either: (1) Load the address of callee from GOT. or (2) Call the PLT stub ("callee@PLT") which is resolved to "jump callee" at runtime. For (1), the address of the callee is loaded into a register then a "call register" instruction is used. It seems callx8 is such an instruction on Xtensa (I know nothing about Xtensa so it's from Google). For (2), the compiler and the assembler cannot determine if the PLT stub is out-of-range for the PC-rel call instruction (as the PLT stubs are generated by the linker). So the only approach legal for the worst case is to assume the PLT stub may be far away from the call site. Then a PC-relative address load instruction will be used to load the address of the PLT stub into a register, then callx8 is used to perform the call. For some of other targets, a code model is defined to guarantee the PLT stubs to be in-range of the PC-rel call instruction. Those targets can simply use PC-rel call to invoke callee@PLT. But again I know nothing about Xtensa and I can't reproduce the behavior you mentioned with GCC trunk. It seems always generating "l32r/callx8" pairs for calls on xtensa-linux-gnu, unless the callee is `static`. And it makes sense to me: "l32r", as a PC-relative address loading instruction, will load the address of callee@PLT correctly.
-- *Vincent Dupaquis* Software security & Cryptography expert 06 24 58 17 05/Europarc de Pichaury Bâtiment B8 1330 rue Guillibert Gautier de la Lauzière 13290 Aix-en-Provence/
www.trusted-objects.com <http://www.trusted-objects.com>
Attachment:
OpenPGP_signature
Description: OpenPGP digital signature