Search code examples
cldweak-linking

override a weak function A with a function B


For an embedded device, I have file containing an array with function pointers storing interrupt handlers, define like that (I can't modify it):

typedef void (*const ISRFunction)(void);

__attribute__((weak)) void ISR0(void){ for(;;); }
__attribute__((weak)) void ISR1(void){ for(;;); }
...
__attribute__((weak)) void ISR78(void){ for(;;); }
...

ISRFunction __vector_table[0x79] = 
{
    (ISRFunction)&ISR0,
    (ISRFunction)&ISR1,
    ...
    (ISRFunction)&ISR78,
    ...
}

I have a second file which defines some functions, which I can't modify. This file is like:

void blinkLed(void)
{ ... }

Finally, I have a main source file, with main function and configuration of device. On interrupt 78, I would like to blink led. So I write a strong function ISR78 like that:

void ISR78(void)
{
    blinkLed();
}

I wondered if there was a solution to override weak function ISR78 directly by blinkLed, ie storing address of blinkLed inside __vector_table without modifying it or rename function?


EDIT:

I actually use GNU gcc 4.9.3 and associated linker (GNU ld 2.24.0). I can modify main.c and Makefile associated to project.


Solution

  • The only way I see to achieve what you want to do is to patch the symbol table of the object file containing the blink symbol with the ISR78 symbol.

    objcopy [...] --redefine-sym blink=ISR78

    should do that. The linker should then automatically insert the address of the former blink into the vector table. Obviously, your blink symbol is gone after that and shouldn't be called from other places.

    I would, however, consider this a hack.

    In case _vector_table is globally accessible and in writable memory (not assumed, that's probably too simple...), you could simply patch it from your own code by

    _vector_table [0x78] = blink;
    

    at runtime.