A technique for pulling selfcontained modules from a library

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've seen this issue discussed several times before, but not with this exact solution, so I'll barge ahead with my own reinterpretation of the wheel...

Fairly often, I generate small, feature-specific modules that qualify as being "generally reuseable" enough to add to the static link library I'm accumulating for use by future products. But because they're self-contained, there's no unresolved references to them from a specific product's application firmware that would get them extracted from said library. The modules usually have some global variable or subroutine name that might be used with a "-u" linker commandline switch, but not always. And if the module was compiled as C++ source, its subroutine names will probably be mangled anyway.

So what ol' Jack Burton does in a situation like that is to #include this header file in such self-contained modules:

// moduleTitle.h - Provides a macro to insert a nonmangled public symbol
//
// Often, a module is so self-contained that a prospective application
// has nothing to "grab onto" to force its extraction from the static
// library.  The following macro can be used to add a non-mangled symbol
// to a module's compiled output file.  Then, the common makefile
// template's "DEMANDEDSYMBOLS" mechanism can be used to add a "force
// symbol to be undefined" for it:
// 
//
#ifndef ModuleTitle
#define ModuleTitle(name) asm(".global " #name "\n.set " #name ", 0xBEADB007");
#endif

So a self-contained module might start out like so:

// someModule.cpp - A pithy description of this module
//
#include "moduleTitle.h"
ModuleTitle(SomeModule)

The common makefile template provides the following service:

#  =============================
#  = Forcing Libray extraction =
#  =============================
#
# Makefiles that include this one can pull even self-contained modules
# from the library by creating undefined references to strategically-
# selected symbols.  To make this process look less imposing, the stock
# Makefile is allowed to set up a simple list of those symbols without
# needing to know the linker commandline switch format.  Here's where
# we expand such a list into the appropriate linker commandline args:
#
LDFLAGS += $(patsubst %,-u %,$(DEMANDEDMODULES))

, so a project-specific Makefile can do something like this:

# List module title to be "demanded" from the probe link archive here.
# Some of the available library modules are self-contained; nothing
# "calls" them from the application code, so the linker doesn't know
# to include them.  To get such a module included, you can add specific
# symbols to the linker's "shopping list".  Such self-contained modules
# should use the "ModuleTitle" macro to provide clearly descriptive names
# that can be added to the list of "symbols to demand"
#
DEMANDEDMODULES += DebugScratchpad
DEMANDEDMODULES += FirmwareUpdate
DEMANDEDMODULES += StackCheck
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the module is never referenced then the only way to execute code therein is either by ISR i.e. functions in .vectors (has KEEP in the linker script) or by adding some startup code to .init* or exit code in .fini (same holds with KEEP), right?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
If the module is never referenced then the only way to execute code therein is either by ISR i.e. functions in .vectors (has KEEP in the linker script) or by adding some startup code to .init* or exit code in .fini (same holds with KEEP), right?
Largely. Dunno about "KEEP" (that's one of the large set of linker features I can't understand), but there are a couple other exceptions:

The codebase I'm developing has a remote interface that executes commands that are specified by enumerated "command tag ID" numbers. The first stage of "parsing" such commands is to dispatch through a table of "command specifications" that is built to have a generous but fixed size, using the same "weak references" technique that ISR vectors use. So a separately-built module can, by providing an overriding (non-weak) definition for one of the allowed slots of the command-set-defining table, extend the feature set of the product in some way.

Also, there are some other subsystems that are extensible by means of populating specifically named subsections so as to add items to a list. The base code knows where the upper and lower boundaries of the lists are (because it put dummy labels in cleverly-adjacently-named subsections, and the linker's been told to SORT the sections), and can therefore tell how big the tables get. So again, the effect is that a module can cleanly extend the functioning of the base code without needing references *from* that base code.


This "extensible list" technique is also how background tasks get added to the crude round-robin task executor. So, separately-built modules can, if pulled in from the library, add quasi-real-time-ish services to the base product.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nice, nice. But... What exactly would be the drawback of keeping/using the "module" in source form (I mean now, in the days of terabyte disk spaces and gigahertz processor clocks)?

Thanks,

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Levenkay wrote:
I've seen this issue discussed several times before, but not with this exact solution, so I'll barge ahead with my own reinterpretation of the wheel...
Your solution is similar to the one that I described earlier this year. In addition to being able to request inclusion of particular symbols via the -u linker option, I also provided the ability to make such a request in code modules (both C and asm). This allows the linker command line to force inclusion of a particular module and then that module forces inclusion of others that it knows that it needs but which might otherwise not be included (e.g. presence of weak symbols).

I've noticed that the presence of a -u option for a particular symbol does not yield a linker error in cases where the symbol is ultimately not found. I don't know if this artifact is intended or not but it does occasionally lead to a bad build (typically during development) that is sometimes difficult to recognize.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup; sorry. I did my search in the wrong space.