2

I'm learning how a linker works in Linux. Here is my code as an example:

// main.c
int printf(const char *format, ...);

void func1(int i)
{
    printf("%d\n", i);
}

int main(void)
{
    func1(1);
    return 0;
}

I execute the command gcc -c main.c and get an obj file named main.o.

Then I execute the command objdump -r main.o and here is the output:

main.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000011 R_X86_64_32       .rodata
000000000000001b R_X86_64_PC32     printf-0x0000000000000004
000000000000002c R_X86_64_PC32     func1-0x0000000000000004


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE
0000000000000020 R_X86_64_PC32     .text
0000000000000040 R_X86_64_PC32     .text+0x0000000000000022

If I'm right, objdump -r will show us all of the relocation tables in the obj file. In this case, printf and func1 are all put into the relocation table.

printf isn't defined in this C file so it needs to be relocated, but why can func1 be found in the relocation table too? As my understanding, func1 should be well defined and can be found in the .text section, it needn't to be relocated, right?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Yves
  • 11,597
  • 17
  • 83
  • 180
  • Functions are globals too so every function will get a relocation entry in C except those which you make `static`, but sadly I don't know the deeper details still. – Eraklon Feb 21 '20 at 09:40
  • @Eraklon Global variables and the function `main` aren't in relocation table. – Yves Feb 21 '20 at 09:54
  • main is an entry point it is not an ordanary function – Eraklon Feb 21 '20 at 09:56
  • @Eraklon OK, so I think I kind of misunderstand what "relocation table" is. Maybe all of global functions must be relocated while linking. – Yves Feb 21 '20 at 10:04

1 Answers1

2

The relocation records are locations that need to be adjusted when addresses of sections are determined. In many architectures, including x86, it is possible to write position-independent code that refers to objects or functions by offsets from one place within a section to another (and so the offsets do not change when whole section is moved) and may refer to objects or functions by offsets across sections with some additional linker assistance (and so the offsets do not change after linking, and the entire combined image may be shifted in memory).

However, the fact that it is possible does not mean your build tools are using position-independent code. For whatever reason, it appears the tools you are using, with the switches you are using, are not generating position-independent code. Thus, when there is a reference to printf or func1, a relocatable reference to it is generated, resulting in a relocation record that must be adjusted by the linker or loader.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • "On macOS, the linker is, by default, allowed to strip “dead subsections” out of code" This may be wrong. It seems you have to enable it by a specify "-dead_strip" explicitly. see https://stackoverflow.com/questions/17710024/clang-removing-dead-code-during-static-linking-gcc-equivalent-of-wl-gc-sect – karlbsm Jun 25 '21 at 14:31
  • @yuansizhu: I think what I meant by it is “allowed” may have been that the default object file formats on macOS are set up for this, so you can enable the `-dead_strip` switch in the linker without changing anything about compilation or anything else about linking and building. But I will remove that passage. – Eric Postpischil Jun 26 '21 at 19:19