Immortal_Buka
Immortal_Buka

Reputation: 79

How I can make alias on external defined function in C?

During compiling this C code

extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));

I've recive this

error: 'NMI_Handler' aliased to undefined symbol 'Default_Handler'

How I can make alias on external defined function?

Compiler:

gcc version 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204] (GNU Tools for Arm Embedded Processors 7-2017-q4-major)

Upvotes: 7

Views: 6324

Answers (4)

Mou
Mou

Reputation: 165

It's popular to employee weak and alias attribute to implement override mechanism for native C project especially in cases of firmware projects.

Both of declaration and definition can be noted by __attribute__((weak)) and its linking priority rules is related to if any declaration exists in a head file.

It would be good tactic that just to code and compile it. Then see what would happen when linking is look for its definition. I usually check symbols by -Wl,-trace,-trace-symbol=ANY_FUNCTION_NAME_YOU_WANT and nm OBJECT_FILE_NAME.

Usually I just create a weak attribute function definition and let other objects override it. An example shown as below:

In C file:

//non-exported weak attribute definition
__attribute__((weak)) void startup_handler_dummy(void) {
        printf("[%s][%s]Entry (NO OVERRIDE HANLDER COMES HERE)\n", __FILE__, __func__);
}

//weak and alias attribute declaration
void startup_handler_dummy_impl(void) __attribute__((weak, alias("startup_handler_dummy")));

//exported weak attribute definition
__attribute__((weak)) void startup_handler(void) {
    startup_handler_dummy_impl();
}

In header file:

#ifndef _BOARD_H_
#define _BOARD_H_
#define STARTUP_HANDLER startup_handler //to export symbol
#endif

Hope my code can help :)

And you can see more details and program screen-shots on MyGitHub.

Upvotes: 0

Jeremy
Jeremy

Reputation: 5311

As suggested here, add the following to your linker command file:

PROVIDE(NMI_Handler = Default_Handler);

(And remove the weak alias declaration from the C code.)

Upvotes: 2

mondaugen
mondaugen

Reputation: 454

To alias an external function, you can use objcopy. Here's an example:

Say I have the definition of a function and I alias it, like in the following program (called myimp.c):

// myimp.c
int
myadd(int x, int y)
{
    return x+y;
}

int
coolguy (int x, int y) __attribute__((alias("myadd")));

If we compile this (but don't link) we get an object file and we can check out its symbols:

# compile
$ cc -c myimp.c
# look at the symbols
$ nm myimp.o
0000000000000000 T coolguy
0000000000000000 T myadd

So we can see that the __attribute__((alias("myadd")) is simply adding a symbol coolguy with the same value, 0000000000000000, as myadd. If you look in the man page for nm, it will say that T means it is a global symbol in the .text section. This makes sense because the function is not static and comprises instructions (as opposed to data).

So if we have the object file, but not the source, and we want to add a function alias we can do so using objcopy --add-symbol.

Say we have the object file resulting from compiling this source code:

// myimp2.c
int
myadd(int x, int y)
{
    return x+y;
}

Compiling as above, we'll get myimp2.o, whose symbol table tools like this:

# look at the symbols
$ nm myimp2.o
0000000000000000 T myadd

So we want to add the coolguy symbol, which we do as follows

# objcopy --add-symbol coolguy=.text:0000000000000000,global myimp2.o myimp2_augmented.o

Look at the documentation on --add-symbol in the objcopy man page. Basically .text specifies the section, after the colon the value, and then global I found by passing a bad type and objcopy failed and told me a list of the valid types, from which I chose global.

Try running nm on myimp2_augmented.o, you'll see that we've added the symbol.

Now you should be able to link with myimp2_augmented.o instead of myimp.o and your program can call coolguy without linking errors.

Upvotes: 8

Paresh Dhandhukiya
Paresh Dhandhukiya

Reputation: 212

here NMI_Handler has a weak definition attribute means that if NMI_Handler is not defined then definition of Default_Handler will be used for NMI_Handler. generally there are strong definition available for interrupts like NMI_Handler or Default_Handler.you might need to add those file in your compilation to remove error.if you wants to handle NMI_Handler in your own way then you can define it somewhere and that definition will be included instead of weak one.

Upvotes: 1

Related Questions