Weak symbol aliases on OS X similar to those on Linux, or a closest equivalent?
Asked Answered
O

1

63

What I do

When writing shared libraries for Linux, I tend to pay attention to relocations, symbol visibility, GOT/PLT etc.

When applicable, I am trying to avoid calling PLT stubs when functions from the same library call each other. For example, let's say a shared object provides two public functions - foo() and bar() (either of those can be called by user). The bar() function, however, also calls foo(). So what I do in this case is this:

  1. Define _foo() and _bar() functions that have private visibility.
  2. Define foo() and bar() weak aliases for _foo() and _bar() respectively.

That way, the code in shared object never uses weak symbols. It only invokes local functions, directly. For example, when _bar() is invoked, it calls _foo() directly.

But users are not aware of _* functions and always use corresponding weak aliases.

How I do it

In Linux, this is achieved by using the following construct:

extern __typeof (_NAME) NAME __attribute__(weak, alias("_NAME"));

The problem

Unfortunately, this does not work for OS X. I have no deep knowledge of OS X or its binary formats, so I poked around a bit and found a few examples of weak functions (like this one), but those don't quite do the same as you can have a weak symbol, but not a weak symbol that is an alias for DSO's local function.

Possible solution...

For now, I have just disabled this feature (that is implemented using macros) so that all symbols are global and have default visibility. The only way I can think of to achieve the same for now is to have all _foo functions with private visibility and have corresponding foo functions with default visibility and calling their "hidden" counterparts.

A better way?

That, however, requires a good chunk of code to be changed. Therefore I would prefer not to go there unless there is really no other way.

So what is the closes OS X alternative or the easiest way to get the same semantics/behavior?

Oppen answered 15/8, 2013 at 19:27 Comment(7)
Is your goal is simply to avoid the overhead of calling via PLT stubs when making a call to a symbol within the same library? Have you confirmed that the linker isn't already taking care of this for you?Indevout
@bdash: Yes, but not only. The other goal is to have compiler perform more optimizations - private symbols are better optimized, including LTO. And linker does not perform this optimization, because it cannot guarantee that LD_PRELOAD won't be used. In other words - once you go dynamic linking, you go all the way.Oppen
My understanding is that what you're after is the default behavior for shared libraries on OS X. The only piece of documentation I've found that comes close to making this explicit is the ld man page section about the -interposable_list argument. It states that calls to symbols within a module will be direct calls unless that symbol is marked as being interposable, in which case it would be made via a dyld stub.Indevout
Would this be an appropriate question for apple.stackexchange or is that site not suited to handling questions about programming on Macs?Kinelski
You should read this: glandium.org/blog/?p=2764Flofloat
Sounds like premature optimization to me.Waki
@NigelNquande No, that site is not for code-level programming unless it's Automator, Applescript, etc. Mostly just Mac usage help. Source: Their 2-minute tour says this.Encyclopedist
D
2

On OS X, calls made within the library are automatically direct calls and do not go through the dyld stub. The evidence to the fact is that if you want to be able to inject alternative functions to service a call, you'll need to use interposable to force indirect access to the symbols and force execution of the call through the dyld stubs. Otherwise, by default, local calls will be direct and will not incur the overhead of running through dyld.

Thus, your optimization on Linux is already the default behavior and the alias is not needed.

Still, if you want to do this just to make your platform compatible code simpler, you can still make the aliases. You just need to use "weak_import" or "weak" (if you want coalesced) as your attribute name.

extern typeof (_NAME) NAME __attribute(weak_import, alias("_NAME"));

Apple reference on Weak Linking: Marking Symbols for Weak Linking
Apple reference on Mach-O runtime binding : Scope and Treatment of Symbol Definitions

Danube answered 13/6, 2014 at 23:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.