Section overlap in ld.

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When compiling a particular legacy project, after an update from an older version of winAVR, i am getting an error in the linking stage. For some reason the .map that is generated has two of my sections overlapping, starting on the same address! the compilation fails spectacularly. Any hints?

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show your linker invocation or any special linker script.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-gcc -mmcu=at90can128 -Wl,-Map=./main.map,--cref -Wl,-gc-sections --output main.elf libs/libmain.a wedcan.o libs/libmain.a libs/libutil.a libs/libcan.a libs/libeeprom.a c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: section INFO [000020be -> 000020dd] overlaps section .bss [000020be
-> 00002200]
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: main.elf: section .bss lma 0x20be overlaps previous sections

static info_s info[OBJECT_NUM] __attribute__ ((section ("INFO")));

This is the array that i want to put at the beginning of RAM. Thanks for any help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Presumably because there's no --section-start given to the linker the INFO section must be being positioned by a special entry in a linker script that you have edited to position it at 20be?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did not explicitly state a location for the INFO section, it is being placed by the linker. Is there some way of putting INFO at the beginning of RAM and having it be undisturbed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure you use --section-start as a command to the linker.

But silly question time (because the above may be the least of your worries!) - my copy of the can128 datasheet says it has 4K of SRAM. The above output is saying it's trying to place .bss (not even the stack) at 20BE to 2200. Well I make that 8382 to 8704. So you haven't even just burst 4K but you have burst 8K too!

This suggests you have a TON of stuff in .data

I'm guessing it maybe literal text strings in fact (or some other constant data tables) and if that's the case you want to coerce it to be located in code flash and not waste precious DRAM. See the guide to using PROGMEM (pgmspace.h) in the Tutorial Forum for more detail.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
section ("section-name")
Normally, the compiler places the objects it generates in sections like data and bss. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a particular section. For example, this small program uses several specific section names:

struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };
struct duart b __attribute__ ((section ("DUART_B"))) = { 0 };
char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
int init_data __attribute__ ((section ("INITDATA"))) = 0;

main()
{
/* Initialize stack pointer */
init_sp (stack + sizeof (stack));

/* Initialize initialized data */
memcpy (&init_data, &data, &edata - &data);

/* Turn on the serial ports */
init_duart (&a);
init_duart (&b);
}

Use the section attribute with an initialized definition of a global variable, as shown in the example. GCC issues a warning and otherwise ignores the section attribute in uninitialized variable declarations.

You may only use the section attribute with a fully initialized global definition because of the way linkers work. The linker requires each object be defined once, with the exception that uninitialized variables tentatively go in the common (or bss) section and can be multiply "defined". You can force a variable to be initialized with the -fno-common flag or the nocommon attribute.

Some file formats do not support arbitrary sections so the section attribute is not available on all platforms. If you need to map the entire contents of a module to a particular section, consider using the facilities of the linker instead.

I was digging through some GCC documentation when i came across this. I'm not actually using a linker script to define my sections, i'm trying to just set an attribute to put an array in it's own section, so that it is forced to the beginning of memory, and undisturbed. As you can see from my variable definition above, it is declared with static scope, not global. I think what is happening is the linker is trying to put it both in the stack (.bss) and in INFO.

Is there some other way i should force this table to the beginning of memory? Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry but on which AVR would:

char stack[10000]

work? I can only assume it's an AVR with an EXTMEM interface as I don't think any of them have 10,000 bytes of RAM internally?!?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It wouldn't, but looking at the .map file from the output it seems that flash memory resides from 0x00000000 to 0x00800000.

I tried using a linker script, see following

phys = 0x00800000;
SECTIONS
{
  INFO phys : AT(phys) {
  }
  .text : AT(phys + SIZEOF(INFO)) {
    *(.text)
    *(.rodata)
  }
  .data : AT(phys + SIZEOF(INFO) + SIZEOF(.text))
  {
    *(.data)
  }
  .bss : AT(phys + SIZEOF(INFO) + SIZEOF(.text) + SIZEOF(.data))
  {
    *(.bss)
  }
  end = .;
}

but it still returns errors

