Check out my first novel, midnight's simulacra!

Working with libraries: Difference between revisions

From dankwiki
m (1 revision)
 
(7 intermediate revisions by the same user not shown)
Line 12: Line 12:
* <tt>-rpath=''path''</tt> (<tt>-R ''directory''</tt> on some linkers; GNU ld supports this) sets the DT_RUNPATH (DT_RPATH without new dtags) dtag, controlling [[rpaths]]
* <tt>-rpath=''path''</tt> (<tt>-R ''directory''</tt> on some linkers; GNU ld supports this) sets the DT_RUNPATH (DT_RPATH without new dtags) dtag, controlling [[rpaths]]
** <tt>--enable-new-dtags</tt> is required to generate DT_RUNPATH or DT_FLAGS dtags specified by newer [[ELF]] systems.
** <tt>--enable-new-dtags</tt> is required to generate DT_RUNPATH or DT_FLAGS dtags specified by newer [[ELF]] systems.
* Set an [[ELF]] entry point via -Wl,-e,<tt>your exported symbol</tt>
** This is how [[glibc|libc6.so]] prints diagnostic information when executed


==Building with libraries==
==Building with libraries==
* If the library supports [http://pkg-config.freedesktop.org pkg-config], and you're willing to depend on that tool being installed, proper compilation flags can be lifted from it:
* If the library supports [[pkg-config]], and you're willing to depend on that tool being installed, proper compilation flags can be lifted from it:
** <tt>pkg-config --cflags ''pkgname''</tt> will pull the preprocessor and compilation flags
** <tt>pkg-config --cflags ''pkgname''</tt> will pull the preprocessor and compilation flags
** <tt>pkg-config --libs ''pkgname''</tt> will pull the linking flags
** <tt>pkg-config --libs ''pkgname''</tt> will pull the linking flags
Line 22: Line 24:
===Environment variables that control ld.so===
===Environment variables that control ld.so===
===Files that control ld.so===
===Files that control ld.so===
* The presence of <tt>/etc/ld.so.nohwcap</tt> precludes use of optimized library versions
===Interpositioning===
* Using the GNU linker, a particular object can wrap a symbol via <tt>-Wl,--wrap,symbolname</tt>. This will result in calls to <tt>symbolname</tt> resolving to <tt>__wrap_symbolname</tt>, and calls to <tt>__real_symbolname</tt> to resolve <tt>symbolname</tt>.
* LD_PRELOAD can force an object to be loaded early in dynamic linking. Export a symbol with the same identifier as the function to be wrapped, and use <tt>dlsym(RTLD_NEXT,symbolname)</tt> to access the wrapped symbol.
** Doing this with no per-call checking, in a thread-safe manner, is left as an exercise for the reader '''FIXME'''
===What the hell is linux-gate.so.1?===
The [[MSR|SYSENTER/SYSEXIT]] instructions of some Pentium processors provides a faster way to switch rings (a callgate, hence the name). [http://www.trilithium.com/johan/2005/08/linux-gate/ This page] explains pretty well what's going on.


==Quality Assurance==
==Quality Assurance==
Line 36: Line 47:
[recombinator](1) $</pre>
[recombinator](1) $</pre>
* ld warn options, especially <tt>--warn-shared-textrel</tt>, <tt>--fatal-warnings</tt>, <tt>--warn-common</tt>, etc
* ld warn options, especially <tt>--warn-shared-textrel</tt>, <tt>--fatal-warnings</tt>, <tt>--warn-common</tt>, etc
* Your libraries oughtn't be installed executable unless they can be meaningfully executed.
** An [[ELF]] object without an entry point, when executed, will coredump
** Either don't set executable bits, or run each installed library and ensure it exits cleanly


==See also==
==See also==

Latest revision as of 08:17, 12 August 2020

Building libraries

gcc issues

  • For predictable results, the same set of options used to generate code (see "Code Gen Options" and "Submodel Options" in the gcc Info pages) must be used to link (see "Link Options" in the gcc Info pages)!
  • -shared should be supplied with the link step to produce a shared object.
  • Regarding -fpic vs -fPIC: -fPIC is only necessary in certain architecture-dependent situations; gcc will let you know if it's needed, and fail out, should you provide -fpic
  • Use -Wl,ldopt to pass options to ld (see below)

ld issues

  • Generally, either the packaging system or build process needs invoke ldconfig with suitable arguments so that the linker cache is updated.
  • The -t option (-Wl,-t as a gcc option) traces input files to ld, and can be useful for debugging, as can -y symbol to trace a given symbol's introduction and use.m
  • soname=name sets the internal DT_SONAME field of an ELF object
  • -fini name and -init name to specify alternative values for the ELF DT_INIT and DT_FINI initialization and finalization fields. By default, _init and _finit are used.
  • -rpath=path (-R directory on some linkers; GNU ld supports this) sets the DT_RUNPATH (DT_RPATH without new dtags) dtag, controlling rpaths
    • --enable-new-dtags is required to generate DT_RUNPATH or DT_FLAGS dtags specified by newer ELF systems.
  • Set an ELF entry point via -Wl,-e,your exported symbol
    • This is how libc6.so prints diagnostic information when executed

Building with libraries

  • If the library supports pkg-config, and you're willing to depend on that tool being installed, proper compilation flags can be lifted from it:
    • pkg-config --cflags pkgname will pull the preprocessor and compilation flags
    • pkg-config --libs pkgname will pull the linking flags
    • pkg-config --list-all lists all libraries registered with pkg-config

Runtime linking

Environment variables that control ld.so

Files that control ld.so

  • The presence of /etc/ld.so.nohwcap precludes use of optimized library versions

Interpositioning

  • Using the GNU linker, a particular object can wrap a symbol via -Wl,--wrap,symbolname. This will result in calls to symbolname resolving to __wrap_symbolname, and calls to __real_symbolname to resolve symbolname.
  • LD_PRELOAD can force an object to be loaded early in dynamic linking. Export a symbol with the same identifier as the function to be wrapped, and use dlsym(RTLD_NEXT,symbolname) to access the wrapped symbol.
    • Doing this with no per-call checking, in a thread-safe manner, is left as an exercise for the reader FIXME

What the hell is linux-gate.so.1?

The SYSENTER/SYSEXIT instructions of some Pentium processors provides a faster way to switch rings (a callgate, hence the name). This page explains pretty well what's going on.

Quality Assurance

  • Use ldd's command line options to check the library.
    • Discover unused direct dependencies with -u -r:
[recombinator](1) $ ldd -u -r /usr/lib/libapr-1.so.0
Unused direct dependencies:
	
	/lib/librt.so.1
	/lib/libcrypt.so.1
[recombinator](1) $ ldd -u -r .out/libdank/libdank.so
Unused direct dependencies:
	
[recombinator](1) $
  • ld warn options, especially --warn-shared-textrel, --fatal-warnings, --warn-common, etc
  • Your libraries oughtn't be installed executable unless they can be meaningfully executed.
    • An ELF object without an entry point, when executed, will coredump
    • Either don't set executable bits, or run each installed library and ensure it exits cleanly

See also