Discussion:
Position independent CODE with position dependent DATA ?
Renaud
2010-07-07 12:16:33 UTC
Permalink
Hi there ! I tried to get an answer over multiple groups, without success.

The spot : my CPU (AVR32) has no MMU, running our own minimal RTOS,
and tasks are compiled as PIC (mandatory) - using GCC.

Without entering into details, we *need* to declare the DATA sections
(bss, data...) to be position dependent, i.e to fall at a fixed
address regardless of CODE position, thus not PC-relative (unlike PIC
is doing as default).

I searched around the LD manual without success... Maybe by declaring
the sections as "shared memory" or something like that ?

Any hints ?

(please, please keep away from endless debat, I need an answer ;))

Thanks !
John Reiser
2010-07-07 14:34:31 UTC
Permalink
Post by Renaud
Without entering into details, we *need* to declare the DATA sections
(bss, data...) to be position dependent, i.e to fall at a fixed
address regardless of CODE position, thus not PC-relative (unlike PIC
is doing as default).
Have you considered using the MEMORY command of a linker script,
which allows placing a segment at a fixed address? Compile as PIC,
load with a linker script that places the ORIGIN of the DATA segment
at a numerical constant address. See "info ld".

Otherwise (or in general):
Who chooses the fixed address, and when?
Is the fixed address a constant that is known before compilation begins?
Is the fixed address the same for ALL programs, or can it vary as long
as it is the same for each instance [revision] of a given program?

Consider loading twice. Load once to get the sizes and a load map.
Write a utility program that reads the sizes and addresses and .o files,
and generates new .o files with symbols that are ABS instead of .data.
Then load a second time to generate the final program.

--
John Reiser
2010-07-07 17:06:03 UTC
Permalink
Our script is already using MEMORY statements: CODE and read-only DATA
are placed in ROM, and DATA in RAM.
In fact the problem is only the GOT (we need to be at a fixed known
address) ...
not relatively to current PC.
Implement a new loader option which would be specified to gcc as

-Wl,-z,fixedGOT=0x4000

--
John Reiser
2010-07-07 18:58:12 UTC
Permalink
Post by John Reiser
Implement a new loader option which would be specified to gcc as
-Wl,-z,fixedGOT=0x4000
At least some parts of a similar idea work already, just by assigning to
_GLOBAL_OFFSET_TABLE_ in a linker script:

ld --other_flags_here --verbose > my.lds

then edit my.lds to remove the header and trailer lines (marked with
"==========") and add the assignment (spaces matter):
----- my.lds
. . .
_GLOBAL_OFFSET_TABLE_ = 0x4000 ;

SECTIONS
{
. . .
-----

$ gcc -fPIC -o hello -Wl,--script=my.lds hello.c
$ nm hello | grep _GLOBAL_OFFSET_TABLE_
00004000 a _GLOBAL_OFFSET_TABLE_

--
Renaud
2010-07-08 06:03:32 UTC
Permalink
Just tried, but as I thought, declaring the symbol address as ABSOLUTE
doesn't changed the addressing style :

$ avr32-nm test.elf | grep _GLOBAL_
00004000 A _GLOBAL_OFFSET_TABLE_

Dissasembly:
...
80018098: 4b 16 lddpc r6,8001815c <-- R6 = 0x8001409A
8001809a: 1e 26 rsub r6,pc <--- GOT = R6 = PC - R6 = 0x4000
... do something with GOT...
8001815c: .word 0x8001409A

The GOT symbol IS at 0x4000, BUT due to PIC behaviour, it's still
considered to be relative to PC, so whatever offset we'll give to
CODE, the same will apply to the GOT symbol.
We need GOTs to be unrelative to CODE.. Should I have to patch GCC ? ;)
Post by John Reiser
Post by John Reiser
Implement a new loader option which would be specified to gcc as
    -Wl,-z,fixedGOT=0x4000
At least some parts of a similar idea work already, just by assigning to
       ld --other_flags_here --verbose  > my.lds
then edit my.lds to remove the header and trailer lines (marked with
----- my.lds
    . . .
_GLOBAL_OFFSET_TABLE_ = 0x4000 ;
SECTIONS
{
    . . .
-----
$ gcc -fPIC -o hello -Wl,--script=my.lds hello.c
$ nm hello | grep _GLOBAL_OFFSET_TABLE_
00004000 a _GLOBAL_OFFSET_TABLE_
--
John Reiser
2010-07-08 14:35:27 UTC
Permalink
Post by Renaud
Just tried, but as I thought, declaring the symbol address as ABSOLUTE
$ avr32-nm test.elf | grep _GLOBAL_
00004000 A _GLOBAL_OFFSET_TABLE_
...
80018098: 4b 16 lddpc r6,8001815c <-- R6 = 0x8001409A
8001809a: 1e 26 rsub r6,pc <--- GOT = R6 = PC - R6 = 0x4000
... do something with GOT...
8001815c: .word 0x8001409A
The GOT symbol IS at 0x4000, BUT due to PIC behaviour, it's still
considered to be relative to PC, so whatever offset we'll give to
CODE, the same will apply to the GOT symbol.
We need GOTs to be unrelative to CODE.. Should I have to patch GCC ? ;)
If the generated code is that stylized, then another option is a utility
program which takes a .o, finds those two-instruction sequences, then
re-writes the code in-place to become:
-----
Post by Renaud
80018098: 4b 16 lddpc r6,8001815c <-- R6 = 0x4000
8001809a: XX XX <<two-byte NOP>>
... do something with GOT...
8001815c: .word 0x4000
-----

--

Loading...