user1192748
user1192748

Reputation: 1005

How can I influence the address of a function?

is there a method to influence, set or define the (relative) address of a function? Maybe there are any possibilities witin the linker script to make sure function abc() always resides at OFFSET+0x0034C0 (just an example). I want to somehow "control" the location of functions inside the memory to make those locations some kind of parametrized. At the moment I am looking for an approach on my x86 using gcc. However, the real application should run on an embedded device.

Regards

Upvotes: 3

Views: 645

Answers (3)

nav
nav

Reputation: 1655

The best way to do this, IMO, is to place functions into user-defined sections as unwind has mentioned above. You can find a simple example that places a function myFunc at a 4kByte boundary below:

Create a new section in your memory by modifying the Linker Script:

/* .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 gcc's attribute feature to place the function into the section we 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 do objdump now, you'll see a section by the name .my_section holding the code of myFunc at address 0x2000, rather than at 0x12e8

Disassembly of section .my_section:

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

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

This code works with Codesourcey gcc suite for ARM-Cortex. I'm not quite sure about x86...

Upvotes: 1

Josh Petitt
Josh Petitt

Reputation: 9579

A typical generalized implementation to this would be a vector table (I've also heard this called a patch table).

First, in your 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
};

Next, in your C file create a static table:

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

Finally expose the address as a void*

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

Now you should be able to get to all the functions as an offset from the base address.

If all your functions have the same call signature you can simplify this by having an array of function pointers instead of the struct. However, both the array and the struct will hold pointers, so the pointer math is basically the same.

This also allows you to locate your patch table at a specific address using the linker.

Upvotes: 1

unwind
unwind

Reputation: 399753

You can probably do it using linker script magic with gcc, yes. Look at how to define section placement, then put directives in your source to put functions in the section(s) of your choice.

Not at all sure if that will work in the x86 machine though, since the operating system might have ... objections. This is more for embedded use directly.

What would be the point of controlling code location on a full operating system?

Upvotes: 8

Related Questions