Position Independent Code

Quick question for someone in the know.

I'm trying to setup some code that can be run from either hwram or lwram depending on the situation. From what I can tell, the gnu c compiler supports a function called position independent code or PIC. I've tried playing around with the option using the kpit compiler and it definitely is generating code that would be position independent, however when I get to the linking stage it complains about _GLOBAL_OFFSET_TABLE_ being missing. That's when I'm using my own linker script and crt0.s file. If I use the default script, I get the typical errors associated with the using default scripts, however the error about _GLOBAL_OFFSET_TABLE_ being missing stops. Does anyone have any experience using PIC or have a working example for SH2?
 
I'm not entirely sure on all the details as they seem to vary with target and operating system, but as I understand it you should define a section in the linker script that collects all the GOT entries and defines the _GLOBAL_OFFSET_TABLE_ symbol at the start of that section. The symbol is then used to locate the GOT at runtime. This also implies that the GOT's address must be fixed unless you have a dynamic linker.

Have you checked the compiler output when not using -fPIC? Due to the architecture SH code is pretty position-independent by nature (relative offsets used for most things) and some small utility routines I've written have turned out to be completely relocatable without any extra effort on my part.
 
antime said:
I'm not entirely sure on all the details as they seem to vary with target and operating system, but as I understand it you should define a section in the linker script that collects all the GOT entries and defines the _GLOBAL_OFFSET_TABLE_ symbol at the start of that section. The symbol is then used to locate the GOT at runtime. This also implies that the GOT's address must be fixed unless you have a dynamic linker.

Have you checked the compiler output when not using -fPIC? Due to the architecture SH code is pretty position-independent by nature (relative offsets used for most things) and some small utility routines I've written have turned out to be completely relocatable without any extra effort on my part.

I managed to to fix the _GLOBAL_OFFSET_TABLE_ issue. Instead of specifying the address in the linker script like so:

OUTPUT_FORMAT("binary")

SECTIONS

{

. = 0x06004000;

.text : { *(.text) }

[etc]

You do it like this:

OUTPUT_FORMAT("binary")

SECTIONS

{

_GLOBAL_OFFSET_TABLE_ = .;

.text : { *(.text) }

[etc]

I'm still getting one more linker error I couldn't figure out though. I'm getting "undefined reference to `_(double, int, void, short, int, _i4, int) __restrict".

From what I could tell from the output, when using a regular compile larger functions were called using jsr's with hard-coded addresses. Where as -fpic generally used bsr or bsrf. Obviously there were other differences relating to fetching positioning from the GOT, but that's the main change I noticed.
 
CyberWarriorX said:
I managed to to fix the _GLOBAL_OFFSET_TABLE_ issue. Instead of specifying the address in the linker script like so:

OUTPUT_FORMAT("binary")

SECTIONS

{

. = 0x06004000;

.text : { *(.text) }

[etc]

You do it like this:

OUTPUT_FORMAT("binary")

SECTIONS

{

_GLOBAL_OFFSET_TABLE_ = .;

.text : { *(.text) }

[etc]

I'm still getting one more linker error I couldn't figure out though. I'm getting "undefined reference to `_(double, int, void, short, int, _i4, int) __restrict".

From what I could tell from the output, when using a regular compile larger functions were called using jsr's with hard-coded addresses. Where as -fpic generally used bsr or bsrf. Obviously there were other differences relating to fetching positioning from the GOT, but that's the main change I noticed.

Just out of curiosity, assuming that this all works: What are you working on?
 
Back
Top