gcc .data and .bss address space

What is the compiler option and/or directive to change the "Addr" field of elf file?

If i use: .bss .data .org 0x100000 it simply increase the "Off" and create a huge file. The chip's ram is at 0x20000000

Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 0009f4 00 AX 0 0 4 [ 2] .rel.text REL 00000000 001e54 000028 08 I 19 1 4 [ 3] .data PROGBITS 00000000 000a28 000000 00 WA 0 0 1 [ 4] .bss NOBITS 00000000 000a28 000000 00 WA 0 0 1 [ 5] .rodata PROGBITS 00000000 000a28 00004c 00 A 0 0 4 user@user:~/mcu$ ls -l stm.elf

-rw-rw-r-- 1 user user 9792 May 3 07:23 stm.elf user@user:~/mcu$ readelf -S stm.elf | head [ 4] .bss NOBITS 00000000 100a28 000000 00 WA 0 0 1 [ 5] .rodata PROGBITS 00000000 100a28 00004c 00 A 0 0 4 user@user:~/mcu$ ls -l stm.elf

-rw-rw-r-- 1 user user 1058368 May 3 07:23 stm.elf

Reply to
Ed Lee
Loading thread data ...

The tool for it is the loader script file. Please get the GNU ld manual from the binutils documents.

Which STM chip (and maybe demo card) are you using? What are the memory ranges you want?

--

-TV
Reply to
Tauno Voipio

But gcc-as does not know about the loader script, and send the global variables to the wrong place.

STM32F411: flash at 0 to 0x8000000, ram at 0x2000000 to 0x2002000.

If i use .org 0x2000000 for .data and .bss. Every ROM image is at least 33Mbytes.

I am just avoiding globals for now. But someone must have solved this problem somewhere.

Reply to
Ed Lee

Sorry, STM32F411: flash at 0 to 0x80000, ram at 0x20000000 to 0x20020000.

Reply to
Ed Lee

The way to feed the linker script is the compiler switch

-Wl,-T,myscript.ld

There is a good reason to add -Wl,-Map=myfile.map to the compiler switches to see what the linker has done.

Please get the compiler and linker manuals and read them.

To set up the runtime system, you need a routine at the very start to copy the initial values from the ROM to the RAM for the .data section.

Here is a model script, which is for raw metal startup:

--- clip clip ---

/* Linker script model for STM32F411 */ /* $Id: myscript.ld tauno $ */

/* Memory regions, STM32F411 */

MEMORY { flash (rx) : org = 0x08000000, len = 512k ram (wx) : org = 0x20000000, len = 128k }

/* ELF program headers */

/* There is a need to specify separately from the default, as the default setup extends the load size down to a 32 KiB boundary, clobbering the boot loader when programming with OpenOCD */

PHDRS { text PT_LOAD ; /* Code and constants */ data PT_LOAD ; /* Initialized read / write data */ bss PT_LOAD ; /* R/W data */ }

/* Linkage instructions */

SECTIONS { /* Exception vector in ROM, keep at offset 0 */

.romvec ORIGIN(flash) : { KEEP(*(.romvec)) /* binary file header */ KEEP(*(.ident)) /* program ID if present */ . = ALIGN(4); } > flash : text = 0xff

/* Code and constants */

.text : { /* code */

*(.text*)

/* other read-only data */

*(.rodata) *(.rodata.*) *(.glue_7*) *(.vfp11_veneer) *(.v4_bx) *(.iplt) *(.rel.dyn) . = ALIGN(4); } > flash : text = 0xff

/* Initialized data with ROM copy */

.data (NOLOAD) : { _rwstart = . ; *(.ramcode) *(.data*) . = ALIGN(4); _rwend = . ; } > ram AT > flash : data

/* Zero-init data */

.bss : { _zistart = . ; *(.bss*) *(COMMON) . = ALIGN(4); _ziend = . ; } > ram AT > ram : bss } /* Section boundaries */

_ldata = LOADADDR(.data) ;

_rostart = ADDR(.romvec) ; _roend = LOADADDR(.data) + SIZEOF(.data) ;

_rwstart = ADDR(.data) ; _rwend = ADDR(.data) + SIZEOF(.data) ;

_zistart = ADDR(.bss) ; _ziend = ADDR(.bss) + SIZEOF(.bss) ;

/* Initial stack pointer */ /* Needs to be at an 8 byte boundary for EABI specification */

_stktop = ALIGN(ORIGIN(ram) + LENGTH(ram) - 7, 8) ;

/* Startup location */

EXTERN(start) ENTRY(start)

--- clip clip ---

--

-TV
Reply to
Tauno Voipio

If you put this in gcc-cc command, it will pass it to gcc-ld, gcc-as will not accept this option. So, gcc-as put global variables at 0x0p and linker put them at 0x2000p (p=page of 0x0000 bytes).

Yes, and the assembler need to know to compile codes for address 0x2000p but put it near 0x0p. It's currently ignoring the linking instructions.

If i use ".text .org 0x100, .data .org 0x2000p and.bss .org 0x2001p", it create a 500 Mbytes file with holes (zeros). So, i need to punch it out for the rom image.

