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