0

For quite a while I've been using linker sections for registering elements that are used at runtime. I find that it's a simple way to make generic and extensible interface. A particularly useful use-case is something like unit tests or a multitool (e.g. busybox) so one can do something like:

$ ./tool <handler>

Where handler is a simple string that is "looked up" at runtime by walking the linker section. In this way, your parser doesn't have to "know" what commands are supported. It just finds their handlers in the linker section dedicated for them or it doesn't.

With GCC I've been doing something like (you can do this with Clang as well):

#define __tool __attribute__((__section__("tools")))

Then each handler I want to register gets a simple structure (with more or less information as needed)

struct tool {
    const char *name;
    const char *help;
    int (*handler)(int argc, char **argv);
}

Then, for each tool you just do something like (often conveniently wrapped in a macro):

int example_tool0(int argc, char **argv)
{
    return -1;
}

static const struct tool example_tool0 = {
    .name = "exmaple_tool0",
    .help = "usage: ...",
    .handler = example_tool0
};

__tool static const struct tool *ptr = &example_tool0;

And used a such:

$ ./tool example_tool0

And because of __tool, each pointer registered in this way is packed into a linker section that can be walked.

Now, on GCC the linker creates two magic variables for each section: __start_SECTION and __stop_SECTION. So, to "walk" all of our registered handlers you just take the size of this section, divide by the size of a pointer, and then strncmp against the name (in this example) in the struct.


All of the above just to say, how can this be done using the OSX/iOS Clang-based toolchain? I would rather not use a custom linker script to achieve this seemingly simple operation.

Is there a way do this on OSX? I have worked around the issue by registering an empty entry at the beginning of the section and at the end. But doing so requires forcing the link order of the object files.

While OSX/iOS uses Clang as their platform compiler, they do not use the LLVM linker. Rather, they implement their own ld64 (which is open source) for whatever reason. So, it may just not be supported. I didn't readily see anything in man ld on OSX, but it's a bit info-dense.

For reference with ELF and GCC

sherrellbc
  • 4,650
  • 9
  • 48
  • 77

1 Answers1

0

And so this has been answered by others already. I did search, but I must have missed this answer. I've actually looked for an answer to this question many times before but must've never used the right words.

https://stackoverflow.com/a/22366882/2446071

In summary, apparently the linker supports syntax to define these desired symbols yourself:

extern char __start_SECTION __asm("section$start$SEGMENT$SECTION");
extern char __stop_SECTION  __asm("section$end$SEGMENT$SECTION");
sherrellbc
  • 4,650
  • 9
  • 48
  • 77