Reply by Christopher Collins●July 10, 20152015-07-10
On 2015-07-09, Stefan Reuther <stefan.news@arcor.de> wrote:
> Les Cargill wrote:
>> Christopher Collins wrote:
>>> The problem is that the compiler does not know that COMMONDATA is at an
>>> absolute address. When I compile the file which accesses my_data, gcc
>>> is in "PIC mode," so it generates code to look up my_data in the GOT.
>>> By time the linker looks at the linker script and notices that
>>> COMMONDATA is a separate section, it is already too late; the object
>>> files already contain GOT references for each global access.
>>>
>>> At least this is my interpretation of what is happening.
>>
>> COMMONMDATA should be "fixed up" by the linker, not the compiler
>> itself. "gcc -c ...." should generate unresolved references to
>> the variables in COMMONDATA ( as viewable by objdump) , and
>> you'll need linker-script-fu to get all that sorted out.
>
> This will not work, because the *compiler* generates different
> unresolved references for PIC than for non-PIC. PIC adds another
> indirection.
>
>
> Stefan
Thank you, Stefan. This has been my observation as well. I have
surrendered to the fact that gcc does not support the specific behavior
I was hoping for.
Also, thank you to everyone else who offered suggestions. I didn't give
all the solutions due appreciation, mostly because there are further
requirements that I neglected to mention, and which render them
inappropriate for my particular problem. That said, I did learn from
all of them, and they may come in handy in the future.
Chris
Reply by Les Cargill●July 10, 20152015-07-10
Stefan Reuther wrote:
> Les Cargill wrote:
>> Christopher Collins wrote:
>>> The problem is that the compiler does not know that COMMONDATA is at an
>>> absolute address. When I compile the file which accesses my_data, gcc
>>> is in "PIC mode," so it generates code to look up my_data in the GOT.
>>> By time the linker looks at the linker script and notices that
>>> COMMONDATA is a separate section, it is already too late; the object
>>> files already contain GOT references for each global access.
>>>
>>> At least this is my interpretation of what is happening.
>>
>> COMMONMDATA should be "fixed up" by the linker, not the compiler
>> itself. "gcc -c ...." should generate unresolved references to
>> the variables in COMMONDATA ( as viewable by objdump) , and
>> you'll need linker-script-fu to get all that sorted out.
>
> This will not work, because the *compiler* generates different
> unresolved references for PIC than for non-PIC. PIC adds another
> indirection.
>
>
> Stefan
>
So it would appear. *Sigh*.
--
Les Cargill
Reply by Simon Clubley●July 9, 20152015-07-09
On 2015-07-09, Stefan Reuther <stefan.news@arcor.de> wrote:
>
> One step in reducing binary size would be to put variables into a big
> struct. This tells the compiler that you don't need a separate offset
> for each variable, but just one, so it reduces the number of GOT address
> loads. This is a general trick that applies whenever PIC is used.
>
> If you manage to pack *all* variables of your program into a struct, you
> can finally replace the variable name in the struct reference ("vars.x")
> by a fixed address using a #define ("#define vars (*(struct varstruct*)
> 0x12340000)").
>
The OP still needs to robustly know what address to use here in the
#define so when they create an instance of the struct in their program
they should place the variable into it's own unique section.
That way, they can use a custom linker script which places the section
at the start of SRAM. However, don't forget to use KEEP() in the linker
script to stop the section from being discarded.
Simon.
--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Reply by Stefan Reuther●July 9, 20152015-07-09
Les Cargill wrote:
> Christopher Collins wrote:
>> The problem is that the compiler does not know that COMMONDATA is at an
>> absolute address. When I compile the file which accesses my_data, gcc
>> is in "PIC mode," so it generates code to look up my_data in the GOT.
>> By time the linker looks at the linker script and notices that
>> COMMONDATA is a separate section, it is already too late; the object
>> files already contain GOT references for each global access.
>>
>> At least this is my interpretation of what is happening.
>
> COMMONMDATA should be "fixed up" by the linker, not the compiler
> itself. "gcc -c ...." should generate unresolved references to
> the variables in COMMONDATA ( as viewable by objdump) , and
> you'll need linker-script-fu to get all that sorted out.
This will not work, because the *compiler* generates different
unresolved references for PIC than for non-PIC. PIC adds another
indirection.
Stefan
Reply by Stefan Reuther●July 9, 20152015-07-09
Christopher Collins wrote:
[PIC]
> This works, but now I am wondering if there is a way to reduce the size of
> the resulting binary. In particular, the above flags cause all global
> variables to be accessed via the global offset table (GOT). However, I
> don't need this extra indirection, because the data and bss sections
> will always be at fixed offsets in SRAM.
One step in reducing binary size would be to put variables into a big
struct. This tells the compiler that you don't need a separate offset
for each variable, but just one, so it reduces the number of GOT address
loads. This is a general trick that applies whenever PIC is used.
If you manage to pack *all* variables of your program into a struct, you
can finally replace the variable name in the struct reference ("vars.x")
by a fixed address using a #define ("#define vars (*(struct varstruct*)
0x12340000)").
Stefan
Reply by Dimiter_Popoff●July 9, 20152015-07-09
On 08.7.2015 г. 09:04, Christopher Collins wrote:
> ....
> If the answer is that gcc just doesn't support the behavior I'm looking
> for, that is OK. I am not demanding a solution from the group :).
I don't know the answer you are after but I am sort of surprised
such a widely used tool is unable to do something so simple.
Makes me feel good about my choice from 20+ years ago to go my
own path :-).
Dimiter
------------------------------------------------------
Dimiter Popoff, TGI http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/
Reply by Les Cargill●July 8, 20152015-07-08
Christopher Collins wrote:
> On 2015-07-08, Les Cargill <lcargill99@comcast.com> wrote:
<snip>
>
> Are you expecting the linker to change the indirect access in the second
> listing to something that looks like the first one, assuming I specify
> the correct sections in the linker script and other C files?
I would hope so.
> I have not
> had any luck in getting this to happen.
>
<rends garment>
> If the answer is that gcc just doesn't support the behavior I'm looking
> for, that is OK. I am not demanding a solution from the group :).
>
> Thanks again,
> Chris
>
--
Les Cargill
Reply by Joe Chisolm●July 8, 20152015-07-08
On Mon, 06 Jul 2015 17:44:11 -0700, Christopher Collins wrote:
> MCU: (ARM Cortex M4)
> Build environment: arm-none-eabi-gcc 4.8.4 20140725
>
> My goal is to build an image that can be run from any properly-aligned
> offset in internal flash (i.e., position-independent). I found the
> following set of gcc flags that achieves this goal:
>
> # Generate position independent code.
> -fPIC
>
> # Access bss via the GOT.
> -mno-pic-data-is-text-relative
>
> # GOT is not PC-relative; store GOT location in a register.
> -msingle-pic-base
>
> # Store GOT location in r9.
> -mpic-register=r9
>
> This works, but now I am wondering if there is a way to reduce the size
> of the resulting binary. In particular, the above flags cause all
> global variables to be accessed via the global offset table (GOT).
> However, I don't need this extra indirection, because the data and bss
> sections will always be at fixed offsets in SRAM. The only part of the
> image that needs to be position independent is the code itself.
> Ideally, I would like to gcc to treat all accesses to global variables
> as though it weren't generating position-independent code.
>
> Any ideas? All input is greatly appreciated.
>
> Chris
As Don has mentioned, try making sure ALL your data elements are in
named sections and then use a linker script to place those sections
at some abs address in sram. The linker can do some amazing fixups.
But maybe not this one. I dont have time to try different methods.
The bigger problem is your startup code is going to have to know which
flash section to jump to and set the interrupt vector table correctly.
You will have to have some smarts in a "boot loader" type code that will
know which section to pick. That will some how have to be written into
the flash each time you upload a new version.
I suspect what you want to be able to do is have multiple versions in
flash and be able to revert to a old version some how. A different
way to do this is have some boot loader code where you tell it the
slot the code will be stored in. NO-PIC the code and link for a
given slot. When you upload, your boot loader determines via carefully
crafted RO variables or function addresses, that the image does indeed
fit into slot X. The boot loader then modifies some flash block to
say which section is active. The boot loader is actually a boot loader
and a pre-loader that always runs on reset. It looks at some reserved
flash block (64 bytes is your minimum), says "this slot is active" and
fixes up the interrupt vector table, jumps to the slot start routine.
--
Chisolm
Republic of Texas
Reply by Christopher Collins●July 8, 20152015-07-08
On 2015-07-08, Les Cargill <lcargill99@comcast.com> wrote:
> COMMONMDATA should be "fixed up" by the linker, not the compiler
> itself. "gcc -c ...." should generate unresolved references to
> the variables in COMMONDATA ( as viewable by objdump) , and
> you'll need linker-script-fu to get all that sorted out.
>
> You want to arrange your source code where everything in COMMONDATA
> is "extern...". As I recall, the linker for GNU affords
> locating as well; you'd absolutely locate COMMONDATA and
> not-absolutely locate everything else.
Either I am not explaining myself very well, or I am not understanding
the suggestions. When I tell gcc to compile a C file as
position-independent code, each access to global data is translated into
a series of instructions that is quite different from what I get when I
don't specify any position-independent flags. I wouldn't expect the
linker to be able to convert the first series of instructions into the
second. Here is an example:
$ cat pic.c
extern int var; /* Specifying the section here makes no difference. */
void test(void)
{
var = 2;
}
### Not position-independent
$ /usr/local/bin/arm-none-eabi-gcc -O1 -c pic.c
$ /usr/local/bin/arm-none-eabi-objdump -dS pic.o
pic.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <test>:
0: e3a02002 mov r2, #2
4: e59f3004 ldr r3, [pc, #4] ; 10 <test+0x10>
8: e5832000 str r2, [r3]
c: e12fff1e bx lr
10: 00000000 .word 0x00000000
### position-independent
$ /usr/local/bin/arm-none-eabi-gcc -fPIC -O1 -c pic.c
$ /usr/local/bin/arm-none-eabi-objdump -dS pic.o
pic.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <test>:
0: e59f3014 ldr r3, [pc, #20] ; 1c <test+0x1c>
4: e08f3003 add r3, pc, r3
8: e59f2010 ldr r2, [pc, #16] ; 20 <test+0x20>
c: e7933002 ldr r3, [r3, r2]
10: e3a02002 mov r2, #2
14: e5832000 str r2, [r3]
18: e12fff1e bx lr
1c: 00000010 .word 0x00000010
20: 00000000 .word 0x00000000
Are you expecting the linker to change the indirect access in the second
listing to something that looks like the first one, assuming I specify
the correct sections in the linker script and other C files? I have not
had any luck in getting this to happen.
If the answer is that gcc just doesn't support the behavior I'm looking
for, that is OK. I am not demanding a solution from the group :).
Thanks again,
Chris