[ECOS] (arm-elf) pointers to items in .data section incorrect after loading

George J. Pantazopoulos robotics@gammaburst.net
Thu Jan 22 06:58:00 GMT 2004

Hey group,
      I'm a newbie developing for an ARM7 target (the Atmel EB40A). I have 
character display hooked up to it using my own drivers.

I have Redboot [ROM] installed on the EB40A, which is used as a bootloader and
debug monitor. Redboot uses locations 0x0000 thru 0xa960 of my board's 256K RAM

      My problem is that the simple C program (Figure 1) runs incorrectly 
being loaded and run by Redboot (via the 'go' command). The baffling thing is
that it worked perfectly in the debugger, but when actually loaded by Redboot
and run, line 5 printed garbage while line 6 still printed the 'a' properly.

Figure 1 - chartest.c
= Begin Code snippet =
1> const char * str1 = "Electric Eye";
3> int main()
4> {
5>  LCDPutChar(  str1[0] );
6>  LCDPutChar(  'a' );
8>  return 0;
9> }
= End Code Snippet =

      I'm using gcc-3.2.1, binutils-2.13.1, newlib-1.11.0, and insight-5.3 and
I've compiled my test program with -nostdlib -nostartfiles and -nodefaultlibs.
(I have a simple crt0.S that inits the stack and fp and calls main() ).

      The linker script starts at address 0x0000. (Yes, I know that when
debugging I have to change this to something above 0xa960 so I won't trample
over the RAM used by Redboot. That's not the problem here).

      I did a lot of investigation and discovered why it doesn't run properly.
Unfortunately, I don't know how to deal with what I found.

      First, I examined the executable with objdump and found that .text 
at 0x0000, and .data starts at 0x0528 (the first and only item in .data is the
string "Electric Eye". Everything is ok here.

      Next, I loaded the program with Redboot. It reported the code was loaded
at address 0xac00. After poking around with the memory 'dump' command, I
confirmed that the sections themselves were correctly relocated, as expected.
For example, section .text was loaded in RAM at 0xac00 (0x0000 + 0xac00).
section .data was correctly loaded at 0xb128 (0x0528 + 0xac00). (Doing a dump
of location 0xb128 revealed the string "Electric Eye" in the dumped output).
Again, everything is ok so far.

      To my horror however, I found that at runtime the pointer 'str1' has the
incorrect (non-relocated) value of 0x0528! I ascertained this by having my LCD
print the value of 'str1' at runtime.

The correct value of this pointer should have been 0xb128 ( 0x0528 + 0xac00 ).

      Then I discovered why the pointer address couldn't have been 
relocated. I
examined the output of objdump some more:

0000:  (code...)
02cc:  ldr r3, [pc, #164]   ;gcc loads into r3 the contents of pc+164 (0x378)
02d0:  str r3, [r11, #-16]  ;r3 used as a pointer to store a value in the 
   ...  (much more code)
0374:  ldmb fp, {fp,sp,pc}  ;a return from some function
0378:  0x0528               ;The problem! This can not get adjusted at runtime!
037C:  (more code here)
   ...  (etc)
0x524: (end of .text)

0x528: "Electric Eye"       ;

      The string lives at the start of the .data section, at 0x0528.

      Basically, the string's *pointer* is itself stored in a pool location
(wedged in bewteen two functions). It is accessed as pc+164, which works 
out to
0x378 using the 0x0000 starting address. We'll just call it 0x0378 here for
simplicity's sake, but this value WILL change at runtime, as it should. Note
the two levels of indirection. 0x0378 is a pointer to a pointer.

      The value 0x0528 (stored at 0x0378) is the location of "Electric Eye" in
section .data. Unfortunately, at runtime .data is mapped to 0xb128 (0x0528 
+ 0xac00)
However, location pc+164 will STILL contain 0x0528 - the wrong value! It 
to be adjusted upward by 0xac00 to compensate for the runtime load address. I
don't see how this can be done in a straightforward way at all, and I'm at a
loss for how to prevent this problem.

     Surely this issue had to have been dealt with already in some way, 
otherwise, even the most rudimentary C programs could not run. I'm probably
doing something wrong. Would someone please point me in the right 
direction? :D

Thanks a million,
George Pantazopoulos

Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss

More information about the Ecos-discuss mailing list