1

I am trying to write my own loader. In this program, I will copy the program to the specific address in RAM, and will jump on to the entry point address by reading the entry point of elf. But, I am not able to understand what is the loader address? Does it mean that the binary needs to be copied only at the loader address specified at compile time. can't I load the program in some other location rather than the load address specified during compile time? My basic question is the following, "can't I load the program in some other location rather than the load address specified during compile time?"

jww
  • 97,681
  • 90
  • 411
  • 885
dexterous
  • 6,422
  • 12
  • 51
  • 99

3 Answers3

1

Precisely.

Fully linked ELF programs contain no relocation information which would allow you to fix up references after loading the program at a different address.

Using the -Ur option to the linker (or an appropriate linker script), you can generate an ELF file with relocations -- writing a loader for these is more difficult though.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64
  • My basic question is the following, "can't I load the program in some other location rather than the load address specified during compile time?" – dexterous Sep 10 '13 at 08:25
  • 2
    And the basic answer is "not without fixing up references after loading". – Sneftel Sep 10 '13 at 08:32
1

Are you targetting ARM, by any chance?

The solution to your problem is PIC/PIE (Position Independent Code/Executable). This way, the program is compiled as follows:

  • any in-function jumps are made relative (things like ifs, cases, loops etc)
  • any intra-section jumps are made indirectly in two steps using GOT (Global Offset Table)
  • inter-section jumps are either relative or indirect, depending on the linker argument "long-jumps"
  • any global data access is made indirectly using GOT

This way, the program contains no absolute addresses anywhere in the code. It also has no relocations in the code. The only relocation needed is the placement of the GOT itself.

GOT is a table that contains addresses of all global objects, functions and data. In a non-PIC code, the absolute addresses of data are embedded directly inside the code. The function needs to know the GOT table address and the entry number in the GOT table corresponding to a particular object. The object number is the only thing embedded in a PIC code. The GOT address is presented to a function by one of the 2 ways I've encountered: a relocation appended at the end of the function body or in a predefined CPU register. I find the latter option better.

PICs are useful if you have memory-mapped ROM where your program is initially loaded and you want to copy it to the RAM to make things faster and to allow modification of data.

Note, that you can do all of the above without PIC, it's just much more hassle. You will have a lot of relocations inside the code (in case of PIC moving of the functions code is a matter of a simple memcpy) and you have to copy all data blocks at once (correctly written PIC executables allow moving of individual objects in different regions of memory).

If you are curious, then I can send you some of my linker scripts for ARM architecture.

haael
  • 972
  • 2
  • 10
  • 22
0

You need to understand ELF file format which is a bit complicated. You can find and overview on Wikipedia.

Following SO posts may be relevant:

Community
  • 1
  • 1
bkausbk
  • 2,740
  • 1
  • 36
  • 52