4

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.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Garf365
  • 3,619
  • 5
  • 29
  • 41
  • Some compilers (don't know about yours) support symbol aliases, which might be something to look into. – user694733 Aug 01 '16 at 10:19
  • Also, you should be very specific about the function types: `void func(void)` (no arguments) and `void func()` (unspecfied number of arguments) are different types. Use `void` always for functions without arguments to avoid problems. – user694733 Aug 01 '16 at 10:22
  • @user694733 thanks for advice, I will take care about it – Garf365 Aug 01 '16 at 10:27
  • Probably I'm not the global vision of the problem, but `weak` is designed to allow to "override" function, isn't it? So you can define/implement your _same_name_function_ to override the `weak` one. – LPs Aug 01 '16 at 12:01
  • @LPs I have already do that. I override the `weak` function with a _same_name_function_ use as a wrapper to function doing real job. I wonder a method to directly override `weak` function with function doing real job – Garf365 Aug 01 '16 at 12:06

2 Answers2

2

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.

tofro
  • 5,640
  • 14
  • 31
  • I will take a look at this method. I prefer a method with `__attribute__` or any specific or generic C code or with linker (linker option or linker script), but it's already a first method. I agree with you considering this as a hack. Also, it can be dangerous if `blink` is use in another place (but because it manages an ISR, it shouldn't be call else where) – Garf365 Aug 01 '16 at 12:27
  • @Garf365 maybe you could use `ld`'s `--defsym` command with an argument like `ISR78=blink` (or is it the other way round?) - I have, however, never tried this myself and don't really know what other implications this might have or whether it will work at all. – tofro Aug 01 '16 at 12:37
  • Finally, it's not the answer I wanted, but it seams to be the only possible answer. Thanks a lot – Garf365 Aug 04 '16 at 07:40
  • @Garf365 Have you tried my last proposal? It looked promising to me. – tofro Aug 04 '16 at 07:44
  • I didn't try your last proposal because `__vector_table` is in an read only memory... but thank, I will remember it if you move __vector_table into RAM – Garf365 Aug 04 '16 at 07:48
  • @Garf365 Actually, with "last proposal" I meant using `ld --defsym ISR78=blink` – tofro Aug 04 '16 at 08:11
  • Actually it works really fine, it's just not what I did expect. – Garf365 Aug 04 '16 at 08:43
2

tl;dr: you have a working solution already, which appears to be the solution explicitly supported and encouraged by using weak symbols in the first place. What improvement do you expect from a different solution?


Linker symbols are looked up by name, so the only alternatives to using the expected name are:

  1. tofro's suggestion to modify the link step directly
  2. modify the function pointer table yourself

The whole point of making ISR78 a weak symbol in the first place is to allow exactly the override (by symbol name) you've already used.

I can't see any way modifying the interrupt vector table is better than just using the expected function name directly, even if it's possible.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • I can understand the OP wants to remove that one indirection (which would typically evaluate to one single branch instruction) - There are problems where every cycle counts. – tofro Aug 04 '16 at 07:43
  • _Which_ one indirection? You're calling through a table, and the linker will fix up the table - including choosing between the weak and other symbols - at link time. There is _no impact_ at function call time whichever of these you choose (unless you use dynamic linking and there's a trampoline function, at least). – Useless Aug 04 '16 at 15:24