Question

I'm trying to create a simple linker for a barebone ARM application. Currently the loader, that loads the module, will simply add the offset to all records inside the .got and .data.rel sections. This works fine in .got, and for all symbols that need relocation inside .data.rel. It will break though for all non-relocatable data, as those will get this offset too.

Example:

void some_function() { return; }

struct a {
    void* fptr;
    int number;
};

static struct a = {
   .fptr = some_function,
   .number = 0x1000,
};

Here a.fptr will correctly address the actual location of the function, but a.number will incorrectly hold 0x1000 + offset, instead of just 0x1000.

How should I distinguish between the two? Is it enough that I check the .symtab section and only relocate addresses that are found there? But what if a symbol is actually at location 0x1000? Or does the linker address this issue (so it will not put a function at address 0x1000)? Does .symtabs actuall contain all symbols that can be found inside .got and .data.rel?

Was it helpful?

Solution

I wrote a basic ELF loader a while ago and I recall that you only add offsets to relocation entries marked as "R_ARM_ABS32".

You can find the code here https://github.com/tangrs/ndless-elfloader/blob/master/elf/elf_load.c

I simply linked my ELF files with --emit-relocs turned on. That way, the linker does all the linking, it just tells me what it did so you can fix up offsets during load time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top