how to use address defined in linkerscript in C source file? - c

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?

Related

How to read the absolute load address of the beginning of shared library data section on runtime?

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.

How do I specify manual relocation for GCC code?

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.

_f_data_rom linker script symbols

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.

Strange definition in C with # sign

I have come across following definition in an embedded C source file:
const preamble_t OAD_Preamble # ".preamble" =
{
HAL_OAD_RC_MAX, // Default program length of max if not using post-processing tool.
OAD_MANUFACTURER_ID, // Manufacturer ID
OAD_TYPE_ID, // Image Type
0x00000001 // Image Version
};
I have no idea about the # part, can you please help me with this?
Edit:
This is in IAR compiler, used with TI SoCs.
This is the way you can specify a memory address or a section in which you would like to place your variable.
".preamble" is the name of a section,
OAD_Preamble is the variable to be placed there.
You can also specify physical address after the at # sign:
const unsigned char port_bit # 0x1800 = BIT0;
More information is in this document.
Note: this is a non-portable compiler extension, not a part of the standard C syntax.

Is it possible to pass command line arguments to GNU LD to create a section, define size and place it in a specific memory?

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 ...

Resources