1/* Sniff out modules from ELF headers visible in memory segments. 2 Copyright (C) 2008-2012, 2014, 2015 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 "../libelf/libelfP.h" /* For NOTE_ALIGN. */ 31#undef _ 32#include "libdwflP.h" 33#include "common.h" 34 35#include <elf.h> 36#include <gelf.h> 37#include <inttypes.h> 38#include <sys/param.h> 39#include <endian.h> 40#include <unistd.h> 41#include <fcntl.h> 42 43 44/* A good size for the initial read from memory, if it's not too costly. 45 This more than covers the phdrs and note segment in the average 64-bit 46 binary. */ 47 48#define INITIAL_READ 1024 49 50#if __BYTE_ORDER == __LITTLE_ENDIAN 51# define MY_ELFDATA ELFDATA2LSB 52#else 53# define MY_ELFDATA ELFDATA2MSB 54#endif 55 56#ifndef MAX 57# define MAX(a, b) ((a) > (b) ? (a) : (b)) 58#endif 59 60 61/* Return user segment index closest to ADDR but not above it. 62 If NEXT, return the closest to ADDR but not below it. */ 63static int 64addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next) 65{ 66 int ndx = -1; 67 do 68 { 69 if (dwfl->lookup_segndx[segment] >= 0) 70 ndx = dwfl->lookup_segndx[segment]; 71 if (++segment >= dwfl->lookup_elts - 1) 72 return next ? ndx + 1 : ndx; 73 } 74 while (dwfl->lookup_addr[segment] < addr); 75 76 if (next) 77 { 78 while (dwfl->lookup_segndx[segment] < 0) 79 if (++segment >= dwfl->lookup_elts - 1) 80 return ndx + 1; 81 ndx = dwfl->lookup_segndx[segment]; 82 } 83 84 return ndx; 85} 86 87/* Return whether there is SZ bytes available at PTR till END. */ 88 89static bool 90buf_has_data (const void *ptr, const void *end, size_t sz) 91{ 92 return ptr < end && (size_t) (end - ptr) >= sz; 93} 94 95/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA. 96 Function comes from src/readelf.c . */ 97 98static bool 99buf_read_ulong (unsigned char ei_data, size_t sz, 100 const void **ptrp, const void *end, uint64_t *retp) 101{ 102 if (! buf_has_data (*ptrp, end, sz)) 103 return false; 104 105 union 106 { 107 uint64_t u64; 108 uint32_t u32; 109 } u; 110 111 memcpy (&u, *ptrp, sz); 112 (*ptrp) += sz; 113 114 if (retp == NULL) 115 return true; 116 117 if (MY_ELFDATA != ei_data) 118 { 119 if (sz == 4) 120 CONVERT (u.u32); 121 else 122 CONVERT (u.u64); 123 } 124 if (sz == 4) 125 *retp = u.u32; 126 else 127 *retp = u.u64; 128 return true; 129} 130 131/* Try to find matching entry for module from address MODULE_START to 132 MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE 133 bytes in format EI_CLASS and EI_DATA. */ 134 135static const char * 136handle_file_note (GElf_Addr module_start, GElf_Addr module_end, 137 unsigned char ei_class, unsigned char ei_data, 138 const void *note_file, size_t note_file_size) 139{ 140 if (note_file == NULL) 141 return NULL; 142 143 size_t sz; 144 switch (ei_class) 145 { 146 case ELFCLASS32: 147 sz = 4; 148 break; 149 case ELFCLASS64: 150 sz = 8; 151 break; 152 default: 153 return NULL; 154 } 155 156 const void *ptr = note_file; 157 const void *end = note_file + note_file_size; 158 uint64_t count; 159 if (! buf_read_ulong (ei_data, sz, &ptr, end, &count)) 160 return NULL; 161 if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size 162 return NULL; 163 164 uint64_t maxcount = (size_t) (end - ptr) / (3 * sz); 165 if (count > maxcount) 166 return NULL; 167 168 /* Where file names are stored. */ 169 const char *fptr = ptr + 3 * count * sz; 170 171 ssize_t firstix = -1; 172 ssize_t lastix = -1; 173 for (size_t mix = 0; mix < count; mix++) 174 { 175 uint64_t mstart, mend, moffset; 176 if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart) 177 || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend) 178 || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset)) 179 return NULL; 180 if (mstart == module_start && moffset == 0) 181 firstix = lastix = mix; 182 if (firstix != -1 && mstart < module_end) 183 lastix = mix; 184 if (mend >= module_end) 185 break; 186 } 187 if (firstix == -1) 188 return NULL; 189 190 const char *retval = NULL; 191 for (ssize_t mix = 0; mix <= lastix; mix++) 192 { 193 const char *fnext = memchr (fptr, 0, (const char *) end - fptr); 194 if (fnext == NULL) 195 return NULL; 196 if (mix == firstix) 197 retval = fptr; 198 if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0) 199 return NULL; 200 fptr = fnext + 1; 201 } 202 return retval; 203} 204 205/* Return true iff we are certain ELF cannot match BUILD_ID of 206 BUILD_ID_LEN bytes. Pass DISK_FILE_HAS_BUILD_ID as false if it is 207 certain ELF does not contain build-id (it is only a performance hit 208 to pass it always as true). */ 209 210static bool 211invalid_elf (Elf *elf, bool disk_file_has_build_id, 212 const void *build_id, size_t build_id_len) 213{ 214 if (! disk_file_has_build_id && build_id_len > 0) 215 { 216 /* Module found in segments with build-id is more reliable 217 than a module found via DT_DEBUG on disk without any 218 build-id. */ 219 return true; 220 } 221 if (disk_file_has_build_id && build_id_len > 0) 222 { 223 const void *elf_build_id; 224 ssize_t elf_build_id_len; 225 226 /* If there is a build id in the elf file, check it. */ 227 elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id); 228 if (elf_build_id_len > 0) 229 { 230 if (build_id_len != (size_t) elf_build_id_len 231 || memcmp (build_id, elf_build_id, build_id_len) != 0) 232 return true; 233 } 234 } 235 return false; 236} 237 238int 239dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, 240 Dwfl_Memory_Callback *memory_callback, 241 void *memory_callback_arg, 242 Dwfl_Module_Callback *read_eagerly, 243 void *read_eagerly_arg, 244 const void *note_file, size_t note_file_size, 245 const struct r_debug_info *r_debug_info) 246{ 247 size_t segment = ndx; 248 249 if (segment >= dwfl->lookup_elts) 250 segment = dwfl->lookup_elts - 1; 251 252 while (segment > 0 253 && (dwfl->lookup_segndx[segment] > ndx 254 || dwfl->lookup_segndx[segment] == -1)) 255 --segment; 256 257 while (dwfl->lookup_segndx[segment] < ndx) 258 if (++segment == dwfl->lookup_elts) 259 return 0; 260 261 GElf_Addr start = dwfl->lookup_addr[segment]; 262 263 inline bool segment_read (int segndx, 264 void **buffer, size_t *buffer_available, 265 GElf_Addr addr, size_t minread) 266 { 267 return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available, 268 addr, minread, memory_callback_arg); 269 } 270 271 inline void release_buffer (void **buffer, size_t *buffer_available) 272 { 273 if (*buffer != NULL) 274 (void) segment_read (-1, buffer, buffer_available, 0, 0); 275 } 276 277 /* First read in the file header and check its sanity. */ 278 279 void *buffer = NULL; 280 size_t buffer_available = INITIAL_READ; 281 Elf *elf = NULL; 282 int fd = -1; 283 284 /* We might have to reserve some memory for the phdrs. Set to NULL 285 here so we can always safely free it. */ 286 void *phdrsp = NULL; 287 288 inline int finish (void) 289 { 290 free (phdrsp); 291 release_buffer (&buffer, &buffer_available); 292 if (elf != NULL) 293 elf_end (elf); 294 if (fd != -1) 295 close (fd); 296 return ndx; 297 } 298 299 if (segment_read (ndx, &buffer, &buffer_available, 300 start, sizeof (Elf64_Ehdr)) 301 || memcmp (buffer, ELFMAG, SELFMAG) != 0) 302 return finish (); 303 304 inline bool read_portion (void **data, size_t *data_size, 305 GElf_Addr vaddr, size_t filesz) 306 { 307 if (vaddr - start + filesz > buffer_available 308 /* If we're in string mode, then don't consider the buffer we have 309 sufficient unless it contains the terminator of the string. */ 310 || (filesz == 0 && memchr (vaddr - start + buffer, '\0', 311 buffer_available - (vaddr - start)) == NULL)) 312 { 313 *data = NULL; 314 *data_size = filesz; 315 return segment_read (addr_segndx (dwfl, segment, vaddr, false), 316 data, data_size, vaddr, filesz); 317 } 318 319 /* We already have this whole note segment from our initial read. */ 320 *data = vaddr - start + buffer; 321 *data_size = 0; 322 return false; 323 } 324 325 inline void finish_portion (void **data, size_t *data_size) 326 { 327 if (*data_size != 0) 328 release_buffer (data, data_size); 329 } 330 331 /* Extract the information we need from the file header. */ 332 const unsigned char *e_ident; 333 unsigned char ei_class; 334 unsigned char ei_data; 335 uint16_t e_type; 336 union 337 { 338 Elf32_Ehdr e32; 339 Elf64_Ehdr e64; 340 } ehdr; 341 GElf_Off phoff; 342 uint_fast16_t phnum; 343 uint_fast16_t phentsize; 344 GElf_Off shdrs_end; 345 Elf_Data xlatefrom = 346 { 347 .d_type = ELF_T_EHDR, 348 .d_buf = (void *) buffer, 349 .d_version = EV_CURRENT, 350 }; 351 Elf_Data xlateto = 352 { 353 .d_type = ELF_T_EHDR, 354 .d_buf = &ehdr, 355 .d_size = sizeof ehdr, 356 .d_version = EV_CURRENT, 357 }; 358 e_ident = ((const unsigned char *) buffer); 359 ei_class = e_ident[EI_CLASS]; 360 ei_data = e_ident[EI_DATA]; 361 switch (ei_class) 362 { 363 case ELFCLASS32: 364 xlatefrom.d_size = sizeof (Elf32_Ehdr); 365 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) 366 return finish (); 367 e_type = ehdr.e32.e_type; 368 phoff = ehdr.e32.e_phoff; 369 phnum = ehdr.e32.e_phnum; 370 phentsize = ehdr.e32.e_phentsize; 371 if (phentsize != sizeof (Elf32_Phdr)) 372 return finish (); 373 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; 374 break; 375 376 case ELFCLASS64: 377 xlatefrom.d_size = sizeof (Elf64_Ehdr); 378 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) 379 return finish (); 380 e_type = ehdr.e64.e_type; 381 phoff = ehdr.e64.e_phoff; 382 phnum = ehdr.e64.e_phnum; 383 phentsize = ehdr.e64.e_phentsize; 384 if (phentsize != sizeof (Elf64_Phdr)) 385 return finish (); 386 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; 387 break; 388 389 default: 390 return finish (); 391 } 392 393 /* The file header tells where to find the program headers. 394 These are what we need to find the boundaries of the module. 395 Without them, we don't have a module to report. */ 396 397 if (phnum == 0) 398 return finish (); 399 400 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; 401 xlatefrom.d_size = phnum * phentsize; 402 403 void *ph_buffer = NULL; 404 size_t ph_buffer_size = 0; 405 if (read_portion (&ph_buffer, &ph_buffer_size, 406 start + phoff, xlatefrom.d_size)) 407 return finish (); 408 409 xlatefrom.d_buf = ph_buffer; 410 411 bool class32 = ei_class == ELFCLASS32; 412 size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr); 413 if (unlikely (phnum > SIZE_MAX / phdr_size)) 414 return finish (); 415 const size_t phdrsp_bytes = phnum * phdr_size; 416 phdrsp = malloc (phdrsp_bytes); 417 if (unlikely (phdrsp == NULL)) 418 return finish (); 419 420 xlateto.d_buf = phdrsp; 421 xlateto.d_size = phdrsp_bytes; 422 423 /* Track the bounds of the file visible in memory. */ 424 GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ 425 GElf_Off file_end = 0; /* Rounded up to effective page size. */ 426 GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ 427 GElf_Off total_filesz = 0; /* Total size of data to read. */ 428 429 /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */ 430 GElf_Addr bias = 0; 431 bool found_bias = false; 432 433 /* Collect the unbiased bounds of the module here. */ 434 GElf_Addr module_start = -1l; 435 GElf_Addr module_end = 0; 436 GElf_Addr module_address_sync = 0; 437 438 /* If we see PT_DYNAMIC, record it here. */ 439 GElf_Addr dyn_vaddr = 0; 440 GElf_Xword dyn_filesz = 0; 441 442 /* Collect the build ID bits here. */ 443 void *build_id = NULL; 444 size_t build_id_len = 0; 445 GElf_Addr build_id_vaddr = 0; 446 447 /* Consider a PT_NOTE we've found in the image. */ 448 inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz) 449 { 450 /* If we have already seen a build ID, we don't care any more. */ 451 if (build_id != NULL || filesz == 0) 452 return; 453 454 void *data; 455 size_t data_size; 456 if (read_portion (&data, &data_size, vaddr, filesz)) 457 return; 458 459 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); 460 461 void *notes; 462 if (ei_data == MY_ELFDATA) 463 notes = data; 464 else 465 { 466 notes = malloc (filesz); 467 if (unlikely (notes == NULL)) 468 return; 469 xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR; 470 xlatefrom.d_buf = (void *) data; 471 xlatefrom.d_size = filesz; 472 xlateto.d_buf = notes; 473 xlateto.d_size = filesz; 474 if (elf32_xlatetom (&xlateto, &xlatefrom, 475 ehdr.e32.e_ident[EI_DATA]) == NULL) 476 goto done; 477 } 478 479 const GElf_Nhdr *nh = notes; 480 while ((const void *) nh < (const void *) notes + filesz) 481 { 482 const void *note_name = nh + 1; 483 const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz); 484 if (unlikely ((size_t) ((const void *) notes + filesz 485 - note_desc) < nh->n_descsz)) 486 break; 487 488 if (nh->n_type == NT_GNU_BUILD_ID 489 && nh->n_descsz > 0 490 && nh->n_namesz == sizeof "GNU" 491 && !memcmp (note_name, "GNU", sizeof "GNU")) 492 { 493 build_id_vaddr = note_desc - (const void *) notes + vaddr; 494 build_id_len = nh->n_descsz; 495 build_id = malloc (nh->n_descsz); 496 if (likely (build_id != NULL)) 497 memcpy (build_id, note_desc, build_id_len); 498 break; 499 } 500 501 nh = note_desc + NOTE_ALIGN (nh->n_descsz); 502 } 503 504 done: 505 if (notes != data) 506 free (notes); 507 finish_portion (&data, &data_size); 508 } 509 510 /* Consider each of the program headers we've read from the image. */ 511 inline void consider_phdr (GElf_Word type, 512 GElf_Addr vaddr, GElf_Xword memsz, 513 GElf_Off offset, GElf_Xword filesz, 514 GElf_Xword align) 515 { 516 switch (type) 517 { 518 case PT_DYNAMIC: 519 dyn_vaddr = vaddr; 520 dyn_filesz = filesz; 521 break; 522 523 case PT_NOTE: 524 /* We calculate from the p_offset of the note segment, 525 because we don't yet know the bias for its p_vaddr. */ 526 consider_notes (start + offset, filesz); 527 break; 528 529 case PT_LOAD: 530 align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1; 531 532 GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align; 533 GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end; 534 GElf_Off filesz_offset = filesz_vaddr - vaddr + offset; 535 536 if (file_trimmed_end < offset + filesz) 537 { 538 file_trimmed_end = offset + filesz; 539 540 /* Trim the last segment so we don't bother with zeros 541 in the last page that are off the end of the file. 542 However, if the extra bit in that page includes the 543 section headers, keep them. */ 544 if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end) 545 { 546 filesz += shdrs_end - file_trimmed_end; 547 file_trimmed_end = shdrs_end; 548 } 549 } 550 551 total_filesz += filesz; 552 553 if (file_end < filesz_offset) 554 { 555 file_end = filesz_offset; 556 if (filesz_vaddr - start == filesz_offset) 557 contiguous = file_end; 558 } 559 560 if (!found_bias && (offset & -align) == 0 561 && likely (filesz_offset >= phoff + phnum * phentsize)) 562 { 563 bias = start - vaddr; 564 found_bias = true; 565 } 566 567 if ((vaddr & -align) < module_start) 568 { 569 module_start = vaddr & -align; 570 module_address_sync = vaddr + memsz; 571 } 572 573 if (module_end < vaddr_end) 574 module_end = vaddr_end; 575 break; 576 } 577 } 578 579 Elf32_Phdr (*p32)[phnum] = phdrsp; 580 Elf64_Phdr (*p64)[phnum] = phdrsp; 581 if (ei_class == ELFCLASS32) 582 { 583 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) 584 found_bias = false; /* Trigger error check. */ 585 else 586 for (uint_fast16_t i = 0; i < phnum; ++i) 587 consider_phdr ((*p32)[i].p_type, 588 (*p32)[i].p_vaddr, (*p32)[i].p_memsz, 589 (*p32)[i].p_offset, (*p32)[i].p_filesz, 590 (*p32)[i].p_align); 591 } 592 else 593 { 594 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) 595 found_bias = false; /* Trigger error check. */ 596 else 597 for (uint_fast16_t i = 0; i < phnum; ++i) 598 consider_phdr ((*p64)[i].p_type, 599 (*p64)[i].p_vaddr, (*p64)[i].p_memsz, 600 (*p64)[i].p_offset, (*p64)[i].p_filesz, 601 (*p64)[i].p_align); 602 } 603 604 finish_portion (&ph_buffer, &ph_buffer_size); 605 606 /* We must have seen the segment covering offset 0, or else the ELF 607 header we read at START was not produced by these program headers. */ 608 if (unlikely (!found_bias)) 609 { 610 free (build_id); 611 return finish (); 612 } 613 614 /* Now we know enough to report a module for sure: its bounds. */ 615 module_start += bias; 616 module_end += bias; 617 618 dyn_vaddr += bias; 619 620 /* NAME found from link map has precedence over DT_SONAME possibly read 621 below. */ 622 bool name_is_final = false; 623 624 /* Try to match up DYN_VADDR against L_LD as found in link map. 625 Segments sniffing may guess invalid address as the first read-only memory 626 mapping may not be dumped to the core file (if ELF headers are not dumped) 627 and the ELF header is dumped first with the read/write mapping of the same 628 file at higher addresses. */ 629 if (r_debug_info != NULL) 630 for (const struct r_debug_info_module *module = r_debug_info->module; 631 module != NULL; module = module->next) 632 if (module_start <= module->l_ld && module->l_ld < module_end) 633 { 634 /* L_LD read from link map must be right while DYN_VADDR is unsafe. 635 Therefore subtract DYN_VADDR and add L_LD to get a possibly 636 corrective displacement for all addresses computed so far. */ 637 GElf_Addr fixup = module->l_ld - dyn_vaddr; 638 if ((fixup & (dwfl->segment_align - 1)) == 0 639 && module_start + fixup <= module->l_ld 640 && module->l_ld < module_end + fixup) 641 { 642 module_start += fixup; 643 module_end += fixup; 644 dyn_vaddr += fixup; 645 bias += fixup; 646 if (module->name[0] != '\0') 647 { 648 name = basename (module->name); 649 name_is_final = true; 650 } 651 break; 652 } 653 } 654 655 if (r_debug_info != NULL) 656 { 657 bool skip_this_module = false; 658 for (struct r_debug_info_module *module = r_debug_info->module; 659 module != NULL; module = module->next) 660 if ((module_end > module->start && module_start < module->end) 661 || dyn_vaddr == module->l_ld) 662 { 663 if (module->elf != NULL 664 && invalid_elf (module->elf, module->disk_file_has_build_id, 665 build_id, build_id_len)) 666 { 667 elf_end (module->elf); 668 close (module->fd); 669 module->elf = NULL; 670 module->fd = -1; 671 } 672 if (module->elf != NULL) 673 { 674 /* Ignore this found module if it would conflict in address 675 space with any already existing module of DWFL. */ 676 skip_this_module = true; 677 } 678 } 679 if (skip_this_module) 680 { 681 free (build_id); 682 return finish (); 683 } 684 } 685 686 const char *file_note_name = handle_file_note (module_start, module_end, 687 ei_class, ei_data, 688 note_file, note_file_size); 689 if (file_note_name) 690 { 691 name = file_note_name; 692 name_is_final = true; 693 bool invalid = false; 694 fd = open (name, O_RDONLY); 695 if (fd >= 0) 696 { 697 Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false); 698 if (error == DWFL_E_NOERROR) 699 invalid = invalid_elf (elf, true /* disk_file_has_build_id */, 700 build_id, build_id_len); 701 } 702 if (invalid) 703 { 704 /* The file was there, but the build_id didn't match. We 705 still want to report the module, but need to get the ELF 706 some other way if possible. */ 707 close (fd); 708 fd = -1; 709 elf_end (elf); 710 elf = NULL; 711 } 712 } 713 714 /* Our return value now says to skip the segments contained 715 within the module. */ 716 ndx = addr_segndx (dwfl, segment, module_end, true); 717 718 /* Examine its .dynamic section to get more interesting details. 719 If it has DT_SONAME, we'll use that as the module name. 720 If it has a DT_DEBUG, then it's actually a PIE rather than a DSO. 721 We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, 722 and they also tell us the essential portion of the file 723 for fetching symbols. */ 724 GElf_Addr soname_stroff = 0; 725 GElf_Addr dynstr_vaddr = 0; 726 GElf_Xword dynstrsz = 0; 727 bool execlike = false; 728 inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) 729 { 730 switch (tag) 731 { 732 default: 733 return false; 734 735 case DT_DEBUG: 736 execlike = true; 737 break; 738 739 case DT_SONAME: 740 soname_stroff = val; 741 break; 742 743 case DT_STRTAB: 744 dynstr_vaddr = val; 745 break; 746 747 case DT_STRSZ: 748 dynstrsz = val; 749 break; 750 } 751 752 return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0; 753 } 754 755 const size_t dyn_entsize = (ei_class == ELFCLASS32 756 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); 757 void *dyn_data = NULL; 758 size_t dyn_data_size = 0; 759 if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 760 && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) 761 { 762 void *dyns = malloc (dyn_filesz); 763 Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns; 764 Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns; 765 if (unlikely (dyns == NULL)) 766 return finish (); 767 768 xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; 769 xlatefrom.d_buf = (void *) dyn_data; 770 xlatefrom.d_size = dyn_filesz; 771 xlateto.d_buf = dyns; 772 xlateto.d_size = dyn_filesz; 773 774 if (ei_class == ELFCLASS32) 775 { 776 if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) 777 for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i) 778 if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val)) 779 break; 780 } 781 else 782 { 783 if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) 784 for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i) 785 if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val)) 786 break; 787 } 788 free (dyns); 789 } 790 finish_portion (&dyn_data, &dyn_data_size); 791 792 /* We'll use the name passed in or a stupid default if not DT_SONAME. */ 793 if (name == NULL) 794 name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]"; 795 796 void *soname = NULL; 797 size_t soname_size = 0; 798 if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0) 799 { 800 /* We know the bounds of the .dynstr section. 801 802 The DYNSTR_VADDR pointer comes from the .dynamic section 803 (DT_STRTAB, detected above). Ordinarily the dynamic linker 804 will have adjusted this pointer in place so it's now an 805 absolute address. But sometimes .dynamic is read-only (in 806 vDSOs and odd architectures), and sometimes the adjustment 807 just hasn't happened yet in the memory image we looked at. 808 So treat DYNSTR_VADDR as an absolute address if it falls 809 within the module bounds, or try applying the phdr bias 810 when that adjusts it to fall within the module bounds. */ 811 812 if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end) 813 && dynstr_vaddr + bias >= module_start 814 && dynstr_vaddr + bias < module_end) 815 dynstr_vaddr += bias; 816 817 if (unlikely (dynstr_vaddr + dynstrsz > module_end)) 818 dynstrsz = 0; 819 820 /* Try to get the DT_SONAME string. */ 821 if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz 822 && ! read_portion (&soname, &soname_size, 823 dynstr_vaddr + soname_stroff, 0)) 824 name = soname; 825 } 826 827 /* Now that we have chosen the module's name and bounds, report it. 828 If we found a build ID, report that too. */ 829 830 Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, 831 module_start, module_end); 832 833 // !execlike && ET_EXEC is PIE. 834 // execlike && !ET_EXEC is a static executable. 835 if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC)) 836 mod->is_executable = true; 837 838 if (likely (mod != NULL) && build_id != NULL 839 && unlikely (INTUSE(dwfl_module_report_build_id) (mod, 840 build_id, 841 build_id_len, 842 build_id_vaddr))) 843 { 844 mod->gc = true; 845 mod = NULL; 846 } 847 848 /* At this point we do not need BUILD_ID or NAME any more. 849 They have been copied. */ 850 free (build_id); 851 finish_portion (&soname, &soname_size); 852 853 if (unlikely (mod == NULL)) 854 { 855 ndx = -1; 856 return finish (); 857 } 858 859 /* We have reported the module. Now let the caller decide whether we 860 should read the whole thing in right now. */ 861 862 const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz 863 : buffer_available >= contiguous ? 0 864 : contiguous - buffer_available); 865 const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0 866 : dynstr_vaddr + dynstrsz - start); 867 const GElf_Off whole = MAX (file_trimmed_end, shdrs_end); 868 869 if (elf == NULL 870 && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available, 871 cost, worthwhile, whole, contiguous, 872 read_eagerly_arg, &elf) 873 && elf == NULL) 874 { 875 /* The caller wants to read the whole file in right now, but hasn't 876 done it for us. Fill in a local image of the virtual file. */ 877 878 void *contents = calloc (1, file_trimmed_end); 879 if (unlikely (contents == NULL)) 880 return finish (); 881 882 inline void final_read (size_t offset, GElf_Addr vaddr, size_t size) 883 { 884 void *into = contents + offset; 885 size_t read_size = size; 886 (void) segment_read (addr_segndx (dwfl, segment, vaddr, false), 887 &into, &read_size, vaddr, size); 888 } 889 890 if (contiguous < file_trimmed_end) 891 { 892 /* We can't use the memory image verbatim as the file image. 893 So we'll be reading into a local image of the virtual file. */ 894 895 inline void read_phdr (GElf_Word type, GElf_Addr vaddr, 896 GElf_Off offset, GElf_Xword filesz) 897 { 898 if (type == PT_LOAD) 899 final_read (offset, vaddr + bias, filesz); 900 } 901 902 if (ei_class == ELFCLASS32) 903 for (uint_fast16_t i = 0; i < phnum; ++i) 904 read_phdr ((*p32)[i].p_type, (*p32)[i].p_vaddr, 905 (*p32)[i].p_offset, (*p32)[i].p_filesz); 906 else 907 for (uint_fast16_t i = 0; i < phnum; ++i) 908 read_phdr ((*p64)[i].p_type, (*p64)[i].p_vaddr, 909 (*p64)[i].p_offset, (*p64)[i].p_filesz); 910 } 911 else 912 { 913 /* The whole file sits contiguous in memory, 914 but the caller didn't want to just do it. */ 915 916 const size_t have = MIN (buffer_available, file_trimmed_end); 917 memcpy (contents, buffer, have); 918 919 if (have < file_trimmed_end) 920 final_read (have, start + have, file_trimmed_end - have); 921 } 922 923 elf = elf_memory (contents, file_trimmed_end); 924 if (unlikely (elf == NULL)) 925 free (contents); 926 else 927 elf->flags |= ELF_F_MALLOCED; 928 } 929 930 if (elf != NULL) 931 { 932 /* Install the file in the module. */ 933 mod->main.elf = elf; 934 elf = NULL; 935 fd = -1; 936 mod->main.vaddr = module_start - bias; 937 mod->main.address_sync = module_address_sync; 938 mod->main_bias = bias; 939 } 940 941 return finish (); 942} 943