Trying to load position independent code on cortex-m3

8.3k views Asked by At

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.

2

There are 2 answers

1
Dan On BEST ANSWER

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.

1
osgx On

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