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.
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.
.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.
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.
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).
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).
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)
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!]
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.