2

For a personal project, I need to write an executable that loads at a non-default memory address. From this SO question, I know I can set the entry address for an ELF and modify the section addresses manually so that the executable is effectively based at some address I choose. However, the answer suggests that this is only works if I don't glibc initialization (which I need for this project), and setting section memory addresses every time I compile would be difficult (not to mention tedious).

It seems like there should be a better way to set a base address for an ELF when building, though I'll resort to doing it manually with a script post-build if need be. This option for ld would be perfect if it wasn't specific to the PE port:

--image-base value
  Use value as the base address of your program or dll. This is the lowest 
  memory location that will be used when your program or dll is loaded. To 
  reduce the need to relocate and improve performance of your dlls, each should 
  have a unique base address and not overlap any other dlls. The default is 
  0x400000 for executables, and 0x10000000 for dlls. [This option is specific 
  to the i386 PE targeted port of the linker]

I haven't yet found an ELF equivalent. Does none exist? Parsing the ELF file myself wouldn't be the end of the world, but it seems like this feature should exist somewhere.

Community
  • 1
  • 1
emprice
  • 912
  • 11
  • 21
  • Dumping the built-in linker response file, modifying it and passing it as linker param to gcc (and thus to ld) ? – Marco van de Voort Mar 08 '13 at 22:32
  • @MarcovandeVoort A quick Google search has yielded nothing on this for `ld` or `gcc`. Can you elaborate or direct me to the right documentation? – emprice Mar 08 '13 at 23:59
  • Why do you need to "load at a non-default memory address"? Maybe you could achieve your initial goal differently.... – Basile Starynkevitch Mar 09 '13 at 08:24
  • 1
    You can pass a linker script to ld with -T. You can see the builtin script by doing a bogus link with ld -verbose – Marco van de Voort Mar 09 '13 at 15:15
  • @MarcovandeVoort Thanks! It's working somewhat now, though it seems like some of the addresses I try work (like `0x200000` or `0x500000`) but not others (like `0x100000`); when it doesn't work, the program is killed. Is there some sort of limitation on which addresses I can use (besides kernel-space ones)? – emprice Mar 10 '13 at 05:19
  • @BasileStarynkevitch I don't see another way to do what I need to. I know I need the address `0x400000` free for memory mapping, so I need my executable to load somewhere out of the way. – emprice Mar 10 '13 at 05:20
  • nosuchthingasstars: I assume it must fall within the defined codesegment? I don't know the details of Linux on this level that well, I mostly use FreeBSD, and I know these entrypoint details mostly from messing with embedded(Microchip) targets. I spun the comments out into a proper answer, so you can accept it. – Marco van de Voort Mar 10 '13 at 12:13

1 Answers1

2

The ELF entry point can be set in the linker response file, which can be passed to ld with -T

Doing a bogus link with --verbose will show you the default linker responsefile (which might be system specific, but in reality it is not that bad, one per arch per OS for the most).

Note that there might be additional constraints (like the entry point residing in a text/codesegment)

For a practical example of lugging along custom linker files, see the Free Pascal project, which does this to implement resources.

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89
  • `-v` just prints out the version. Use `--verbose` instead. (This leads to a lot of output, so you may pipe it through `less`) – dCSeven May 18 '19 at 11:50