| '\" t |
| .\" Copyright (C) 2015 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" |
| .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
| .\" |
| .TH dlinfo 3 (date) "Linux man-pages (unreleased)" |
| .SH NAME |
| dlinfo \- obtain information about a dynamically loaded object |
| .SH LIBRARY |
| Dynamic linking library |
| .RI ( libdl ,\~ \-ldl ) |
| .SH SYNOPSIS |
| .nf |
| .B #define _GNU_SOURCE |
| .B #include <link.h> |
| .B #include <dlfcn.h> |
| .P |
| .BR "int dlinfo(void *restrict " handle ", int " request \ |
| ", void *restrict " info ); |
| .fi |
| .SH DESCRIPTION |
| The |
| .BR dlinfo () |
| function obtains information about the dynamically loaded object |
| referred to by |
| .I handle |
| (typically obtained by an earlier call to |
| .BR dlopen (3) |
| or |
| .BR dlmopen (3)). |
| The |
| .I request |
| argument specifies which information is to be returned. |
| The |
| .I info |
| argument is a pointer to a buffer used to store information |
| returned by the call; the type of this argument depends on |
| .IR request . |
| .P |
| The following values are supported for |
| .I request |
| (with the corresponding type for |
| .I info |
| shown in parentheses): |
| .TP |
| .BR RTLD_DI_LMID " (\fILmid_t *\fP)" |
| Obtain the ID of the link-map list (namespace) in which |
| .I handle |
| is loaded. |
| .TP |
| .BR RTLD_DI_LINKMAP " (\fIstruct link_map **\fP)" |
| Obtain a pointer to the |
| .I link_map |
| structure corresponding to |
| .IR handle . |
| The |
| .I info |
| argument points to a pointer to a |
| .I link_map |
| structure, defined in |
| .I <link.h> |
| as: |
| .IP |
| .in +4n |
| .EX |
| struct link_map { |
| ElfW(Addr) l_addr; /* Difference between the |
| address in the ELF file and |
| the address in memory */ |
| char *l_name; /* Absolute pathname where |
| object was found */ |
| ElfW(Dyn) *l_ld; /* Dynamic section of the |
| shared object */ |
| struct link_map *l_next, *l_prev; |
| /* Chain of loaded objects */ |
| \& |
| /* Plus additional fields private to the |
| implementation */ |
| }; |
| .EE |
| .in |
| .TP |
| .BR RTLD_DI_ORIGIN " (\fIchar *\fP)" |
| Copy the pathname of the origin of the shared object corresponding to |
| .I handle |
| to the location pointed to by |
| .IR info . |
| .TP |
| .BR RTLD_DI_SERINFO " (\fIDl_serinfo *\fP)" |
| Obtain the library search paths for the shared object referred to by |
| .IR handle . |
| The |
| .I info |
| argument is a pointer to a |
| .I Dl_serinfo |
| that contains the search paths. |
| Because the number of search paths may vary, |
| the size of the structure pointed to by |
| .I info |
| can vary. |
| The |
| .B RTLD_DI_SERINFOSIZE |
| request described below allows applications to size the buffer suitably. |
| The caller must perform the following steps: |
| .RS |
| .IP (1) 5 |
| Use a |
| .B RTLD_DI_SERINFOSIZE |
| request to populate a |
| .I Dl_serinfo |
| structure with the size |
| .RI ( dls_size ) |
| of the structure needed for the subsequent |
| .B RTLD_DI_SERINFO |
| request. |
| .IP (2) |
| Allocate a |
| .I Dl_serinfo |
| buffer of the correct size |
| .RI ( dls_size ). |
| .IP (3) |
| Use a further |
| .B RTLD_DI_SERINFOSIZE |
| request to populate the |
| .I dls_size |
| and |
| .I dls_cnt |
| fields of the buffer allocated in the previous step. |
| .IP (4) |
| Use a |
| .B RTLD_DI_SERINFO |
| to obtain the library search paths. |
| .RE |
| .IP |
| The |
| .I Dl_serinfo |
| structure is defined as follows: |
| .IP |
| .in +4n |
| .EX |
| typedef struct { |
| size_t dls_size; /* Size in bytes of |
| the whole buffer */ |
| unsigned int dls_cnt; /* Number of elements |
| in \[aq]dls_serpath\[aq] */ |
| Dl_serpath dls_serpath[1]; /* Actually longer, |
| \[aq]dls_cnt\[aq] elements */ |
| } Dl_serinfo; |
| .EE |
| .in |
| .IP |
| Each of the |
| .I dls_serpath |
| elements in the above structure is a structure of the following form: |
| .IP |
| .in +4n |
| .EX |
| typedef struct { |
| char *dls_name; /* Name of library search |
| path directory */ |
| unsigned int dls_flags; /* Indicates where this |
| directory came from */ |
| } Dl_serpath; |
| .EE |
| .in |
| .IP |
| The |
| .I dls_flags |
| field is currently unused, and always contains zero. |
| .TP |
| .BR RTLD_DI_SERINFOSIZE " (\fIDl_serinfo *\fP)" |
| Populate the |
| .I dls_size |
| and |
| .I dls_cnt |
| fields of the |
| .I Dl_serinfo |
| structure pointed to by |
| .I info |
| with values suitable for allocating a buffer for use in a subsequent |
| .B RTLD_DI_SERINFO |
| request. |
| .TP |
| .BR RTLD_DI_TLS_MODID " (\fIsize_t *\fP, since glibc 2.4)" |
| Obtain the module ID of this shared object's TLS (thread-local storage) |
| segment, as used in TLS relocations. |
| If this object does not define a TLS segment, zero is placed in |
| .IR *info . |
| .TP |
| .BR RTLD_DI_TLS_DATA " (\fIvoid **\fP, since glibc 2.4)" |
| Obtain a pointer to the calling |
| thread's TLS block corresponding to this shared object's TLS segment. |
| If this object does not define a PT_TLS segment, |
| or if the calling thread has not allocated a block for it, |
| NULL is placed in |
| .IR *info . |
| .TP |
| .BR RTLD_DI_PHDR " (\fIconst ElfW(Phdr *)\fP, since glibc 2.34.1)" |
| .\" glibc commit d056c212130280c0a54d9a4f72170ec621b70ce5 (2.36) |
| .\" glibc commit 28ea43f8d64f0dd1f2de75525157730e1532e600 (2.35.1) |
| .\" glibc commit 91c2e6c3db44297bf4cb3a2e3c40236c5b6a0b23 (2.34.1) |
| Obtain the address of this shared object's program header and place it |
| in |
| .IR *info . |
| This |
| .B dlinfo |
| call returns the number of program headers in the shared object. |
| .SH RETURN VALUE |
| On success, |
| .BR dlinfo () |
| returns 0 |
| (if not specified explicitly), |
| or a positive value corresponding to the request. |
| On failure, it returns \-1; the error can be diagnosed using |
| .BR dlerror (3). |
| .SH ATTRIBUTES |
| For an explanation of the terms used in this section, see |
| .BR attributes (7). |
| .TS |
| allbox; |
| lbx lb lb |
| l l l. |
| Interface Attribute Value |
| T{ |
| .na |
| .nh |
| .BR dlinfo () |
| T} Thread safety MT-Safe |
| .TE |
| .SH VERSIONS |
| The sets of requests supported by the various implementations |
| overlaps only partially. |
| .SH STANDARDS |
| GNU. |
| .SH HISTORY |
| glibc 2.3.3. |
| Solaris. |
| .SH EXAMPLES |
| The program below opens a shared objects using |
| .BR dlopen (3) |
| and then uses the |
| .B RTLD_DI_SERINFOSIZE |
| and |
| .B RTLD_DI_SERINFO |
| requests to obtain the library search path list for the library. |
| Here is an example of what we might see when running the program: |
| .P |
| .in +4n |
| .EX |
| $ \fB./a.out /lib64/libm.so.6\fP |
| dls_serpath[0].dls_name = /lib64 |
| dls_serpath[1].dls_name = /usr/lib64 |
| .EE |
| .in |
| .SS Program source |
| \& |
| .\" SRC BEGIN (dlinfo.c) |
| .EX |
| #define _GNU_SOURCE |
| #include <dlfcn.h> |
| #include <link.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| \& |
| int |
| main(int argc, char *argv[]) |
| { |
| void *handle; |
| Dl_serinfo serinfo; |
| Dl_serinfo *sip; |
| \& |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s <libpath>\[rs]n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| /* Obtain a handle for shared object specified on command line. */ |
| \& |
| handle = dlopen(argv[1], RTLD_NOW); |
| if (handle == NULL) { |
| fprintf(stderr, "dlopen() failed: %s\[rs]n", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| /* Discover the size of the buffer that we must pass to |
| RTLD_DI_SERINFO. */ |
| \& |
| if (dlinfo(handle, RTLD_DI_SERINFOSIZE, &serinfo) == \-1) { |
| fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\[rs]n", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| /* Allocate the buffer for use with RTLD_DI_SERINFO. */ |
| \& |
| sip = malloc(serinfo.dls_size); |
| if (sip == NULL) { |
| perror("malloc"); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| /* Initialize the \[aq]dls_size\[aq] and \[aq]dls_cnt\[aq] fields in the newly |
| allocated buffer. */ |
| \& |
| if (dlinfo(handle, RTLD_DI_SERINFOSIZE, sip) == \-1) { |
| fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\[rs]n", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| /* Fetch and print library search list. */ |
| \& |
| if (dlinfo(handle, RTLD_DI_SERINFO, sip) == \-1) { |
| fprintf(stderr, "RTLD_DI_SERINFO failed: %s\[rs]n", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| \& |
| for (size_t j = 0; j < serinfo.dls_cnt; j++) |
| printf("dls_serpath[%zu].dls_name = %s\[rs]n", |
| j, sip\->dls_serpath[j].dls_name); |
| \& |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .\" SRC END |
| .SH SEE ALSO |
| .BR dl_iterate_phdr (3), |
| .BR dladdr (3), |
| .BR dlerror (3), |
| .BR dlopen (3), |
| .BR dlsym (3), |
| .BR ld.so (8) |