From patchwork Thu Oct 12 21:56:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ben Woodard X-Patchwork-Id: 825120 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-85770-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="Wj3yuc7r"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yCl8448cYz9sCZ for ; Fri, 13 Oct 2017 08:57:40 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id :mime-version:content-type:content-transfer-encoding; q=dns; s= default; b=Ip8fx9mw/UoVm9hgtOux1zjWZuZN1VygzmIZ4qFKB4uErqjq0gFGG 0RXeebDyNMm02WdzUvcAGE7n3chmV2JVThe8khjy/lDHeM0IuFoMu9T0TptHguN5 +vtHqAI7tbJfzZfJBsO33EtM5oeghVicHed4JURGw3Eu99vbP/ODGw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id :mime-version:content-type:content-transfer-encoding; s=default; bh=ZKvszyUhZiUzWxfY2aydYB/fmks=; b=Wj3yuc7r3tMymvZYmvj2TgJzyjCY T4M79jv2LBNnL94izk7Spax5rKdRoHeVlQVL45tfmP6exgdZVPnJqBWoDF1DmFuT o/zrHfN4lWY2uaqtDNgmJde6kjoDQarai6B91YFYKZiXAqFB8c1K/XkJkKVgisG3 PpuMByE01e7Qzks= Received: (qmail 12823 invoked by alias); 12 Oct 2017 21:57:31 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 9803 invoked by uid 89); 12 Oct 2017 21:57:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-22.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, URIBL_RED autolearn=ham version=3.3.2 spammy=resident, associates, Environmental, accordance X-HELO: mail-qk0-f169.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bce3QFswDsspynAspQ5MZ/ch0WawtEAUJ7xzwH8C2x8=; b=bRkR+94FhA1K1VDkxIKdHgDaoNJ/P0zpOy+KnqtqyltJ2r3Sm/j735gUnYnZMep1Ny bK1wUDjD1fc/KKDy9qiIcGmGuCRi5S65z0YDC8f+pMWfLMz3vp/QQuOpynqw1eEBZQyv meGQSbZP+4Xfz2BoHdtv3uFC5Hp5CEFi2tIICOrou1XugT2wjFjkjZqejvHK8DxjV4cv JU4ecn1onhjsXqpXAOS1TdRlldMeqxBkOs8IPxK5dhzJ4wYNR82IV2sPJZguitp083DN xsnJWBZMi6fi6KMBt/B8oVq3C9WTllP8FDsKgpRJJmjdi1LN4kFYmxZXAnK0LgEfwgLz b5Rg== X-Gm-Message-State: AMCzsaWTxr3RwOsL5DQtvEivn5DmOx4MPbi4RZ1W7CdbW127AgWs1vDl d1M87Ty8XIgcB2d755jClkzv1w== X-Google-Smtp-Source: ABhQp+QcVYbsh0eoJP6mc1Z6OqAO1LAoEunTX76I7tgIM3bbqO2PpqcT/08JDn0cETuX8SscsPkg/w== X-Received: by 10.55.155.79 with SMTP id d76mr2416402qke.288.1507845438952; Thu, 12 Oct 2017 14:57:18 -0700 (PDT) From: Ben Woodard To: libc-alpha@sourceware.org Cc: codonell@redhat.com, fwiemer@redhat.com, ricaljasan@pacific.net, Ben Woodard Subject: [PATCH] Resend: Add a new chapter on the dynamic linker Date: Thu, 12 Oct 2017 14:56:58 -0700 Message-Id: <20171012215658.8524-1-woodard@redhat.com> MIME-Version: 1.0 Add a new chapter covering dynamic linking to the glibc manual. Remove previous placeholder documents. Can we restart the review process on this with the intent of this getting merged. It has been through review once and all concerns were addressed however this patch was never merged. --- ChangeLog | 4 + manual/Makefile | 2 +- manual/dynamic.texi | 1191 +++++++++++++++++++++++++++++++++++++++++++++++++++ manual/libdl.texi | 10 - manual/signal.texi | 2 +- 5 files changed, 1197 insertions(+), 12 deletions(-) create mode 100644 manual/dynamic.texi delete mode 100644 manual/libdl.texi diff --git a/ChangeLog b/ChangeLog index e8f8382a5c..ce74b76d33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6109,6 +6109,10 @@ * socket/opensock.c (__opensock): Likewise. * sysdeps/unix/sysv/linux/opensock.c (__opensock): Likewise. +2017-08-16 Ben Woodard + * manual/Makefile (chapters): Add dynamic chapter. + * manual/dynamic.texi: New file + 2017-08-16 Joseph Myers [BZ #21944] diff --git a/manual/Makefile b/manual/Makefile index 3b4c7c934a..3f6b486978 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -39,7 +39,7 @@ chapters = $(addsuffix .texi, \ pipe socket terminal syslog math arith time \ resource setjmp signal startup process ipc job \ nss users sysinfo conf crypt debug threads \ - probes tunables) + probes dynamic tunables) appendices = lang.texi header.texi install.texi maint.texi platform.texi \ contrib.texi licenses = freemanuals.texi lgpl-2.1.texi fdl-1.3.texi diff --git a/manual/dynamic.texi b/manual/dynamic.texi new file mode 100644 index 0000000000..6207225c5e --- /dev/null +++ b/manual/dynamic.texi @@ -0,0 +1,1191 @@ +@node Dynamic Linking, Program Basics, Signal Handling, Top +@c %MENU% Loading libraries, finding functions, and other symbols +@chapter Dynamic Linker + +On every operating system currently supported by @theglibc{}, the +operating system provides a facility for run time dynamic +linking. This facility is implemented by @theglibc{}'s dynamic linker. +This benefits the operating system by allowing the resident RAM used +by libraries to be shared between processes. Runtime dynamic linking +also enhances the security and maintainability of the operating +system. As long as the ABI, application binary interface, is +maintained through proper library versioning, a new version of a +library can be installed on a system to fix bugs or resolve a security +issue without the need to recompile all the applications which make +use of that library. + +Because run time linking is so intimately involved with the lauching +of almost every program, it exists at the interface between the +operating system kernel and the system libraries. Thus configuration +and administration of the run time dynamic linker is operating system +specific. Individuals who are interested in this topic are encouraged +to look at the operating system documentation. +@c which is often found in +@c the @cite{ld.so(8)} and the @cite{ldconfig(8)} man pages. +@c pindex ld.so +@c pindex ldconfig + +The same run time dynamic linking capability which allows applications +to be loaded along with their libraries at initial execution time has +also been made available to application programmers through a group of +run time dynamic linker function explained below. This facility is +often used for plugins to add optional or extended features to an +application without introducing library dependencies. + +The run time dynamic linker also provides several mechanisms which +allow the system administrator or user to modify its operation when +running an application. Many of the tools to modify glibc's run time +linker's operation are environmental variables. However, if more +sophisticated manipulation of the process of run time linking and +symbol resolution is needed, the dynamic has a kind of plugin +called an audit library. + +@menu +* Concepts of Dynamic Linking:: Introduction to dynamic linking. +* Environmental Variables:: Variables that can be used affect the operation + of dynamic linker. +* Dynamic Linker API Functions:: Functions to load libraries, find functions + and other symbols. +* Audit Interface:: Monitor or intercede in the operation of the dynamic linker +@end menu + +@node Concepts of Dynamic Linking +@section Concepts of Dynamic linking + +When you compile a file and are left with an object file that is +called a compilation unit. At the time that it is compiled, the +compiler can see all the variables and functions that are within the +file and it can fill in references to those function and +variables. Many times there are functions or variables that exist +outside of a particular compilation unit. If you link object files +then the linker is able to find the location of referenced symbols or +functions in other compilation unit's object files, insert them into +the resulting executable, and bind the references to them. + +Libraries are a special kind object file which include the partially +linked aggregation of many compilation unit's object files. You can +link with a library one of two ways. Linking with a library statically +is the old original way of linking. This is no different than linking +with any other object file. Linking statically is not recommended in +almost all cases. The second way of linking is dynamically linking +with the library. In this case, the linker makes sure that all the +functions and symbols referred to by your program can be found in the +libraries that you are linking with but instead of copying the +function or variable over into the resulting executable, it stores a +reference to the library in the executable's header and replaces the +references to the function with calls to stub functions that will make +sure that the needed library is loaded into memory and then will +ultimately call the required function. Variables that exist in +libraries are handled similarly through a level of indirection. + +@menu +* Finding a Library:: The process of resolving the location of a library +* Finding a Symbol:: The process of resolving symbols within libraries +* Binding a Variable:: How the GOT is used to bind a variable in a library +* Binding a Function:: How the PLT is used to bind functions from libraries +* Linkage Tables:: Using non-global linking to avoid potential symbol conflicts +@end menu + +@node Finding a Library +@subsection Finding a Library +@cindex Finding a Library, Dynamic Linking +Binaries that are not linked statically require the dynamic linker to +load the libraries into the process's address space before beginning +to run the executable. The shared libraries needed by am executable or +a library are stored in dynamic section of the ELF header. The list of +the libraries needed can be quickly enumerated with the +@command{readelf} command. +@pindex readelf + +@cindex NEEDED, dynamic linking +@cindex DT_NEEDED +@example +$ readelf -d /usr/bin/ls | grep NEEDED +0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1] +0x0000000000000001 (NEEDED) Shared library: [libcap.so.2] +0x0000000000000001 (NEEDED) Shared library: [libacl.so.1] +0x0000000000000001 (NEEDED) Shared library: [libc.so.6] +$ readelf -d /lib64/libselinux.so.1 | grep NEEDED +0x0000000000000001 (NEEDED) Shared library: [libpcre.so.1] +0x0000000000000001 (NEEDED) Shared library: [liblzma.so.5] +0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] +0x0000000000000001 (NEEDED) Shared library: [libc.so.6] +0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2] +@end example + +The full set libraries needed by an executable or a library and all of +its dependencies and where they are currently being found can be +enumerated with the @command{ldd} command. +@pindex ldd + +@example +$ ldd /usr/bin/ls +linux-vdso.so.1 => (0x00007fff3e5e9000) +libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f0e913ce000) +libcap.so.2 => /lib64/libcap.so.2 (0x00007f0e911c9000) +libacl.so.1 => /lib64/libacl.so.1 (0x00007f0e90fbf000) +libc.so.6 => /lib64/libc.so.6 (0x00007f0e90c02000) +libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f0e90995000) +liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f0e9076f000) +libdl.so.2 => /lib64/libdl.so.2 (0x00007f0e9056b000) +/lib64/ld-linux-x86-64.so.2 (0x00007f0e9160b000) +libattr.so.1 => /lib64/libattr.so.1 (0x00007f0e90366000) +libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f0e90149000) +@end example + +@pindex ldd +To make the association between between the library listed as needed +in the ELF dynamic section and where they are located as shown by the +@command{ldd} command, the run time linker has to look in several +places. This process is known as object search. A library can audit or +interpose itself into this process of locating a library by +implementing the the @code{la_objsearch()} function. +@findex la_objsearch + +If a library listed as NEEDED includes a slash in its name, then it is +assumed to be either an absolute or relative pathname as is often the +case when a library is specified on the command line. When a pathname +is found as the target of the NEEDED section it is resolved as such. + +@vindex LD_LIBRARY_PATH +@cindex RPATH +@cindex DT_RPATH +Sometimes a library's location will be explicitly referenced using a +deprecated feature called a RPATH. Specifying the location of a +library using RPATHs is not recommended for a variety of reasons +including the fact that it its extremely high precedence makes it +impossible for system administrators to point at other locations using +things like @env{LD_LIBRARY_PATH} and the inability to edit the RPATHs +because limited space in the ELF header for the pathname prevents +changing it to something suitable for file hierarchy appropriate to +that system. Any RPATHs found in a binary or a library can found using +the readelf command as follows. + +@pindex readelf +@example +$ readelf -d /usr/bin/apropos | grep RPATH +0x000000000000000f (RPATH) Library rpath: [/usr/lib64/man-db] +@end example + +@vindex LD_LIBRARY_PATH +The first place that the run time linker looks for a NEEDED library +after following RPATHs is in any directory found in the colon +separated list of directories found in the @env{LD_LIBRARY_PATH} +environmental variable. This list of directories is searched first to +facilitate replacing libraries found elsewhere in the search +path. This is particularly useful when debugging problems but +extensive use of @env{LD_LIBRARY_PATH} is not recommended because it +bypasses the caching of where to find libraries which is done later in +the object search process. This caching greatly improves the +performance of object search by avoiding the necessity to enumerate +the contents of every directory containing libraries configured into +the system. Thus extensive use of @env{LD_LIBRARY_PATH} could have +substantial negative performance implications. + +@cindex RUNPATH +@cindex DT_RUNPATH +After processing @env{LD_LIBRARY_PATH}, an ELF directive similar to RPATH +called RUNPATH is searched. This ELF directive is what libtool and +other compile time linkers insert when linking with libraries in +unusual directories specified on the link command line. Any RUNPATHs +found in an ELF executable or library can be listed by printing the +dynamic section of the ELF header. + +@pindex readelf +@example +$ readelf -d /usr/bin/tracker-control | grep RUNPATH +0x000000000000001d (RUNPATH) Library runpath: [/usr/lib64/tracker-1.0] +@end example + +Very occasionally RPATH and RUNPATH may include some macros that will +be expanded before objects search is performed in the directories +specified. Users are encouraged to look at the linux ld.so man page +for more details. + +@pindex ldconfig +@cindex ld.so.cache +@vindex LD_LIBRARY_PATH +While RPATH and RUNPATH ELF entries are quite rare and while use of +@env{LD_LIBRARY_PATH} is well known its use is uncommon, the normal +behavior of the run time linker starts out looking in the +@file{/etc/ld.so.cache} which is created when @command{ldconfig} is +run. + +@pindex ldconfig +@cindex ld.so.conf +@command{ldconfig} will cache the location of the libraries in the trusted +library directories (@file{/lib} and @file{/usr/lib} and also +@file{/lib64} and @file{/usr/lib64} on 64bit systems). The operating +system provider or the local sysadmin may also include additional +directories that the linker should search for libraries. These are +specified in @file{/etc/ld.so.conf} but before they are searched, this +configuration file must be compiled into @file{ld.so.cache} by the +@command{ldconfig} command. + +@node Finding a Symbol +@subsection Finding a Symbol +When two objects are linked dynamically, the location of symbols which +are referenced in one object file which exist an an other object file +cannot be resolved until run time. This is because the location within +a process's address space where a library will be loaded is +intentionally slightly non-deterministic to make hacking more +difficult and because different applications can load the same object +file in different locations. This is why libraries must be compiled as +position independent code. These unresolved symbols are known as +relocations. You can use the @command{readelf} command to list the +relocations needing to be satisfied within an object file. + +@example +$ readelf --relocs /usr/bin/ls + +Relocation section '.rela.dyn' at offset 0x1688 contains 9 entries: + Offset Info Type Sym. Value Sym. Name + Addend +00000061af88 000800000006 R_X86_64_GLOB_DAT 0000000000000000 free + 0 +00000061af90 000f00000006 R_X86_64_GLOB_DAT 0000000000000000 stdout + 0 +00000061af98 001d00000006 R_X86_64_GLOB_DAT 0000000000000000 optind + 0 +00000061afa0 004500000006 R_X86_64_GLOB_DAT 0000000000000000 optarg + 0 +[...] + +Relocation section '.rela.plt' at offset 0x1760 contains 115 entries: + Offset Info Type Sym. Value Sym. Name + Addend +00000061b018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 __ctype_toupper_loc + 0 +00000061b020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __uflow + 0 +00000061b028 000300000007 R_X86_64_JUMP_SLO 0000000000000000 getenv + 0 +00000061b030 000400000007 R_X86_64_JUMP_SLO 0000000000000000 cap_to_text + 0 +00000061b038 000600000007 R_X86_64_JUMP_SLO 0000000000000000 sigprocmask + 0 +00000061b040 000700000007 R_X86_64_JUMP_SLO 0000000000000000 raise + 0 +00000061b048 000800000007 R_X86_64_JUMP_SLO 0000000000000000 free + 0 +[...] +@end example + +The dynamic linker's job is to find the required symbol in the shared +libraries. The symbols available within an object file can be +enumerated with the @command{readelf --dyn-sym} command. + +@example +$ readelf --dyn-syms /usr/lib64/libc.so.6 | grep -v " _" + +Symbol table '.dynsym' contains 2224 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 000000000001f4f0 0 SECTION LOCAL DEFAULT 12 + 2: 00000000003b3568 0 SECTION LOCAL DEFAULT 22 + 10: 00000000000717c0 348 FUNC GLOBAL DEFAULT 12 putwchar@@GLIBC_2.2.5 + 14: 0000000000115d70 192 FUNC GLOBAL DEFAULT 12 setrpcent@@GLIBC_2.2.5 + 17: 0000000000100770 33 FUNC GLOBAL DEFAULT 12 epoll_create@@GLIBC_2.3.2 + 18: 00000000000e42b0 33 FUNC WEAK DEFAULT 12 sched_get_priority_min@@GLIBC_2.2.5 + 20: 0000000000100980 33 FUNC GLOBAL DEFAULT 12 klogctl@@GLIBC_2.2.5 + 22: 0000000000053920 143 FUNC GLOBAL DEFAULT 12 dprintf@@GLIBC_2.2.5 + [...] +@end example + +All of the relocations needed by the executable and all its libraries +will be satisfied by the objects loaded. For example two of the +symbols needed by the @command{ls} can be found in the +@file{/usr/lib64/libc.so.6} library. + +@example +$ readelf --relocs /usr/bin/ls | egrep stdout\|opendir +00000061af90 000f00000006 R_X86_64_GLOB_DAT 0000000000000000 stdout + 0 +00000061b0e0 001e00000007 R_X86_64_JUMP_SLO 0000000000000000 opendir + 0 +$ readelf --dyn-syms /usr/lib64/libc.so.6 | egrep " stdout| opendir" + 1036: 00000000003b88e8 8 OBJECT GLOBAL DEFAULT 32 stdout@@GLIBC_2.2.5 + 1270: 00000000000c0350 13 FUNC WEAK DEFAULT 12 opendir@@GLIBC_2.2.5 +@end example + +After the symbol is found in the object file, the reference to the +symbol must be patched so that the code can referring to it can make +use of it. This is known as binding a symbol. + +@node Binding a Variable +@subsection Binding a Variable +Binding a variable is the process of patching the location of a symbol +in the processes current address space into the code which refers to +it. There might be hundreds if not thousands of uses of a particular +variabletherefore patching in the location into every one of those +uses would increase the amount of time spent in the dynamic linker +before main was started. Also patching the actual destination memory +address into the code of the object that refers to it would change the +in memory version of that object so that it could no longer be shared +with all the other processes using that object. The solution to these +two problems is to have indirect references to the external variables +and to place tables of these indirect references in a region of memory +not shared by users of that object. This indirection can be easily +seen when looking at the assembly code for a simple function. In this +case x86_64 is used but a similar mechanism is used for most +architectures. + +@example +$ cat test.c +extern int foo; + +int function(void) @{ + return foo; +@} +$ gcc -shared -fPIC -g -o libtest.so test.c +$ gdb libtest.so -q -ex "disassemble function" -ex quit +Reading symbols from libtest.so...done. +Dump of assembler code for function function: + 0x00000000000006d0 <+0>: push %rbp + 0x00000000000006d1 <+1>: mov %rsp,%rbp + 0x00000000000006d4 <+4>: mov 0x200905(%rip),%rax # 0x200fe0 + 0x00000000000006db <+11>: mov (%rax),%eax + 0x00000000000006dd <+13>: pop %rbp + 0x00000000000006de <+14>: retq +End of assembler dump. +$ readelf --relocs libtest.so | egrep dyn\|Type\|foo +Relocation section '.rela.dyn' at offset 0x470 contains 9 entries: + Offset Info Type Sym. Value Sym. Name + Addend +000000200fe0 000400000006 R_X86_64_GLOB_DAT 0000000000000000 foo + 0 +$ readelf --sections libtest.so | egrep -A1 Nr\|20\]\|Key\|order + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align +-- + [20] .got PROGBITS 0000000000200fd0 00000fd0 + 0000000000000030 0000000000000008 WA 0 0 8 +-- +Key to Flags: + W (write), A (alloc), X (execute), M (merge), S (strings), l (large) + I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) + O (extra OS processing required) o (OS specific), p (processor specific) +@end example + +The address of the variable foo is located at the address 0x200905 +past the current instruction pointer. GDB nicely computes this for you +to be 0x200fe0. This matches the address of the location in the +relocation section. When you find that address in the list of sections +within the ELF file you find that it is in a section called the +``GOT'' which stands for the global offset table. We can see from the +flags that this region is both wriable and dynamically allocated. At +run time it is allocated and then then the dynamic linker inserts the +location of foo into 0x200fe0. This is the process known as binding a +symbol. + +@node Binding a Function +@subsection Binding a Function + +@cindex procedure linkage table +@cindex PLT +Binding a function is very similar to binding a variable except there +are a couple of other features and requirements that add a little bit +of additional complexity. Some of the additional complexity is due to +the need to make function calls between position independent code +which needs to be in read only memory. A couple of other important +features are lazy binding and the ability to audit function calls +between objects. + +Like variable relocations, the requirement to have references in read +only memory so executable sections can be shared necessitates the use +of indirection. A simple approach would be to put the address to the +function in the GOT. However, another layer of indirection is needed +to support lazy binding of functions. + +The way this is accomplished is through another section of read-only +executable code called the Procedure Linkage Table, or PLT. The +executing code calls a tiny bit of stub code in the PLT. This stub +code jumps to the location of an associated entry in the GOT. This is +not a call, this is a jump and so returning the function's return +value and call stack is not disturbed. + +@example +$ cat test.c +int foo(void); + +int function(void) @{ + return foo(); +@} +$ gcc -shared -fPIC -o libtest.so test.c +$ gdb libtest.so -q -ex "disassemble function" -ex quit +Reading symbols from libtest.so...done. +Dump of assembler code for function function: + 0x00000000000006e0 <+0>: push %rbp + 0x00000000000006e1 <+1>: mov %rsp,%rbp + 0x00000000000006e4 <+4>: callq 0x5c0 + 0x00000000000006e9 <+9>: pop %rbp + 0x00000000000006ea <+10>: retq +End of assembler dump. +$ gdb libtest.so -q -ex "disassemble 0x5c0" -ex quit +Reading symbols from libtest.so...done. +Dump of assembler code for function foo@@plt: + 0x00000000000005c0 <+0>: jmpq *0x200a5a(%rip) # 0x201020 + [...] +End of assembler dump. +$ readelf --relocs libtest.so +[...] +Relocation section '.rela.plt' at offset 0x530 contains 3 entries: + Offset Info Type Sym. Value Sym. Name + Addend +[...] +000000201020 000400000007 R_X86_64_JUMP_SLO 0000000000000000 foo + 0 +[...] +@end example + +After a function is bound, the entry in the GOT pointed to by the PLT +stub code will contain the address of the function in the process's +address space. Before the function is bound, usually at the time when +the object is loaded, the dynamic later inserts value in the GOT that +enables lazy binding and auditing. This value and the mechanism by +which these stub functions work is explained below. + +@cindex Lazy Binding +@cindex Binding, Lazy +When the dynamic linker loads an object, it doesn't take the time to +process all the relocations for functions. Instead it preloads the +entries for each function in the GOT with the value of the instruction +immediately after the jump made from the PLT's stub function. + +Continuing with our example from above: + +@example +$ gdb libtest.so -q -ex "disassemble 0x5c0" -ex "x 0x201020" -ex quit +Reading symbols from libtest.so...done. +Dump of assembler code for function foo@@plt: + 0x00000000000005c0 <+0>: jmpq *0x200a5a(%rip) # 0x201020 + 0x00000000000005c6 <+6>: pushq $0x1 + 0x00000000000005cb <+11>: jmpq 0x5a0 +End of assembler dump. +0x201020 : 0x000005c6 +@end example + +So in this case the address 0x201020 from the current instruction +would be initially set to the address of the pushq instruction found +at the offset of 0x5c6. + +The push stores the function within the object on the stack. Then it +jumps to 0x5a0 which is a special entry in the PLT called PLT0. It +pushes the offset of the library onto the stack and then jumps to a +resolver function which is in part of the dynamic linker. At the end +of the resolution function, if the library is not being profiled or +audited then, the resolver function will store the location of the +function in the GOT. + +@example +$ gdb libtest.so --quiet -ex "disassemble 0x5a0, 0x5ac" -ex quit +Reading symbols from libtest.so...done. +Dump of assembler code from 0x5a0 to 0x5ac: + 0x00000000000005a0: pushq 0x200a62(%rip) # 0x201008 + 0x00000000000005a6: jmpq *0x200a64(%rip) # 0x201010 +End of assembler dump. +@end example + +While calling into some static stub code which does an indirect jump +to a function pointer from the GOT is straight forward enough, this +trick of preloading the GOT entries for a function with the +instruction immediately after the indirect jump to the very next +instruction after the indirect jump can be confusing at first. The +trick to understanding it is realizing that after the function is +bound, the code after that indirect jump is never reached. + +@node Linkage Tables +@subsection Linkage Tables +@findex dlopen +@findex dlmopen +Linkage tables are lists of the objects that the dynamic linker has +loaded into the process's address space. They are defined in +@file{} and made up of the @code{link_map} structure. The +executable, the libraries that it needs to run, and any object files +that it opens with @code{dlopen} will be linked together in a doubly +linked list in a base link map. However, a process which opens objects +using @code{dlmopen} will have other link maps as well. + +These @code{link_map} structures should be considered read only and +should not be modified. In addition to the the @code{l_next} and +@code{l_prev} pointers connecting the list, each @code{link_map} +structure has the @code{l_name} which is the name of the object +represented by this structure. In most cases, this value is filled in, +however the name of the executable object being run is not set because +it is loaded before the dynamic linker object @code{ld_linux} is +loaded. Each @code{link_map} structure also has a @code{l_addr} which +provides the difference between the address in ELF file and the +address of the object in memory. This can be used to associate the +location in the object file with the associated location in +memory. Finally, they also have a @code{l_ld} pointer which points to +the object file's ELF dynamic section. The contents of the ELF dynamic +section can be viewed using the @command{readelf} command. + +@example +$ readelf -d /usr/bin/ls + +Dynamic section at offset 0x1ad88 contains 27 entries: + Tag Type Name/Value + 0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1] + 0x0000000000000001 (NEEDED) Shared library: [libcap.so.2] + 0x0000000000000001 (NEEDED) Shared library: [libacl.so.1] + 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] + 0x000000000000000c (INIT) 0x402228 + 0x000000000000000d (FINI) 0x412bfc + 0x0000000000000019 (INIT_ARRAY) 0x61a290 + 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) + 0x000000000000001a (FINI_ARRAY) 0x61a298 + 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) + 0x000000006ffffef5 (GNU_HASH) 0x400298 + 0x0000000000000005 (STRTAB) 0x400f30 + 0x0000000000000006 (SYMTAB) 0x4002d0 + 0x000000000000000a (STRSZ) 1468 (bytes) + 0x000000000000000b (SYMENT) 24 (bytes) + 0x0000000000000015 (DEBUG) 0x0 + 0x0000000000000003 (PLTGOT) 0x61b000 + 0x0000000000000002 (PLTRELSZ) 2760 (bytes) + 0x0000000000000014 (PLTREL) RELA + 0x0000000000000017 (JMPREL) 0x401760 + 0x0000000000000007 (RELA) 0x401688 + 0x0000000000000008 (RELASZ) 216 (bytes) + 0x0000000000000009 (RELAENT) 24 (bytes) + 0x000000006ffffffe (VERNEED) 0x4015f8 + 0x000000006fffffff (VERNEEDNUM) 2 + 0x000000006ffffff0 (VERSYM) 0x4014ec + 0x0000000000000000 (NULL) 0x0 +@end example + +For further information regarding the dynamic section the @cite{Executable and Linkable Format (ELF)} standard. + +@node Environmental Variables +@section Environmental Variables +@c TODO: currently nothing here + +@env{LD_LIBRARY_PATH} +@vindex LD_LIBRARY_PATH +@c TODO + +@env{LD_PRELOAD} +@vindex LD_PRELOAD +@c TODO + +@env{LD_DEBUG} +@vindex LD_DEBUG +@c TODO + +@env{LD_DEBUG_OUTPUT} +@vindex LD_DEBUG_OUTPUT +@c TODO + +@env{LD_PROFILE} +@vindex LD_PROFILE +@c TODO + +@env{LD_PROFILE_OUTPUT} +@vindex LD_PROFILE_OUTPUT +@c TODO + +@env{LD_HWCAP} +@vindex LD_HWCAP +@c TODO + +@env{LD_AUDIT} +@vindex LD_AUDIT +@c TODO + +@env{LD_ASSUME_KERNEL} +@vindex LD_ASSUME_KERNEL +@c TODO + +@env{LD_BIND_NOW} +@vindex LD_BIND_NOW +@c TODO + +@env{LD_BIND_NOT} +@vindex LD_BIND_NOT +@c TODO + +@env{LD_TRACE_LOADED_OBJECTS} +@vindex LD_TRACE_LOADED_OBJECTS +@c TODO + +@env{LD_TRACE_PRELINKING} +@vindex LD_TRACE_PRELINKING +@c TODO + +@env{LD_SHOW_AUXV} +@vindex LD_SHOW_AUXV +@c TODO + +@env{LD_USE_LOAD_BIAS} +@vindex LD_USE_LOAD_BIAS +@c TODO + +@env{LD_WARN} +@vindex LD_WARN +@c TODO + +@env{LD_VERBOSE} +@vindex LD_VERBOSE +@c TODO + +@env{LDD_ARGV0g} +@vindex LDD_ARGV0g +@c TODO + +@node Dynamic Linker API Functions +@section Dynamic Linker API Functions +@cindex Dynamic Linker API Functions +@Theglibc in conjunction with the underlying operating system provides +several functions which can be called from applications to load +linkable objects, most frequently libraries and plugins, and find the +addresses of symbols within them so that they can subsequently be +called through a function pointer. These functions are well documented +in their associated man pages. + +These functions are all defined in @file{} and exist in the +@file{libdl} library. + +@findex dlopen +@deftypefun void *dlopen(const char *@var{filename}, int @var{flag}) +@safety{@prelim{}@mtsafe{}@asunsafe{}@acunsafe{}} +@c TODO +@end deftypefun + +@findex dlmopen +@deftypefun void *dlmopen(Lmid_t @var{lmid}, const char *@var{filename}, int @var{flag}) +@safety{@prelim{}@mtsafe{}@asunsafe{}@acunsafe{}} +@c TODO - there isn't even a man page for this +@end deftypefun + +@findex dlerror +@deftypefun char *dlerror() +@safety{@prelim{}@mtsafe{}@asunsafe{}@acunsafe{}} +@c TODO +@end deftypefun + +@findex dlsym +@deftypefun void *dlsym(void *@var{handle}, const char @var{*symbol}) +@safety{@prelim{}@mtsafe{}@asunsafe{}@acunsafe{}} +@c TODO +@end deftypefun + +@findex dlclose +@deftypefun int dlclose(void *@var{handle}) +@safety{@prelim{}@mtsafe{}@asunsafe{}@acunsafe{}} +@c TODO +@end deftypefun +@node Audit Interface +@section Audit Interface +@cindex rtld-audit +@cindex Audit, dynamic linking + +The dynamic linker provides an interface to monitor and intercept its +functioning. Since this interface was modeled after the Solaris's +audit interface, a good reference to it's operation is the Oracle +@cite{Solaris Linker and Libraries Guide}. +@c The linux man page for +@c rtld-audit(7) has a brief summary of the interface. + +@vindex LD_AUDIT +To run a program with an audit library, set the @env{LD_AUDIT} +environment variable to a colon separated list of shared libraries +which implement any subset of the functions listed above containing +@code{la_version()} which is required to be present in all audit libraries. +@findex la_version + +The current implementation of the run time linker audit interface +currently includes the following functions. + +@menu +* la_version:: Negotiate the version of the audit interface. +* la_objsearch:: Called when searching for a library. +* la_activity:: Called the link map is updated. +* la_objopen:: Called when an object file is opened. +* la_objclose:: Called just before the object file is unloaded. +* la_preinit:: Called after libraries are loaded but before main is called. +* la_symbind:: Called when a symbol is bound. +* la_pltenter:: Called when entering the PLT. +* la_pltexit:: Called when exiting the PLT. +@end menu + +@node la_version +@subsection la_version +@deftypefun unsigned int la_version(unsigned int @var{version}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} +@findex la_version + +This is the only function guaranteed to be implemented by the every +version of the audit interface. It is also the only function required +to be defined in every audit library. + +The parameter passed in, is the highest version of the audit interface +that the run time linker implements. An audit library should check +this version to make sure that the run time linker implements a +version of the audit interface that is compatible and sufficient for +its needs. The audit library should return the version of the +interface that it intends to use to use. While this is likely to be +the same as the version passed in as a parameter, it can also be an +older version. This allows an older audit library to still work with a +newer version of the audit interface. Currently, the run time linker +supports all previous versions of the audit interface and it is +expected that it will continue to provide backward compatibility with +these older versions of the interface for the foreseeable future. It +is unlikely that this guarantee of backward compatibility will be +broken during the lifetime of the ELF, Executable and Linkable File, +file format, but if the run time linker cannot support the version of +the audit interface returned by the auditing library's la_version() +function then that audit library will be ignored. One example where +this might be the case is if an audit library was compiled against a +newer version of glibc which implemented a newer version of the +interface and it required those new capabilities to run properly. The +audit library can also choose to return zero and the run time linker +will then ignore that audit library. + +The current version of the audit interface implemented by the run time +linker is defined as LAV_CURRENT in @file{link.h}. Thus a suggested +implementation of @code{la_version()} without the capability to run against +version one of the audit interface would be: + +@example +#define _GNU_SOURCE +#include + +#define LAV_DESIGN 2 +#if LAV_DESIGN > LAV_CURRENT +#error Please compile against a newer version of glibc +#endif + +unsigned int la_version(unsigned int version)@{ + if(version >= LAV_CURRENT) + return version; + return 0; +@} +@end example + +Since the difference between version one and version two of the audit +interface are very minor. It is very likely that almost all audit +libraries were either designed to be run against version one of the +interface or can easily be modified to run in a backward compatibility +mode with version one of the audit interface. +@end deftypefun + +@node la_objsearch +@subsection la_objsearch +@deftypefun char *la_objsearch(const char *@var{name}, uintptr_t *@var{cookie}, unsigned int @var{flag}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} +@findex la_objsearch + +Within a run time linker audit library @code{la_obsearch()} is +invoked each time the run time dynamic linker is going to search for +an object. This function may be called multiple times during the +process of resolving the location of a library. Initially, the run +time linker passes in the name of the object found from DT_NEEDED +record in the dynamic section of the ELF header or the name passed +into the @code{dlopen()} function. This results in the first +invocation of the @code{la_objsearch()} function with the name of the +name of the object being searched for and the flag being set to +LA_SER_ORIG. Subsequent steps in the object resolution process such as +RPATH and RUNPATH records in the ELF header or @env{LD_LIBRARY_PATH} +passed in through the environment will result in invocations of the +@code{la_objsearch()} function. For example a simple program that just +needs libc for printf will result in two invocations of +@code{la_objsearch()}. The first will be the initial search and the +second will be from the paths found in the @file{ld.so.cache}. + +@pindex nm +@pindex readelf +@example +$ nm ./main | grep `` U `` + U __libc_start_main@@GLIBC_2.2.5 + U printf@@GLIBC_2.2.5 +$ readelf -d ./main | egrep ``NEEDED|RPATH|RUNPATH'' + 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] +$ LD_AUDIT=./audit.so ./main +name=libc.so.6 cookie=0x7f7bc625b5c8 flag=LA_SER_ORIG +name=/lib64/libc.so.6 cookie=0x7f7bc625b5c8 flag=LA_SER_CONFIG +@end example + +The possible values for flag are: + +@var{LA_SER_ORIG} This is the original name either found in the ELF +dynamic header or the parameter passed in by dlopen(3). + +@var{LA_SER_CONFIG} This is the name found in +@file{/etc/ld.so.cache}. Most of the time system libraries will be +found in the cache rather than being found by using +@var{LA_SER_DEFAULT}. + +@var{LA_SER_DEFAULT} This is much more unusual than might be +expected. This will only happen if ldconfig has never been run or if +new libraries were added to the default directories since the last +time that ldconfig(8) was run. + +@var{LA_SER_LIBPATH} This flag is returned when the library is found in one +of the directories specified in the environment variable +@env{LD_LIBRARY_PATH}. +@vindex LD_LIBRARY_PATH + +@var{LA_SER_RUNPATH} This flag is returned when the library is found +in a directory specified in either the RPATH or RUNPATH ELF headers. + +The @var{cookie} is an opaque handle that refers to the object file +which requested the object be opened. In the case of shared libraries +needed by the original executable's object file, the @var{cookie} will +refer to an unnamed object at the root of the link-map. When an object +being searched for is required by another object as is the case when +you have library dependencies, the cookie will refer to the object +which has the dependency. In the case, where @code{dlopen} or +@code{dlmopen} is called the cookie will refer to the object which +initiated one of those function calls. +@findex dlopen +@findex dlmopen +@end deftypefun + +@node la_activity +@subsection la_activity +@findex la_activity +@deftypefun void la_activity( uintptr_t *@var{cookie}, unsigned int @var{flag}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +@findex dlmopen +The dynamic linker will call the @code{la_activity()} function any +time that it is updating the link-map. @var{cookie} identifies the +head of the chain of link maps that is being updated. Most +applications will have a single link-map that will be updated, the +global link map. However an application that makes use of +@code{dlmopen()} will have other link maps. The @var{flag} will be one +of the following values. + +@vindex LA_ACT_ADD +@var{LA_ACT_ADD} indicates that new objects are being added to the +link map. During initial executable startup, the object that you are +executing and ld.so and a third unnamed object that is part of the +dynamic linker are inserted into the base link map before +@code{la_activity} is called for the first time with @var{LA_ACT_ADD} +indicating that the link map is going to be added to. It may be +important for some audit libraries expecting a static link map to +recognize that the link map may be updated without notification before +the first call of @code{la_activity} with @var{LA_ACT_ADD}. + +@findex dlclose +@vindex LA_ACT_DELETE +@var{LA_ACT_DELETE} indicates that objects are being removed from the link +map. This only will happen as a result of a @code{dlclose} function +call. + +@vindex LA_ACT_CONSISTENT +@var{LA_ACT_CONSISTENT} indicates that the link-map activity has finished +and that the link-map is now consistent. + +If an application doesn't call any of the @code{dl*} functions, then +before starting @code{main} then the dynamic linker will first add the +shared libraries and then report that the link map is consistent. It +does not repeatedly call la_activity each and every time a library is +added to the link map. For that, an audit library should implement +@code{la_objopen()}. +@findex la_objopen + +@example +$ readelf -d /usr/bin/ls | grep NEEDED +0x0000000000000001 (NEEDED) Shared library: [libselinux.so.1] +0x0000000000000001 (NEEDED) Shared library: [libcap.so.2] +0x0000000000000001 (NEEDED) Shared library: [libacl.so.1] +0x0000000000000001 (NEEDED) Shared library: [libc.so.6] +$ LD_AUDIT=./audit.so ls +cookie=0x7fcd7463d5c8 flag=LA_ACT_ADD +cookie=0x7fcd7463d5c8 flag=LA_ACT_CONSISTENT +@end example +@end deftypefun + +@node la_objopen +@subsection la_objopen +@findex la_objopen +@deftypefun unsigned int la_objopen( struct link_map *@var{map}, Lmid_t @var{lmid}, uintptr_t *@var{cookie}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +The @code{la_objopen} function is called every time an object is added +to the link map. The first time that it is called is when the actual +binary that you are running is loaded. Since this is before even the +dynamic linker is fully loaded, the @var{l_name} is not set. The next +time it is run is when the dynamic linker itself being loaded. This +brings along another unnamed object in the link map. After that, every +shared library triggers a call to @code{la_objopen}. + +@findex la_symbind +@findex la_pltenter +@findex la_pltexit +Implementing @code{la_objopen} is practically required in every audit +library that is interested in implementing @code{la_symbind}, +@code{la_pltenter}, @code{la_pltexit} because it must set flags when +the object is being opened that indicate to the dynamic linker that +further auditing is desired. + +@findex dlopen +@findex dlmopen +@vindex LM_ID_BASE +@vindex LM_ID_NEWLM +There can be multiple @code{link_maps}. When an object is loaded at +process startup or with the normal @code{dlopen} function, then +@var{lmid} will be set to @var{LM_ID_BASE}. However when an object is +opened with @code{dlmopen}, lmid will be set to @var{LM_ID_NEWLM} +indicating that the object has been loaded into its own link map. + +The link map is the top of a NULL terminated doubly linked list of +@code{link_map} structures. In the case of the base link map, at the +root of the list are three objects. The first is the executable being +run and the other two are part of the dynamic linker itself. + +The cookie is an opaque handle that associates operations pertaining +to that object to an object being loaded. Since, this is the first use +of each cookie, the cookie provided to @code{la_objopen} serves as the +declaration of cookie for subsequent use. + +@vindex LA_FLG_NOBIND +@vindex LA_FLG_BINDFROM +@vindex LA_FLG_BINDTO +@findex la_symbind +The return value of the function is either @var{LA_FLG_NOBIND} which +is defined to be zero, or it is a bitwise OR of one or more of +@var{LA_FLG_BINDFROM} and @var{LA_FLG_BINDTO}. For the +@code{la_symbind} function to be called, the symbol being referenced +must be in an object where the return value of @code{la_objopen} must +include @var{LA_FLG_BINDTO} and the object from where it is referenced +must have had a return value that included @var{LA_FLG_BINDFROM}. + +If you wanted to see all the places where a particular executable +calls a function from libc, the @code{la_objopen} might include a +fragment of code like: +@example + if(map->l_prev==NULL) // the main executable + retval=LA_FLG_BINDFROM; + if( strstr(map->l_name,"libc.so")!=NULL) + retval=LA_FLG_BINDTO; + return retval; +@end example + +@vindex LA_FLG_NOBIND +The return value of either @var{LA_FLG_NOBIND} or 0 indicates that +no further monitoring is desired for this particular object by this +auditing library. In other words you are not interested in auditing +the binding of symbols within this object. + +Unless it is needed, it is advisable to not audit the binding of +symbols. The auditing of the binding of symbols not without costs. In +the normal case when a function in a separate object is first +referenced, the location is determined and it is stored in the GOT so +that subsequent calls do not incur additional overhead. However, when +an object's symbol binding is audited, then each reference is +intercepted for auditing. + +@vindex LA_FLG_BINDTO +The @var{LA_FLG_BINDTO} flag is set when auditing symbols that exists +in the object currently being opened. These are the symbols being called. + +@vindex LA_FLG_BINDFROM +The @var{LA_FLG_BINDFROM} flag is set when auditing references to +symbols that exist in other objects. These are the calls from this +object to symbols found in other objects. +@end deftypefun + +@node la_objclose +@subsection la_objclose +@findex la_objclose +@deftypefun unsigned int la_objclose(uintptr_t *@var{cookie}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +This function is called after any termination code in the object has +been executed and just prior to the object being unloaded from +memory. The @var{cookie} is the one for the object returned by +@var{la_objload}. Currently the return value from this function being +is ignored. + +@findex dlclose +When the libraries are loaded as part of the standard process startup, +they are not closed when a process exits therefore this function is +not called except as a result of @code{dlclose()} +@end deftypefun + +@node la_preinit +@subsection la_preinit +@findex la_preinit +@deftypefun void la_preinit(uintptr_t *@var{cookie}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +The @code{la_preinit} is called after all the shared libraries are +loaded, the link map is consistent, and after @code{__libc_start_main} +but before the executable object's @code{main} is called. + +The cookie passed in refers to the executable object being run. +@end deftypefun + +@node la_symbind +@subsection la_symbind +@findex la_symbind +@deftypefun uintptr_t la_symbind(Elf_Sym *@var{sym}, unsigned int @var{ndx}, uintptr_t *@var{refcook}, uintptr_t *@var{defcook}, unsigned int *@var{flags}, const char *@var{symname}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +@code{uintptr_t la_symbind(Elf_Sym *@var{sym}, unsigned int @var{ndx}, uintptr_t *@var{refcook}, uintptr_t *@var{defcook}, unsigned int *@var{flags}, const char *@var{symname})} + +@code{uintptr_t la_symbind64(Elf64_Sym *@var{sym}, unsigned int @var{ndx}, uintptr_t *@var{refcook}, uintptr_t *@var{defcook}, unsigned int *@var{flags}, const char *@var{symname})} + +The exact name and argument types of vary from architecture to +architecture. The definition or definitions appropriate to your +architecture can be found in @file{/usr/include/bits/link.h}. The one +used above as an example is from the x86_64 where there are two +versions of @code{la_symbind} one for 32 bit symbols and one for 64 +bit symbols. + +@findex la_objopen +@findex la_pltenter +@vindex LA_FLG_BINDFROM +@vindex LA_FLG_BINDTO +One of these functions is invoked when symbol binding occurs between +objects. It is only called when the object from which the binding was +triggered is marked @var{LA_FLG_BINDFROM} and the function being +called is in an object marked @var{LA_FLG_BINDTO} by +@code{la_obopen}. Usually, with normal lazy binding, this symbol +binding occurs when the function is first called. This symbol binding +occurs before the @code{la_pltenter} function is called. This symbol +binding can occur at different times if lazy binding is not being +used. + +@vindex st_name, Elf_Sym +@var{sym} is a pointer to a Elf structure defined in +@file{elf.h}. There are different versions of this structure with +different word sizes for multilib systems. The structure +includes @var{st_value} which is the function pointer to the function +which is being called. + +@var{ndx} refers to the index into the table of symbols within the +object being referred to by @var{defcook}, the cookie for the object +where the symbol is defined. From the command line this same table +along with its indexes can be printed by using the @command{readelf +-s} command. + +The symbol is being called from the symbol referred to by +@var{refcook}, the cookie for the object referencing the symbol. + +@vindex LA_SYMB_DLSYM +@vindex LA_SYMB_ALTVALUE +@findex dlsym +The flags parameter is a pointer to a bit mask. The +@var{LA_SYMB_DLSYM} indicates that the symbol was as a result of a +call through @code{dlsym}. The other flag @var{LA_SYMB_ALTVALUE} +indicates that @code{la_symbind} provided an alternative value for the +symbol. + +@vindex LA_SYMB_NOPLTENTER +@vindex LA_SYMB_NOPLTEXIT +Applications wishing to prevent subsequent passes through the +@code{ls_pltenter} or the @code{ls_pltexit} functions can or in +@var{LA_SYMB_NOPLTENTER} and/or @var{LA_SYMB_NOPLTEXT} +respectively. These flags can be subsequently re-enabled if +desired. However, modifying the variable pointed to by the @var{flags} +parameter outside of the scope of this function will lead to +unspecified behavior. +@end deftypefun + +@node la_pltenter +@subsection la_pltenter +@findex la_pltenter +@deftypefun Elf64_Addr la_x86_64_gnu_pltenter (Elf64_Sym *@var{sym}, unsigned int @var{ndx}, uintptr_t *@var{refcook}, uintptr_t *@var{defcook}, La_x86_64_regs *@var{regs}, unsigned int *@var{flags}, const char *@var{symname}, long int *@var{framesizep}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +The exact name and argument types of vary from architecture to +architecture. The definition or definitions appropriate to your +architecture can be found in @file{/usr/include/bits/link.h}. The one +used above as an example is from the x86_64. + +@vindex LA_FLG_BINDFROM +@vindex LA_FLG_BINDTO +@findex la_symbind +@findex la_pltexit +@vindex LA_SYMB_NOPLTENTER +This function is invoked just before calling a function through the +PLT. It is only called when the the object making the call is marked +@var{LA_FLG_BINDFROM} and the function being called is in an object +marked @var{LA_FLG_BINDTO} and when no previous calls to +@code{la_sybind}, @code{la_pltenter}, or @code{la_pltexit} have set +the @var{LA_SYMB_NOPLTENTER} bit in their @var{flags} parameter. + +@vindex st_name, Elf_Sym +@var{sym} is a pointer to a Elf structure defined in +@file{elf.h}. There are different versions of this structure with +different word sizes for multilib systems. The structure +includes @var{st_value} which is the function pointer to the function +which is being called. + +@var{ndx} refers to the index into the table of symbols within the +object being referred to by @var{defcook}. From the command line this +same table along with its indexes can be printed by using the +@command{readelf -s} command. + +The symbol is being called from the symbol referred to by @var{refcook}. + +The @var{regs} parameter is highly architecturally specific. It +contains the registers that are used for the call to this PLT +entry. It is defined in @file{/usr/include/bits/link.h}. + +@vindex LA_SYMB_DLSYM +@vindex LA_SYMB_ALTVALUE +@findex dlsym +@findex la_symbind +The flags parameter is a pointer to a bit mask and has the same +meaning as it does as when used in la_symbind. The @var{LA_SYMB_DLSYM} +indicates that the symbol was as a result of a call through +@code{dlsym}. The other flag @var{LA_SYMB_ALTVALUE} indicates that +@code{la_symbind} provided an alternative value for the symbol. + +@findex ls_pltenter +@findex ls_pltexit +@vindex LA_SYMB_NOPLTENTER +@vindex LA_SYMB_NOPLTEXIT +Applications wishing to prevent subsequent passes through the +@code{ls_pltenter} or the @code{ls_pltexit} functions can or in +@var{LA_SYMB_NOPLTENTER} and/or @var{LA_SYMB_NOPLTEXIT} +respectively. These flags can be subsequently re-enabled if +desired. However, modifying the variable pointed to by the @var{flags} +parameter outside of the scope of this function will lead to +unspecified behavior. + +The @var{framesizep} parameter is used to communicate back to the +dynamic linker the size of the stack frame needed by fucntion actually +being called when modifying the arguments to the function being +called. Modifing the arguments to the function being called must be +done in accordance with the ABI for the architecture. This technique +is needed when calling functions whose ABI does not match the one for +the original function linked to by the referring object. + +@end deftypefun + +@node la_pltexit +@subsection la_pltexit +@findex la_pltexit +@deftypefun unsigned int la_i86_gnu_pltexit(Elf32_Sym *@var{sym}, unsigned int @var{ndx}, uintptr_t *@var{refcook}, uintptr_t *@var{defcook}, const La_i86_regs *@var{inregs}, La_i86_retval *@var{outregs}, const char *@var{symname}) +@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{}} + +The exact name and argument types of vary from architecture to +architecture. The definition or definitions appropriate to your +architecture can be found in @file{/usr/include/bits/link.h}. The one +used above as an example is from the x86_64. + +@findex la_objopen +@findex la_pltenter +@vindex LA_FLG_BINDFROM +@vindex LA_FLG_BINDTO +@findex la_sybind +This function is invoked just before control returns to the caller for +the symbol referenced by this PLT entry. It is only called when the +the object making the call is marked @var{LA_FLG_BINDFROM} and the +function being called is in an object marked @var{LA_FLG_BINDTO} and +the function being called is in an object marked @var{LA_FLG_BINDTO} +and when no previous calls to @code{la_sybind}, @code{la_pltenter}, or +@code{la_pltexit} have set the @var{LA_SYMB_NOPLTEXIT} bit in their +@var{flags} parameter. + +@vindex st_name, Elf_Sym +@var{sym} is a pointer to a Elf structure defined in +@file{elf.h}. There are different versions of this structure with +different word sizes for multilib systems. The structure +includes @var{st_value} which is the function pointer to the function +which is being called. + +@var{ndx} refers to the index into the table of symbols within the +object being referred to by @var{defcook}. From the command line this +same table along with its indexes can be printed by using the +@command{readelf -s} command. + +The symbol is being called from the symbol referred to by @var{refcook}. + +The @var{inregs} and @var{outregs} are both architecture dependent +and are defined by in @file{/usr/include/bits/link.h}. The +@var{inregs} parameter points to a structure containing the registers +used to call this PLT entry. Similarly, @var{outregs} points to a +structure containing the return values for the call to this PLT +entry. This value can be modified and the changes will be visible to +the caller of this PLT entry. + +The return value for this function is currently ignored. +@end deftypefun diff --git a/manual/libdl.texi b/manual/libdl.texi deleted file mode 100644 index e3fe0452d9..0000000000 --- a/manual/libdl.texi +++ /dev/null @@ -1,10 +0,0 @@ -@c FIXME these are undocumented: -@c dladdr -@c dladdr1 -@c dlclose -@c dlerror -@c dlinfo -@c dlmopen -@c dlopen -@c dlsym -@c dlvsym diff --git a/manual/signal.texi b/manual/signal.texi index 9577ff091d..8e2b900b49 100644 --- a/manual/signal.texi +++ b/manual/signal.texi @@ -1,4 +1,4 @@ -@node Signal Handling, Program Basics, Non-Local Exits, Top +@node Signal Handling, Dynamic Linking, Non-Local Exits, Top @c %MENU% How to send, block, and handle signals @chapter Signal Handling