Forums

strangeness with objcopy and large binaries

Started by Peter Harrison May 17, 2009
I have built the CodeSourcery ARM compiler (2008q3). I have a linker 
script for the STM32 with the following sections:

MEMORY {
   FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
   RAM   (xrw): ORIGIN = 0x20000000, LENGTH = 20K
}
SECTIONS {
         .isr_vector : {
                 . = ALIGN(4);
                 KEEP(*(.isr_vector))
                 . = ALIGN(4);
         } >FLASH
         .text : {
                 . = ALIGN(4);
                 *(.text)
                 *(.text.*)
                 *(.rodata)
                 *(.rodata*)
                 . = ALIGN(4);
                 _etext = .;
         } >FLASH
         .data : AT ( _etext ) {
                 . = ALIGN(4);
                 _sdata = .;
                 *(.data)
                 *(.data.*)
                 . = ALIGN(4);
                 _edata = .;

         } >RAM
         .bss : {
                 . = ALIGN(4);
                 _sbss = .;
                 *(.bss)
                 *(COMMON)
                 . = ALIGN(4);
                 _ebss = .;
         } >RAM
}

When I build my application, I create the binary image with

arm-eabi-objcopy -O binary main.elf main.bin

That creates a binary that is 400M in size. Presumably because 
(0x20000000-0x08000000) is about that size.

The problem seems to occur when there is nothing in the .data section. 
Possibly because it is being thrown out by the linker. I found some 
stuff in the ld manual that suggests that, if I change the .data section 
to this:

.data : AT ( _etext ) {
   . = ALIGN(4);
   _sdata = .;
   KEEP(*(.data))
   KEEP(*(.data.*))
   . = ALIGN(4);
   _edata = .;
   } >RAM

all will be OK in the world. or, at least, my tiny part of it.

