1

It is possible to implement a static function registry in C for gcc/clang by using the section variable attribute and relying on the ELF linker to define the __start_<section> and __stop_<section> symbols pointing to the address of the custom section.

(See below for an example using this approach, which should illustrate the point.)

This approach, however, is very specific to GCC, ELF and Unix/Linux.

Is there an alternative approach to solve this same problem of static function registry, only in a more portable way?

In particular, I would like to be able to target MSVC compiler for Windows.


As an example, consider this program using this set of source files:

1) registry.h

struct reg_func {
    const char *name;
    int (*func)(void);
};

#define REGISTER_FUNC(name)                     \
    static int func_ ## name(void);             \
    static struct reg_func descr_ ## name       \
        __attribute__((section("registry")))    \
            = { # name, func_ ## name };        \
    static int func_ ## name(void)

extern struct reg_func __start_registry;
extern struct reg_func __stop_registry;

2) a.c

#include "registry.h"

REGISTER_FUNC(a) {
    return 1;
}

3) b.c

#include "registry.h"

REGISTER_FUNC(b) {
    return 4;
}

4) c.c

#include "registry.h"

REGISTER_FUNC(cde) {
    return 999;
}

5) main.c

#include <stdio.h>
#include "registry.h"

int main(int argc, char *argv[]) {
    struct reg_func *p;
    for (p = &__start_registry; p < &__stop_registry; p++) {
        printf("Function %s returned %d.\n", p->name, p->func());
    }
    return 0;
}

6) Makefile

registry: main.o a.o b.o c.o
        $(CC) -o $@ $^

Build with:

$ make
cc    -c -o main.o main.c
cc    -c -o a.o a.c
cc    -c -o b.o b.c
cc    -c -o c.o c.c
cc -o registry main.o a.o b.o c.o

Execute with:

$ ./registry 
Function a returned 1.
Function b returned 4.
Function cde returned 999.
filbranden
  • 8,522
  • 2
  • 16
  • 32
  • 1
    No. Manipulating (information from) object files is inherently platform specific. Unless someone has written a library that provides a common interface atop the platform specific APIs, there's not much you can do (except write the common API yourself). – Jonathan Leffler Dec 14 '18 at 00:44
  • Actually I think I'm fine with using the appropriate #ifdef's as necessary... Any idea what would be the way to accomplish this on MSVC compiler? Google searches got me nowhere, not sure which keywords would get me where I need... – filbranden Dec 14 '18 at 02:49
  • 1
    I think I found what I was looking for... `__declspec(allocate("registry$u"))` and some more magic to order sections before and after that one... https://stackoverflow.com/a/14783759/9447571 – filbranden Dec 14 '18 at 04:14

0 Answers0