Reputation: 428
Symbols in mach-o files can be marked as 'indirect' (I
in output from nm
, defined in the headers using the constant N_INDR
). It seems this type of symbol is rarely used in practice (or perhaps has a very specific, limited use). The only example I've come across is in the macOS system library /usr/lib/system/liblaunch.dylib
. Here's a partial output from running nm
on that file:
U __spawn_via_launchd
0000000000000018 I __spawn_via_launchd
U __vproc_get_last_exit_status
0000000000000049 I __vproc_get_last_exit_status
U __vproc_grab_subset
000000000000007a I __vproc_grab_subset
As this output shows, the same symbol is listed twice, once as U
and again as I
. This is true of all the I
symbols in the file.
Examining the symbol table entries in more detail show that while the U
entries reference another linked library (libxpc.dylib), the I
entries reference nothing.
Searching for "mach-o indirect symbols" doesn't seem to produce many useful results. Most, including Apple's documentation, cover the stubs used to implement lazy weak symbols. I don't think this is related to the I
indirect symbols, mainly because lazy weak linked symbols in other files are not marked as I
, but I'll be happy to be told different.
The source files from the Darwin archives are also lacking useful comments.
So I have 3 questions:
What is the canonical explanation for what indirect symbols are?
How does the linker at compile time and the link loader at load time interpret and process these symbols?
How do you define a symbol in a source file as indirect? (I'm mostly interested in a C / Clang answer, but I'm sure future readers will welcome answers for other languages too.)
(For what it's worth, my current best guess is that this is a way to allow symbols to be removed from a library while maintaining compatibility, as long as those symbols are available elsewhere. A way of keeping the linker happy at compile time and pointing the link loader to the moved implementation at load time. But that's just a guess.)
UPDATE
After some more research I can answer question 3. This is, of course, controlled by the linker, and the option I was looking for was -reexport_symbol
. This will create the I
entry in the symbol table (and if the symbol isn't already present it will also create the U
entry). There is also the -reexport_symbols_list
option which takes a file of symbol names and creates indirect symbols for each.
Upvotes: 10
Views: 1733