Option -fno-plt has no effect

Asked by Ervin Oro on 2018-05-29

Goal: to generate position independent code (PIC) that does function calls through the global offset tablee (GOT) and does not use a procedure linkage table (PLT). GCC has option -fno-plt for that purpouse (https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Code-Gen-Options.html#index-fno-plt): "Do not use the PLT for external function calls in position-independent code. Instead, load the callee address at call sites from the GOT and branch to it."

Expected result: when compiling with -fpic -fno-plt, each function call should contain instructions to read function address from .got and then branch to that address.

Actual result: direct function calls are generated instead (bl to constant relocatable address):

$ cat test.c
void f2();

void f1() {
$ arm-none-eabi-gcc -c -fpic -fno-plt test.c -o test_no_plt.o
$ arm-none-eabi-gcc -c -fpic -fplt test.c -o test_plt.o
$ diff -b test_no_plt.o test_plt.o

This shows, that -fplt and -fno-plt generate identical outputs. Both contain direct function calls that get replaced with PLT by linker when using arm-none-eabi-ld -shared. Using regular version of gcc, different binaries are generated as expected (one contains function call to relocated address, the other one dereferences address from GOT first and then calls)

I am using prebuilt binary distribution of the toolchain:
arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204]
Host is Ubuntu 18.04 LTS.

Question information

English Edit question
GNU Arm Embedded Toolchain Edit question
No assignee Edit question
Last query:
Last reply:
Ervin Oro (ervinoro) said : #1

The same issue also exists on Windows host. There also -fplt and -fno-plt generate identical outputs.

Tejas Belagod (belagod-tejas) said : #2


Support for -fno-plt is not implemented presently. How important is this feature for you?


Marco (ocramo) said : #3

Having -fno-plt work would greatly simplify my current work on an customized embedded dynamic linker.

Marco (ocramo) said : #4

The use and creation of the plt can be circumvented by the use of function pointers. This will create a jump directly through GOT instead of creating a plt entry.

extern int importfoo (void); //external function
extern int (*importbar)(void); //external function pointer

void foobar() //call them to see what assembly is created

//calling importfoo
336: f7ff ffe3 bl 300 <importfoo@plt>
//calling imporbar
33a: 4b08 ldr r3, [pc, #32] ; (35c <foo+0x4c>) ;load offset inside GOT
33c: f859 3003 ldr.w r3, [r9, r3] ;load address of importbar pointer from GOT+offset
340: 681b ldr r3, [r3, #0] ;load the (function) address importbar is pointing to
342: 4798 blx r3 ;branch to it (ideally to bar ;-)

for foo this will create a PLT section, moreover one that relies on fixed distance between text and data (more precise between plt code and .got) (see my linked posting)
calling importfoo() function will create a branching like this:

and a plt code like this:
00000300 <importfoo@plt>:
 300: f240 0cf0 movw ip, #240 ; 0xf0
 304: f2c0 0c01 movt ip, #1
 308: 44fc add ip, pc
 30a: f8dc f000 ldr.w pc, [ip]
 30e: bf00 nop

For reference:
compiler flags used:
-mcpu=cortex-m4 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fPIC -g3 -mno-pic-data-is-text-relative -msingle-pic-base -mpic-register=r9 -std=gnu11 -MMD -MP -MF

linker flags:
-mcpu=cortex-m4 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fPIC -g3 -mno-pic-data-is-text-relative -msingle-pic-base -mpic-register=r9 -nostdlib -Xlinker --gc-sections -Wl,-Map,"example.map" --specs=rdimon.specs -Wl,--start-group -lgcc -lc -lc -lm -lrdimon -Wl,--end-group -shared

GNU Tools ARM Embedded version: 6 2017-q2-update

Marco (ocramo) said : #5
Logan Hunter (hunterl) said : #6

Hey, is there any possibility of the -fno-plt functionality being implemented? It would be excellent to not have to use the function pointer workaround Marco mentioned before to support external function calls in dynamically linked libraries, and there doesn't seem to be a way to get the generated PLT to work with msingle-pic-base/mpic-data-is-text-relative/mpic-register (as in - not rely on a fixed offset between the PLT and the GOT). Thanks!

Can you help with this problem?

Provide an answer of your own, or ask Ervin Oro for more information if necessary.

To post a message you must log in.