Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Continuing Linux Porting issues



Still having a bit of trouble with implementing a hack to force loading of my libraries/plugins.

If I add an _init symbol to each libaray that I'm going to dlopen (so I can dlsym it to force the library to initialize itself) it works pretty good EXCEPT if I have cross-library dependencies, then I get problems with multiply defined _init symbols. ie: if libfoo.dylib depends on libbar.dylib then I link libfoo.dylib with -lbar and get a multiply defined _init symbol.

I'm currently thinking about putting a unique symbol in each library (ie: _init_foo, _init_bar) but this seems like a really nasty way to solve the problem. Is there something better? Either a way to get around the multiply defined symbols or some existing symbol in each library I can lookup?

Thanks
Greg Corson
Sony R&D

Greg Corson wrote:

Thanks to Geoffrey and others I think I have solved the worst of the problems I'm having. There are just a few implementation details I could use some help on.

First, building all my dylibs with -single_module solves the problems I was having with needing DYLD_BIND_AT_LAUNCH.

The idea of forcing a dylib to load and initialize itself by looking up a symbol in the library also works nicely.

The main implementation problem I have is that there is no common symbol in all of my .dylib files to lookup. I really don't want to add code to put, say, an _init and associated #ifdef OSX kind of code into all 100 or so libraries. Is there some symbol guaranteed to be in every library that I could lookup with dlsym? (or some way to add one from the command line during compile/link?)

I tried dumping the libraries with otool and found a few common symbols like ___initialize_Cplusplus, __dyld_func_lookup and the (supposedly) linker defined symbol __mh_dylib_header but dlsym couldn't find any of these (maybe they are not exported?)

Thanks for all the help.

Greg
Sony R&D


Geoffrey Schmit wrote:

On 05/05/2004 at 11:13 AM, email@hidden wrote:



So I'm porting a big Linux C++ application that makes heavy use of
plug-ins. I've built all the plugins on OSX as .dylib files and am
linking them in with either -l in the linker or by calling dlopen the
first time each library is used. The application makes heavy use of
the factory pattern, most classes are created by a factory class. When a library is loaded it registers all it's classes automatically
with the factory (usually during the libraries static init phase),
then classes are created by sending requests to the factory.


You didn't mention any problems related to a dynamic library registering
its classes with the factory when its static initializers are invoked,
but you may encounter one. In my experience (using NSAddImage rather
than dlopen which is a new addition), when a dynamic library is
programmatically loaded and not accessed, its static initializers are
not invoked. As a result its classes will not be registered with the
factory. This challenge can be overcome by looking up a symbol exported
from the dynamic library. Simply looking up a symbol (you don't even
need to invoke it) will result in the static initializers being invoked.



Anyway, I am having serious problems getting all of this to load and
run correctly. I am building everything with a modified Makefile (no
Xcode) and using Xcode to debug it. The first problem seems to be
that unless I set DYLD_BIND_AT_LAUNCH my program fails the minute it
trys to call a static method in one of the key libraries. If I do
set the BIND option, it gets a little farther but still does
something disturbing.


The -bind_at_load linker option may be more convenient than setting the
DYLD_BIND_AT_LAUNCH environment variable. However, once your other
static initializer problems are solved, this may not be needed.



With DYLD_BIND_AT_LAUNCH turned OFF, the first time I call a static
method in libapplication, the application immediately freezes up,
even before executing a line of code in libapplication. The debugger
shows me about 120 stack frames deep stuck in a mutex waiting on a
semaphore. The same pattern of calls repeats about 12 times, this
pattern includes calls to:

__dyld_call_module_initializers_for_library
__dyld_call_module_initializers
__dyld_link_in_need_modules
__dyld_bind_lazy_symbol_reference
__dyld_stub_binding_helper_interface

This appears to be doing lazy linking of symbols in the library, but
at some point it just gives up and hangs in the mutex, I'm not sure
why. I do know that initializing the classes in libapplication will
require initializing many classes in the other libraries as well.


I'm aware of a couple of problems related to the Mac OS X dynamic loader
and its handling of static initializers. My experience has been that
these problems result in static initializers not being invoked rather
than hangs, however. The source to dyld is available:
<http://www.opensource.apple.com/darwinsource/>. It is part of the
cctools package.



If I TURN ON the DYLD_BIND_AT_LAUNCH then the program makes it
through the initial startup code, but some of the modules in
libapplication never have their static initialization code called,
preventing them from registering with the object factory so the
program quickly fails because it thinks some of the classes it needs
aren't there. Under linux, when this library is loaded, all the
initialization code for all the classes in the library are
automatically called, under OSX this doesn't seem to happen.


Based on a previous thread on this list (search for "Dynamic Library
Loading and Static Constructors"), my understanding is that the C++
specification doesn't require a static constructor to be invoked until
immediately before that static object is to be accessed.

In my experience, the Mac OS X dynamic loader will invoke all the static
constructors in a module before any function in that module is invoked.
Therefore, if you want all of your static constructors in your dynamic
library to be invoked before any function in your dynamic library is
invoked, you can pass the -single_module option to the linker which will
combine all your modules into one.

You mentioned that initializing classes in one dynamic library will
require initializing classes in other dynamic libraries. If there are
dependencies between static initializers in different dynamic libraries,
you may have problems since the order in which the static initializers
in different dynamic libraries are invoked is not related to the
dependencies between dynamic libraries. If you encounter this problem,
let me know and I can provide some potential hacks to work around this
problem.

geoff
_______________________________________________
darwin-development mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-development
Do not post admin requests to the list. They will be ignored.
_______________________________________________
darwin-development mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-development
Do not post admin requests to the list. They will be ignored.


References: 
 >Re: Continuing Linux Porting issues (From: email@hidden)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.