How to link a static library to its own section [duplicate] - c

My application calls some functions which are placed in an external static library. I link the external static library to my application and everything works (in this case I'm using GCC).
Nevertheless, the locations (addresses) of text, .data and .bss sections of the library are chosen by the linker. I can choose/change their locations by modifying the linker script, but it's tedious as I have to specify all the functions, variables, etc. of the library. What I mean it's something like:
. = 0x1000; /* new location */
KEEP(*(.text.library_function1));
KEEP(*(.text.library_function2));
[...]
An alternative solution is to build the external library by placing a section attribute for each function/variable, and then modifying the linker by re-locating the whole section. Something like:
/* C source file */
unsigned char __attribute__((section (".myLibrarySection"))) variable1[10];
unsigned char __attribute__((section (".myLibrarySection"))) variable2[10];
/* Linker script */
. = 0x1000;
KEEP(*(.myLibrarySection))
However, I'd like to be able to relocate entire .text, .data and .bss segments of an external static library without the need of using these tricks.
I'd like something like this (in linker script):
. = 0x1000;
KEEP(*(.text.library_file_name))
Is it possible using GCC toolchain?
Is it possible using other toolchains (IAR, Keil, etc.)?

You can use the archive:filename syntax in ld.
First place all the .o files from your external library into a static library .a file, if they aren't already. That is the normal way static library binaries are distributed.
Then in the linker script, specify:
.text.special : {
. = 0x1000;
*libspecial.a:*(.text .text.*)
}
.text {
*(.text .text.*)
}
The wildcard will pick all the files coming from libspecial.a and place them in the first section. The later wildcard will then pick anything left over. If there is a need to place the .text.special section after the normal section, you can use EXCLUDE_FILE directive in a similar way.

Can you just postprocess your lib to rename sections?
# Untested!
TMP=`mktemp -d`
trap "rm -rf $TMP" EXIT
cd $TMP
ar x path/to/your/lib.a
for o in *.o; do
for s in text data bss; do
objcopy --rename-section .$s=.mynew$s $o
done
done
ar rcs path/to/your/lib.a *.o

Related

Place segments of external static library to specific locations

My application calls some functions which are placed in an external static library. I link the external static library to my application and everything works (in this case I'm using GCC).
Nevertheless, the locations (addresses) of text, .data and .bss sections of the library are chosen by the linker. I can choose/change their locations by modifying the linker script, but it's tedious as I have to specify all the functions, variables, etc. of the library. What I mean it's something like:
. = 0x1000; /* new location */
KEEP(*(.text.library_function1));
KEEP(*(.text.library_function2));
[...]
An alternative solution is to build the external library by placing a section attribute for each function/variable, and then modifying the linker by re-locating the whole section. Something like:
/* C source file */
unsigned char __attribute__((section (".myLibrarySection"))) variable1[10];
unsigned char __attribute__((section (".myLibrarySection"))) variable2[10];
/* Linker script */
. = 0x1000;
KEEP(*(.myLibrarySection))
However, I'd like to be able to relocate entire .text, .data and .bss segments of an external static library without the need of using these tricks.
I'd like something like this (in linker script):
. = 0x1000;
KEEP(*(.text.library_file_name))
Is it possible using GCC toolchain?
Is it possible using other toolchains (IAR, Keil, etc.)?
You can use the archive:filename syntax in ld.
First place all the .o files from your external library into a static library .a file, if they aren't already. That is the normal way static library binaries are distributed.
Then in the linker script, specify:
.text.special : {
. = 0x1000;
*libspecial.a:*(.text .text.*)
}
.text {
*(.text .text.*)
}
The wildcard will pick all the files coming from libspecial.a and place them in the first section. The later wildcard will then pick anything left over. If there is a need to place the .text.special section after the normal section, you can use EXCLUDE_FILE directive in a similar way.
Can you just postprocess your lib to rename sections?
# Untested!
TMP=`mktemp -d`
trap "rm -rf $TMP" EXIT
cd $TMP
ar x path/to/your/lib.a
for o in *.o; do
for s in text data bss; do
objcopy --rename-section .$s=.mynew$s $o
done
done
ar rcs path/to/your/lib.a *.o

How to make duplicate sections in ELF file

I have a requirement where I need to create a duplicate/copy section of .data section.
I've tried creating a dummy section with same size of data section in linker script and copy the contents of data section to the dummy section in the init functions of my ELF image, but that doesn't suit my requirement, as I want the copy/duplicate section to be created along with final ELF image not during the execution of it.
Below is what I wanted in my linker script,
SECTIONS {
.data : { <data section contents> }
.dummydata : { <copy of .data section> }
}
Can anyone help to write the linker script to match above requirement?
I don't think this can be done with just ld and a linker script. Given this line from here:
If a file name matches more than one wildcard pattern, or if a file
name appears explicitly and is also matched by a wildcard pattern, the
linker will use the first match in the linker script.
It sounds like the linker script will only put the data (or anything) in one section.
However all hope is not lost. You can copy the section using objcopy and then add the section using objcopy again
objcopy -O binary --only-section=.data your-file temp.bin
objcopy --add-section .dummydata=temp.bin your-file
This will append the section to be the last section with a VMA/LMA of 0. You can then use objcopy to move the section to the desired location.
objcopy --change-section-address .dummydata=desired-address your-file
Of course if there is something already there that would be problematic. Luckily you can create a hole right after your first .data with something like:
data_start = .;
.data : { *(.data) }
data_end = .;
. += (data_end - data_start);
This should create a hole right after your first data, big enough to put another copy of data right after it. If this isn't exactly where you want it to be just add (data_end - data_start) where you want the hole.
Finally you can change the section flags, again with objcopy
objcopy --set-section-flags .dummydata=the-flags-you-want your-file
Not as clean as just duplicating something in the linker script but it should work.

How to prohibit the use of global variables on compile time

Is there a way to prohibit the use of global variables?
I want GCC to generate an error on compile time when a global variable is defined.
We have a code that should be run per thread and want to allow only use of stack (which is thread safe)
Is there way to enforce it ?
Some GCC flag or other way to verify it ?
One approach would be to generate a linker map file (e.g. pass option -Wl,-Map,program.map to gcc), and examine the .data and .bss output sections for any contributions from the object files that you want to run without globals.
For instance, if my source file hello.c has:
static int gTable[100];
the linker map file will have something like this in it:
.bss 0x0000000000600940 0x1b0
*(.dynbss)
.dynbss 0x0000000000000000 0x0 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o
*(.bss .bss.* .gnu.linkonce.b.*)
.bss 0x0000000000600940 0x0 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o
.bss 0x0000000000600940 0x0 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crti.o
.bss 0x0000000000600940 0x1 /usr/lib/gcc/x86_64-linux-gnu/4.7/crtbegin.o
*fill* 0x0000000000600941 0x1f 00
.bss 0x0000000000600960 0x190 hello.o
You can see that hello.o is contributing 0x190 (400) bytes to the .bss section. I've used the approach of parsing a link map file with a Python script to generate code size and RAM usage metrics for an embedded project with reasonable success in the past; the text output format from the linker is pretty stable.
No such functionality in gcc. Some workaround would be to incorporate in the build process a static analysis tool which can detect globals. Still the compilation would not fail, but at least you would be warned in some way. I can see that PC-Lint (www.gimpel.com) has a check for
non const non volatile global variables, locating these can assist multi-threaded applications in detecting non re-entrant situations
Probably other tools may include similar functionality.
I would use ctags to extract the symbols from the source code and then search the output with a (perl or python) script for global variables.
E.g. following line would tell you whether a C soucre file hello.c contains global variables:
ctags -f- hello.c | perl -ne"#a=split(/\t/, $_); if ($a[3] eq qq(v)){ print qq(Has global variables.); exit 0; }"

Place a function at very start of binary

I'm working on a toy operating system and bootloader. I'm trying to write the kernel in C, and then convert it to binary for direct jumping to from the bootloader (i.e., I'm not loading an ELF or anything like that).
I've got the linker file setup with the proper origin (I'm loading the kernel to address 0xC0000000) and confirm with objdump that it's using it correctly. However, it's not placing my entry point at the start (0xC0000000) like I wanted. I guess that's not what the ENTRY directive is for.
My problem is simply that I want to place a particular function, kernel_main at address 0xC0000000. Is there a way I can accomplish this using gcc for compiling and linking?
Here is what the relevant parts of my linker file look like:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
/* etc. */
}
The ENTRY linker command tells the linker which symbol the loader should jump to when it loads the program. If you're making your own operating system it's really not used since there is no loader.
Instead, as you know, the program simply starts at the first code address.
To make place a special segment of code first, you could place it in a special code segment, and put it first in the list:
.text BLOCK(4K) : ALIGN(4K)
{
*(.text.boot) *(.text)
}
The segments in the list is placed in the order they are given.
The ENTRY directive is only useful for output formats that support an entrypoint. Since you're using a binary output, this won't work. What you can do is write a small stub in a separate source file (i.e. entry.c or entry.asm or whatever). Then, in the ld script, before the *(.text) line, you can put entry.o(.text). This instructs ld to load the symbols from a specific object file (whereas * denotes all object files). So the new ld script would look like this:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
entry.o(.text)
*(.text)
}
/* etc. */
}
As long as entry.o contains just one function (that simply calls your kernel main), this should work.

