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.
Related
First of all, Engilish is not my native language. Please excuse if there are any mistakes.
As stated above, I want to create an ELF executable from process memory image. Up until now, I successfully extracted an ELF Header, Program Headers and a list of Elf64_Dyn structures resides in Dynamic segment. I also restored GOT. However, I can't figure out how to reconstruct section headers.
The problem is when an ELF executable is loaded into memory, section headers are not loaded. If we use a list of Elf64_Dyn structures inside Dynamic segment, we can get .rela* sections' address, GOT's address, string table's address, and so on. However, it doesn't contain addresses for sections like .text and .data. To reconstruct section headers we need section's offset and address, but it seems that there is no way to get these information.
How can I reconstruct section headers properly?
Thanks for your consideration.
How can I reconstruct section headers properly?
You can't, but you don't have to -- sections (and section headers) are not used at runtime (at least not by the dynamic loader).
You can also run strip --strip-all a.out to remove them from a "normal" ELF binary, which will continue to run just fine.
I want to build a library which is relocatable (ie. nothing other than local variables. I also want to force the location of the library to be at a fixed location in memory. I think this has to be done in the makefile, but I am confused as to what I have to do to force the library to be loaded at a fixed location. This is using mb-gcc.
The reason I need this is I want to write a loader where I dont want to clobber over the code that is actually doing the copy of the other program. So I want the program that is doing the copying to be located somewhere else at a location that is not being used (ie. ddr).
If I have all the functions that do the compiled into a library, what special makefile arguments do I need to force this to be loaded at location 0x80000000 for example.
Any help would be greatly appreciated. Thanks in advance.
You write a linker script, and tell the compiler/linker to use it by using the -T script.ld option (to gcc and/or ld, depending on how you build your firmware files).
In your library C source files, you can use the __attribute__((section ("name"))) syntax to put your functions and variables into a specific section. The linker script can then decide where to put each section -- often at a fixed address for these kinds of devices. (You'll often see macro declarations like #define FIRMWARE __attribute__((section(".text.firmware"))) or similar, to make the code easier to read and understand.)
If you create a separate firmware file just for your library, then you don't need to add the attributes to your code, just write the linker script to put the .text (executable code), .rodata (read-only constants), and .bss (uninitialized variables) sections at suitable addresses.
A web search for microblaze "linker script" finds some useful examples, and even more guides. Some of them must be suitable for your tools.
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
In this case, is right that address of:
.data start at 0x08048054 up to 0x08048054+0x0000e
.bss start at 0x08048054+0x0000e up to 0x0804805+0x00016
or am I missing something? please clarify it for me.
EDIT
I used this command to get the information as in the image:
readelf -l filename
Ok, so where do I begin... Yes both .data and .bss are in that region in memory. The problem is that there is no way to figure out what order they are in.
We can assume that the default order is followed and make an educated guess but I don't like that.
Through the lengthy comment thread under the question you mentioned something interesting, that wasn't evident in your question.
the executable isn't dynamically linked as file command says: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped in this case, there's no a linker script, isn't? – The Mask
In this case the library contains the symbol table with all of the symbol offsets. This table includes section information. It will be processed by the linker when you compile your application. At that point it is your linker script that controls the order in which the .data and .bss sections are out put in.
If it is the default linker script, look it up. If it is custom, you should have access to it and can read it. If unsure elaborate here and we'll try and help :)
I myself have asked a question that is unrelated but offers example code of a linker script and some C code. In that linker script the .bss segment came after the .data segment.
You are looking at the program header information, whereas the section headers are probably what you need. There may be many sections contained within a program header and you cannot precisely infer the sizes and alignment requirements of the various sections.
To see the section headers, use:
readelf -S
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.