How can I influence the address of a function?

Is there a way to influence, set, or determine the (relative) address of a function? Perhaps there is some possibility in the linker script to make sure the abc () function is always at OFFSET + 0x0034C0 (just an example). I want to somehow "control" the location of functions within memory to make those locations invalid. At the moment I'm looking for an approach on my x86 using gcc. However, a real application must run on an embedded device.

Hello

+3


source to share


3 answers


Maybe you can do it with linker script magic with gcc, yes. See how to define placement, then put directives in your source to place the functions in the sections you want.

Not at all sure if this will work on an x86 machine though, since the operating system might have ... objections. It's more for embedded use directly.



What will be the control over the location of the codes in the full operating system?

+8


source


A typical generic implementation for this would be a vector table (I also hear this is called a patch table).

First, in the C file, write your functions:

void my_first_function(int){ /* do something */ }
void my_second_function(int){ /* do something */ }

      

Then, in your C file, create a structure that defines the layout of the table:

struct MyVectorTable
{
  void (*first_function)(int);
  int (*second_function)(float, char);

  // all the rest
};

      

Then, in your C file, create a static table:



static struct MyVectorTable my_vector_table = {
  my_first_function,
  my_second_function,
};

      

Finally, output the address as a void *

void* get_table_base_address(void) { return &my_vector_table; }

      

Now you can get all functions as an offset from the base address.

If all your functions have the same call signature, you can simplify it by providing an array of function pointers instead of a structure. However, both the array and the structure will contain pointers, so the pointer math will be basically the same.

It also allows you to find the patch table at a specific address using the linker.

+1


source


The best way to do this, IMO, is to place functions in custom sections as described above. You can find a simple example that puts a function myFunc

on the 4kByte boundary below:

Create a new section in your memory by changing the Script linker:

/* .my_section will be the name of the section in the final executable */
.my_section : ALIGN (8)
{
    . = ALIGN (0x1000);

    KEEP(*(.mysection))    /* The section will be called ".mysection" in the
                              compiled translation unit (.obj) */

    . = ALIGN (8);
} >rom

      

Now use the gcc function attribute

to place the function in the section you just created:

void myFunc(void) __attribute__ ((section(".mysection"))); // The section name to use 
                                                           // here is ".mysection", 
                                                           // not ".my_section"

// Looks like you need to use __attribute__ along with function declaration, rather 
// than with the function definition, though I'm not sure why

void myFunc(void)
{
    // ...
}

      

If you are by now objdump

, you will see a section titled .my_section

containing the code myFunc

at the address 0x2000

, not at0x12e8

Disassembly of section .my_section:

000012e8 <myFunc-0xd18>:
        ...

00002000 <myFunc>:
    2000:       b508            push    {r3, lr}
    ...

      

This code works with the Codesourcey gcc

ARM-Cortex package . I'm not entirely sure about x86 ...

+1


source







All Articles