7

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)
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Immortal_Buka
  • 79
  • 2
  • 5

4 Answers4

7

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.

mondaugen
  • 425
  • 5
  • 12
  • Here is what I don't get about this example: in C code, it is explicit that `coolguy` is an alias of `myadd`; so presumably if you `printf` them both as pointers (`%p`), you should get the same address. However, I don't see how `objcopy --add-symbol coolguy=.text:0000000000000000,global` establishes an alies to specifically `myadd` - it looks like it just enters a symbol in the table, without it pointing to anything? – sdbbs Apr 18 '23 at 15:01
  • try adding this to the above source code and then compile as before: `int anotherfun(int x) { return x - 1; } int blahblah (int x) __attribute__((alias("anotherfun"))); ` You will see this symbol table ` % nm myimp.o 0000000000000018 T anotherfun 0000000000000018 T blahblah 0000000000000000 T coolguy 0000000000000000 T myadd ` So I imagine one would change 0000000000000000 to 0000000000000018 in the above `objcopy` command to alias one of those new symbols. – mondaugen Apr 19 '23 at 16:10
2

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.)

Jeremy
  • 5,055
  • 1
  • 28
  • 44
1

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.

  • 2
    you need to define NMI_Handler or Default_Handler if your code is not including it in compilation. – Paresh Dhandhukiya Feb 07 '18 at 11:03
  • 1
    I know, that external function need defination. I have it. I want to make alias on that external defined function. – Immortal_Buka Feb 07 '18 at 11:08
  • 1
    if you have already defined Default_Handler somewhere and it gets included in compilation then it should't throw error. – Paresh Dhandhukiya Feb 07 '18 at 11:14
  • 2
    The problem is that (per GCC manual) given `void f () __attribute__ ((weak, alias ("fred")));`, "It is an error if ‘fred’ is not defined in the same translation unit." That case in question here is one where fred is defined in _another_ translation unit. – Jeremy Sep 25 '20 at 11:45
0

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.

Mou
  • 145
  • 1
  • 6