I have an embedded application which will have a bootloader which will decide to run 1 of two applications directly from internal flash. I am trying to make these apps position independent so that they both can be compiled for the same base address. There is no operating system, so no dynamic linker is available. So far I have tried building with -fpie option (using gcc) with not too much success. The function calls appear to be correct but the global data does not have the correct address. The locally defined global data seems to have it's address offset by the amount that the app is offset from its original base address. The global data which is declared in other files has a completely wrong address(and if I build with -fpic then both the locally declared global data and global data in other files are completely wrong). I suspect I need to do some manipulation of the GOT section when my app starts but I am not sure.
I finally got it working. It looks like I need to do the following: All code needs to be complied with -fpic (previously I was trying -fpie)
Also I had my linker script needed modification. I was forcing the GOT into the sram section and it was located after the dynamic section which was in flash. Looks like everything works properly if the GOT section is located prior to the dynamic section in the flash. Not sure why this matters but it seemed to fix everything - prior to this it was as if the code did not locate the GOT properly since the GOT had the correct values stored in it but the address of all my variables were incorrect.
PIE (and PIC) code needs a relocation process after loading at some address (different from default) and before it will be runned. I suggest you consult the code of ld.so
. Also, you should check the relocations table in your binary (e.g. using readelf -r
).
Here is a good presentation on PIE (it is about OpenBSD, but the process is same). http://www.openbsd.org/papers/nycbsdcon08-pie/ or http://www.dcbsdcon.org/speakers/slides/miller_dcbsdcon2009.pdf
I guess you should not only to change a GOT, but to also to find all Relocations and to do them.
Basically, processing of PIE binary by ld.so is almost the same as processing a dynamic library with PIC, with relocating not a library, but the executable image itself.
The "Wrong addresses" you see is a place, where an actual value would be written by relocation solving. As for i386 http://books.google.com/books?id=Id9cYsIdjIwC&pg=PA174 there are relocations:
- R_386_GOTPC
- R_386_GOT32
- R_386_GOTOFF
- R_386_RELATIVE
Linker should resolve all of them before the code can access a global data.
Readelf -r sample:
Dynamically linked one
$ readelf -r fdyn
Relocation section '.rel.dyn' at offset 0x27c contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049ff0 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x284 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
0804a004 00000207 R_386_JUMP_SLOT 00000000 __libc_start_main
PIE:
$ readelf -r fPIE
Relocation section '.rel.dyn' at offset 0x388 contains 6 entries:
Offset Info Type Sym.Value Sym. Name
00001fe8 00000008 R_386_RELATIVE
00001ff0 00000008 R_386_RELATIVE
00002010 00000008 R_386_RELATIVE
00001fe0 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
00001fe4 00000206 R_386_GLOB_DAT 00000000 _Jv_RegisterClasses
00001fec 00000406 R_386_GLOB_DAT 00000000 __cxa_finalize
Relocation section '.rel.plt' at offset 0x3b8 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
00002000 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
00002004 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main
00002008 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize
来源:https://stackoverflow.com/questions/5024387/trying-to-load-position-independent-code-on-cortex-m3