> On Mon, Dec 5, 2011 at 1:40 AM, Tom Gall <tom.g...@linaro.org> wrote:
> > I probably know the answer to this already but ...
> >
> > For shared libs one can define and use something like:
> >
> > void __attribute__ ((constructor)) my_init(void);
> > void __attribute__ ((destructor)) my_fini(void);
> >
> > Which of course allows your lib to run code just after the library is
> > loaded and just before the library is going to be unloaded. This helps
> > keep out cruft such as the following out of your design:
> >
> > PleaseCallThisLibraryFunctionFirstOrThereWillBeAnErrorWhichYouWillHitCausingYouToPostToTheMailingListAskingTheSameQuestionThatHasBeenAsked1000sOfTimes();
> >
> > Yeah .. you know the function. I don't like it either.
> >
> > Unfortunately this doesn't work when people link in the .a from your
> > lib. Libs like libjpeg-turbo in theory should never ever need to be
> > linked in that fashion but consider the browsers who link to the
> > universe instead of using system shared libs.

On Mon, Dec 05, 2011 at 04:19:11PM +0800, Kito Cheng wrote:
> Here is some triky way for this problem, you can put the constructor
> and destructor to the source file which contain necessary function
> call in your libraries to enforce the linker to archive your
> constructor and destructor.
> 
> However if this solution is not work for your situation, you can apply
> the patch in attach for build script to enable the
> LOCAL_WHOLE_STATIC_LIBRARIES for executable,
> 
> After patch you can just add a line in your Android.mk :
> 
> LOCAL_WHOLE_STATIC_LIBRARIES += libfoo
> 
> The most disadvantage of this way is you should always link libfoo by
> LOCAL_WHOLE_STATIC_LIBRARIES...and this patch don't send to linaro and
> aosp yet.

[...]

Part of the problem here is that .a libraries lack the dependency and
linkage metadata that shared libraries have.

-2)

Put up with the need to call an explicit initialisation function
for the library.  A lot of commonly-used libraries require an
initialisation call, and I'm not sure it causes that much of a
problem in practice...

-1)

Put a C++ wrapper around just enough of your library such that your
constructor/destructor code is recognised as a needed static
constructor/descructor by the toolchain.

I can't think of a very nice way of doing this, so I won't elaborate
on it...  

It's also not really a solution, since you still need to pull in a
dummy static object from somewhere in order to cause the construcor
and descructor to get called.

0)

libtool or similar may help solve this problem, but I don't know much
about this -- also, for solving the problem, that approach only works
if uses of your library link via libtool.

1)

One hacky approach is to rename your library to libmylib-real.a, and
then make replace libmylib.a with a linker script which pulls in the
needed constructor as well as the real library:

libmylib.a:
        EXTERN(__mylib_constructor)
        INPUT(/path/to/libmylib-real.a)

This works, providing that __mylib_constructor is external (normally,
you would be able have the constructor function static, but it needs
to be externally visible in order to be pulled in in this way.

2)

Another way of doing a similar thing is to mark __mylib_constructor
as undefined in all the objects that make up the library.

Unfortunately, there seems to be no obvious way of doing that: the
assembler generates undefined symbol references automatically for
unresolved references at assembly time.  There's no way for force
the existence of an undefined symbol without an actual reference to
it.  objcopy/elfedit don't seem to support adding such a symbol
either.  It would be simple to write a tool to add the undefined
symbol reference (such tools may exist already), but binutils doesn't
seem to provide this for you.  The plausible-looking -u option to
gcc doesn't do anything unless doing a link.

One other way of doing it without a special tool is to insert a bogus
relocation into the text section of each object with an assembler
.reloc directive specifying relocation type R_<arch>_NONE.

There isn't really a portable way to do that, though.  The name of
the relocation changes per-arch, and some arches have other quirks
(on ARM for example, .reloc cannot refer to the current location,
but seems instead to need to refer to a defined symbol which is non-zero
distance away from the location counter).


One advantage to this approach is that your .a file looks just
like any other .a file.  Also, you can include that dependency
in only those objects which really require the library to be
initialised (normally, this is not a huge benefit though, since
probably most of your objects _do_ require the library to be
initialised).

A disadvantage (other than portability problems) is that, like (1),
the constructor symbol must be external (not static)... so it
pollutes the symbol table and isn't protected against people calling
it directly.

You can create a dummy symbol instead of referring to the constructor
symbol directly though -- this solves the second problem.

3)

Finally, you can split your contructor/destructor code out into a
separate .o file (say mylib-ctors.o), and use the linker script
trick for (1) to forcibly include this object when linking:

libmylib.a:
        INPUT(/path/to/mylib-ctors.o /path/to/mylib-real.a)

This avoids some of the disadvantages of the other approaches,
but you still end up with a strange-looking library which is really
a linker script.

This is closer to how the C library traditionally solves the problem
(i.e., the crt*.o stuff).  libc.so also tends to be a linker script,
which deals with the fact that some parts of libc must be statically
linked from a separate library when linking to -lc.


Obviously, approaches (1)..(3) all suffer from arch or toolchain
portability problems (or both).  (The GNU/GCC __constructor__ thing
is obviously a portability problem in itself, it you're minded to
care about it.)

Cheers
---Dave

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to