]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man3/dl_iterate_phdr.3
Many pages: Fix style issues reported by `make lint-groff`
[thirdparty/man-pages.git] / man3 / dl_iterate_phdr.3
1 .\" Copyright (c) 2003, 2017 by Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
4 .\"
5 .TH DL_ITERATE_PHDR 3 2021-03-22 "GNU" "Linux Programmer's Manual"
6 .SH NAME
7 dl_iterate_phdr \- walk through list of shared objects
8 .SH LIBRARY
9 Standard C library
10 .RI ( libc ", " \-lc )
11 .SH SYNOPSIS
12 .nf
13 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
14 .B #include <link.h>
15 .PP
16 .B int dl_iterate_phdr(
17 .BI " int (*" callback ")(struct dl_phdr_info *" info ,
18 .BI " size_t " size ", void *" data ),
19 .BI " void *" data );
20 .fi
21 .SH DESCRIPTION
22 The
23 .BR dl_iterate_phdr ()
24 function allows an application to inquire at run time to find
25 out which shared objects it has loaded,
26 and the order in which they were loaded.
27 .PP
28 The
29 .BR dl_iterate_phdr ()
30 function walks through the list of an
31 application's shared objects and calls the function
32 .I callback
33 once for each object,
34 until either all shared objects have been processed or
35 .I callback
36 returns a nonzero value.
37 .PP
38 Each call to
39 .I callback
40 receives three arguments:
41 .IR info ,
42 which is a pointer to a structure containing information
43 about the shared object;
44 .IR size ,
45 which is the size of the structure pointed to by
46 .IR info ;
47 and
48 .IR data ,
49 which is a copy of whatever value was passed by the calling
50 program as the second argument (also named
51 .IR data )
52 in the call to
53 .BR dl_iterate_phdr ().
54 .PP
55 The
56 .I info
57 argument is a structure of the following type:
58 .PP
59 .in +4n
60 .EX
61 struct dl_phdr_info {
62 ElfW(Addr) dlpi_addr; /* Base address of object */
63 const char *dlpi_name; /* (Null\-terminated) name of
64 object */
65 const ElfW(Phdr) *dlpi_phdr; /* Pointer to array of
66 ELF program headers
67 for this object */
68 ElfW(Half) dlpi_phnum; /* # of items in \fIdlpi_phdr\fP */
69
70 /* The following fields were added in glibc 2.4, after the first
71 version of this structure was available. Check the \fIsize\fP
72 argument passed to the dl_iterate_phdr callback to determine
73 whether or not each later member is available. */
74
75 unsigned long long dlpi_adds;
76 /* Incremented when a new object may
77 have been added */
78 unsigned long long dlpi_subs;
79 /* Incremented when an object may
80 have been removed */
81 size_t dlpi_tls_modid;
82 /* If there is a PT_TLS segment, its module
83 ID as used in TLS relocations, else zero */
84 void *dlpi_tls_data;
85 /* The address of the calling thread\(aqs instance
86 of this module\(aqs PT_TLS segment, if it has
87 one and it has been allocated in the calling
88 thread, otherwise a null pointer */
89 };
90 .EE
91 .in
92 .PP
93 (The
94 .IR ElfW ()
95 macro definition turns its argument into the name of an ELF data
96 type suitable for the hardware architecture.
97 For example, on a 32-bit platform,
98 .I ElfW(Addr)
99 yields the data type name
100 .IR Elf32_Addr .
101 Further information on these types can be found in the
102 .IR <elf.h> " and " <link.h>
103 header files.)
104 .PP
105 The
106 .I dlpi_addr
107 field indicates the base address of the shared object
108 (i.e., the difference between the virtual memory address of
109 the shared object and the offset of that object in the file
110 from which it was loaded).
111 The
112 .I dlpi_name
113 field is a null-terminated string giving the pathname
114 from which the shared object was loaded.
115 .PP
116 To understand the meaning of the
117 .I dlpi_phdr
118 and
119 .I dlpi_phnum
120 fields, we need to be aware that an ELF shared object consists
121 of a number of segments, each of which has a corresponding
122 program header describing the segment.
123 The
124 .I dlpi_phdr
125 field is a pointer to an array of the program headers for this
126 shared object.
127 The
128 .I dlpi_phnum
129 field indicates the size of this array.
130 .PP
131 These program headers are structures of the following form:
132 .PP
133 .in +4n
134 .EX
135 typedef struct {
136 Elf32_Word p_type; /* Segment type */
137 Elf32_Off p_offset; /* Segment file offset */
138 Elf32_Addr p_vaddr; /* Segment virtual address */
139 Elf32_Addr p_paddr; /* Segment physical address */
140 Elf32_Word p_filesz; /* Segment size in file */
141 Elf32_Word p_memsz; /* Segment size in memory */
142 Elf32_Word p_flags; /* Segment flags */
143 Elf32_Word p_align; /* Segment alignment */
144 } Elf32_Phdr;
145 .EE
146 .in
147 .PP
148 Note that we can calculate the location of a particular program header,
149 .IR x ,
150 in virtual memory using the formula:
151 .PP
152 .in +4n
153 .EX
154 addr == info\->dlpi_addr + info\->dlpi_phdr[x].p_vaddr;
155 .EE
156 .in
157 .PP
158 Possible values for
159 .I p_type
160 include the following (see
161 .I <elf.h>
162 for further details):
163 .PP
164 .in +4n
165 .EX
166 #define PT_LOAD 1 /* Loadable program segment */
167 #define PT_DYNAMIC 2 /* Dynamic linking information */
168 #define PT_INTERP 3 /* Program interpreter */
169 #define PT_NOTE 4 /* Auxiliary information */
170 #define PT_SHLIB 5 /* Reserved */
171 #define PT_PHDR 6 /* Entry for header table itself */
172 #define PT_TLS 7 /* Thread\-local storage segment */
173 #define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
174 #define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
175 .\" For PT_GNU_STACK, see http://www.airs.com/blog/archives/518
176 #define PT_GNU_RELRO 0x6474e552 /* Read\-only after relocation */
177 .EE
178 .in
179 .SH RETURN VALUE
180 The
181 .BR dl_iterate_phdr ()
182 function returns whatever value was returned by the last call to
183 .IR callback .
184 .SH VERSIONS
185 .BR dl_iterate_phdr ()
186 has been supported in glibc since version 2.2.4.
187 .SH ATTRIBUTES
188 For an explanation of the terms used in this section, see
189 .BR attributes (7).
190 .ad l
191 .nh
192 .TS
193 allbox;
194 lbx lb lb
195 l l l.
196 Interface Attribute Value
197 T{
198 .BR dl_iterate_phdr ()
199 T} Thread safety MT-Safe
200 .TE
201 .hy
202 .ad
203 .sp 1
204 .SH CONFORMING TO
205 The
206 .BR dl_iterate_phdr ()
207 function is not specified in any standard.
208 Various other systems provide a version of this function,
209 although details of the returned
210 .I dl_phdr_info
211 structure differ.
212 On the BSDs and Solaris, the structure includes the fields
213 .IR dlpi_addr ,
214 .IR dlpi_name ,
215 .IR dlpi_phdr ,
216 and
217 .I dlpi_phnum
218 in addition to other implementation-specific fields.
219 .SH NOTES
220 Future versions of the C library may add further fields to the
221 .I dl_phdr_info
222 structure; in that event, the
223 .I size
224 argument provides a mechanism for the callback function to discover
225 whether it is running on a system with added fields.
226 .PP
227 The first object visited by
228 .I callback
229 is the main program.
230 For the main program, the
231 .I dlpi_name
232 field will be an empty string.
233 .SH EXAMPLES
234 The following program displays a list of pathnames of the
235 shared objects it has loaded.
236 For each shared object, the program lists some information
237 (virtual address, size, flags, and type)
238 for each of the objects ELF segments.
239 .PP
240 The following shell session demonstrates the output
241 produced by the program on an x86-64 system.
242 The first shared object for which output is displayed
243 (where the name is an empty string)
244 is the main program.
245 .PP
246 .in +4n
247 .EX
248 $ \fB./a.out\fP
249 Name: "" (9 segments)
250 0: [ 0x400040; memsz: 1f8] flags: 0x5; PT_PHDR
251 1: [ 0x400238; memsz: 1c] flags: 0x4; PT_INTERP
252 2: [ 0x400000; memsz: ac4] flags: 0x5; PT_LOAD
253 3: [ 0x600e10; memsz: 240] flags: 0x6; PT_LOAD
254 4: [ 0x600e28; memsz: 1d0] flags: 0x6; PT_DYNAMIC
255 5: [ 0x400254; memsz: 44] flags: 0x4; PT_NOTE
256 6: [ 0x400970; memsz: 3c] flags: 0x4; PT_GNU_EH_FRAME
257 7: [ (nil); memsz: 0] flags: 0x6; PT_GNU_STACK
258 8: [ 0x600e10; memsz: 1f0] flags: 0x4; PT_GNU_RELRO
259 Name: "linux\-vdso.so.1" (4 segments)
260 0: [0x7ffc6edd1000; memsz: e89] flags: 0x5; PT_LOAD
261 1: [0x7ffc6edd1360; memsz: 110] flags: 0x4; PT_DYNAMIC
262 2: [0x7ffc6edd17b0; memsz: 3c] flags: 0x4; PT_NOTE
263 3: [0x7ffc6edd17ec; memsz: 3c] flags: 0x4; PT_GNU_EH_FRAME
264 Name: "/lib64/libc.so.6" (10 segments)
265 0: [0x7f55712ce040; memsz: 230] flags: 0x5; PT_PHDR
266 1: [0x7f557145b980; memsz: 1c] flags: 0x4; PT_INTERP
267 2: [0x7f55712ce000; memsz: 1b6a5c] flags: 0x5; PT_LOAD
268 3: [0x7f55716857a0; memsz: 9240] flags: 0x6; PT_LOAD
269 4: [0x7f5571688b80; memsz: 1f0] flags: 0x6; PT_DYNAMIC
270 5: [0x7f55712ce270; memsz: 44] flags: 0x4; PT_NOTE
271 6: [0x7f55716857a0; memsz: 78] flags: 0x4; PT_TLS
272 7: [0x7f557145b99c; memsz: 544c] flags: 0x4; PT_GNU_EH_FRAME
273 8: [0x7f55712ce000; memsz: 0] flags: 0x6; PT_GNU_STACK
274 9: [0x7f55716857a0; memsz: 3860] flags: 0x4; PT_GNU_RELRO
275 Name: "/lib64/ld\-linux\-x86\-64.so.2" (7 segments)
276 0: [0x7f557168f000; memsz: 20828] flags: 0x5; PT_LOAD
277 1: [0x7f55718afba0; memsz: 15a8] flags: 0x6; PT_LOAD
278 2: [0x7f55718afe10; memsz: 190] flags: 0x6; PT_DYNAMIC
279 3: [0x7f557168f1c8; memsz: 24] flags: 0x4; PT_NOTE
280 4: [0x7f55716acec4; memsz: 604] flags: 0x4; PT_GNU_EH_FRAME
281 5: [0x7f557168f000; memsz: 0] flags: 0x6; PT_GNU_STACK
282 6: [0x7f55718afba0; memsz: 460] flags: 0x4; PT_GNU_RELRO
283 .EE
284 .in
285 .SS Program source
286 \&
287 .EX
288 #define _GNU_SOURCE
289 #include <link.h>
290 #include <stdlib.h>
291 #include <stdio.h>
292 #include <stdint.h>
293
294 static int
295 callback(struct dl_phdr_info *info, size_t size, void *data)
296 {
297 char *type;
298 int p_type;
299
300 printf("Name: \e"%s\e" (%d segments)\en", info\->dlpi_name,
301 info\->dlpi_phnum);
302
303 for (int j = 0; j < info\->dlpi_phnum; j++) {
304 p_type = info\->dlpi_phdr[j].p_type;
305 type = (p_type == PT_LOAD) ? "PT_LOAD" :
306 (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" :
307 (p_type == PT_INTERP) ? "PT_INTERP" :
308 (p_type == PT_NOTE) ? "PT_NOTE" :
309 (p_type == PT_INTERP) ? "PT_INTERP" :
310 (p_type == PT_PHDR) ? "PT_PHDR" :
311 (p_type == PT_TLS) ? "PT_TLS" :
312 (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" :
313 (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" :
314 (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL;
315
316 printf(" %2d: [%14p; memsz:%7jx] flags: %#jx; ", j,
317 (void *) (info\->dlpi_addr + info\->dlpi_phdr[j].p_vaddr),
318 (uintmax_t) info\->dlpi_phdr[j].p_memsz,
319 (uintmax_t) info\->dlpi_phdr[j].p_flags);
320 if (type != NULL)
321 printf("%s\en", type);
322 else
323 printf("[other (%#x)]\en", p_type);
324 }
325
326 return 0;
327 }
328
329 int
330 main(int argc, char *argv[])
331 {
332 dl_iterate_phdr(callback, NULL);
333
334 exit(EXIT_SUCCESS);
335 }
336 .EE
337 .SH SEE ALSO
338 .BR ldd (1),
339 .BR objdump (1),
340 .BR readelf (1),
341 .BR dladdr (3),
342 .BR dlopen (3),
343 .BR elf (5),
344 .BR ld.so (8)
345 .PP
346 .IR "Executable and Linking Format Specification" ,
347 available at various locations online.