3

I have built a static library (*.a for gcc, *.lib for keil). One of its source file, compiled into library, contains definition of RADIO_IRQHandler. An excerpt from this source file, called "ral_irq_handlers.c", is below:

...
void ral_symbol_import(void) //dummy function
{
    return;
}
...
void RADIO_IRQHandler(void)
{
    ...
}
...

This IRQ symbol definition should override the weak definition which is declared in startup file. The startup file is not compiled into any static library and is just a regular file inside the project.

An excerpt of arm_startup_xxx.s file (keil toolchain) is below:

Default_Handler PROC
                ...
                EXPORT   RADIO_IRQHandler [WEAK]
                ...
...
RADIO_IRQHandler
...
                B .
                ENDP
                ALIGN

An excerpt of similar gcc_startup_xxx.s file (gcc toolchain) is below:

.globl  Default_Handler
.type   Default_Handler, %function
Default_Handler:
    b       .
    .size   Default_Handler, . - Default_Handler

    .macro  IRQ handler
    .weak   \handler
    .set    \handler, Default_Handler
    .endm    
    ...
    IRQ  RADIO_IRQHandler
    ...
    .end

Then I observed a strange behaviour. When I use any API function from "ral_irq_handlers.c" source file (compiled into library) inside one of the project source files, the linking is done correctly. Example:

...
int main(void)
{
    ral_symbol_import();
    ...
}
...

However, if I don't use any API function of "ral_irq_handlers.c" source file, the linker cannot find the RADIO_IRQHandler symbol defined in my library. Can I somehow do this without this ugly hack (calling the dummy function to force correct linking)?

I would like to modify only the library code without touching the startup files.

aldarel
  • 446
  • 2
  • 7

1 Answers1

1

As far as I know you cannot do that easily, as linker will only search your library if it cannot find the symbol for the handler. As it can find it (weak definition in the startup) it doesn't look any further.

However you may solve it by linking your library like that:

... -Wl,--whole-archive -l:path/to/our/library.a -Wl,--no-whole-archive ...

Also you don't actually have to call the dummy function to cause the linking of module. All you need is telling the linker you need it, for example like that:

void ral_symbol_import(void);
void (* const variable)() = &ral_symbol_import;
Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
  • The linking flag works quite well, but it is very invasive. Can you somehow declare void RADIO_IRQHandler(void) function to be more visible inside the library (some special statement)? Or maybe build the library in such a way that this particular symbol is linked correctly? – aldarel Feb 16 '17 at 10:51
  • 1
    @aldarel - sorry, I have no idea for other options that would work from "inside" the library... All solutions I have are for the project that uses the library. You can also force linking of some symbol via linker script (or linker command line), but this is the same thing. I had a similar problem once and these are all I got from here - https://sourceware.org/ml/binutils/2015-09/msg00272.html – Freddie Chopin Feb 16 '17 at 11:24
  • With GCC for ARM Embedded Processors 6-2017-q2-update and some optimizations turned on, I had to attach `__attribute__((used))` to `variable` declaration or the variable was not emitted and the wrong weak function was linked. – lorcap Oct 24 '18 at 07:57