Branch data Line data Source code
1 : : /* Report modules by examining dynamic linker data structures.
2 : : Copyright (C) 2008-2010 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #include <config.h>
30 : : #include "libdwflP.h"
31 : :
32 : : #include <byteswap.h>
33 : : #include <endian.h>
34 : :
35 : : /* This element is always provided and always has a constant value.
36 : : This makes it an easy thing to scan for to discern the format. */
37 : : #define PROBE_TYPE AT_PHENT
38 : : #define PROBE_VAL32 sizeof (Elf32_Phdr)
39 : : #define PROBE_VAL64 sizeof (Elf64_Phdr)
40 : :
41 : : #if BYTE_ORDER == BIG_ENDIAN
42 : : # define BE32(x) (x)
43 : : # define BE64(x) (x)
44 : : # define LE32(x) bswap_32 (x)
45 : : # define LE64(x) bswap_64 (x)
46 : : #else
47 : : # define LE32(x) (x)
48 : : # define LE64(x) (x)
49 : : # define BE32(x) bswap_32 (x)
50 : : # define BE64(x) bswap_64 (x)
51 : : #endif
52 : :
53 : :
54 : : /* Examine an auxv data block and determine its format.
55 : : Return true iff we figured it out. */
56 : : static bool
57 : 4 : auxv_format_probe (const void *auxv, size_t size,
58 : : uint_fast8_t *elfclass, uint_fast8_t *elfdata)
59 : : {
60 : 12 : const union
61 : : {
62 : 4 : char buf[size];
63 : 4 : Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
64 : 4 : Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
65 : 4 : } *u = auxv;
66 : :
67 : 22 : inline bool check64 (size_t i)
68 : : {
69 [ - + ]: 22 : if (u->a64[i].a_type == BE64 (PROBE_TYPE)
70 [ # # ]: 0 : && u->a64[i].a_un.a_val == BE64 (PROBE_VAL64))
71 : : {
72 : 0 : *elfdata = ELFDATA2MSB;
73 : 0 : return true;
74 : : }
75 : :
76 [ + + ]: 22 : if (u->a64[i].a_type == LE64 (PROBE_TYPE)
77 [ + - ]: 2 : && u->a64[i].a_un.a_val == LE64 (PROBE_VAL64))
78 : : {
79 : 2 : *elfdata = ELFDATA2LSB;
80 : 22 : return true;
81 : : }
82 : :
83 : : return false;
84 : : }
85 : :
86 : 38 : inline bool check32 (size_t i)
87 : : {
88 [ + + ]: 38 : if (u->a32[i].a_type == BE32 (PROBE_TYPE)
89 [ + - ]: 1 : && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32))
90 : : {
91 : 1 : *elfdata = ELFDATA2MSB;
92 : 1 : return true;
93 : : }
94 : :
95 [ + + ]: 37 : if (u->a32[i].a_type == LE32 (PROBE_TYPE)
96 [ + - ]: 1 : && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32))
97 : : {
98 : 1 : *elfdata = ELFDATA2LSB;
99 : 38 : return true;
100 : : }
101 : :
102 : : return false;
103 : : }
104 : :
105 [ + - ]: 26 : for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
106 : : {
107 [ + + ]: 22 : if (check64 (i))
108 : : {
109 : 2 : *elfclass = ELFCLASS64;
110 : 2 : return true;
111 : : }
112 : :
113 [ + + ][ - + ]: 20 : if (check32 (i * 2) || check32 (i * 2 + 1))
114 : : {
115 : 2 : *elfclass = ELFCLASS32;
116 : 2 : return true;
117 : : }
118 : : }
119 : :
120 : : return false;
121 : : }
122 : :
123 : : /* This is a Dwfl_Memory_Callback that wraps another memory callback.
124 : : If the underlying callback cannot fill the data, then this will
125 : : fall back to fetching data from module files. */
126 : :
127 : : struct integrated_memory_callback
128 : : {
129 : : Dwfl_Memory_Callback *memory_callback;
130 : : void *memory_callback_arg;
131 : : void *buffer;
132 : : };
133 : :
134 : : static bool
135 : 54 : integrated_memory_callback (Dwfl *dwfl, int ndx,
136 : : void **buffer, size_t *buffer_available,
137 : : GElf_Addr vaddr,
138 : : size_t minread,
139 : : void *arg)
140 : : {
141 : 54 : struct integrated_memory_callback *info = arg;
142 : :
143 [ + + ]: 54 : if (ndx == -1)
144 : : {
145 : : /* Called for cleanup. */
146 [ + - ]: 24 : if (info->buffer != NULL)
147 : : {
148 : : /* The last probe buffer came from the underlying callback.
149 : : Let it do its cleanup. */
150 [ - + ]: 24 : assert (*buffer == info->buffer); /* XXX */
151 : 24 : *buffer = info->buffer;
152 : 24 : info->buffer = NULL;
153 : 24 : return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
154 : : vaddr, minread,
155 : : info->memory_callback_arg);
156 : : }
157 : 0 : *buffer = NULL;
158 : 0 : *buffer_available = 0;
159 : : return false;
160 : : }
161 : :
162 [ - + ]: 30 : if (*buffer != NULL)
163 : : /* For a final-read request, we only use the underlying callback. */
164 : 0 : return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
165 : : vaddr, minread, info->memory_callback_arg);
166 : :
167 : : /* Let the underlying callback try to fill this request. */
168 [ + + ]: 30 : if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
169 : : vaddr, minread, info->memory_callback_arg))
170 : : {
171 : 24 : *buffer = info->buffer;
172 : : return true;
173 : : }
174 : :
175 : : /* Now look for module text covering this address. */
176 : :
177 : : Dwfl_Module *mod;
178 : 6 : (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
179 [ + + ]: 6 : if (mod == NULL)
180 : : return false;
181 : :
182 : : Dwarf_Addr bias;
183 : 4 : Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
184 [ - + ]: 4 : if (unlikely (scn == NULL))
185 : : {
186 : : #if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
187 : : /* If we have no sections we can try to fill it from the module file
188 : : based on its phdr mappings. */
189 : : if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
190 : : return INTUSE(dwfl_elf_phdr_memory_callback)
191 : : (dwfl, 0, buffer, buffer_available,
192 : : vaddr - mod->main.bias, minread, mod->main.elf);
193 : : #endif
194 : : return false;
195 : : }
196 : :
197 : 0 : Elf_Data *data = elf_rawdata (scn, NULL);
198 [ # # ]: 0 : if (unlikely (data == NULL))
199 : : // XXX throw error?
200 : : return false;
201 : :
202 [ # # ]: 0 : if (unlikely (data->d_size < vaddr))
203 : : return false;
204 : :
205 : : /* Provide as much data as we have. */
206 : 0 : void *contents = data->d_buf + vaddr;
207 : 0 : size_t avail = data->d_size - vaddr;
208 [ # # ]: 0 : if (unlikely (avail < minread))
209 : : return false;
210 : :
211 : : /* If probing for a string, make sure it's terminated. */
212 [ # # ][ # # ]: 0 : if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
213 : : return false;
214 : :
215 : : /* We have it! */
216 : 0 : *buffer = contents;
217 : 54 : *buffer_available = avail;
218 : : return true;
219 : : }
220 : :
221 : : static size_t
222 : : addrsize (uint_fast8_t elfclass)
223 : : {
224 : 22 : return elfclass * 4;
225 : : }
226 : :
227 : : /* Report a module for each struct link_map in the linked list at r_map
228 : : in the struct r_debug at R_DEBUG_VADDR.
229 : :
230 : : For each link_map entry, if an existing module resides at its address,
231 : : this just modifies that module's name and suggested file name. If
232 : : no such module exists, this calls dwfl_report_elf on the l_name string.
233 : :
234 : : Returns the number of modules found, or -1 for errors. */
235 : :
236 : : static int
237 : 3 : report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
238 : : Dwfl *dwfl, GElf_Addr r_debug_vaddr,
239 : : Dwfl_Memory_Callback *memory_callback,
240 : : void *memory_callback_arg)
241 : : {
242 : : /* Skip r_version, to aligned r_map field. */
243 : 3 : GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
244 : :
245 : 3 : void *buffer = NULL;
246 : 3 : size_t buffer_available = 0;
247 : 33 : inline int release_buffer (int result)
248 : : {
249 [ + + ]: 33 : if (buffer != NULL)
250 : 24 : (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
251 : : memory_callback_arg);
252 : 33 : return result;
253 : : }
254 : :
255 : : GElf_Addr addrs[4];
256 : 19 : inline bool read_addrs (GElf_Addr vaddr, size_t n)
257 : : {
258 : 38 : size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */
259 : :
260 : : /* Read a new buffer if the old one doesn't cover these words. */
261 [ + + ]: 19 : if (buffer == NULL
262 [ + + ]: 10 : || vaddr < read_vaddr
263 [ + + ]: 8 : || vaddr - read_vaddr + nb > buffer_available)
264 : : {
265 : 16 : release_buffer (0);
266 : :
267 : 16 : read_vaddr = vaddr;
268 : 16 : int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
269 [ + - ]: 16 : if (unlikely (segndx < 0)
270 [ + - ]: 16 : || unlikely (! (*memory_callback) (dwfl, segndx,
271 : : &buffer, &buffer_available,
272 : : vaddr, nb, memory_callback_arg)))
273 : : return true;
274 : : }
275 : :
276 : 38 : const union
277 : : {
278 : 19 : Elf32_Addr a32[n];
279 : 19 : Elf64_Addr a64[n];
280 : 19 : } *in = vaddr - read_vaddr + buffer;
281 : :
282 [ + + ]: 19 : if (elfclass == ELFCLASS32)
283 : : {
284 [ + + ]: 14 : if (elfdata == ELFDATA2MSB)
285 [ + + ]: 32 : for (size_t i = 0; i < n; ++i)
286 [ - + ]: 25 : addrs[i] = BE32 (in->a32[i]);
287 : : else
288 [ + + ]: 32 : for (size_t i = 0; i < n; ++i)
289 : 25 : addrs[i] = LE32 (in->a32[i]);
290 : : }
291 : : else
292 : : {
293 [ + - ]: 5 : if (elfdata == ELFDATA2MSB)
294 [ # # ]: 0 : for (size_t i = 0; i < n; ++i)
295 [ # # ]: 0 : addrs[i] = BE64 (in->a64[i]);
296 : : else
297 [ + + ]: 36 : for (size_t i = 0; i < n; ++i)
298 : 17 : addrs[i] = LE64 (in->a64[i]);
299 : : }
300 : :
301 : : return false;
302 : : }
303 : :
304 [ - + ]: 3 : if (unlikely (read_addrs (read_vaddr, 1)))
305 : 0 : return release_buffer (-1);
306 : :
307 : 3 : GElf_Addr next = addrs[0];
308 : :
309 : 3 : Dwfl_Module **lastmodp = &dwfl->modulelist;
310 : 3 : int result = 0;
311 : :
312 : : /* There can't be more elements in the link_map list than there are
313 : : segments. DWFL->lookup_elts is probably twice that number, so it
314 : : is certainly above the upper bound. If we iterate too many times,
315 : : there must be a loop in the pointers due to link_map clobberation. */
316 : 3 : size_t iterations = 0;
317 [ + + ][ + - ]: 19 : while (next != 0 && ++iterations < dwfl->lookup_elts)
318 : : {
319 [ - + ]: 16 : if (read_addrs (next, 4))
320 : 0 : return release_buffer (-1);
321 : :
322 : 16 : GElf_Addr l_addr = addrs[0];
323 : 16 : GElf_Addr l_name = addrs[1];
324 : 16 : GElf_Addr l_ld = addrs[2];
325 : 16 : next = addrs[3];
326 : :
327 : : /* If a clobbered or truncated memory image has no useful pointer,
328 : : just skip this element. */
329 [ + + ]: 16 : if (l_ld == 0)
330 : 1 : continue;
331 : :
332 : : /* Fetch the string at the l_name address. */
333 : 15 : const char *name = NULL;
334 [ + - ]: 15 : if (buffer != NULL
335 [ + + ]: 15 : && read_vaddr <= l_name
336 [ + - ]: 1 : && l_name + 1 - read_vaddr < buffer_available
337 [ - + ]: 1 : && memchr (l_name - read_vaddr + buffer, '\0',
338 : 1 : buffer_available - (l_name - read_vaddr)) != NULL)
339 : : name = l_name - read_vaddr + buffer;
340 : : else
341 : : {
342 : 14 : release_buffer (0);
343 : 14 : read_vaddr = l_name;
344 : 14 : int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
345 [ + - ]: 14 : if (likely (segndx >= 0)
346 [ + + ]: 14 : && (*memory_callback) (dwfl, segndx,
347 : : &buffer, &buffer_available,
348 : : l_name, 0, memory_callback_arg))
349 : 8 : name = buffer;
350 : : }
351 : :
352 [ + + ][ - + ]: 15 : if (name != NULL && name[0] == '\0')
353 : 0 : name = NULL;
354 : :
355 : : /* If content-sniffing already reported a module covering
356 : : the same area, find that existing module to adjust.
357 : : The l_ld address is the only one we know for sure
358 : : to be within the module's own segments (its .dynamic). */
359 : 15 : Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, l_ld);
360 [ + + ]: 15 : if (mod != NULL)
361 : : {
362 : : /* We have a module. We can give it a better name from l_name. */
363 [ + + ][ + + ]: 14 : if (name != NULL && mod->name[0] == '[')
364 : : {
365 : 5 : char *newname = strdup (basename (name));
366 [ + - ]: 5 : if (newname != NULL)
367 : : {
368 : 5 : free (mod->name);
369 : 5 : mod->name = newname;
370 : : }
371 : : }
372 : :
373 [ + + ][ - + ]: 14 : if (name == NULL && mod->name[0] == '/')
374 : 0 : name = mod->name;
375 : :
376 : : /* If we don't have a file for it already, we can pre-install
377 : : the full file name from l_name. Opening the file by this
378 : : name will be the fallback when no build ID match is found.
379 : : XXX hook for sysroot */
380 [ + + ][ + - ]: 14 : if (name != NULL && mod->main.name == NULL)
381 : 9 : mod->main.name = strdup (name);
382 : : }
383 [ - + ]: 1 : else if (name != NULL)
384 : : {
385 : : /* We have to find the file's phdrs to compute along with l_addr
386 : : what its runtime address boundaries are. */
387 : :
388 : : // XXX hook for sysroot
389 : 0 : mod = INTUSE(dwfl_report_elf) (dwfl, basename (name),
390 : : name, -1, l_addr);
391 : : }
392 : :
393 [ + + ]: 15 : if (mod != NULL)
394 : : {
395 : 14 : ++result;
396 : :
397 : : /* Move this module to the end of the list, so that we end
398 : : up with a list in the same order as the link_map chain. */
399 [ + + ]: 14 : if (mod->next != NULL)
400 : : {
401 [ + + ]: 13 : if (*lastmodp != mod)
402 : : {
403 : 11 : lastmodp = &dwfl->modulelist;
404 [ + + ]: 18 : while (*lastmodp != mod)
405 : 7 : lastmodp = &(*lastmodp)->next;
406 : : }
407 : 13 : *lastmodp = mod->next;
408 : 13 : mod->next = NULL;
409 [ + + ]: 63 : while (*lastmodp != NULL)
410 : 50 : lastmodp = &(*lastmodp)->next;
411 : 13 : *lastmodp = mod;
412 : : }
413 : :
414 : 16 : lastmodp = &mod->next;
415 : : }
416 : : }
417 : :
418 : 3 : return release_buffer (result);
419 : : }
420 : :
421 : : static GElf_Addr
422 : 0 : consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
423 : : uint_fast8_t *elfclass, uint_fast8_t *elfdata,
424 : : Dwfl_Memory_Callback *memory_callback,
425 : : void *memory_callback_arg)
426 : : {
427 : : GElf_Ehdr ehdr;
428 [ # # ]: 0 : if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
429 : : return 0;
430 : :
431 [ # # ]: 0 : if (at_entry != 0)
432 : : {
433 : : /* If we have an AT_ENTRY value, reject this executable if
434 : : its entry point address could not have supplied that. */
435 : :
436 [ # # ]: 0 : if (ehdr.e_entry == 0)
437 : : return 0;
438 : :
439 [ # # ]: 0 : if (mod->e_type == ET_EXEC)
440 : : {
441 [ # # ]: 0 : if (ehdr.e_entry != at_entry)
442 : : return 0;
443 : : }
444 : : else
445 : : {
446 : : /* It could be a PIE. */
447 : : }
448 : : }
449 : :
450 : : // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
451 : : /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory
452 : : address where &r_debug was written at runtime. */
453 : 0 : GElf_Xword align = mod->dwfl->segment_align;
454 : 0 : GElf_Addr d_val_vaddr = 0;
455 [ # # ]: 0 : for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
456 : : {
457 : : GElf_Phdr phdr_mem;
458 : 0 : GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
459 [ # # ]: 0 : if (phdr == NULL)
460 : : break;
461 : :
462 [ # # ][ # # ]: 0 : if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
[ # # ]
463 : 0 : align = phdr->p_align;
464 : :
465 [ # # ]: 0 : if (at_phdr != 0
466 [ # # ]: 0 : && phdr->p_type == PT_LOAD
467 [ # # ]: 0 : && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
468 : : {
469 : : /* This is the segment that would map the phdrs.
470 : : If we have an AT_PHDR value, reject this executable
471 : : if its phdr mapping could not have supplied that. */
472 [ # # ]: 0 : if (mod->e_type == ET_EXEC)
473 : : {
474 [ # # ]: 0 : if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
475 : : return 0;
476 : : }
477 : : else
478 : : {
479 : : /* It could be a PIE. If the AT_PHDR value and our
480 : : phdr address don't match modulo ALIGN, then this
481 : : could not have been the right PIE. */
482 [ # # ]: 0 : if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
483 : 0 : != (at_phdr & -align))
484 : : return 0;
485 : :
486 : : /* Calculate the bias applied to the PIE's p_vaddr values. */
487 : 0 : GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
488 : 0 : + phdr->p_vaddr));
489 : :
490 : : /* Final sanity check: if we have an AT_ENTRY value,
491 : : reject this PIE unless its biased e_entry matches. */
492 [ # # ][ # # ]: 0 : if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
493 : : return 0;
494 : :
495 : : /* If we're changing the module's address range,
496 : : we've just invalidated the module lookup table. */
497 : 0 : GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
498 [ # # ]: 0 : if (bias != mod_bias)
499 : : {
500 : 0 : mod->low_addr -= mod_bias;
501 : 0 : mod->high_addr -= mod_bias;
502 : 0 : mod->low_addr += bias;
503 : 0 : mod->high_addr += bias;
504 : :
505 : 0 : free (mod->dwfl->lookup_module);
506 : 0 : mod->dwfl->lookup_module = NULL;
507 : : }
508 : : }
509 : : }
510 : :
511 [ # # ]: 0 : if (phdr->p_type == PT_DYNAMIC)
512 : : {
513 : 0 : Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
514 : : phdr->p_filesz, ELF_T_DYN);
515 [ # # ]: 0 : if (data == NULL)
516 : 0 : continue;
517 : 0 : const size_t entsize = gelf_fsize (mod->main.elf,
518 : : ELF_T_DYN, 1, EV_CURRENT);
519 : 0 : const size_t n = data->d_size / entsize;
520 [ # # ]: 0 : for (size_t j = 0; j < n; ++j)
521 : : {
522 : : GElf_Dyn dyn_mem;
523 : 0 : GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
524 [ # # ][ # # ]: 0 : if (dyn != NULL && dyn->d_tag == DT_DEBUG)
525 : : {
526 : 0 : d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
527 : : break;
528 : : }
529 : : }
530 : : }
531 : : }
532 : :
533 [ # # ]: 0 : if (d_val_vaddr != 0)
534 : : {
535 : : /* Now we have the final address from which to read &r_debug. */
536 : 0 : d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
537 : :
538 : 0 : void *buffer = NULL;
539 : 0 : size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
540 : :
541 : 0 : int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
542 : :
543 [ # # ]: 0 : if ((*memory_callback) (mod->dwfl, segndx,
544 : : &buffer, &buffer_available,
545 : : d_val_vaddr, buffer_available,
546 : : memory_callback_arg))
547 : : {
548 : : const union
549 : : {
550 : : Elf32_Addr a32;
551 : : Elf64_Addr a64;
552 : 0 : } *u = buffer;
553 : :
554 : : GElf_Addr vaddr;
555 [ # # ]: 0 : if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
556 [ # # ]: 0 : vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
557 [ # # ]: 0 : ? BE32 (u->a32) : LE32 (u->a32));
558 : : else
559 : 0 : vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
560 [ # # ][ # # ]: 0 : ? BE64 (u->a64) : LE64 (u->a64));
561 : :
562 : 0 : (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
563 : : memory_callback_arg);
564 : :
565 [ # # ]: 0 : if (*elfclass == ELFCLASSNONE)
566 : 0 : *elfclass = ehdr.e_ident[EI_CLASS];
567 [ # # ]: 0 : else if (*elfclass != ehdr.e_ident[EI_CLASS])
568 : : return 0;
569 : :
570 [ # # ]: 0 : if (*elfdata == ELFDATANONE)
571 : 0 : *elfdata = ehdr.e_ident[EI_DATA];
572 [ # # ]: 0 : else if (*elfdata != ehdr.e_ident[EI_DATA])
573 : : return 0;
574 : :
575 : : return vaddr;
576 : : }
577 : : }
578 : :
579 : : return 0;
580 : : }
581 : :
582 : : /* Try to find an existing executable module with a DT_DEBUG. */
583 : : static GElf_Addr
584 : 0 : find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
585 : : uint_fast8_t *elfclass, uint_fast8_t *elfdata,
586 : : Dwfl_Memory_Callback *memory_callback,
587 : : void *memory_callback_arg)
588 : : {
589 [ # # ]: 0 : for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
590 [ # # ]: 0 : if (mod->main.elf != NULL)
591 : : {
592 : 0 : GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
593 : : elfclass, elfdata,
594 : : memory_callback,
595 : : memory_callback_arg);
596 [ # # ]: 0 : if (r_debug_vaddr != 0)
597 : : return r_debug_vaddr;
598 : : }
599 : :
600 : : return 0;
601 : : }
602 : :
603 : :
604 : : int
605 : 4 : dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
606 : : Dwfl_Memory_Callback *memory_callback,
607 : : void *memory_callback_arg)
608 : : {
609 : 4 : GElf_Addr r_debug_vaddr = 0;
610 : :
611 : 4 : uint_fast8_t elfclass = ELFCLASSNONE;
612 : 4 : uint_fast8_t elfdata = ELFDATANONE;
613 [ + - ]: 4 : if (likely (auxv != NULL)
614 [ + - ]: 4 : && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
615 : : {
616 : 4 : GElf_Addr entry = 0;
617 : 4 : GElf_Addr phdr = 0;
618 : 4 : GElf_Xword phent = 0;
619 : 4 : GElf_Xword phnum = 0;
620 : :
621 : : #define AUXV_SCAN(NN, BL) do \
622 : : { \
623 : : const Elf##NN##_auxv_t *av = auxv; \
624 : : for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \
625 : : { \
626 : : Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val); \
627 : : if (av[i].a_type == BL##NN (AT_ENTRY)) \
628 : : entry = val; \
629 : : else if (av[i].a_type == BL##NN (AT_PHDR)) \
630 : : phdr = val; \
631 : : else if (av[i].a_type == BL##NN (AT_PHNUM)) \
632 : : phnum = val; \
633 : : else if (av[i].a_type == BL##NN (AT_PHENT)) \
634 : : phent = val; \
635 : : else if (av[i].a_type == BL##NN (AT_PAGESZ)) \
636 : : { \
637 : : if (val > 1 \
638 : : && (dwfl->segment_align == 0 \
639 : : || val < dwfl->segment_align)) \
640 : : dwfl->segment_align = val; \
641 : : } \
642 : : } \
643 : : } \
644 : : while (0)
645 : :
646 [ + + ]: 4 : if (elfclass == ELFCLASS32)
647 : : {
648 [ + + ]: 2 : if (elfdata == ELFDATA2MSB)
649 [ - + ][ + + ]: 26 : AUXV_SCAN (32, BE);
[ + + ][ + + ]
[ + + ][ + + ]
[ + - ][ + - ]
[ - + ][ + + ]
650 : : else
651 [ + + ][ + + ]: 21 : AUXV_SCAN (32, LE);
[ + + ][ + + ]
[ + + ][ + - ]
[ + - ][ - + ]
[ + + ]
652 : : }
653 : : else
654 : : {
655 [ + - ]: 2 : if (elfdata == ELFDATA2MSB)
656 [ # # ][ # # ]: 0 : AUXV_SCAN (64, BE);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
657 : : else
658 [ + + ][ + + ]: 40 : AUXV_SCAN (64, LE);
[ + + ][ + + ]
[ + + ][ + - ]
[ + - ][ - + ]
[ + + ]
659 : : }
660 : :
661 : : /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */
662 : 4 : GElf_Addr dyn_vaddr = 0;
663 : 4 : GElf_Xword dyn_filesz = 0;
664 : 4 : GElf_Addr dyn_bias = (GElf_Addr) -1;
665 : :
666 : 17 : inline bool consider_phdr (GElf_Word type,
667 : : GElf_Addr vaddr, GElf_Xword filesz)
668 : : {
669 [ + + + ]: 17 : switch (type)
670 : : {
671 : : case PT_PHDR:
672 [ + - ]: 3 : if (dyn_bias == (GElf_Addr) -1
673 : : /* Do a sanity check on the putative address. */
674 [ + - ]: 3 : && ((vaddr & (dwfl->segment_align - 1))
675 : 6 : == (phdr & (dwfl->segment_align - 1))))
676 : : {
677 : 3 : dyn_bias = phdr - vaddr;
678 : 3 : return dyn_vaddr != 0;
679 : : }
680 : : break;
681 : :
682 : : case PT_DYNAMIC:
683 : 3 : dyn_vaddr = vaddr;
684 : 3 : dyn_filesz = filesz;
685 : 17 : return dyn_bias != (GElf_Addr) -1;
686 : : }
687 : :
688 : : return false;
689 : : }
690 : :
691 [ + - ][ + - ]: 4 : if (phdr != 0 && phnum != 0)
692 : : {
693 : : Dwfl_Module *phdr_mod;
694 : 4 : int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
695 : 8 : Elf_Data in =
696 : : {
697 : : .d_type = ELF_T_PHDR,
698 : : .d_version = EV_CURRENT,
699 : 4 : .d_size = phnum * phent,
700 : : .d_buf = NULL
701 : : };
702 [ + - ]: 4 : if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size,
703 : : phdr, phnum * phent, memory_callback_arg))
704 : : {
705 : 4 : union
706 : : {
707 : : Elf32_Phdr p32;
708 : : Elf64_Phdr p64;
709 : 4 : char data[phnum * phent];
710 : 4 : } buf;
711 : 8 : Elf_Data out =
712 : : {
713 : : .d_type = ELF_T_PHDR,
714 : : .d_version = EV_CURRENT,
715 : : .d_size = phnum * phent,
716 : 4 : .d_buf = &buf
717 : : };
718 : 4 : in.d_size = out.d_size;
719 [ + + ][ + - ]: 4 : if (likely ((elfclass == ELFCLASS32
720 : : ? elf32_xlatetom : elf64_xlatetom)
721 : : (&out, &in, elfdata) != NULL))
722 : : {
723 : : /* We are looking for PT_DYNAMIC. */
724 : 8 : const union
725 : : {
726 : 4 : Elf32_Phdr p32[phnum];
727 : 4 : Elf64_Phdr p64[phnum];
728 : 4 : } *u = (void *) &buf;
729 [ + + ]: 4 : if (elfclass == ELFCLASS32)
730 : : {
731 [ + - ]: 10 : for (size_t i = 0; i < phnum; ++i)
732 [ + + ]: 10 : if (consider_phdr (u->p32[i].p_type,
733 : 10 : u->p32[i].p_vaddr,
734 : 10 : u->p32[i].p_filesz))
735 : : break;
736 : : }
737 : : else
738 : : {
739 [ + + ]: 8 : for (size_t i = 0; i < phnum; ++i)
740 [ + + ]: 7 : if (consider_phdr (u->p64[i].p_type,
741 : : u->p64[i].p_vaddr,
742 : : u->p64[i].p_filesz))
743 : : break;
744 : : }
745 : : }
746 : :
747 : 4 : (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
748 : : memory_callback_arg);
749 : : }
750 : : else
751 : : /* We could not read the executable's phdrs from the
752 : : memory image. If we have a presupplied executable,
753 : : we can still use the AT_PHDR and AT_ENTRY values to
754 : : verify it, and to adjust its bias if it's a PIE.
755 : :
756 : : If there was an ET_EXEC module presupplied that contains
757 : : the AT_PHDR address, then we only consider that one.
758 : : We'll either accept it if its phdr location and e_entry
759 : : make sense or reject it if they don't. If there is no
760 : : presupplied ET_EXEC, then look for a presupplied module,
761 : : which might be a PIE (ET_DYN) that needs its bias adjusted. */
762 : 4 : r_debug_vaddr = ((phdr_mod == NULL
763 [ # # ]: 0 : || phdr_mod->main.elf == NULL
764 [ # # ]: 0 : || phdr_mod->e_type != ET_EXEC)
765 : : ? find_executable (dwfl, phdr, entry,
766 : : &elfclass, &elfdata,
767 : : memory_callback,
768 : : memory_callback_arg)
769 [ # # ]: 0 : : consider_executable (phdr_mod, phdr, entry,
770 : : &elfclass, &elfdata,
771 : : memory_callback,
772 : : memory_callback_arg));
773 : : }
774 : :
775 : : /* If we found PT_DYNAMIC, search it for DT_DEBUG. */
776 [ + + ]: 4 : if (dyn_filesz != 0)
777 : : {
778 [ + - ]: 3 : if (dyn_bias != (GElf_Addr) -1)
779 : 3 : dyn_vaddr += dyn_bias;
780 : :
781 : 3 : Elf_Data in =
782 : : {
783 : : .d_type = ELF_T_DYN,
784 : : .d_version = EV_CURRENT,
785 : : .d_size = dyn_filesz,
786 : : .d_buf = NULL
787 : : };
788 : 3 : int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
789 [ + - ]: 3 : if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
790 : : dyn_vaddr, dyn_filesz, memory_callback_arg))
791 : : {
792 : 6 : union
793 : : {
794 : : Elf32_Dyn d32;
795 : : Elf64_Dyn d64;
796 : 3 : char data[dyn_filesz];
797 : 3 : } buf;
798 : 6 : Elf_Data out =
799 : : {
800 : : .d_type = ELF_T_DYN,
801 : : .d_version = EV_CURRENT,
802 : : .d_size = dyn_filesz,
803 : 3 : .d_buf = &buf
804 : : };
805 : 3 : in.d_size = out.d_size;
806 [ + + ][ + - ]: 3 : if (likely ((elfclass == ELFCLASS32
807 : : ? elf32_xlatetom : elf64_xlatetom)
808 : : (&out, &in, elfdata) != NULL))
809 : : {
810 : : /* We are looking for DT_DEBUG. */
811 : 6 : const union
812 : : {
813 : 3 : Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)];
814 : 3 : Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)];
815 : 3 : } *u = (void *) &buf;
816 [ + + ]: 3 : if (elfclass == ELFCLASS32)
817 : : {
818 : 2 : size_t n = dyn_filesz / sizeof (Elf32_Dyn);
819 [ + - ]: 28 : for (size_t i = 0; i < n; ++i)
820 [ + + ]: 28 : if (u->d32[i].d_tag == DT_DEBUG)
821 : : {
822 : 2 : r_debug_vaddr = u->d32[i].d_un.d_val;
823 : 2 : break;
824 : : }
825 : : }
826 : : else
827 : : {
828 : 1 : size_t n = dyn_filesz / sizeof (Elf64_Dyn);
829 [ + - ]: 10 : for (size_t i = 0; i < n; ++i)
830 [ + + ]: 10 : if (u->d64[i].d_tag == DT_DEBUG)
831 : : {
832 : 1 : r_debug_vaddr = u->d64[i].d_un.d_val;
833 : 1 : break;
834 : : }
835 : : }
836 : : }
837 : :
838 : 3 : (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
839 : : memory_callback_arg);
840 : : }
841 : : }
842 : : }
843 : : else
844 : : /* We have to look for a presupplied executable file to determine
845 : : the vaddr of its dynamic section and DT_DEBUG therein. */
846 : 0 : r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
847 : : memory_callback, memory_callback_arg);
848 : :
849 [ + + ]: 4 : if (r_debug_vaddr == 0)
850 : : return 0;
851 : :
852 : : /* For following pointers from struct link_map, we will use an
853 : : integrated memory access callback that can consult module text
854 : : elided from the core file. This is necessary when the l_name
855 : : pointer for the dynamic linker's own entry is a pointer into the
856 : : executable's .interp section. */
857 : 3 : struct integrated_memory_callback mcb =
858 : : {
859 : : .memory_callback = memory_callback,
860 : : .memory_callback_arg = memory_callback_arg
861 : : };
862 : :
863 : : /* Now we can follow the dynamic linker's library list. */
864 : 4 : return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
865 : : &integrated_memory_callback, &mcb);
866 : : }
867 : 0 : INTDEF (dwfl_link_map_report)
|