]>
Commit | Line | Data |
---|---|---|
6736a802 | 1 | .\" Copyright (c) 2003, 2017 by Michael Kerrisk <mtk.manpages@gmail.com> |
fea681da | 2 | .\" |
5fbde956 | 3 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
fea681da | 4 | .\" |
1d767b55 | 5 | .TH DL_ITERATE_PHDR 3 2021-03-22 "GNU" "Linux Programmer's Manual" |
fea681da MK |
6 | .SH NAME |
7 | dl_iterate_phdr \- walk through list of shared objects | |
b813014f AC |
8 | .SH LIBRARY |
9 | Standard C library | |
10 | .RI ( libc ", " \-lc ) | |
fea681da MK |
11 | .SH SYNOPSIS |
12 | .nf | |
b80f966b | 13 | .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" |
fea681da | 14 | .B #include <link.h> |
f90f031e | 15 | .PP |
1ae6b2c7 | 16 | .B int dl_iterate_phdr( |
1210ac32 | 17 | .BI " int (*" callback ")(struct dl_phdr_info *" info , |
1ae6b2c7 AC |
18 | .BI " size_t " size ", void *" data ), |
19 | .BI " void *" data ); | |
fea681da MK |
20 | .fi |
21 | .SH DESCRIPTION | |
22 | The | |
d355f1ed | 23 | .BR dl_iterate_phdr () |
cf50118f | 24 | function allows an application to inquire at run time to find |
797981eb MK |
25 | out which shared objects it has loaded, |
26 | and the order in which they were loaded. | |
847e0d88 | 27 | .PP |
fea681da | 28 | The |
d355f1ed | 29 | .BR dl_iterate_phdr () |
fea681da MK |
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 | |
c7094399 | 36 | returns a nonzero value. |
847e0d88 | 37 | .PP |
fea681da MK |
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 | |
d355f1ed | 53 | .BR dl_iterate_phdr (). |
847e0d88 | 54 | .PP |
fea681da MK |
55 | The |
56 | .I info | |
57 | argument is a structure of the following type: | |
847e0d88 | 58 | .PP |
088a639b | 59 | .in +4n |
b8302363 | 60 | .EX |
3c8e93ad | 61 | struct dl_phdr_info { |
fea681da | 62 | ElfW(Addr) dlpi_addr; /* Base address of object */ |
d064d41a | 63 | const char *dlpi_name; /* (Null\-terminated) name of |
2968ea1a | 64 | object */ |
fea681da MK |
65 | const ElfW(Phdr) *dlpi_phdr; /* Pointer to array of |
66 | ELF program headers | |
67 | for this object */ | |
f81fb444 | 68 | ElfW(Half) dlpi_phnum; /* # of items in \fIdlpi_phdr\fP */ |
9b14ad2d MK |
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 | ||
ae85f653 | 75 | unsigned long long dlpi_adds; |
9b14ad2d MK |
76 | /* Incremented when a new object may |
77 | have been added */ | |
ae85f653 | 78 | unsigned long long dlpi_subs; |
9b14ad2d MK |
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; | |
861d36ba MK |
85 | /* The address of the calling thread\(aqs instance |
86 | of this module\(aqs PT_TLS segment, if it has | |
9b14ad2d | 87 | one and it has been allocated in the calling |
91a2771d | 88 | thread, otherwise a null pointer */ |
3c8e93ad | 89 | }; |
b8302363 | 90 | .EE |
3c8e93ad | 91 | .in |
847e0d88 | 92 | .PP |
fea681da | 93 | (The |
63aa9df0 | 94 | .IR ElfW () |
fea681da MK |
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, | |
48a11e1d MK |
98 | .I ElfW(Addr) |
99 | yields the data type name | |
100 | .IR Elf32_Addr . | |
fea681da MK |
101 | Further information on these types can be found in the |
102 | .IR <elf.h> " and " <link.h> | |
103 | header files.) | |
847e0d88 | 104 | .PP |
fea681da MK |
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. | |
847e0d88 | 115 | .PP |
fea681da MK |
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. | |
847e0d88 | 130 | .PP |
fea681da | 131 | These program headers are structures of the following form: |
e646a1ba | 132 | .PP |
088a639b | 133 | .in +4n |
e646a1ba | 134 | .EX |
3c8e93ad | 135 | typedef struct { |
fea681da MK |
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 */ | |
3c8e93ad | 144 | } Elf32_Phdr; |
b8302363 | 145 | .EE |
3c8e93ad | 146 | .in |
847e0d88 | 147 | .PP |
fea681da MK |
148 | Note that we can calculate the location of a particular program header, |
149 | .IR x , | |
fba59d25 | 150 | in virtual memory using the formula: |
847e0d88 | 151 | .PP |
207050fa MK |
152 | .in +4n |
153 | .EX | |
154 | addr == info\->dlpi_addr + info\->dlpi_phdr[x].p_vaddr; | |
155 | .EE | |
156 | .in | |
847e0d88 | 157 | .PP |
c4054f82 MK |
158 | Possible values for |
159 | .I p_type | |
160 | include the following (see | |
1ae6b2c7 | 161 | .I <elf.h> |
c4054f82 | 162 | for further details): |
847e0d88 | 163 | .PP |
c4054f82 | 164 | .in +4n |
b8302363 | 165 | .EX |
c4054f82 MK |
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 */ | |
d064d41a | 172 | #define PT_TLS 7 /* Thread\-local storage segment */ |
c4054f82 MK |
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 | |
d064d41a | 176 | #define PT_GNU_RELRO 0x6474e552 /* Read\-only after relocation */ |
b8302363 | 177 | .EE |
e646a1ba | 178 | .in |
2b2581ee MK |
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 . | |
24377d40 MK |
184 | .SH VERSIONS |
185 | .BR dl_iterate_phdr () | |
186 | has been supported in glibc since version 2.2.4. | |
1ee2274c ZL |
187 | .SH ATTRIBUTES |
188 | For an explanation of the terms used in this section, see | |
189 | .BR attributes (7). | |
c466875e MK |
190 | .ad l |
191 | .nh | |
1ee2274c ZL |
192 | .TS |
193 | allbox; | |
c466875e | 194 | lbx lb lb |
1ee2274c ZL |
195 | l l l. |
196 | Interface Attribute Value | |
197 | T{ | |
198 | .BR dl_iterate_phdr () | |
199 | T} Thread safety MT-Safe | |
200 | .TE | |
c466875e MK |
201 | .hy |
202 | .ad | |
847e0d88 | 203 | .sp 1 |
47297adb | 204 | .SH CONFORMING TO |
2b2581ee MK |
205 | The |
206 | .BR dl_iterate_phdr () | |
c9629ff8 MK |
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 | |
1ae6b2c7 | 217 | .I dlpi_phnum |
c9629ff8 | 218 | in addition to other implementation-specific fields. |
70476aa4 MK |
219 | .SH NOTES |
220 | Future versions of the C library may add further fields to the | |
1ae6b2c7 | 221 | .I dl_phdr_info |
70476aa4 MK |
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. | |
847e0d88 | 226 | .PP |
f1e1b550 | 227 | The first object visited by |
1ae6b2c7 | 228 | .I callback |
f1e1b550 MK |
229 | is the main program. |
230 | For the main program, the | |
231 | .I dlpi_name | |
232 | field will be an empty string. | |
a14af333 | 233 | .SH EXAMPLES |
c13182ef | 234 | The following program displays a list of pathnames of the |
fea681da | 235 | shared objects it has loaded. |
6736a802 MK |
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. | |
847e0d88 | 239 | .PP |
6736a802 MK |
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. | |
41a64b30 | 245 | .PP |
6736a802 | 246 | .in +4n |
b8302363 | 247 | .EX |
6736a802 MK |
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 | |
d064d41a | 259 | Name: "linux\-vdso.so.1" (4 segments) |
6736a802 MK |
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 | |
d064d41a | 275 | Name: "/lib64/ld\-linux\-x86\-64.so.2" (7 segments) |
6736a802 MK |
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 | |
b8302363 | 283 | .EE |
e646a1ba | 284 | .in |
6736a802 MK |
285 | .SS Program source |
286 | \& | |
e7d0bb47 | 287 | .EX |
fea681da MK |
288 | #define _GNU_SOURCE |
289 | #include <link.h> | |
290 | #include <stdlib.h> | |
291 | #include <stdio.h> | |
8eb90116 | 292 | #include <stdint.h> |
fea681da MK |
293 | |
294 | static int | |
295 | callback(struct dl_phdr_info *info, size_t size, void *data) | |
296 | { | |
6736a802 | 297 | char *type; |
88893a77 | 298 | int p_type; |
6736a802 | 299 | |
d1a71985 | 300 | printf("Name: \e"%s\e" (%d segments)\en", info\->dlpi_name, |
6736a802 | 301 | info\->dlpi_phnum); |
fea681da | 302 | |
88893a77 | 303 | for (int j = 0; j < info\->dlpi_phnum; j++) { |
6736a802 MK |
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; | |
230ed833 | 315 | |
8eb90116 | 316 | printf(" %2d: [%14p; memsz:%7jx] flags: %#jx; ", j, |
6736a802 | 317 | (void *) (info\->dlpi_addr + info\->dlpi_phdr[j].p_vaddr), |
8eb90116 AC |
318 | (uintmax_t) info\->dlpi_phdr[j].p_memsz, |
319 | (uintmax_t) info\->dlpi_phdr[j].p_flags); | |
6736a802 | 320 | if (type != NULL) |
d1a71985 | 321 | printf("%s\en", type); |
6736a802 | 322 | else |
dc97703b | 323 | printf("[other (%#x)]\en", p_type); |
6736a802 | 324 | } |
fea681da | 325 | |
fea681da MK |
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 | } | |
e7d0bb47 | 336 | .EE |
47297adb | 337 | .SH SEE ALSO |
fea681da MK |
338 | .BR ldd (1), |
339 | .BR objdump (1), | |
340 | .BR readelf (1), | |
a7634f01 | 341 | .BR dladdr (3), |
fea681da | 342 | .BR dlopen (3), |
3f89dd3d | 343 | .BR elf (5), |
173fe7e7 | 344 | .BR ld.so (8) |
847e0d88 | 345 | .PP |
173fe7e7 | 346 | .IR "Executable and Linking Format Specification" , |
fea681da | 347 | available at various locations online. |