EmbDev.net

Forum: ARM programming with GCC/GNU tools Yagarto BUG: static vars are offset in memory by 4 bytes.


von (unknown) (Guest)


Rate this post
useful
not useful
I'm using:
yagarto-bu-2.23.1_gcc-4.7.2-c-c++_nl-1.20.0_gdb-7.5.1_eabi_20121222
and it is working well with a project containing dozens of source files.

Then I add the following source files:
FooClass.h
1
class FooClass {
2
public:
3
  FooClass(){};
4
  static FooFrame m_fooFrame;
5
};
FooClass.cpp
1
#include "FooClass.h"
2
FooFrame FooClass::m_fooFrame;

Here's the file for the static member:
FooFrame.h
1
class FooFrame {
2
public:
3
  FooFrame(){};
4
};
No need for FooFrame.cpp

Trivial right? Well, the result is that static vars are erroneously 
shifted in memory by 4 bytes.

Here's the map file. These vars reside at __data_start and are copied 
there from ROM by the startup code. Adding FooClass doesn't alter these 
vars at the beginning. That's all fine and dandy.
1
                0x40000200        0x1 src\UserIO.o
2
                0x40000200                UserIO::m_dummySystemStatus
3
 *fill*         0x40000201        0x3 
4
 .data._ZN3SAL15m_uart0BaudRateE
5
                0x40000204        0x4 src\SAL.o
6
                0x40000204                SAL::m_uart0BaudRate
7
 .data._ZN3SAL15m_uart1BaudRateE
8
                0x40000208        0x4 src\SAL.o
9
                0x40000208                SAL::m_uart1BaudRate

This is the happy memory of the ARM7 before adding FooClass:
1
40000200 01000000 80250000 80250000 01010100
This is correct. You can see m_dummySystemStatus, and the two baud rates 
(9600 baud becomes 0x80250000 :-). Great!

Now lets add FooClass to the project and look at memory:
1
40000200 FFFFFFFF 01000000 80250000 80250000

What the heck? You can see that the static members have been moved by 1 
word (4 bytes) and any code that uses them crashes in a pile.

I'm using James P. Lynch's linker script (modified for the LPC2148):
1
/*  Author:  James P. Lynch   */                                                                            /* identify the Entry Point  */
2
3
ENTRY(_startup)
4
/* specify the LPC2148 memory areas  */
5
6
MEMORY 
7
{
8
  flash           : ORIGIN = 0,          LENGTH = 512K  /* FLASH ROM                              */  
9
  ram_isp_low(A)    : ORIGIN = 0x40000120, LENGTH = 223    /* variables used by Philips ISP bootloader  */     
10
  ram           : ORIGIN = 0x40000200, LENGTH = 32224  /* free RAM area              */
11
  ram_isp_high(A)    : ORIGIN = 0x40007FE0, LENGTH = 32    /* variables used by Philips ISP bootloader  */
12
}
13
14
15
/* define a global symbol _stack_end  */
16
17
_stack_end = 0x40007EDC;
18
19
/* now define the output sections  */
20
21
SECTIONS 
22
{
23
  . = 0;                /* set location counter to address zero  */
24
  
25
  startup : {
26
    *(.startup)
27
    . = ALIGN(0x4);
28
    } >flash    /* the startup code goes into FLASH */
29
  
30
  
31
32
    .text : {
33
        CREATE_OBJECT_SYMBOLS
34
        *(.text .text.* .gnu.linkonce.t.*)
35
        *(.plt)
36
        *(.gnu.warning)
37
        *(.glue_7t) *(.glue_7)
38
39
        . = ALIGN (4);
40
        /* These are for static constructors and destructors under ELF */
41
        KEEP (*crtbegin.o(.ctors))
42
        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
43
        KEEP (*(SORT(.ctors.*)))
44
        KEEP (*crtend.o(.ctors))
45
        KEEP (*crtbegin.o(.dtors))
46
        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
47
        KEEP (*(SORT(.dtors.*)))
48
        KEEP (*crtend.o(.dtors))
49
50
        *(.rodata .rodata.* .gnu.linkonce.r.*)
51
52
        *(.ARM.extab* .gnu.linkonce.armextab.*)
53
        *(.gcc_except_table)
54
        *(.eh_frame_hdr)
55
        *(.eh_frame)
56
57
        *(.init)
58
        *(.fini)
59
60
        PROVIDE_HIDDEN (__preinit_array_start = .);
61
        KEEP (*(.preinit_array))
62
        PROVIDE_HIDDEN (__preinit_array_end = .);
63
        PROVIDE_HIDDEN (__init_array_start = .);
64
        KEEP (*(SORT(.init_array.*)))
65
        KEEP (*(.init_array))
66
        PROVIDE_HIDDEN (__init_array_end = .);
67
        PROVIDE_HIDDEN (__fini_array_start = .);
68
        KEEP (*(.fini_array))
69
        KEEP (*(SORT(.fini_array.*)))
70
        PROVIDE_HIDDEN (__fini_array_end = .);
71
    } >flash
72
73
    /* .ARM.exidx is sorted, so has to go in its own output section.  */
74
    .ARM.exidx : {
75
        __exidx_start = .;
76
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
77
        __exidx_end = .;
78
    } >flash
79
    _etext = .;
80
81
82
  
83
    .data : {
84
        __data_load = LOADADDR (.data);
85
        __data_start = .;
86
        KEEP(*(.jcr))
87
        *(.got.plt) *(.got)
88
        *(.shdata)
89
        *(.data .data.* .gnu.linkonce.d.*)
90
        . = ALIGN (4);
91
        _edata = .;
92
    } >ram AT >flash
93
94
    .bss : {
95
        __bss_start__ = . ;
96
        *(.shbss)
97
        *(.bss .bss.* .gnu.linkonce.b.*)
98
        *(COMMON)
99
        . = ALIGN (4);
100
        __bss_end__ = .;
101
    } >ram
102
103
}
104
  _end = .;              /* define a global symbol marking the end of application RAM */

