Weak linkage in C programming

When linking C programs there are (in general) only a couple of errors you’re likely to see. If, for example, you have two functions in different files, both with external linkage, then the files will compile okay, but when you link you’ll likely see an error along these lines:

linking…
weak_linkage.axf: Error: L6200E: Symbol foo multiply defined (by foo.o and foo2.o).
Target not created

Most of the time this makes sense and is as expected; however there is a particular instance where it gets in the way.

If we need to supply a code framework where we need placeholders (stubs) for someone else to fill in at a later date, it can sometimes mean developing complex makefiles and/or conditional compilation to allow new code to be introduced as seamlessly as possible.

However, there is a hidden gem supported by most linkers called “weak linkage”. The principle of weak linkage is that you can define a function and tag it as (surprisingly) weak, e.g.

// foo_weak.c
__weak int foo(void)
{
// ...
return 1;
}

This then can be called from the main application:

// main.c
int foo(void);

int main(void)
{
foo();
while(1);
}

This project can build built as normal:

compiling main.c…
compiling foo_weak.c…
linking…
Program Size: Code=372 RO-data=224 RW-data=4 ZI-data=4196
“weak_linkage.axf” – 0 Error(s), 0 Warning(s).

At some time later we can add another file with the same function signature to the project

// foo.c
int foo(void)
{
// override weak function
return 2;
}

If we rebuild, normally we would get the “multiply defined” symbols error, however with weak linkage the linker will now bind the new “strong” function to the call in main.

compiling main.c…
compiling foo_weak.c…
compiling foo.c…
linking…
Program Size: Code=372 RO-data=224 RW-data=4 ZI-data=4196
“weak_linkage.axf” – 0 Error(s), 0 Warning(s).

As you can also see, the weak function is optimized away.

A good example of the use of weak linkage is the definition of the default interrupt handlers in CMSIS.

This example code is based on Keil’s uVision v4.60 compiler/linker, however both GCC and IAR also support weak linkage.

Posted on January 25th, 2013
» Feed to this thread
» Trackback

2 Comments a “Weak linkage in C programming”

  1. Peter Bushell says:

    Interesting!

    Some time ago I spotted this feature being used in the interrupt vectors, as you say, but they were in Assembly Language. I didn’t know that you could make it work in C (with these compilers, at least).

    Having said this, I’m not sure I like the feature very much. Once, the linker kept picking up the default interrupt, even though I had a proper one in the build as well. I had neither the time nor the inclination to diagnose the problem properly; I just removed the weak reference, for this case, and everything worked fine. I’m all for keeping things simple, even if it sometimes involves a little more work. Even if the implementation always actually worked properly, having two possible link candidates is surely more confusing than having just one, to a casual observer trying to understand what’s going on.

  2. Sticky Bits » Blog Archive » Developing a Generic Hard Fault handler for ARM Cortex-M3/Cortex-M4 says:

    [...] all the exceptions handlers are build with “Weak” linkage in CMSIS, it is very easy to create your own Hard Fault handler. Simply define a function with the [...]

Leave a Reply