,bss is technically incorrect, because it is saying to zero out all memory between 0x0p and 0x2001p, but at least it doesn't do anything and doesn't take up any storage space.

punch stm.xlf Section Address Offset Size .text 00000000 00000034 00000a10 fe ff ff ea 04 b0 2d e5 .data 00000000 00000a44 20000004 78 56 34 12 fa 3f 00 20 .bss 00000000 20010a48 20010004 .rodata 00000000 20010a48 00000048 fa 3f 00 20 04 01 00 00

punch stm.elf stm.xlf Section Address Offset Size .text 00000100 00000034 00000910 fe ff ff ea 04 b0 2d e5 .data 20000000 e0000a44 00000004 78 56 34 12 .bss 20010000 00000a48 00000004 .rodata 00000000 00001a48 00000048 fa 3f 00 20 04 01 00 00

punch rewrite the elf sections when a third argument is provided.

Reply to
Ed Lee

Please show the exact command line you're using for the as, so we can correct it. If you're using GCC to assemble a .s or .S file, the normal switches apply.

There is a good reason to use the assembler only to create the .o file and make the linking in a separate step (using gcc again).

Please remove the .org directives from your assembler code. The linker script is the proper way to locate various program sections. If you want to have a piece of code or data located separately, create an own section for the blob and tell the linker where it's wanted to go. For an example, see the section .romvec in the linker script.

What is punch? A STM weirdness?

The GNU way to look at ELF files is objdump (arm-none-elf-objdump, maybe). objdump -h myfile.elf is the way to look in. Besides, you should have the information already in the link map, if you request it from the linker.

--

-TV
Reply to
Tauno Voipio

field of elf file?

nual

l variables to the wrong place.

ast 33Mbytes.

s problem somewhere.

ll not accept this option. So, gcc-as put global variables at 0x0p and link er put them at 0x2000p (p=page of 0x0000 bytes).

p but put it near 0x0p. It's currently ignoring the linking instructions.

t create a 500 Mbytes file with holes (zeros). So, i need to punch it out f or the rom image.

ory between 0x0p and 0x2001p, but at least it doesn't do anything and doesn 't take up any storage space.

user@user:~/mcu$ arm-none-eabi-gcc -g -Wall -nostdlib main.s -T stm.ld

user@user:~/mcu$ arm-none-eabi-as -g main.s -T stm.ld arm-none-eabi-as: unrecognized option '-T'

user@user:~/mcu$ arm-none-eabi-ld main.o -T stm.ld

But gcc-as generates the wrong addresses with memory access.

Punch is a custom program to reduce the holely file by mmu instructions fro m the project. This still require an intermediate 500M bytes file to gener ate the virtual address sections, then map to the physical address sections . Of course, the proper way to do it is to patch gcc with the mmu instruct ions.

mmu instructions:

.rodata 0 to 0x100 (boot and interrupt vectors) .text 0x100 to 0x2000p .data 0x2000p to 0x2001p .bss 0x2001p to 0x2002p

Punch generates the same information as objdump and readelf, but only the 4 sections necessary. Future version (TODO) is to remap the sections accord ing to the mmu instructions.

Reply to
Ed Lee

You did not look at the command: arm-none-eabi-gcc -g -nostdlib -Wl,-T,stm.ld -Wl,-Map=main.map \

-o linked.elf main.s

The output of as (.o) is a sybolic binary file, which is the located by ld.

I would do the job in two steps, to keep things simple:

arm-none-eabi-gcc -g -c -Wl,main.lst main.s arm-none-eabi-gcc -g -nostdlib -Wl,-T,stm.ld -Wl,-Map=main.map \

-o linked.elf main.o

To create a ROM image (e.g. Intel hex):

arm-none-eabi-objcopy -O ihex linked.elf linked.hex

You do not need a special program to reduce the linked file, just a proper linker script. You can use objdump with the -j switch to pick the desired sections from the absolute ELF file.

--

-TV
Reply to
Tauno Voipio

The memory control unit in STM32F411 is not a MMU, but a MPU, memory protection unit. You can easily get the section limits from the linker script. A symbol defined in a linker script is available to the code as an external address.

Your list corresponds roughly to what I have in the linker script, your .rodata is called .romvec in the script. .rodata is not a good name for the vector section, as it will contain compiler-generated constants. For the startup vector, you need to define two 32-bit constants into a separately named section (I used .romvec).

In assembly code, the section is named simply with the .section directive.

In C code the section is named with the __attribute__(()) declaration on the constant array.

--

-TV
Reply to
Tauno Voipio

Looks OK

Given correct main.o shoud be OK.

If you write correct asm your addresses will be correct.

Look at following:

------------------------------------

.syntax unified .cpu cortex-m4

.text .Lstack: .word 0x20020000 .Lstart: .word start

.text .org 512 .global start .thumb .thumb_func .type start, %function start: ldr r2, .L4 .L2: ldr r3, [r2] adds r3, r3, #1 str r3, [r2] b .L2 .align 2 .L4: .word c

.comm c,4,4

------------------------------------

Store to anull.s and do:

