Search code examples
cgccassemblyarmfirmware

Is it possible to delay resolving a .weakreference in gcc-as until link time? (GCC)


If you want to declare .weakreference for a set of interrupt vectors such as:

.weakreference ISR_SPI_HANDLER, defaultExceptionHandler

in a startup.S file or some framework include, it's very useful except that if you then declare ISR_SPI_HANDLER as a function in your main.c file, ISR_SPI_HANDLER in the startup.S still resolves to defaultExceptionHandler because .weakreference only works in local scope (terminology? pre-linking). However, .weak functions as it's expected, and allows you to "override" the definition with a definition in main.c, but if you don't, you'll always resolve to 0x00, which is inferior obviously to resolving to a default vector.

How can I overcome this?


Solution

  • Do not use the .weakref in the assembler. Instead just use ISR_SPI_HANDLER as an external. The assembler naturally wants to optimize to PC relative jumps to known locations. You are fighting this and someone else will want the call to defaultExceptionHandler.

    Instead use the linker,

      .text : {
        *(.text);
        ISR_SPI_HANDLER = DEFINED(ISR_SPI_HANDLER) ? ISR_SPI_HANDLER : defaultExceptionHandler;
        …
      }
    

    Alternatively, split startup.S with the .weak, .set and defaultExceptionHandler declaration in one file and another that is using/calling ISR_SPI_HANDLER.

    However, .weak functions as it's expected, and allows you to "override" the definition with a definition in main.c, but if you don't, you'll always resolve to 0x00, which is inferior obviously to resolving to a default vector.

    The typical case is define a function and use .weak in the same file. Ie, you need to use .weak where the routine is defined (but another object files may override this). To achieve this and keep defaultExceptionHandler for other uses,

       .weak ISR_SPI_HANDLER
       .set ISR_SPI_HANDLER, defaultExceptionHandler
    

    For ARM Thumb code, you may need .thumb_set instead. I believe this is the effect you wanted.

    Why .weakref? I think that this is better suited to machine generated code such as a compiler would generate.