ARM Technical Support Knowledge Articles

How does __weak work?

Applies to: DS-5, RealView Development Suite (RVDS)

Answer

The ARM compilation tools support the concept of "weak" references and definitions.  These can provide additional flexibility in the way the linker includes various (typically library) functions and variables in a build.

Weak references

If the linker can not resolve normal (non-weak) references to symbols included in the link, it will attempt to do so by finding the symbol in a library, and report an error if it can not.  Once such a reference has been resolved, the section it is resolved to is marked as used, so will not later be removed by the linker as an unused section.  Each non-weak reference must be resolved by exactly one definition (if there are multiple definitions, the linker will also report an error). 

Function or variable declarations in C source files can be marked with the __weak qualifier.  As with extern, this qualifier tells the compiler that a function or variable is declared in another compilation unit (source file).  As the definition of this function/variable may not be available to compiler, it creates a (weak) reference to be resolved by the linker.

The compiler will not load an object from a library in order to resolve a weak reference.  It will only be able to resolve the weak reference if the definition will be included in the image for other reasons.  The weak reference will not cause the linker to mark the section containing the definition as used, so it may be removed by the linker as unused.  The definition may already exist in the image for several reasons:

  1. The symbol is strongly referenced somewhere else in the code.
  2. The symbol definition exists in the same ELF section as a symbol definition that is included for any of these reasons*.
  3. The symbol definition is in a section that has been specified using --keep, or contains an ENTRY point.
  4. The symbol definition is in an object file included in the link (not a libary unless the object within the library has been explicitly included on the link line), and the --no_remove option is used.

In summary, a weak reference will be resolved if the definition is already included in the image, but will not affect whether or not that definition is included.

An unresolved weak function call will be replaced either with a NOP (no-operation instruction), or a BL (Branch with link instruction) to the following instruction - effectively the function call just does not happen.

Example usage:

A library contains a function foo(), that will be called in some builds of an application but not in others.  If it is used, init_foo() must be called first.  Weak references can be used to "automate" the call to init_foo().

The library can define init_foo() and foo() in the the same ELF section*.  The application initialisation code should call init_foo() weakly.  Now if the application includes foo() for any reason, it will also include init_foo() and this will be called from the initialisation code.  In any builds that do not include foo(), the call to init_foo() will be removed by the linker.

In this scenario, there is no need to rebuild the initialisation code between builds that include foo() and don't include foo().  There is also no possibility of accidentally building an application with a version of the initialisation code that does not call init_foo(), and other parts of the application that call foo().

foo.c (typically built into a library):

void init_foo()
{
  // Some initialisation code
}

void foo()
{
  // A function that is included in some builds
  // and requires init_foo() to be called first.
}

init.c:

__weak void init_foo(void);

int main(void)
{
  init_foo();
  // Rest of code that may make calls foo() directly or indirectly.
}


Weak references can also be generated by the assembler:

init.s:

      IMPORT init_foo WEAK

      AREA init, CODE, readonly

      BL init_foo

      ;Rest of code

      END

Weak Definitions

A function definition (or EXPORTed label in assembler) can also be marked as weak, as can a variable definition.  In this case, a weak symbol definition is created in the object file.

A weak definition can be used to resolve any reference to that symbol in the same way as a normal definition.  However, if another (non-weak) definition of that symbol exists in the build, the linker will use that definition instead of the weak definition, and not produce an error due to multiply-defined symbols.

Example usage:

A simple or dummy implementation of a function can be provided as a WEAK definition.  This allows the software to be built (with defined behaviour) without providing a 'full' implementation of this function, but also allows a full implementation to be provided for some builds if required.

* A note on ELF sections:

Typically, the code for multiple functions defined within a single source file will be placed into a single ELF section by the compiler.  Certain build options may alter this behaviour, so should be used with caution if your build is relying on the grouping of files into ELF sections:

  1. The compiler command line option --split_sections results in each function being placed in its own section.  In the above case compiling the library with this option would result in foo() and init_foo() being placed in separate sections, so init_foo() would not be automatically included in the build due to a call to foo().
  2. The linker feedback mechanism (--feedback) would record init_foo() as being unused during the link step.  This will cause the compiler to place init_foo() into its own section during subsequent compilations, also allowing this to be removed.
  3. The compiler directive #pragma arm section also instructs the compiler to generate a separate ELF section for some functions.

Article last edited on: 2010-04-13 10:31:41

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential