'Why are there global offset tables and procedure linkage tables in statically linked executables?

I've done a bunch of reading on dynamic linker relocations and position independent code including procedure linkage tables and global offset tables. I don't understand why a statically linked executable needs a PLT and GOT. I compiled a hello world program on my ubuntu x86_64 machine and when I dump the section headers with readelf -S it shows PLT and GOT sections.

I also created a shared library with a simple increment function that I compiled with gcc -shared without -fpic and I also see PLT and GOT sections. I didn't expect this either.



Solution 1:[1]

I don't understand why a statically linked executable needs a PLT and GOT.

It doesn't.

I compiled a hello world program on my ubuntu x86_64 machine and when I dump the section headers with readelf -S it shows PLT and GOT sections.

This is an accident of implementation. The sections come from crt1.o, and there isn't a separate crt1s.o for fully-static linking, so you end up with .plt and .got entries from there.

You can strip these sections, and the binary will still work:

objcopy -R.got -R.plt a.out a.out2

Note: do not strip .rela.plt, as that section is still needed to implement IFUNCs.

Solution 2:[2]

I found that gcc generates a .got and .got.lpt when generating position independent code and taking the address of a function defined in another source file.

My test files were:

part1.c:

extern void afunc();

int _start()
{
  return 0x55 & (__SIZE_TYPE__) afunc;
}

part2.c:

void afunc() {}

My test was (substitute your own gcc version):

for o in s 4 3 2 1 0
do
  aarch64-linux-gnu-gcc-10 -fPIC part1.c part2.c -o static.elf -static -nostdlib -O$o &&
  aarch64-linux-gnu-objdump -x static.elf | grep 'GLOBAL_OFFSET'
done

I get the following output for all optimization levels:

0000000000410fd8 l     O .got   0000000000000000 _GLOBAL_OFFSET_TABLE_

Replacing -fPIC with -fno-PIC and the segment goes away.

You can tell if your compiler defaults to -fPIC by running this:

aarch64-linux-gnu-gcc-10 -mcmodel=large -x c - < /dev/null 

From which, I get the error, if it does:

cc1: sorry, unimplemented: code model ‘large’ with ‘-fPIC’

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Employed Russian
Solution 2 Simon Willcocks