I am working on startup code of micro controller 32 bit and codewarrior compiler , As we have to deal with linker script. Certain variables that used in startup code for initilization of RAM and stack come from linker script.
Linker Script initialize these variables with different address. Problem is one variable have wrong address. In linker script it initialized by following command _f_data_rom.
Could any one tell me how linker initiazed variables that provides
address for stack , RAM initialization?
What this command means _f_data_rom ?
it looks like
RC_SDATA_SRC = _f_sdata_rom;
RC_SDATA_DEST = _f_sdata;
RC_SDATA_SIZE = (SIZEOF(.sdata)+3) / 4;
RC_DATA_SRC = _f_data_rom;
RC_DATA_DEST = _f_data;
RC_DATA_SIZE = (SIZEOF(.data)+3) / 4;
Looking at this document at page 69 you have to look at __ppc_eabi_linker.h how those variable are exported, e.g: this link to file
Into the same document, at page 65 you can find the form that configure addresses for linker. Take a look at that and check those settings.
Related
Lets consider this example:
glob.c source code is linked to shared library named glob.so. From main.c that link against glob.so I want to read the value of 'global_offset' variable at runtime(I don't think it's possible to do at compile time). My compiler is gcc 4.8.5 MinGW.
glob.c:
int glob_shared_var = 69;
main.c:
size_t global_offset = // read shared library load offset
size_t relative_glob_shared_var_offset = // read offset value from e.g. nm glob.a symbols table
printf("glob_shared_var value: %d \n", *(int *)(global_offset + relative_glob_shared_var_offset));
console output:
glob_shared_var value: 69
Ok so I read little bit more about GNU LD linker scripts and I learned about __data_start__ and __data_end__ symbols which are added to the beginning and ending of each consolidated binary by default. What I guess could work is create custom linker script rule that creates __data_start_glob__ and __data_end_glob__ symbols accordingly next to them to uniquely identify each shared library while producing them.
After library creation I would produce text file dump from it and grep offset addresses of each symbol in the library and put it to simple flat text file which will be then read at runtime.
reading address of shared library data section at runtime would look like this:
usize_t = glob_offset = &__data_start_glob__;
usize_t = glob_shared_var_offset; // read from flat file
int val = *(int *)(glob_offset + glob_shared_var_offset);
I know that use-case for this will be very limited, but maybe someone will have similar crazy idea in the future.
In a C application, I want to place a big buffer at an address after the variables, stack and dma address ranges. Of course I can define a section in the wanted location in the linker script and declare a big array in C and give a section attribute to the array. But I want to do it without actually declaring the big array because it makes the executable too big. I want to use the array address to do the same.
I'm using gcc and try to use an address I define in the linker script inside the C source file.
Here is how I tried it.
in the linker script file (which is ldabtsm.lds.S in my case),
...
. = ALIGN(16777216);
.vimbuffs : {
*(.vimbuffs)
}
vimbuffs = .;
...
I tried using vimbuffs in the C source file.
So I did (if I can print, I can use it anyway..)
extern unsigned int vimbuffs; // from linker script
printf("vimbuffs = %x\n", vimbuffs);
From the map file, I can see the vimbufs is assigned to 0x3b3f6000 which is just right, I want it to be aligned. But when run the program and print the value, I see
vimbuffs = a07f233d
What is wrong?
I am in a situation in an embedded system (an xtensa processor) where I need to manually override a symbol, but the symbol happens to be in the middle of another symbol. When I try using -Wl,--wrap=symbol it won't work, since the symbol isn't its own thing.
What I need to do is specify (preferably in a GCC .S, though .c is okay) where the code will end up. Though the actual symbol will be located somewhere random by the compiler, I will be memcpying the code into the correct place.
40101388 <replacement_user_vect>:
40101388: 13d100 wsr.excsave1 a0
4010138b: 002020 esync
4010138e: 011fc5 call0 4010258c <_UserExceptionVector_1>
My problem is GCC creates the assembly with relative jumps assuming the code will be located where it is in flash, while the eventual location will be fixed in an interrupt vector. How do I tell GCC / GNU as "put the code wherever you feel like, but, trust me it will actually execute from {here}"
Though my code is at 0x40101388 (GCC decided) it will eventually reside and execute from 0x40100050. How do I trick GCC by telling it "put the code HERE" but pretend it's located "HERE"
EDIT: I was able to get around this, as it turns out, the function I needed to modify was held in the linker script, individually. I was able to just switch it out in the linker script. Though I still would love to know the answer, I now have a work-around.
In the linker script each output section has two associated addresses: VMA and LMA -- the address for which the code is linked and the address where the code will be loaded.
Put the code that needs to be relocated into separate section, add an output section to your linker script with desired VMA and LMA and put an input section matching the name of the code section inside it.
E.g. the following C code
void f(void) __attribute__((section(".relocatable1.text")))
{
...
}
extern char _relocatable1_lma[];
extern char _relocatable1_vma_start[];
extern char _relocatable1_vma_end[];
void relocatable1_copy(void)
{
memcpy(_relocatable1_vma_start, _relocatable1_lma,
_relocatable1_vma_end - _relocatable1_vma_start);
}
Together with the following piece of ld script, with VMA substituted with the desired target code location
SECTIONS {
...
.some_section : { ... }
.relocatable1 VMA : AT(LOADADDR(.some_section) + SIZEOF(.some_section)) {
_relocatable1_vma_start = . ;
*(.relocatable1.literal .relocatable1.text) ;
_relocatable1_vma_end = . ;
}
_relocatable1_lma = LOADADDR(.relocatable1) ;
...
}
should do what you want.
How to write function at particular memory location in flash memory? Is there any directive for that? Do i need particular linker?
If you are using keil ide you can place a function at a specific address using .ARM.__at_address as the section name. To place the function add at 0x20000, specify:
int add(int n1,int n2) __attribute__((section(".ARM.__at_0x20000")));
int add(int n1,int n2)
{
return n1+n2;
}
Do you use the keil toolchain?
If yes, perhaps http://www.keil.com/support/docs/359.htm helps.
Edit:
The .obj file is generated by the compiler. I am not sure what you mean with 'how can i configure .obj file'.
The linker mentioned above takes the obj files, links them together and places code and variables.
You should start with a project which compiles and links without errors.
Then you have:
- Some c files. One of them with your function.
- A linkfile with the settings for the linker.
- A makefile or some kind of batchfile which calls compiler and linker with the necessary arguments.
If you have that, you can look into the m51 file for the name of the symbol for your function.
The m51 file is a textfile generated by the lx51 linker with interesting information about which symbols are there and what the linker has done with them.
The keil documentation for the linker I mentioned says: The compiler creates a symbol name for the function using the following format: ?PR?function_name?file_name.
This means: You will find the names of all functions of your project in the m51 file. If your function is in file file_x and named func_x. The symbol name will be PR?func_x?file_x
In http://www.keil.com/support/man/docs/lx51/lx51_segments.htm you can find some information about the usage of the SEGMENTS directive of the lx51 linker. According to that:
SEGMENTS (PR?func_x?file_x(C:0x1234))
should place your function to address 0x1234 in code memory.
Actually I have no keil toolchain. Therefore I cannot test all that myself.
But I am sure that you can manage that yourself if you start with a simple working example, change things step by step and check what happens.
Good Luck.
Helmut
Use ORG directive.
For example, for a function to start at location 2000H
ORG 2000H
MY_FUNC:
: YOUR CODE HERE
RET
I want to create a section in RAM, allocate a specific size and place it an an address? Is it possible to do all these operations without passing a linker script "file" or w/o modifying the existing linker script ?
.myspace :
{
. = 0x10000;
. = . + STACK_SIZE;
} > ram
Is it possible to do all the operation done by linker script in command line with GNU LD/GCC ?
Seems like a way outdated answer, but anyway.
It's not possible to reserve the section size via ld command line options, but if the next section starts at the end of your special section, you can try something like this:
ld --section-start=.myspace=0x10000 -Ttext=0x11000 ...