avr-gcc -mmcu=at90can128 -Wl,-Map=./main.map,--cref  -T linkscr.ld --output main.elf libs/libmain.a libs/libmain.a libs/libutil.a libs/libcan.a  libs/libeeprom.a 
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: section .data [00801db8 -> 00801dbd] overlaps section .vectors [00801
db8 -> 00801e4b]
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: section INFO [00801dbe -> 00801ddd] overlaps section .bss [00801db
e -> 00801f00]
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: main.elf: Not enough room for program headers, try linking with -N
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: final link failed: Bad value

Thanks for your help, i think we're almost there

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you are gettnig your code and your data's mixed up. You don't want .text up at 0x8xxxxx

GCC is written for Von Neumann architecture computers which may well have ROM, RAM and other memory spaces but they are all within a single composite memory space.

The AVRs are Harvard achitecture so have code, RAM, EEPOM memory spaces that are all separate and that are all addressed from location 0x0000 upwards. But 0x012A in code space is not the same as 0x012A in RAM space.

So to get round this the "trick" used is to recognise that the AVR code space will never get much beyond 512KB or 1M or something so an offset of 0x800000 is added to RAM addresses to make 0x80012A quite distinct from 0x00012A in code space. (and another offset is used to the base of EEPROM)

So your linker script does not look right if it's starting everything, including .text (the ROM code) off at 0x800000

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're right! brain fart there. I moved .text down to 0x00000000 but i'm still getting a few errors.
INFO still seems to be overlapping .bss

c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/bin/ld.exe: section INFO [00800016 -> 00800035] overlaps section .bss [0080001
6 -> 00800158]
c:/winavr/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtcan128.o: In function `__vectors':
../../../../crt1/gcrt1.S:52: undefined reference to `__data_end'
../../../../crt1/gcrt1.S:52: undefined reference to `__data_start'
../../../../crt1/gcrt1.S:53: undefined reference to `__data_start'
../../../../crt1/gcrt1.S:53: undefined reference to `__data_load_start'
../../../../crt1/gcrt1.S:54: undefined reference to `__data_load_start'
../../../../crt1/gcrt1.S:54: undefined reference to `__data_load_start'
../../../../crt1/gcrt1.S:57: undefined reference to `__data_end'

It seems the vector table is involved now. Any ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hey, i've looked at a few more examples of linker scripts on the web, and refined mine like so:

SECTIONS
{
  . = 0x00000000;
  .text : { *(.text) }
  . = 0x00800000;
  INFO : {
  }
  .data : 
  {
    *(.data)
  }
  .bss : 
  {
    *(.bss)
  }
}

This gives only the __vectors portion of the error above...I'm so close, it's just one minor detail i'm missing...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Got it. I needed to put flags at the beginnings and endings of my data and bss sections. Thanks for pointing me in the right direction!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You do realise that all this use of home brew linker scripts is completely pointless and you could achieve what you want using --section-start as I advised previously don't you?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but with --section-start, don't i have to know the exact address i need to start ALL of my sections at? I don't want to have to change my makefile every time i change what i'm putting in INFO.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, i have everything working as far as linker scripts go. One question: if i define a static variable local to a file, and put it in EEPROM, it does not auto-initialize or show up in the .map output of the linker. Any idea why?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you talking about using EEMEM? But they'll need to be global.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why? a file-scoped static variable is still persistent, why must it be global?

static int foo_eeprom EEMEM;
static int foo_sram;

if these declarations reside outside of any function, why is the first line not kosher?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wdouglass wrote:
Why? a file-scoped static variable is still persistent, why must it be global?

Because the manual (in fact the very text you quoted above!) says so:
Quote:
Use the section attribute with an initialized definition of a global variable, as shown in the example. GCC issues a warning and otherwise ignores the section attribute in uninitialized variable declarations.

I actually went looking for that in C:\WinAVR-20070525\doc\gcc\HTML\gcc-4.1.2\gcc\Variable-Attributes.html before I realised that you'd already posted exactly the same text.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

is there any way that you know of to create a static variable in EEPROM?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why is "static" important? What's the problem with "global"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Static scoping is important for proper memory manipulation within my project. It is a design requirement.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But if nothing outside the one file accesses it - what's the difference? Or are you worried about cross-module name pollution?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cross-module name pollution is an issue, yes. Also, it makes for cleaner, less buggy code.