This is the mail archive of the crossgcc@sources.redhat.com mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more information.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Duplicating a section in a link


Steve:


On Thu, May 23, 2002 at 11:27:06AM -0600, Steve Pye wrote:
> Hi Bill,
> 
> Thanks for the response.  Please allow me to follow up:
> 


Sorry for responding out of order, but it actually makes sense here...

> 4) I wrote a piece of test code to see how initialized data works,
> and it appears that there are no special provisions, i.e., for
> int sam = 200;
> I get
> .data
> _sam:
>   .word 200

Yes, but take the 200 off, and you'll see that you get a different
section.  I'm using the term ".initdata" generically; each
architecture version of the toolchain has its own names for each
section, because each architecture has its own ABI (not necessarily
defined by the GNU guys).  Apparently yours uses ".data", which
suggests that if you take the 200 off, you'll get ".bss".


[and now back to the orignal time-space arrangement...  b.g.]

> 1) My application currently has no initialized variables and no
> real-startup code.  I have an assembler module which sets up
> appropriate StrongARM registers then jumps to my 'C' entry point.

Ok.  You'll have to beef up your startup system a bit, to initialize
all your initialized global data.  Examples abound in crt0.S files
everywhere.  You have noticed that it isn't working, right?  :^)

> 2) By simply copying the data from flash to RAM, are you relying on
> the fact that subroutine calls on the ARM are always 'branch relative
> to the Program Counter' and therefore, as long as the code in the one
> .c module only makes calls to functions also in the .c module, these
> 'branches' should always work regardless of where the code is
> physically in memory?

Nope.  What I'm talking about is independent of how calls are
implemented by the compiler and linker.  The approach works uniformly
well in all cases.

> 3) If the answer to 2) is 'yes', then I think I can manually copy
> the appropriate piece of flash to a buffer area in RAM.

Of course, you can always do that.  The question is how much work do
you want to do on your own (including getting the thunk that jumps
into your copied-around code right), and how much do you want the
tools to do for you.  Understanding how the mechanism works will help
you answer that question.

When you define an initialized global object,

  int x = 10;

the linker creates a symbol called 'x' that is sizeof(int) bytes in
size, located in the .initdata memory section.  Your linker command
file then places the .initdata section in an address region that is
physically occupied by RAM in the target system.  'x' is in .initdata,
so 'x' ends up in RAM.

But now there's the question of what to do with the 10.

Every storage object managed by the linker has (among other things) a
"virtual address" (VMA), and a "load address" (LMA).  Normally, the
two are the same address, because if you tell the linker to put
function foo() at address 0x1234, you expect that if you look in the
output file at address 0x1234, there will be the first instruction of
foo().

But if the linker attempts to put a 10 at an address in RAM, it'll do
nobody any good once you power-cycle the device.  So instead, a linker
script uses the AT keyword to give .initdata a VMA in RAM, but an LMA
in ROM.  The address of 'x' then is in RAM, but if you look in the
linker's output file, you'll see a 10 loaded at some ROM address.

The startup code finds the .initdata image in ROM, and copies it to
its VMA address at startup.  Hence, the 10 automagically appears at
the address of 'x' when you get to main().

How does the startup code find the 10?  Most linker command files load
the .initdata section at the end of their .text section, which is
marked with a symbol conventionally called "_etext".  Likewise, linker
command file authors usually mark the beginning and end of the
.initdata section with symbols like "_data" and "_edata".

With all that out of the way, the "automagic" initialization is just this:

  extern char _etext, _data, _edata;
  memcpy (&_data, &_etext, &_edata - &_data);

... or the equivalent asm code.  No magic at all, actually.

> The Greenhills compiler allows you to do this.  And in the
> Greenhills case, the address in the map for the RAM code is actually
> in RAM, i.e. after the code has been copied from flash to RAM, the
> entry subroutine can be called directly.

Hopefully you see now that gcc provides the equivalent functionality.
In fact, This Is Just How Linkers Work.  The only difference may be
that Greenhills shrink-wraps the feature a little better, but probably
at the expense of some flexibility.  I'll take the GNU way, myself.

