In GCC, the MEMORY command describes the location and size of blocks of memory in the target.
The command must be used this way.
MEMORY
{
name [(attr)] : ORIGIN = origin, LENGTH = len
...
}
Now, I have a linker file used by the linker (a GCC based linker for Infineon Tricore microcontrollers, tricore-ld) defining a RAM memory section this way:
MEMORY
{
ram (w!xp): org = 0x70000000, len = 32k
...
}
Could you explain what 'p' means in (w!xp)? What does 'p' mean in general?
Not a standard linker script, not unusual for a custom micro-controller target of course. Perhaps forked a long time ago. It however can be easily reverse-engineered, GCC has always used the ELF format for object files. Google "elf section attributes", out pops this hit, pretty helpful here.
So you got alloc, exec, write, progbits. Aha, p == progbits. So (w!xp) surely should be interpreted as "section is writable, not executable, initial data is stored in the executable image".
Nothing very special, that's the traditional .data section in a C program. Compare to .bss, not p.
Info added by OP:
From this presentation on the UNIX ELF Format:
PROGBITS: This holds program contents including code, data, and debugger information.
NOBITS: Like PROGBITS. However, it occupies no space.
SYMTAB and DYNSYM: These hold symbol table.
STRTAB: This is a string table, like the one used in a.out.
REL and RELA: These hold relocation information.
DYNAMIC and HASH: This holds information related to dynamic linking.
Related
Recently I realized that the size of my executables is quite large. I am developing software for Cortex-M microcontrollers, using Eclipse and GCC.
To check this out, I used an example project I found on the internet, that simply blinks an LED by manipulating the registers directly and that is makefile based.
I created a very similar project using my libraries, startup code, linker scripts etc that uses Eclipse's managed makefiles.
The first project compiled successfully, and produced a binary file of app. 6kB. The second project produced a binary file of app.48kB! That is obviously quite a large difference for essentially the same result, and the later is definitely a huge file, for just blinking an LED. In both cases optimizations were off.
In my own libraries, there are some volatile buffers, that may be the excuse for the large BSS, or data sections, so I decided to begin by concentrating on the text section (which is still 5 times larger 5kB to 27kB).
I took a look at the map file to see what is really linked to the binary file. Same or similar functions had also similar size.
There is one thing that seems very-very odd to me. There are functions wich are defined only once in the whole project, but appear to have been linked multiple times, each time from a different object file, and each time occupying space in the text section. Take a look for example to function .text.port_lock.
Is this normal? How can I reduce the final file size, and how can I tell the toolchain to only link once each function?
The map file
Edit:
As stated in the comments the two programs are not different, it is the same thing, with minor modifications (e.g. startup code, and function to access the GPIO register). I am not testing GCC's ability to optimize code, thus I used -O0. I try to understand the map file, and why I see the some functions multiple times.
You are misreading the map file. None of the occurrences of .text.port_lock,
for example, represents a definition of the ChibiOS function void port_lock(void).
All the occurrences of .text.port_lock refer to input linker sections.
The first 4 occurrences, lying within the section of the map file titled
Discarded input sections, refer to input linker sections that the linker
discarded. For example:
.text.port_lock
0x00000000 0x1c /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmempools.o)
means that the linker found a section .text.port_lock of size 28 bytes
in input file /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmempools.o)
and threw it away.
The next 6 occurrences, lying within the the section of the map file titled
Linker script and memory map all refer to input linker sections that were
mapped into the output .text section. For example the first one:
.text.port_lock
0x000012a8 0x1c /tmp/ccaossic.ltrans0.ltrans.o
means that the linker found a section .text.port_lock of size 28 bytes
in input file /tmp/ccaossic.ltrans0.ltrans.o
and mapped it at address 0x000012a8 in the output .text section. Likewise the
second occurrence:
.text.port_lock
0x00001f70 0x1c /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
means that an input section of the same name and size also was found in input
file /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
and was mapped at address 0x00001f70 in the output .text section.
Altogether there are .text.port_lock input sections, all of them 28 bytes,
mapped in your output .text section from these input files:
/tmp/ccaossic.ltrans0.ltrans.o
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chthreads.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcore_v7m.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmemcore.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chschd.o)
In all 6 of these cases, the input section contains no symbols, and in particular
no functions. For contrast, here is an example of an input section that does contain symbols:
.text 0x000002f0 0x28 /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcoreasm_v7m.o)
0x000002f0 _port_switch
0x00000300 _port_thread_start
0x00000310 _port_switch_from_isr
0x00000314 _port_exit_from_isr
This is the input .text section from /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcoreasm_v7m.o).
The map file contains no indication that the port_lock function is linked multiple times. It contains no
indication that this function is linked at all. If it were linked multiple times then there
would have been a multiple-definition linkage error (except in the event that it had
been annotated as a weak symbol).
Why these six 28-byte input sections containing no symbols are all linked, or if they
need to be, is a matter about which I have no adequate evidence or ChibiOS expertise. I notice
that all but one of the object files from which these input sections come are
archive members of libChibios. In that light, it is worth remembering that if your linkage
requires an archive member for any reason then by default you will link the whole
archive member, even it contains more stuff than you need. On the other hand, the fact
that some port_lock input sections are discarded and some are kept suggests that there
is a need to keep the ones that are kept. If for my own cunning reasons I write a source file
essentially like:
static int __attribute__((section(".text.foo"))) __attribute__((used))
boo(int i)
{
return i * 2;
}
int bar(int i)
{
return boo(i);
}
then in my map file you will see an empty input section called .text.foo. This
doesn't tell you anything about the symbols I'm linking.
How can I tell the toolchain to only link once each function?
The linker will not link any symbol definition more than once, except in the special
case of weak symbols. Your map file contains no evidence of any function being linked more than once.
How can I reduce the final file size?
Compile with -Os for your release, of course. And to minimize linkage redundancy,
see this question.
Reading a linker map file is usually a clunky way of investigating the symbols and sections
in your binaries. Prefer objdump, readelf
and nm
I am using gcc to compile some code for an ARM Cortex-M4F microcontroller. My application uses a large collection of data that I have conveniently written into a C file: large arrays of ints and floats, circular linked lists pointing to those various arrays, various structs, that sort of thing.
When I compile this it adds up to about 500K of data, plus a few hundred K for the actual application. gcc is putting all this data conveniently into the .data section; ld then tries to build the elf putting the .data section into RAM and .text (code) section into FLASH. The mcu I am using doesn't have 500K of RAM so it cannot build the ELF, but it does have 1M of FLASH. I tried changing my linker script so that both .data and .text are put into FLASH which "worked" but there are some other bit of code that expect its data to go into RAM, so ultimately execution failed; I can't make that sweeping change.
What I need is to tell gcc to put every single object in this C file into the .text section so it can go into FLASH with the rest of the non-mutable stuff, or at least some other section which I can then instruct my linker script what to do with so that it doesn't interfere with existing blobs that have no problem fitting in RAM. I don't know how to do that. Here is a very slimmed down example of what I have
/* data.c */
static char* option_array_0_0[] =
{
"O=0.40",
"K=FOO",
"JAR=JAR",
};
static int width_array_0_0[] =
{
0,
1,
1,
};
Window window_array_0[] =
{
{
option_array,
width_array,
},
};
/* main.c */
extern Window window_array_0[];
int main()
{
/* Do stuff */
}
The stuff in data.c, window_array_0 and everything (or most everything, maybe the string arrays are going to .text?) it links to, is being put in .data which my linker script puts into RAM. I want it all in a different section which I can then put into FLASH. There are thousands of these types of arrays in there, plus hundreds of structs and dozens of other bits of information. Is this possible to change? As a test I replaced my "window_array_0" with a char[500000] of random data and that compiled without complaint so I assume it put it all into .text (as would be expected), I just don't know how to make it do so for arbitrary objects.
Thanks for your help.
As other commenters pointed, 'static const' items usually end up in .rodata section which is likely to be placed right next to .text in potentially read-only memory. The caveat is that it may or may not be true in your case as that is specific to particular target and may be changed by particular build process (i.e. linker options, specific section specified via __attribute__((section("name"))) in C code, linker script, binaries tweaked after build with various binutils, etc).
If you need to have precise control over in-memory layout and you know what you're doing, you can use LD script to do it. Among other things it will let you specify that .rodata from file data.o should be placed just before/after .text from all other .o files linked into the executable.
You can use arm-<your toolchain variant>-ld -verbose to dump default linker script and use it as a starting point for tweaking.
Most compilers/linkers, if you declare a variable as static const, it will place it in the text section instead of data. Obviously, these must be preinitialized and not modified at run-time, but that's the only way it makes sense to go in flash.
Somewhere in the code (.text section) put like a sample:
__attribute__((section(".text")))
const int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};
or without const if you want a variable to change:
__attribute__((section(".text")))
int test[0x0A] = {0,0,0,0,0,0,0,0,0,0};
Then try changing it:
test[0] = 0xffffffff;
This works on my Linux 32 intel machine.
IIRC, code in flash is usually required to be ROPI (read only position independent). So option_array_0_0 and width_array_0_0 would need const qualifiers (read only). However:
Window window_array_0[] =
{
{
option_array,
width_array,
},
};
needs to be changed somehow (I'm assuming option_array and width_array are indeed arrays). That makes window_array_0 not position independent.
All non-trivial embedded projects shall have a linker script. It defines where different symbols (function, global variables, debug symbols, ...) shall be placed in memory. Here is some tutorial about gcc linker script.
forcing all data to be placed in one section might not be the best solution!
NOTE: Since these arrays are NOT constants, it doesn't make sense to store them in data section! because this means you will end up over-writing code section by you code (which is PRETTY dangerous). Either make them const or create a no-init section which is not initialized by the loader, and you initialize it on reset.
These-days I'm referring File Handling System Calls in Linux.
Furthermore I understood ELF which is Executable and Linkable Format , contains set of sections.
Those are .bss , .data , .rodata , .text , .comment , and unknown
I referred Wikipedia and this Website to study
So I have below questions
why ELF file uses set of sections?
what is the task of each above section ?
what is the feasibility of this using set of sections ?
A good reference for the ELF file format is the Object Files chapter of the System V ABI. In particular, special sections describes the uses of most of the sections you're likely to encounter.
why ELF file uses set of sections?
An object file contains lots of different classes of data, and it makes sense to group similar data into sections, especially since some sections' contents can be read directly into a process's image when the OS execs the ELF file.
.bss contains uninitialized data, such as int a; declared at global level in a C program. Actually, it contains nothing except the size that needs to be allocated when the ELF file is loaded into a process, because all variables in bss are initialized to 0.
.data contains initialized data, such as int a = 1000; declared at global level in a C program.
.rodata contains read-only data, such as character string literals and global level variables declared as const in C. When the OS execs the ELF file, it will load this section into an area of memory that is read-only.
.text contains executable instructions. When the OS execs the ELF file, it will load this section into an area of memory that is read-only. Sometimes .text and .rodata wind up being loaded into the same area of a process's memory.
.comment typically contains the name and version of the compiler(s) used to generate the file.
Not all of the sections described in the documentation may be present in all ELF files; in particular, running the strip command on the ELF file will remove the .symtab and .debug sections.
I'm trying to debug a linker problem that I have, when writing a kernel.
The issue is that I have a variable SCAN_CODE_MAPPING that I'm not able to use -- it appears to be empty or something. I can fix this by changing the way I link my program, but I don't know why.
When I look inside the generated binary file using objdump, the data for the variable is definitely there, so there's just something broken with the reference to it.
Here's a gist with both of the linker scripts and the part of the symbol table that's different between the two files.
What confuses me is that both of the symbol tables have all the same symbols, they're all the same length, and they appear to contain the right data. The only difference that I can see is that they're not in the same order.
So far I've tried
inspecting the SCAN_CODE_MAPPING memory location to make sure it has the data I expect and hasn't been zeroed out
checking that all the symbols are the same
checking that all the symbol contents are the same length
looking at .data.rel.ro.local to make sure it has the address of the data
One possible clue is this warning:
warning: uninitialized space declared in non-BSS section `.text': zeroing
which I get in both the broken and the correct case.
What should I try next?
The problem here turned out to be that I was writing an OS, and only 12k of it was being loaded instead of the whole thing. So the linker script was actually working fine.
The main tools I used to understand binaries were:
nm
objdump
readelf
You can get a ton more information using "readelf".
In particular, take a look at the program headers:
readelf -l program
Your BSS section is quite different than the standard one, which probably causing the warning. Here's what the default looks like on my system:
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
If an input section doesn't match anything in your linker script, the linker still has to place it somewhere. Make sure you're covering all the input sections.
Note that there is a difference between sections and segments. Sections are used by the linker, but the only thing the program loader looks at are the segments. The text segment includes the text section, but it also includes other sections. Sections that go into the same segment must be adjacent. So order does matter.
The rodata section usually goes after the text section. These are both read-only during execution and will show up once in your program headers as a LOAD entry with read & execute permissions. That LOAD entry is the text segment.
The bss section usually goes after the data section. These are both writable during execution and will show up once in your program headers as a LOAD entry with read & write permissions. That LOAD entry is the data segment.
If you change the order, it affects how the linker generates the program headers. The program headers, rather than the section headers, are used when loading your program prior to executing it. Make sure to check the program headers when using a custom linker script.
If you can give more specifics about what your actual symptoms are, then it'll be easier to help.
I am programming an ARM Cortex-R4 and I have a few binary files that I'd like to execute them from TCRAM, just to see if the increase in performance is good enough.
I know I'd have to write a function to copy the binaries to the RAM (which can be accomplished with the linker script, and knowing the size of the binaries). But how would they run?
Imagine this: The first binary has func1(), func2(), func3() and func4(). I'd copy the entire module to TCRAM and how would I call a function there? I'd have to use a function pointer to that specific function? And what if func4(), calls func2() and func3()? If I'm not mistaken they'd point to the piece of code located in the flash. Does that mean I'd have to re write those funcs? Use entirely function pointers? I've been told that just the linker script is enough to do all of this and I needn't worry about anything, but I still don't understand how it works.
On GCC: Just put the function in the .data section:
__attribute__( ( section(".data") ) )
It will be copied over with the rest of your initialzed variables by the startup code (no need to mess with the linker scipt). You may also need a "long_call" option as well if the function ends up "far away" from the rest of the code after being placed into RAM.
__attribute__( ( long_call, section(".data") ) )
Example:
__attribute__( ( long_call, section(".data") ) ) void ram_foobar (void) { ... }
You may get an compiler warning that can be safely ignored:
Warning: ignoring changed section attributes for .data
You have two options.
Copy them as you suggest, compile with pc relative.
Use a linker file with a different load/run address.
A simple copy will only work if the routines do not use any absolute addresses. It maybe fine if they do use the absolute address as I guess you are going to leave a copy in standard RAM. However, this may not get the full benefit of the TCM.
With a linker script, you can specify a different LOAD and RUN locations.
sections {
.text { *(.text); } >FLASH
.tcm {
*(.tcm);
} >TCM_MEM AT>FLASH
.data { *(.data); } > RAM
.bss : NOLOAD { *(.bss); } > RAM
}
Note especially AT>FLASH.
See also: gnu linker map file... and many more on stackoverflow. The Gnu Ld manual has information on LMA sections (LOAD address). Your LMA would be flash, but the VMA (RUN address) would be TCM. The manual link above also shows how to copy. The RAM, FLASH, and TCM_MEM are defined with ld MEMORY information, depending on the addresses are for your board. All of this will be documented in a MAP file. Be sure to generate a MAP file and examine the addresses to double check your ld script.
The 2nd case also requires a copy (at start-up or at least before the first TCM function use). However, the compiler can use absolute addresses and they will be in the TCM memory. Also any function within the main DRAM can call the TCM function directly. With the first case, you must use function pointers to call the TCM code. If you wish global variables to be placed in this memory, you can use attributes to put them in different sections and use gnu ld to place them appropriately. I think there is ITCM and DTCM? So maybe this doesn't apply for you, or you need two sections.
The linker script is more generic and will work best if you put complicated functionality in the TCM. Just using -fpic, etc and copying may get things working quickly, especially if you only have a single pure function.
Nowadays (then-a-days as well?) you can just use the macro __RAM_FUNC, __RAMFUNC_EXT(bank, name) or __RAMFUNC(bank)