How to use a generated linker map with a shared library?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to use a generated linker map with a shared library?

Paul Smith
I'm really stuck: maybe someone can provide a hint.

I'm trying to create a shared library from a bunch of object files, and
use a linker script to mark almost all the symbols as local.  The tricky
thing is I'm auto-generating the linker script via a shell script that
examines the object files for my library (using readelf) to find global
symbols.

I basically need a process like this:

   1. Start with source files and a linker map generator shell script
   2. Compile all the code into object files
   3. If any file was recompiled (or the generator script) is modified, re-
      run the generator script to recreate the linker script
   4. If any file was recompiled or the linker script was recreated,
      rebuild the shared library, using the linker script.

In "make-ese" it would be trivial: something like:

  libmy.so: $(OBJECTS) link.script ; <link .so> ...

  link.script: $(OBJECTS) genlinkscript ; <generate script> ...

I simply can't figure out how to create something like this in CMake.

I have a custom command to create the linker script:

  add_custom_command(OUTPUT out.script
      COMMAND genlinkscript ${CMAKE_CURRENT_BINARY_DIR}
      DEPENDS <<SOMETHING GOES HERE>>
      VERBATIM)

And I have an add_library command to create the shared library:

  add_library(mylib SHARED foo.cpp foo.h out.script)

  set_property(TARGET mylib APPEND_STRING PROPERTY
        LINK_FLAGS " -Wl,--version-script=out.script")

But what can my custom_command depend on, so that it's run AFTER all the
object files are created, but BEFORE the shared library is created?

I tried to do this using an OBJECT library, but see my previous post
that adding OBJECT libraries as dependencies of custom commands doesn't
work.

What can I do?  I'm happy with a solution that works only on Linux (I
can use if()/endif() to turn it off on my other platforms, which don't
use these linker scripts anyway).
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use a generated linker map with a shared library?

Craig Scott-3
While not directly answering your question, it seems you may be trying to deal with symbol visibility. Are you aware of CMake's symbol visibility features? A good place to start would be the GenerateExportHeader module, the documentation for which does a reasonable job of showing how to use the visibility features CMake provides.

Dealing with your question more directly, you may want to look at the TARGET form of add_custom_command() and in particular, the PRE_LINK keyword. See the Build Events section near the bottom of the page for the add_custom_command() docs.




On Sun, Jan 15, 2017 at 10:46 AM, Paul Smith <[hidden email]> wrote:
I'm really stuck: maybe someone can provide a hint.

I'm trying to create a shared library from a bunch of object files, and
use a linker script to mark almost all the symbols as local.  The tricky
thing is I'm auto-generating the linker script via a shell script that
examines the object files for my library (using readelf) to find global
symbols.

I basically need a process like this:

   1. Start with source files and a linker map generator shell script
   2. Compile all the code into object files
   3. If any file was recompiled (or the generator script) is modified, re-
      run the generator script to recreate the linker script
   4. If any file was recompiled or the linker script was recreated,
      rebuild the shared library, using the linker script.

In "make-ese" it would be trivial: something like:

  libmy.so: $(OBJECTS) link.script ; <link .so> ...

  link.script: $(OBJECTS) genlinkscript ; <generate script> ...

I simply can't figure out how to create something like this in CMake.

I have a custom command to create the linker script:

  add_custom_command(OUTPUT out.script
      COMMAND genlinkscript ${CMAKE_CURRENT_BINARY_DIR}
      DEPENDS <<SOMETHING GOES HERE>>
      VERBATIM)

And I have an add_library command to create the shared library:

  add_library(mylib SHARED foo.cpp foo.h out.script)

  set_property(TARGET mylib APPEND_STRING PROPERTY
        LINK_FLAGS " -Wl,--version-script=out.script")

But what can my custom_command depend on, so that it's run AFTER all the
object files are created, but BEFORE the shared library is created?

I tried to do this using an OBJECT library, but see my previous post
that adding OBJECT libraries as dependencies of custom commands doesn't
work.