Does that sound right? Is this the 'proper' thing to do? there is also 
mention of the --gc-sections option for the linker. Would it be simpler 
not to use this?
On May 17, 1:51=A0pm, Peter Harrison <peter.harri...@helicron.net>
wrote:
> I have built the CodeSourcery ARM compiler (2008q3). I have a linker > script for the STM32 with the following sections: > > MEMORY { > =A0 =A0FLASH (rx) : ORIGIN =3D 0x08000000, LENGTH =3D 128K > =A0 =A0RAM =A0 (xrw): ORIGIN =3D 0x20000000, LENGTH =3D 20K} > > SECTIONS { > =A0 =A0 =A0 =A0 =A0.isr_vector : { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0KEEP(*(.isr_vector)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0} >FLASH > =A0 =A0 =A0 =A0 =A0.text : { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.text) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.text.*) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.rodata) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.rodata*) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_etext =3D .; > =A0 =A0 =A0 =A0 =A0} >FLASH > =A0 =A0 =A0 =A0 =A0.data : AT ( _etext ) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_sdata =3D .; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.data) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.data.*) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_edata =3D .; > > =A0 =A0 =A0 =A0 =A0} >RAM > =A0 =A0 =A0 =A0 =A0.bss : { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_sbss =3D .; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(.bss) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*(COMMON) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0. =3D ALIGN(4); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_ebss =3D .; > =A0 =A0 =A0 =A0 =A0} >RAM > > } > > When I build my application, I create the binary image with > > arm-eabi-objcopy -O binary main.elf main.bin > > That creates a binary that is 400M in size. Presumably because > (0x20000000-0x08000000) is about that size. > > The problem seems to occur when there is nothing in the .data section. > Possibly because it is being thrown out by the linker. I found some > stuff in the ld manual that suggests that, if I change the .data section > to this: > > .data : AT ( _etext ) { > =A0 =A0. =3D ALIGN(4); > =A0 =A0_sdata =3D .; > =A0 =A0KEEP(*(.data)) > =A0 =A0KEEP(*(.data.*)) > =A0 =A0. =3D ALIGN(4); > =A0 =A0_edata =3D .; > =A0 =A0} >RAM > > all will be OK in the world. or, at least, my tiny part of it. > > Does that sound right? Is this the 'proper' thing to do? there is also > mention of the --gc-sections option for the linker. Would it be simpler > not to use this?
Suggest you narrow it down a bit more with a few examples prior messing with the linker script, but... objcopy has at least one bug relating to internal accidental sign- extension converting to 64-bit addresses (which it uses internally), and CodeSourcery just fixed it (ask me how I know... ) When you've narrowed it down a bit perhaps best to submit a trouble ticket ! Hope that helps, Best Regards, Dave
Peter Harrison wrote:
> I have built the CodeSourcery ARM compiler (2008q3). I have a linker > script for the STM32 with the following sections: > > MEMORY { > FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K > RAM (xrw): ORIGIN = 0x20000000, LENGTH = 20K > } > SECTIONS { > .isr_vector : { > . = ALIGN(4); > KEEP(*(.isr_vector)) > . = ALIGN(4); > } >FLASH > .text : { > . = ALIGN(4); > *(.text) > *(.text.*) > *(.rodata) > *(.rodata*) > . = ALIGN(4); > _etext = .; > } >FLASH > .data : AT ( _etext ) { > . = ALIGN(4); > _sdata = .; > *(.data) > *(.data.*) > . = ALIGN(4); > _edata = .; > > } >RAM > .bss : { > . = ALIGN(4); > _sbss = .; > *(.bss) > *(COMMON) > . = ALIGN(4); > _ebss = .; > } >RAM > } > > When I build my application, I create the binary image with > > arm-eabi-objcopy -O binary main.elf main.bin > > That creates a binary that is 400M in size. Presumably because > (0x20000000-0x08000000) is about that size. > > The problem seems to occur when there is nothing in the .data section. > Possibly because it is being thrown out by the linker. I found some > stuff in the ld manual that suggests that, if I change the .data section > to this: > > .data : AT ( _etext ) { > . = ALIGN(4); > _sdata = .; > KEEP(*(.data)) > KEEP(*(.data.*)) > . = ALIGN(4); > _edata = .; > } >RAM > > all will be OK in the world. or, at least, my tiny part of it. > > Does that sound right? Is this the 'proper' thing to do? there is also > mention of the --gc-sections option for the linker. Would it be simpler > not to use this?
Have you had a look at your map file to see if there is anything in .data, or .bss? It might also be as simple as objcopy doing exactly what you asked it to do - copying all the sections to a .bin file. When using objcopy, I typically have flags such as "-j .text -j .data" to specify the sections I want copied - other sections, such as .bss, are then dropped during the copy.
David Brown wrote:
> Peter Harrison wrote:
>> >> When I build my application, I create the binary image with >> >> arm-eabi-objcopy -O binary main.elf main.bin >> >> That creates a binary that is 400M in size. Presumably because >> (0x20000000-0x08000000) is about that size. >> >> The problem seems to occur when there is nothing in the .data section. >> Possibly because it is being thrown out by the linker. I found some >> stuff in the ld manual that suggests that, if I change the .data >> section to this: >> >> .data : AT ( _etext ) { >> . = ALIGN(4); >> _sdata = .; >> KEEP(*(.data)) >> KEEP(*(.data.*)) >> . = ALIGN(4); >> _edata = .; >> } >RAM >> >> all will be OK in the world. or, at least, my tiny part of it. >> >> Does that sound right? Is this the 'proper' thing to do? there is also >> mention of the --gc-sections option for the linker. Would it be >> simpler not to use this? > > Have you had a look at your map file to see if there is anything in > .data, or .bss? It might also be as simple as objcopy doing exactly > what you asked it to do - copying all the sections to a .bin file. When > using objcopy, I typically have flags such as "-j .text -j .data" to > specify the sections I want copied - other sections, such as .bss, are > then dropped during the copy.
I have tried that and asking for specific sections seems to work but I worry that the startup values for initialised data would not be included as they seem not to have an LMA that follows on in the .text section. Without the KEEP() directive, the .data section is otherwise empty. That is when I get trouble. If there is stuff in the .data section, it all works as advertised. Presumably because the garbage collection is not throwing out the empty .data section.
Peter Harrison wrote:
> David Brown wrote: >> Peter Harrison wrote: > >>> >>> When I build my application, I create the binary image with >>> >>> arm-eabi-objcopy -O binary main.elf main.bin >>> >>> That creates a binary that is 400M in size. Presumably because >>> (0x20000000-0x08000000) is about that size. >>> >>> The problem seems to occur when there is nothing in the .data >>> section. Possibly because it is being thrown out by the linker. I >>> found some stuff in the ld manual that suggests that, if I change the >>> .data section to this: >>> >>> .data : AT ( _etext ) { >>> . = ALIGN(4); >>> _sdata = .; >>> KEEP(*(.data)) >>> KEEP(*(.data.*)) >>> . = ALIGN(4); >>> _edata = .; >>> } >RAM >>> >>> all will be OK in the world. or, at least, my tiny part of it. >>> >>> Does that sound right? Is this the 'proper' thing to do? there is >>> also mention of the --gc-sections option for the linker. Would it be >>> simpler not to use this? >> >> Have you had a look at your map file to see if there is anything in >> .data, or .bss? It might also be as simple as objcopy doing exactly >> what you asked it to do - copying all the sections to a .bin file. >> When using objcopy, I typically have flags such as "-j .text -j .data" >> to specify the sections I want copied - other sections, such as .bss, >> are then dropped during the copy. > > I have tried that and asking for specific sections seems to work but I > worry that the startup values for initialised data would not be included > as they seem not to have an LMA that follows on in the .text section. > > Without the KEEP() directive, the .data section is otherwise empty. That > is when I get trouble. If there is stuff in the .data section, it all > works as advertised. Presumably because the garbage collection is not > throwing out the empty .data section.
The C startup code has a loop that will read through the flash copy of the initial data and copy it to its address in RAM. If you have no .data section, perhaps the linker ends up using some sort of default addresses for some of the symbols used in the startup code.