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

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.

Related

Link symbols with absolute address to PIC binary

I'm creating a new image that is constructed from multiple binary images (combined together through python script). The problem is that the last binary image must be compiled with fPIC, but the previous images are not. The last image (the one compiled with fPIC) reuse the functions from the other binary images with --just-symbols.
The problem is that when I'm trying to call the function from the other binary (symbol received by --just symbols), the address of the symbol is relative and not absolute which this causes a hard fault.
How do I link symbols with absolute address to PIC binary?
Code example:
File fun.c compiled into fun.elf stripped to fun.bin:
int fun(int a,int b)
{
print("help\r\n");
}
File fail.c compiled with -fPIC to and --just-symbols=fun.elf:
int fail(void)
{
fun(1,3);
}
In the sample, the address of fun in fail.bin is relative instead of absolute.
So, after some more research I found out this cannot be done.
you cannot force a pc of an application that was compiled with the fPIC flag to not use PIC for special symbols (in my case symbols from --just-symbols).
the solution I choose is actually parsing the not PIC elf file and get the addresses for the needed functions. use those addresses and cast them to the needed function.

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

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?

Replacing the symbol name in the symbol table to a new longer name in relocatable ELF object file

This is for a relocatable ELF object file, not fully-linked ELF or ELF shared library.
Currently if there is a program such as main.c:
int main() {
foo();
return 0;
}
and compile with gcc -c main.c it will generate a main.o.
I want to replace the call to foo with fool or food (a longer name) after the object file is already created.
Because currently the relocatable ELF will be broken if we extend past the length 3 of foo.
How can I do this?
I want to replace the call to foo with fool or food (a longer name) after the object file is already created.
This is quite possible, but far from trivial.
First, you need to copy the .symtab section to the end of the file, and append the desired string food\0 to it.
Second, you need to update the section table and replace the offset and length of the original .symtab with the offset and size if the section added in previous step.
Last, you need to find the symbol (in the .symtab section) and update its st_name with the offset of the food string added in the first step.
And that's all there is to it.

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.

ld: access beyond end of merged section

i'm trying to link a simple c program on an arm debian machine (a raspberry pi) and when linking the ogject file the linker returns me the error in the subject.
my program is as simple as
simple.c:
int main(){
int a = 2;
int b = 3;
int c = a+b;
}
i compile it with
$>gcc -o simple.obj simple.c
and then link it with
$>ld -o simple.elf simple.obj
ld: simple.obj: access beyond end of merged section (33872)
i can't understand why...
if i try to read the elf file with objdump -d it doesn't manage to decompile the .text section (it only prints address, value, .word and again value preceded by 0x) but the binary data is the same as the one i get from the decompiled simple.obj.
the only difference is in the loading start (and consequent) addresses of the binary data: the elf file starts at 0x8280, the object file starts at 0x82a0.
what does all this mean?
EDIT:
this is the dump for the obj file: http://pastebin.com/YZ94kRk4
and this is the dump for the elf file: http://pastebin.com/3C3sWqrC
i tried compiling with -c option that makes gcc stop after assembly time (it already did the linking part) but now i have a different problem: it says that there is no _start section in my object file...
the new dumps are:
simple.obj: http://pastebin.com/t0TqmgPa
simple.elf: http://pastebin.com/qD35cnqw
You are misunderstanding the effect of the commands you ran. If you run:
$ gcc -o simple.obj simple.c
it already creates the program you want to run, it's already linked. You don't need to link it again, especially by running ld directly unless you know what you are doing. Even if its extension is obj, it doesn't matter, it's just the name of the file, but the content of the file is already a complete Linux program. So if you run:
$ ./simple.obj
it will execute your code.
You usually don't call ld directly, but instead you use gcc as a front-end to compile and link. This is because gcc takes care of linking also important libraries that you are not linking such as the startup code, and that's the reason why your second attempt resulted in "no _start section" or something like that.
Could you print the output of the objdump -d command?
Btw, notice that 33872 == 0x8450.
I am not familiar with raspberry PI's memory map, so if you'r following any tutorials about this or have some other resource to help me help you out - it would be great :)

Resources