What can I do?  I'm happy with a solution that works only on Linux (I
can use if()/endif() to turn it off on my other platforms, which don't
use these linker scripts anyway).
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake



--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use a generated linker map with a shared library?

Paul Smith
On Sun, 2017-01-15 at 12:08 +1100, Craig Scott wrote:
> While not directly answering your question, it seems you may be trying
> to deal with symbol visibility. Are you aware of CMake's symbol
> visibility features? A good place to start would be the
> GenerateExportHeader module, the documentation for which does a
> reasonable job of showing how to use the visibility features CMake
> provides.

Yes, thanks for that info.  My situation is that I need to force ALL
symbols to be private, even those from external static shared libraries
that I'm linking in (whose symbols have global visibility by default).

So I need a linker script that contains (this is for GCC's ld):

  {
      global: ...;
      local: *;
  };

I need the "local: *;" to hide the external symbols, but to keep it from
hiding all my global symbols I need to list them all explicitly in the
global: section.

> Dealing with your question more directly, you may want to look at the
> TARGET form of add_custom_command() and in particular, the PRE_LINK
> keyword. See the Build Events section near the bottom of the page for
> the add_custom_command() docs.

Oh beauty!  That seems to be just what I need.  Thanks!
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use a generated linker map with a shared library?

Clinton Stimpson
In reply to this post by Paul Smith


On Jan 14, 2017 7:16 PM, Paul Smith <[hidden email]> wrote:

On Sun, 2017-01-15 at 12:08 +1100, Craig Scott wrote:
> While not directly answering your question, it seems you may be trying
> to deal with symbol visibility. Are you aware of CMake's symbol
> visibility features? A good place to start would be the
> GenerateExportHeader module, the documentation for which does a
> reasonable job of showing how to use the visibility features CMake
> provides.

Yes, thanks for that info.  My situation is that I need to force ALL
symbols to be private, even those from external static shared libraries
that I'm linking in (whose symbols have global visibility by default).

Have you tried the "--exclude-libs ALL" linker option?  Using that should hide symbols from static libraries.

Clint

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use a generated linker map with a shared library?

Paul Smith
On Mon, 2017-01-16 at 09:07 -0700, [hidden email] wrote:
> > Yes, thanks for that info.  My situation is that I need to force ALL 
> > symbols to be private, even those from external static shared libraries 
> > that I'm linking in (whose symbols have global visibility by default).
>
> Have you tried the "--exclude-libs ALL" linker option?  Using that
> should hide symbols from static libraries.

Yes, I looked at this.  I can't quite figure out what algorithm it uses
though.  It gives me _almost_ the same results as my linker script with
"local: *;", but not quite:

With the linker script if I use:

  nm libfoo.so | grep ' [A-TV-Z] '

I see only and exactly the symbols I marked as global in my code, and
nothing else as global.

If I use --exclude-libs=ALL then I see the symbols I marked as global
and _almost_ all the other symbols are local, but there some
exceptions; for example:

0000000001f925a0 A __bss_start
0000000001f925a0 A _edata
0000000001fc0f4f A _end
000000000098c648 T _fini
000000000015b1b8 T _init

In addition, some C++ templated symbols (very complex) are public as
"W" (global weak symbols).  I don't know why.

I wonder whether _fini and _init need to be exported in order to
properly handle global ctor/dtor when the library is loaded/unloaded?
 Hm.  I may need to do some experimentation here.

I don't see any point in the static data symbols being public.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use a generated linker map with a shared library?

Paul Smith
On Tue, 2017-01-17 at 13:20 -0500, Paul Smith wrote:
> I wonder whether _fini and _init need to be exported in order to
> properly handle global ctor/dtor when the library is loaded/unloaded?
>  Hm.  I may need to do some experimentation here.

FWIW I tried some experimentation with both dynamic linking and
dlopen()/dlclose() methods of loading the shared library, and all my
global ctors and dtors appeared to be invoked as expected in both
situations regardless of whether the _fini and _init symbols were
public...

So I dunno.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Loading...