7

I'm trying to understand the linking stage of C toolchain. I wrote a sample program and dissected the resulting object file. While this helped me to get a better understanding of the processes involved, there are some things which remain unclear to me.

Here are:

Part 1: Handling of initialized variables.

Is it correct, that theses relocation table entries...

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
0000002b dir32             .data
00000035 dir32             .data
0000003f dir32             .data

... are basically telling the linker, that the addresses stored at offset 2b, 35 and 3f from .text are not absolute adresses, but relative adresses (= offsets) in relation to .data? It is my understanding that this enables the linker to

  • either convert these relative adresses to absolute adresses for creation of a non-relocatable object file,
  • or just adjust them accordingly in case the object file gets linked with some other object file.

Part 2: Handling of uninitialized variables.

I don't understand why uninitalized variables are handled so differently to initialized variables. Why are the register adresses stored in the opcode,

  • equal for all the uninitialized variables (0x0, 0x0 and 0x0), while being
  • different for all the initialized variables (0x0, 0x4 and 0x8)?

Also the value field of their relocation table entries is entirely unclear to me. I would have expected the .bss section to be referenced there.

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
0000000d dir32             _var1_zeroed-0x00000004
00000017 dir32             _var2_zeroed-0x00000004
00000021 dir32             _var3_zeroed-0x00000004
Multisync
  • 767
  • 6
  • 25

1 Answers1

3

... are basically telling the linker, that the addresses stored at offset ...

No, the linker is no longer involved with this. The relocation tables tell the loader, the part of the operating system that's responsible for loading the executable image into memory about the addresses.

The linker builds the executable image based on the assumption that everything is ideal and the image can be loaded at the intended address. If that's the case then everything is hunky-dory, nothing needs to be done. If there's a conflict however, the virtual address space is already in use by something else, then the image needs to be relocated at a different address.

That requires addresses to be patched, the offset between the ideal and the actual load address needs to be added. So if the .data section ends up at another address then addresses .text+0x2b, .text+0x35, etcetera, must be changed. No different for the uninitialized variables, the linker already picked an address for them but when _var1_zeroed-0x00000004 ends up at another address then .text+0x0d, .text+0x17, etcetera, need to be changed.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • "The linker builds the executable image based on the assumption that everything is ideal and the image can be loaded at the intended address." This doesn't seem to apply to the object file referred to in the question. Please note that the register file adresses stored in the opcodes are **equal** for all the uninitialized variables. Can you elaborate on that? – Multisync Oct 06 '14 at 17:52
  • Hmm, rats, object files are one step earlier. The linker assigns addresses. – Hans Passant Oct 06 '14 at 17:56
  • Hmm.. so why were, in contrast to that, the adresses for the **initialized** variables already assigned by the compiler? – Multisync Oct 06 '14 at 18:08
  • The compiler must pick an offset in .data to make the variable match the initial value. The linker merges the .data sections so still changes the address. – Hans Passant Oct 06 '14 at 18:16