Make or Shell Variables In Linker Script

Is it possible for a linker script to access makefile/shell variables and make a decision based on the said variable?
For example, suppose I want to change the start of the RAM area below without using a different linker script, would it be possible to use a make variable to do this?
MEMORY
{
ifeq ($(SOME_VAR),0)
RAM (wx) : ORIGIN = 0x100000, LENGTH = 128K
else
RAM (wx) : ORIGIN = 0x200000, LENGTH = 128K
endif
}
ld does not import any variables from the environment, so it cannot use them directly. The best way to do this is to create your own linker script with the environment variables you want to export, and have the original linker script include it as so:
makefile:
foo:
echo SOMEVAR=$(SOMEVAR) > environment_linker_script
ld ...
enviroment_linker_script:
SOMEVAR=xxx
master_linker_script:
include environment_linker_script
ifeq ($(SOME_VAR),0) ...
I doubt it although it would depend on the linker you're using. It might be possible for the linker to read some exported variables from make but as I said all this would be dependent on specific linker functionality. Another idea could be as long as the linker file isn't going to be too complicated one option would be to actually generate it using your makefile. There are many examples you could google for about having makefiles generate header files, you could follow the same path for generating a linker file.
If the solution of deciding within the makefile which one of several linker scripts is not sufficient, then generating the script within make might be a viable option.
This solution relies on GNU make's verbatim variables, which get exported to environment variables and are referenced with $$.
I am using this for defining a path variable to be used to include a linker script in another linker script like so:
define LDSCRIPT_DEF
/* Include the original libopencm3 linker script */
INCLUDE $(OPENCM3_DIR)/lib/stm32/f4/stm32f405x6.ld
/* Do custom stuff */
endef
export LDSCRIPT_DEF
$(LDSCRIPT):
#echo "$$LDSCRIPT_DEF" > $(LDSCRIPT)
Explanation: this is a part of the makefile and only works if the makefiles use $(LDSCRIPT) as a prerequisite in all relevant rules.

Resources