So my question is, can you help me identify where I'm going wrong?
Thank you!
David

von (prx) A. K. (prx)


Rate this post
useful
not useful
Build a minimzed testcase which allows others to reproduce the problem.

von Jörg W. (dl8dtl) (Moderator)


Rate this post
useful
not useful
David Lee wrote:
> _stack_end = 0x40007EDC;

Make this either 0x40007ed8, or 0x40007ee0.  It's not immediately
obvious to me whether your problem might fall into this, but I've once
stumbled across that one myself (on a Cortex-M3 though).

von (unknown) (Guest)


Rate this post
useful
not useful
Thank you for the reply. I've tried both addresses and it did not fix 
the problem. Were you thinking that the address should be on a word 
boundary?

I am also working to reduce this problem to a small size test case so 
that I can post the entire project.

In the mean time I am using static pointers to classes and initializing 
them through constructors. It is distasteful, but so is most of my work 
recently.

Cheers,
David

von Dr. Sommer (Guest)


Rate this post
useful
not useful
David Lee wrote:
> __data_load = LOADADDR (.data);
>         __data_start = .;
Can you verify that those addresses are correctly set?

von Jörg W. (dl8dtl) (Moderator)


Rate this post
useful
not useful
David Lee wrote:
> Were you thinking that the address should be on a word boundary?

On a 64-bit boundary.  This is the maximum alignment requirement in ARM
cores (for “double” values).

von Uwe Bonnes (Guest)


Rate this post
useful
not useful
Can you try with a recent arm gcc from 
https://launchpad.net/gcc-arm-embedded?

von (unknown) (Guest)


Rate this post
useful
not useful
I will work on this today. Thanks!

von (unknown) (Guest)


Rate this post
useful
not useful
Hi Uwe,
Thank you for the suggestion (and implicit encouragement).
I upgraded from Yagarto's gcc-4.7.2 to launchpad's 4.8-2013-q4-major.

The offset problem is gone. My code runs fine now.

I have a question for all. Do new version of cross gcc for ARM introduce 
as many bugs as they fix? Is successful development a matter of just 
finding the version that compiles "your code" correctly?

Cheers to all,
David

von MarcVonWindscooting (Guest)


Rate this post
useful
not useful
(unknown) wrote:
> Do new version of cross gcc for ARM introduce
> as many bugs as they fix?

A "cross gcc" is not that much different from a "normal" gcc for your 
host system.

My experience is: gcc is much more reliable than the programs I write 
myself. MEANING: errors that show up are almost always MY errors.

Switching to another gcc does not necessarily mean your problem is gone. 
It might as well have gone because the conditions have changed a bit: 
new segments/removed segments/different code size/different arrangement 
of segments/alignment/...(a million other possibilities)...

Have you searched a bug tracker for something that sounds like your 
problem?
If your problem is a gcc problem and it shows up only rarely then the 
gcc developer would definitely appreciate you reporting that bug. 
Because one thing is true about bugs: they persist and show up at the 
most inappropriate moment in a project...

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.