arm-none-eabi-as -c anull.s -o anull.o arm-none-eabi-ld anull.o -T f411.ld -o anull.elf

AFAICS it generates .elf file as you want. There is little weirdness with interrupt vectors: Tauno Voipio wanted vectors in separate section but I normally put them in .text, so using his linker script with my asm gives empty .romvec. Above I put just two vectors (should be enough to run) but in something serious there would be a subsection (written in C).

--
                              Waldek Hebisch
Reply to
antispam

r2 = 550 (aprox)

r3 = c

r3 = d

store d to memory location 550

Segmentation violation. Can't write to ROM.

Reply to
Ed Lee

In general (since forever) you can't go wrong with MORE sections. This makes the layout of the code visible to the link/load phase.

I put the *ROM* copy of vectors in one section and the *RAM* copy in another (as the code will switch to the RAM copy once the ROM image has been verified and RAM initialized, program loaded, etc.).

Likewise, the boot loader, BIST, etc.

This lets you juggle where things should "fit" in the final image instead of having to examine the code, itself, to determine the structure. The tools are already there; let them do the work.

[It also makes it easier to reuse "sections" from one project to the next]
Reply to
Don Y

Wrong, this is PC relative load that load value stored at .L4, that is 0x20000000 (address of c).

No, this is store to RAM (to c).

--
                              Waldek Hebisch
Reply to
antispam

PC is approx 520. The assembler does not know about 0x20000000.

Reply to
Ed Lee

You probably imagine something more complicated than STM32F411.

The example is a toy which IMO fulfils its purpose. As I wrote I have vectors as subsection, in linker script I can put it where I want it, simply to the moment it was most convenient to put it in .text. With my setup I can link .text so that it goes to RAM, which is convenient for debugging small programs or to ROM (usual setup). Script provided by Tauno Voipio creates overlapped sections in final executable, I do not know why. I can imagine use of overlapped sections in RAM, but what they buy in ROM?

Personaly, I am trying to avoid unnecessary complexity. Currently linker scripts give me enough possibilities to rearrange code, so I felt no need to additionally juggle sections in executable (that would be different if an OS was present, but I am talking here about programs running on bare hardware).

--
                              Waldek Hebisch
Reply to
antispam

I try to solve similar problems in very similar ways. So, I don't have to explain why I did "something different" in one case (but not another).

I've not examined the post so can't comment on specifics.

As to overlaying "ROM", I've done so (ages ago) in the era of bank-switched hardware -- switching ROM *out* of an address space after POST so those reserved locations (common in smaller MPUs) could be more effectively used (out of RAM).

Likewise, swapping banks of RAM into portions of the logical address space (to support independent stacks and heaps for many threads).

You can also overlay read and write accesses to portions of an address space (e.g., read an address yields one datum while writing drives another -- most common in mapped I/O)

Dunno.

But, in each case, doing it in the code makes the code more brittle; if the address map changes, then the *code* has to change. And, the change has to be ferreted out (instead of exposed in a simple script).

Every project I've built runs on bare iron. Even my current project has to install the POST/BIST/loader/etc. on bare iron *before* it can load (over the wire) the actual OS and, then, the application.

On reset, I have to ensure the initial PC, etc. is available (from "ROM"). A small/tight checksum routine to verify the next stage of boot is intact. Then, code to verify the hardware can be used *by* that next stage of the boot (i.e., do I have any functional RAM?)

Eventually, invoking specific test routines for *this* hardware (different set of I/Os than other devices running the same boot code) by probing a portion of the address space into which those ROM-based routines would exist. All that before beginning to set up the environment and network stack to download the OS image.

Plus, a "safe" copy of the boot loader so I can reflash without fear of making a brick.

Having a "rich" structure/methodology to call upon for juggling these various "boxes" makes it easier to add as new requirements come along. And, exposes these details at a higher level (so the Next Guy isn't scratching his head wondering why "this is here" and "that is there").

[I.e., it's easier to document a script than it is to embed lots of notes in a variety of different files and HOPING the Next Guy can find all of them!]
Reply to
Don Y

Have you tried provided commands? There is also objdump, run

arm-none-eabi-objdump -D anull.elf

to see what is in .elf file. And compare with

arm-none-eabi-objdump -D anull.o

And yes, assember produces relocatable code and does not know addresses. It is linker job to put addresses into ELF executable.

--
                              Waldek Hebisch
Reply to
antispam

Yes, i have been looking at object files, elf and bin files, with objdump, readelf, od and hexdump. The linker relocates the data to the ram address, but does not change the content, which is still pointing to the rom address.

I am just trying to convince myself how is that possible to work without the assembler knowing the actual physical address of ram.

Reply to
Ed Lee

"RAM" is just a set of one (or more) labels that you have located in a data segment.

How does the assembler know how to access a subroutine that you've defined IN ANOTHER MODULE?

The linkage editor knows how to resolve cross-module labels. So, you can reference a location in "ROM" or "RAM" without the actual instruction knowing the difference.

The loader maps addresses of sections to physical addresses.

So, you end up with a binary that has been *bound* to a specific set of constraints -- inter-module and inter-section.

Reply to
Don Y

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.