> I guess I also need to copy over the strings (.rdata) for this .c
> module - can I apply a section name to the strings in this module?

> You mention that GCC allows a section associated with each 'C'
> function.  Greenhills allows the .text and .rdata sections for an
> entire module to be renamed by simple #pragmas at the beginning of
> the module - does GCC have anything equivalent?

With gcc, you can apply a different, arbitrary section name to every
single storage object in a module if you like.  See the
__attribute__((section())) keyword, which works something like this
(from memory, which is a highly volatile data store in my case):

  int y __attribute__((section(".my_section_for_y")));
  void foo (void) __attribute__((".my_section_for_foo")));

> 4) I wrote a piece of test code to see how initialized data works,
> and it appears that there are no special provisions, i.e., for
> int sam = 200;
> I get
> .data
> _sam:
>   .word 200

Yes, but take the 200 off, and you'll see that you get a different
section.  I'm using the term ".initdata" generically; each
architecture version of the toolchain has its own names for each
section, because each architecture has its own ABI.  Apparently yours
uses ".data", which suggests that if you take the 200 off, you'll get
".bss".

> The only compile option that I'm using that I think might control
> this is -N.  I'll do some experimenting with this.

Doing this with command line options is the Wrong Way, except in the
simplest circumstances (of which yours may actually be one).


b.g.


> 
> -----Original Message-----
> From:	William A. Gatliff [SMTP:bgat@billgatliff.com]
> Sent:	Thursday, May 23, 2002 9:43 AM
> To:	Steve Pye
> Cc:	'crossgcc@sources.redhat.com'
> Subject:	Re: Duplicating a section in a link
> 
> Steve:
> 
> 
> If you don't mind if the code is always copied to RAM at startup,
> i.e. you have enough RAM to have the code there whether you're using
> it or not, then put the contents of single.c into your initialized
> data section along with all your other initdata.  Your startup code
> would then copy it to RAM just like it's doing now for your
> initialized globals, and the linker would resolve addresses to their
> RAM locations.
> 
> See gcc's __attribute__((section())) extension, and the linker's AT
> directive (which you won't need to worry about if initdata already
> works in your system).  I talk about these in my gcc article at
> http://billgatliff.com.
> 
> Put another way, the linker is already doing the duplication you want,
> but only for your initdata because traditionally that's all we ask it
> for.  So call your single.c functions initdata, and capitalize on that.
> 
> To get the section name gcc emits for initdata, create a file that
> just has this in it:
> 
> 
>   int x = 10;
> 
> ... and compile it to asm.  Don't test with an initial value of zero,
> however, because gcc will usually optimize that by placing x into the
> .bss section, which isn't what you want.
> 
> 
> HTH,
> 
> 
> b.g.
> 
> 
> 
> On Thu, May 23, 2002 at 09:21:16AM -0600, Steve Pye wrote:
> > 
> > Hello,
> > 
> > My application runs mainly out of flash memory, but a part of 
> > the code has to run out of RAM.  All 
> > the code that is to run from RAM is contained in a single .c
> > source file.  I'd like the linker to resolve all code addresses 
> > for this module to be in RAM, however I also need the linked
> > object for this module to be included in the ROM image so that
> > it can be programmed into flash and then later copied into
> > RAM at run-time.
> > 
> > I think this can be done by
> > 1) assigning a section name to the code/strings contained in the .c file
> > 2) telling the linker that this section should be linked in RAM
> > 3) telling the linker that a copy of this section should also be placed in ROM
> > 
> > Do you know how I can do 1,2,3? Or whom I should ask?
> > 
> > BTW the target is StrongARM1110.
> > 
> > Thanks very much.
> > 
> > Best regards,
> > Steve.
> > 
> > 
> > ------
> > Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
> > Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com
> > 
> 
> -- 
> Bill Gatliff
> bgat@billgatliff.com
> 
> 

-- 
Bill Gatliff
bgat@billgatliff.com

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]