1 /* libunwind - a platform-independent unwind library 2 Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. 3 Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com> 4 5 This file is part of libunwind. 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 "Software"), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be 16 included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 25 26 /* Locate an FDE via the ELF data-structures defined by LSB v1.3 27 (http://www.linuxbase.org/spec/). */ 28 29 #include <stddef.h> 30 #include <stdio.h> 31 #include <limits.h> 32 33 #include "dwarf_i.h" 34 #include "dwarf-eh.h" 35 #include "libunwind_i.h" 36 37 struct table_entry 38 { 39 int32_t start_ip_offset; 40 int32_t fde_offset; 41 }; 42 43 #ifndef UNW_REMOTE_ONLY 44 45 #ifdef __linux 46 #include "os-linux.h" 47 #endif 48 49 static int 50 linear_search (unw_addr_space_t as, unw_word_t ip, 51 unw_word_t eh_frame_start, unw_word_t eh_frame_end, 52 unw_word_t fde_count, 53 unw_proc_info_t *pi, int need_unwind_info, void *arg) 54 { 55 unw_accessors_t *a = unw_get_accessors (unw_local_addr_space); 56 unw_word_t i = 0, fde_addr, addr = eh_frame_start; 57 int ret; 58 59 while (i++ < fde_count && addr < eh_frame_end) 60 { 61 fde_addr = addr; 62 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 0, 0, arg)) 63 < 0) 64 return ret; 65 66 if (ip >= pi->start_ip && ip < pi->end_ip) 67 { 68 if (!need_unwind_info) 69 return 1; 70 addr = fde_addr; 71 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, 72 need_unwind_info, 0, 73 arg)) 74 < 0) 75 return ret; 76 return 1; 77 } 78 } 79 return -UNW_ENOINFO; 80 } 81 #endif /* !UNW_REMOTE_ONLY */ 82 83 #ifdef CONFIG_DEBUG_FRAME 84 /* Load .debug_frame section from FILE. Allocates and returns space 85 in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the 86 local process, in which case we can search the system debug file 87 directory; 0 for other address spaces, in which case we do not; or 88 -1 for recursive calls following .gnu_debuglink. Returns 0 on 89 success, 1 on error. Succeeds even if the file contains no 90 .debug_frame. */ 91 /* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */ 92 93 static int 94 load_debug_frame (const char *file, char **buf, size_t *bufsize, 95 int is_local, Elf_W(Addr)* segbase_bias) 96 { 97 FILE *f; 98 Elf_W (Ehdr) ehdr; 99 Elf_W (Half) shstrndx; 100 Elf_W (Shdr) *sec_hdrs = NULL; 101 char *stringtab = NULL; 102 unsigned int i; 103 size_t linksize = 0; 104 char *linkbuf = NULL; 105 106 *buf = NULL; 107 *bufsize = 0; 108 109 f = fopen (file, "r"); 110 111 if (!f) 112 return 1; 113 114 if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1) 115 goto file_error; 116 117 /* Verify this is actually an elf file. */ 118 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) 119 goto file_error; 120 121 shstrndx = ehdr.e_shstrndx; 122 123 Debug (4, "opened file '%s'. Section header at offset %d\n", 124 file, (int) ehdr.e_shoff); 125 126 fseek (f, ehdr.e_shoff, SEEK_SET); 127 sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr))); 128 if (sec_hdrs == NULL || fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum 129 || shstrndx >= ehdr.e_shnum) 130 goto file_error; 131 132 Debug (4, "loading string table of size %ld\n", 133 (long) sec_hdrs[shstrndx].sh_size); 134 size_t sec_size = sec_hdrs[shstrndx].sh_size; 135 stringtab = malloc (sec_size); 136 fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET); 137 if (stringtab == NULL || fread (stringtab, 1, sec_size, f) != sec_size) 138 goto file_error; 139 140 for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++) 141 { 142 size_t sec_position = sec_hdrs[i].sh_name; 143 if (sec_position >= sec_size) 144 continue; 145 char *secname = &stringtab[sec_position]; 146 147 if (sec_position + sizeof(".debug_frame") <= sec_size 148 && strcmp (secname, ".debug_frame") == 0) 149 { 150 *bufsize = sec_hdrs[i].sh_size; 151 *buf = malloc (*bufsize); 152 fseek (f, sec_hdrs[i].sh_offset, SEEK_SET); 153 if (*buf == NULL || fread (*buf, 1, *bufsize, f) != *bufsize) 154 goto file_error; 155 156 Debug (4, "read %zd bytes of .debug_frame from offset %ld\n", 157 *bufsize, (long) sec_hdrs[i].sh_offset); 158 } 159 else if (sec_position + sizeof(".gnu_debuglink") <= sec_size 160 && strcmp (secname, ".gnu_debuglink") == 0) 161 { 162 linksize = sec_hdrs[i].sh_size; 163 linkbuf = malloc (linksize); 164 fseek (f, sec_hdrs[i].sh_offset, SEEK_SET); 165 if (linkbuf == NULL || fread (linkbuf, 1, linksize, f) != linksize) 166 goto file_error; 167 168 Debug (4, "read %zd bytes of .gnu_debuglink from offset %ld\n", 169 linksize, (long) sec_hdrs[i].sh_offset); 170 } 171 /* ANDROID support update. */ 172 // Do not process the compressed section for local unwinds. 173 // Uncompressing this section can consume a large amount of memory 174 // and cause the unwind to take longer, which can cause problems 175 // when an ANR occurs in the system. Compressed sections are 176 // only used to contain java stack trace information. Since ART is 177 // one of the only ways that a local trace is done, and it already 178 // dumps the java stack, this information is redundant. 179 else if (local_map_list == NULL 180 && sec_position + sizeof(".gnu_debugdata") <= sec_size 181 && strcmp (secname, ".gnu_debugdata") == 0) 182 { 183 size_t xz_size = sec_hdrs[i].sh_size; 184 uint8_t* xz_data = malloc (xz_size); 185 struct elf_image mdi; 186 if (xz_data == NULL) 187 goto file_error; 188 fseek (f, sec_hdrs[i].sh_offset, SEEK_SET); 189 if (fread (xz_data, 1, xz_size, f) != xz_size) { 190 free(xz_data); 191 goto file_error; 192 } 193 Debug (4, "read %zd bytes of .gnu_debugdata from offset %ld\n", 194 xz_size, (long) sec_hdrs[i].sh_offset); 195 if (elf_w (xz_decompress) (xz_data, xz_size, 196 (uint8_t**)&mdi.u.mapped.image, &mdi.u.mapped.size)) { 197 uint8_t* found_section; 198 Elf_W(Addr) old_text_vaddr, new_text_vaddr; 199 mdi.valid = elf_w (valid_object_mapped) (&mdi); 200 mdi.mapped = true; 201 Debug (4, "decompressed .gnu_debugdata\n"); 202 if (elf_w (find_section_mapped) (&mdi, ".debug_frame", &found_section, bufsize, NULL)) { 203 Debug (4, "found .debug_frame in .gnu_debugdata\n"); 204 *buf = malloc (*bufsize); 205 if (*buf == NULL) { 206 free(xz_data); 207 free(mdi.u.mapped.image); 208 goto file_error; 209 } 210 memcpy(*buf, found_section, *bufsize); 211 // The ELF file might have been relocated since .gnu_debugdata was created. 212 if (elf_w (find_section_mapped) (&mdi, ".text", NULL, NULL, &old_text_vaddr)) { 213 int j; 214 for (j = 1; j < ehdr.e_shnum; j++) { 215 if (sec_hdrs[j].sh_name + sizeof(".text") <= sec_size 216 && strcmp(&stringtab[sec_hdrs[j].sh_name], ".text") == 0) { 217 new_text_vaddr = sec_hdrs[j].sh_addr; 218 *segbase_bias = new_text_vaddr - old_text_vaddr; 219 Debug (4, "ELF file was relocated by 0x%llx bytes since it was created.\n", 220 (unsigned long long)*segbase_bias); 221 break; 222 } 223 } 224 } 225 } else { 226 Debug (1, "can not find .debug_frame inside .gnu_debugdata\n"); 227 } 228 free(mdi.u.mapped.image); 229 } else { 230 Debug (1, "failed to decompress .gnu_debugdata\n"); 231 } 232 free(xz_data); 233 } 234 /* End of ANDROID update. */ 235 } 236 237 free (stringtab); 238 free (sec_hdrs); 239 240 fclose (f); 241 242 /* Ignore separate debug files which contain a .gnu_debuglink section. */ 243 if (linkbuf && is_local == -1) 244 { 245 free (linkbuf); 246 return 1; 247 } 248 249 if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL) 250 { 251 char *newname, *basedir, *p; 252 static const char *debugdir = "/usr/lib/debug"; 253 int ret; 254 255 /* XXX: Don't bother with the checksum; just search for the file. */ 256 basedir = malloc (strlen (file) + 1); 257 newname = malloc (strlen (linkbuf) + strlen (debugdir) 258 + strlen (file) + 9); 259 if (basedir == NULL || newname == NULL) 260 goto file_error; 261 262 p = strrchr (file, '/'); 263 if (p != NULL) 264 { 265 memcpy (basedir, file, p - file); 266 basedir[p - file] = '\0'; 267 } 268 else 269 basedir[0] = 0; 270 271 strcpy (newname, basedir); 272 strcat (newname, "/"); 273 strcat (newname, linkbuf); 274 ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias); 275 276 if (ret == 1) 277 { 278 strcpy (newname, basedir); 279 strcat (newname, "/.debug/"); 280 strcat (newname, linkbuf); 281 ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias); 282 } 283 284 if (ret == 1 && is_local == 1) 285 { 286 strcpy (newname, debugdir); 287 strcat (newname, basedir); 288 strcat (newname, "/"); 289 strcat (newname, linkbuf); 290 ret = load_debug_frame (newname, buf, bufsize, -1, segbase_bias); 291 } 292 293 free (basedir); 294 free (newname); 295 } 296 free (linkbuf); 297 298 return 0; 299 300 /* An error reading image file. Release resources and return error code */ 301 file_error: 302 free(stringtab); 303 free(sec_hdrs); 304 free(linkbuf); 305 free(*buf); 306 fclose(f); 307 308 return 1; 309 } 310 311 /* Locate the binary which originated the contents of address ADDR. Return 312 the name of the binary in *name (space is allocated by the caller) 313 Returns 0 if a binary is successfully found, or 1 if an error occurs. */ 314 315 /* ANDROID support update. */ 316 /* Removed the find_binary_for_address function. */ 317 /* End of ANDROID update. */ 318 319 /* Locate and/or try to load a debug_frame section for address ADDR. Return 320 pointer to debug frame descriptor, or zero if not found. */ 321 322 static struct unw_debug_frame_list * 323 locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname, 324 unw_word_t start, unw_word_t end) 325 { 326 struct unw_debug_frame_list *w, *fdesc = 0; 327 int err; 328 char *buf; 329 size_t bufsize; 330 /* ANDROID support update. */ 331 char *name = NULL; 332 Elf_W(Addr) segbase_bias = 0; 333 /* End of ANDROID update. */ 334 335 /* First, see if we loaded this frame already. */ 336 337 for (w = as->debug_frames; w; w = w->next) 338 { 339 Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end); 340 if (addr >= w->start && addr < w->end) 341 return w; 342 } 343 344 /* ANDROID support update. */ 345 /* If the object name we receive is blank, there's still a chance of locating 346 the file by looking at the maps cache. */ 347 348 if (strcmp (dlname, "") == 0) 349 { 350 #ifdef UNW_LOCAL_ONLY 351 name = map_local_get_image_name (addr); 352 #else 353 struct map_info *map = map_find_from_addr (as->map_list, addr); 354 if (map) 355 name = strdup (map->path); 356 #endif 357 if (!name) 358 /* End of ANDROID update. */ 359 { 360 Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n", 361 (uint64_t) addr); 362 return 0; 363 } 364 } 365 else 366 name = (char*) dlname; 367 368 err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space, &segbase_bias); 369 370 if (!err) 371 { 372 fdesc = malloc (sizeof (struct unw_debug_frame_list)); 373 374 fdesc->start = start; 375 fdesc->end = end; 376 fdesc->debug_frame = buf; 377 fdesc->debug_frame_size = bufsize; 378 fdesc->segbase_bias = segbase_bias; 379 fdesc->index = NULL; 380 fdesc->next = as->debug_frames; 381 382 as->debug_frames = fdesc; 383 } 384 385 /* ANDROID support update. */ 386 if (name != dlname) 387 free(name); 388 /* End of ANDROID update. */ 389 390 return fdesc; 391 } 392 393 struct debug_frame_tab 394 { 395 struct table_entry *tab; 396 uint32_t length; 397 uint32_t size; 398 }; 399 400 static void 401 debug_frame_tab_append (struct debug_frame_tab *tab, 402 unw_word_t fde_offset, unw_word_t start_ip) 403 { 404 unsigned int length = tab->length; 405 406 if (length == tab->size) 407 { 408 tab->size *= 2; 409 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size); 410 } 411 412 tab->tab[length].fde_offset = fde_offset; 413 tab->tab[length].start_ip_offset = start_ip; 414 415 tab->length = length + 1; 416 } 417 418 static void 419 debug_frame_tab_shrink (struct debug_frame_tab *tab) 420 { 421 if (tab->size > tab->length) 422 { 423 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length); 424 tab->size = tab->length; 425 } 426 } 427 428 static int 429 debug_frame_tab_compare (const void *a, const void *b) 430 { 431 const struct table_entry *fa = a, *fb = b; 432 433 if (fa->start_ip_offset > fb->start_ip_offset) 434 return 1; 435 else if (fa->start_ip_offset < fb->start_ip_offset) 436 return -1; 437 else 438 return 0; 439 } 440 441 PROTECTED int 442 dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip, 443 unw_word_t segbase, const char* obj_name, 444 unw_word_t start, unw_word_t end) 445 { 446 unw_dyn_info_t *di; 447 struct unw_debug_frame_list *fdesc = 0; 448 unw_accessors_t *a; 449 unw_word_t addr; 450 451 Debug (15, "Trying to find .debug_frame for %s\n", obj_name); 452 di = di_debug; 453 454 fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end); 455 456 if (!fdesc) 457 { 458 Debug (15, "couldn't load .debug_frame\n"); 459 return found; 460 } 461 else 462 { 463 char *buf; 464 size_t bufsize; 465 unw_word_t item_start, item_end = 0; 466 uint32_t u32val = 0; 467 uint64_t cie_id = 0; 468 struct debug_frame_tab tab; 469 470 Debug (15, "loaded .debug_frame\n"); 471 472 buf = fdesc->debug_frame; 473 bufsize = fdesc->debug_frame_size; 474 475 if (bufsize == 0) 476 { 477 Debug (15, "zero-length .debug_frame\n"); 478 return found; 479 } 480 481 /* Now create a binary-search table, if it does not already exist. */ 482 if (!fdesc->index) 483 { 484 addr = (unw_word_t) (uintptr_t) buf; 485 486 a = unw_get_accessors (unw_local_addr_space); 487 488 /* Find all FDE entries in debug_frame, and make into a sorted 489 index. */ 490 491 tab.length = 0; 492 tab.size = 16; 493 tab.tab = calloc (tab.size, sizeof (struct table_entry)); 494 495 while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) 496 { 497 uint64_t id_for_cie; 498 item_start = addr; 499 500 dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); 501 502 if (u32val == 0) 503 break; 504 else if (u32val != 0xffffffff) 505 { 506 uint32_t cie_id32 = 0; 507 item_end = addr + u32val; 508 dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, 509 NULL); 510 cie_id = cie_id32; 511 id_for_cie = 0xffffffff; 512 } 513 else 514 { 515 uint64_t u64val = 0; 516 /* Extended length. */ 517 dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); 518 item_end = addr + u64val; 519 520 dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); 521 id_for_cie = 0xffffffffffffffffull; 522 } 523 524 /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ 525 526 if (cie_id == id_for_cie) 527 ; 528 /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ 529 else 530 { 531 unw_word_t fde_addr = item_start; 532 unw_proc_info_t this_pi; 533 int err; 534 535 /*Debug (1, "Found FDE at %.8x\n", item_start);*/ 536 537 err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, 538 a, &fde_addr, 539 &this_pi, 0, 540 (uintptr_t) buf, 541 NULL); 542 if (err == 0) 543 { 544 Debug (15, "start_ip = %lx, end_ip = %lx\n", 545 (long) this_pi.start_ip, (long) this_pi.end_ip); 546 debug_frame_tab_append (&tab, 547 item_start - (unw_word_t) (uintptr_t) buf, 548 this_pi.start_ip); 549 } 550 /*else 551 Debug (1, "FDE parse failed\n");*/ 552 } 553 554 addr = item_end; 555 } 556 557 debug_frame_tab_shrink (&tab); 558 qsort (tab.tab, tab.length, sizeof (struct table_entry), 559 debug_frame_tab_compare); 560 /* for (i = 0; i < tab.length; i++) 561 { 562 fprintf (stderr, "ip %x, fde offset %x\n", 563 (int) tab.tab[i].start_ip_offset, 564 (int) tab.tab[i].fde_offset); 565 }*/ 566 fdesc->index = tab.tab; 567 fdesc->index_size = tab.length; 568 } 569 570 di->format = UNW_INFO_FORMAT_TABLE; 571 di->start_ip = fdesc->start; 572 di->end_ip = fdesc->end; 573 di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name; 574 di->u.ti.table_data = (unw_word_t *) fdesc; 575 di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); 576 di->u.ti.segbase = segbase + fdesc->segbase_bias; 577 578 found = 1; 579 Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " 580 "gp=0x%lx, table_data=0x%lx\n", 581 (char *) (uintptr_t) di->u.ti.name_ptr, 582 (long) di->u.ti.segbase, (long) di->u.ti.table_len, 583 (long) di->gp, (long) di->u.ti.table_data); 584 } 585 return found; 586 } 587 588 #endif /* CONFIG_DEBUG_FRAME */ 589 590 #ifndef UNW_REMOTE_ONLY 591 592 /* ptr is a pointer to a dwarf_callback_data structure and, on entry, 593 member ip contains the instruction-pointer we're looking 594 for. */ 595 HIDDEN int 596 dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) 597 { 598 struct dwarf_callback_data *cb_data = ptr; 599 unw_dyn_info_t *di = &cb_data->di; 600 const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text; 601 unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip; 602 Elf_W(Addr) load_base, max_load_addr = 0; 603 int ret, need_unwind_info = cb_data->need_unwind_info; 604 unw_proc_info_t *pi = cb_data->pi; 605 struct dwarf_eh_frame_hdr *hdr; 606 unw_accessors_t *a; 607 long n; 608 int found = 0; 609 #ifdef CONFIG_DEBUG_FRAME 610 unw_word_t start, end; 611 #endif /* CONFIG_DEBUG_FRAME*/ 612 613 ip = cb_data->ip; 614 615 /* Make sure struct dl_phdr_info is at least as big as we need. */ 616 if (size < offsetof (struct dl_phdr_info, dlpi_phnum) 617 + sizeof (info->dlpi_phnum)) 618 return -1; 619 620 Debug (15, "checking %s, base=0x%lx)\n", 621 info->dlpi_name, (long) info->dlpi_addr); 622 623 phdr = info->dlpi_phdr; 624 load_base = info->dlpi_addr; 625 p_text = NULL; 626 p_eh_hdr = NULL; 627 p_dynamic = NULL; 628 629 /* See if PC falls into one of the loaded segments. Find the 630 eh-header segment at the same time. */ 631 for (n = info->dlpi_phnum; --n >= 0; phdr++) 632 { 633 if (phdr->p_type == PT_LOAD) 634 { 635 Elf_W(Addr) vaddr = phdr->p_vaddr + load_base; 636 637 if (ip >= vaddr && ip < vaddr + phdr->p_memsz) 638 p_text = phdr; 639 640 if (vaddr + phdr->p_filesz > max_load_addr) 641 max_load_addr = vaddr + phdr->p_filesz; 642 } 643 else if (phdr->p_type == PT_GNU_EH_FRAME) 644 p_eh_hdr = phdr; 645 else if (phdr->p_type == PT_DYNAMIC) 646 p_dynamic = phdr; 647 } 648 649 if (!p_text) 650 return 0; 651 652 if (p_eh_hdr) 653 { 654 if (p_dynamic) 655 { 656 /* For dynamicly linked executables and shared libraries, 657 DT_PLTGOT is the value that data-relative addresses are 658 relative to for that object. We call this the "gp". */ 659 Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base); 660 for (; dyn->d_tag != DT_NULL; ++dyn) 661 if (dyn->d_tag == DT_PLTGOT) 662 { 663 /* Assume that _DYNAMIC is writable and GLIBC has 664 relocated it (true for x86 at least). */ 665 di->gp = dyn->d_un.d_ptr; 666 break; 667 } 668 } 669 else 670 /* Otherwise this is a static executable with no _DYNAMIC. Assume 671 that data-relative addresses are relative to 0, i.e., 672 absolute. */ 673 di->gp = 0; 674 pi->gp = di->gp; 675 676 hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base); 677 if (hdr->version != DW_EH_VERSION) 678 { 679 Debug (1, "table `%s' has unexpected version %d\n", 680 info->dlpi_name, hdr->version); 681 return 0; 682 } 683 684 a = unw_get_accessors (unw_local_addr_space); 685 addr = (unw_word_t) (uintptr_t) (hdr + 1); 686 687 /* (Optionally) read eh_frame_ptr: */ 688 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, 689 &addr, hdr->eh_frame_ptr_enc, pi, 690 &eh_frame_start, NULL)) < 0) 691 return ret; 692 693 /* (Optionally) read fde_count: */ 694 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, 695 &addr, hdr->fde_count_enc, pi, 696 &fde_count, NULL)) < 0) 697 return ret; 698 699 if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) 700 { 701 /* If there is no search table or it has an unsupported 702 encoding, fall back on linear search. */ 703 if (hdr->table_enc == DW_EH_PE_omit) 704 /* ANDROID support update. */ 705 { 706 /* End of ANDROID update. */ 707 Debug (4, "table `%s' lacks search table; doing linear search\n", 708 info->dlpi_name); 709 /* ANDROID support update. */ 710 } 711 /* End of ANDROID update. */ 712 else 713 /* ANDROID support update. */ 714 { 715 /* End of ANDROID update. */ 716 Debug (4, "table `%s' has encoding 0x%x; doing linear search\n", 717 info->dlpi_name, hdr->table_enc); 718 /* ANDROID support update. */ 719 } 720 /* End of ANDROID update. */ 721 722 eh_frame_end = max_load_addr; /* XXX can we do better? */ 723 724 if (hdr->fde_count_enc == DW_EH_PE_omit) 725 fde_count = ~0UL; 726 if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) 727 abort (); 728 729 /* XXX we know how to build a local binary search table for 730 .debug_frame, so we could do that here too. */ 731 cb_data->single_fde = 1; 732 found = linear_search (unw_local_addr_space, ip, 733 eh_frame_start, eh_frame_end, fde_count, 734 pi, need_unwind_info, NULL); 735 if (found != 1) 736 found = 0; 737 } 738 else 739 { 740 di->format = UNW_INFO_FORMAT_REMOTE_TABLE; 741 di->start_ip = p_text->p_vaddr + load_base; 742 di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; 743 di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; 744 di->u.rti.table_data = addr; 745 assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0); 746 di->u.rti.table_len = (fde_count * sizeof (struct table_entry) 747 / sizeof (unw_word_t)); 748 /* For the binary-search table in the eh_frame_hdr, data-relative 749 means relative to the start of that section... */ 750 di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr; 751 752 found = 1; 753 Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, " 754 "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr, 755 (long) di->u.rti.segbase, (long) di->u.rti.table_len, 756 (long) di->gp, (long) di->u.rti.table_data); 757 } 758 } 759 760 #ifdef CONFIG_DEBUG_FRAME 761 /* Find the start/end of the described region by parsing the phdr_info 762 structure. */ 763 start = (unw_word_t) -1; 764 end = 0; 765 766 for (n = 0; n < info->dlpi_phnum; n++) 767 { 768 if (info->dlpi_phdr[n].p_type == PT_LOAD) 769 { 770 unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr; 771 unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz; 772 773 if (seg_start < start) 774 start = seg_start; 775 776 if (seg_end > end) 777 end = seg_end; 778 } 779 } 780 781 found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip, 782 info->dlpi_addr, info->dlpi_name, start, 783 end); 784 #endif /* CONFIG_DEBUG_FRAME */ 785 786 return found; 787 } 788 789 HIDDEN int 790 dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, 791 unw_proc_info_t *pi, int need_unwind_info, void *arg) 792 { 793 struct dwarf_callback_data cb_data; 794 intrmask_t saved_mask; 795 int ret; 796 797 Debug (14, "looking for IP=0x%lx\n", (long) ip); 798 799 memset (&cb_data, 0, sizeof (cb_data)); 800 cb_data.ip = ip; 801 cb_data.pi = pi; 802 cb_data.need_unwind_info = need_unwind_info; 803 cb_data.di.format = -1; 804 cb_data.di_debug.format = -1; 805 806 SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); 807 ret = dl_iterate_phdr (dwarf_callback, &cb_data); 808 SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); 809 810 if (ret <= 0) 811 { 812 Debug (14, "IP=0x%lx not found\n", (long) ip); 813 return -UNW_ENOINFO; 814 } 815 816 if (cb_data.single_fde) 817 /* already got the result in *pi */ 818 return 0; 819 820 /* search the table: */ 821 if (cb_data.di.format != -1) 822 ret = dwarf_search_unwind_table (as, ip, &cb_data.di, 823 pi, need_unwind_info, arg); 824 else 825 ret = -UNW_ENOINFO; 826 827 if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1) 828 ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi, 829 need_unwind_info, arg); 830 return ret; 831 } 832 833 static inline const struct table_entry * 834 lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip) 835 { 836 unsigned long table_len = table_size / sizeof (struct table_entry); 837 const struct table_entry *e = NULL; 838 unsigned long lo, hi, mid; 839 840 /* do a binary search for right entry: */ 841 for (lo = 0, hi = table_len; lo < hi;) 842 { 843 mid = (lo + hi) / 2; 844 e = table + mid; 845 Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset); 846 if (rel_ip < e->start_ip_offset) 847 hi = mid; 848 else 849 lo = mid + 1; 850 } 851 if (hi <= 0) 852 return NULL; 853 e = table + hi - 1; 854 return e; 855 } 856 857 #endif /* !UNW_REMOTE_ONLY */ 858 859 #ifndef UNW_LOCAL_ONLY 860 861 /* Lookup an unwind-table entry in remote memory. Returns 1 if an 862 entry is found, 0 if no entry is found, negative if an error 863 occurred reading remote memory. */ 864 static int 865 remote_lookup (unw_addr_space_t as, 866 unw_word_t table, size_t table_size, int32_t rel_ip, 867 struct table_entry *e, void *arg) 868 { 869 unsigned long table_len = table_size / sizeof (struct table_entry); 870 unw_accessors_t *a = unw_get_accessors (as); 871 unsigned long lo, hi, mid; 872 unw_word_t e_addr = 0; 873 int32_t start; 874 int ret; 875 876 /* do a binary search for right entry: */ 877 for (lo = 0, hi = table_len; lo < hi;) 878 { 879 mid = (lo + hi) / 2; 880 e_addr = table + mid * sizeof (struct table_entry); 881 if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0) 882 return ret; 883 884 if (rel_ip < start) 885 hi = mid; 886 else 887 lo = mid + 1; 888 } 889 if (hi <= 0) 890 return 0; 891 e_addr = table + (hi - 1) * sizeof (struct table_entry); 892 if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0 893 || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0) 894 return ret; 895 return 1; 896 } 897 898 #endif /* !UNW_LOCAL_ONLY */ 899 900 PROTECTED int 901 dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, 902 unw_dyn_info_t *di, unw_proc_info_t *pi, 903 int need_unwind_info, void *arg) 904 { 905 const struct table_entry *e = NULL, *table; 906 unw_word_t segbase = 0, fde_addr; 907 unw_accessors_t *a; 908 #ifndef UNW_LOCAL_ONLY 909 struct table_entry ent; 910 #endif 911 int ret; 912 unw_word_t debug_frame_base; 913 size_t table_len; 914 915 #ifdef UNW_REMOTE_ONLY 916 assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE); 917 #else 918 assert (di->format == UNW_INFO_FORMAT_REMOTE_TABLE 919 || di->format == UNW_INFO_FORMAT_TABLE); 920 #endif 921 assert (ip >= di->start_ip && ip < di->end_ip); 922 923 if (di->format == UNW_INFO_FORMAT_REMOTE_TABLE) 924 { 925 table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data; 926 table_len = di->u.rti.table_len * sizeof (unw_word_t); 927 debug_frame_base = 0; 928 } 929 else 930 { 931 #ifndef UNW_REMOTE_ONLY 932 struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data; 933 934 /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address 935 space. Both the index and the unwind tables live in local memory, but 936 the address space to check for properties like the address size and 937 endianness is the target one. */ 938 as = unw_local_addr_space; 939 table = fdesc->index; 940 table_len = fdesc->index_size * sizeof (struct table_entry); 941 debug_frame_base = (uintptr_t) fdesc->debug_frame; 942 #endif 943 } 944 945 a = unw_get_accessors (as); 946 947 #ifndef UNW_REMOTE_ONLY 948 if (as == unw_local_addr_space) 949 { 950 segbase = di->u.rti.segbase; 951 e = lookup (table, table_len, ip - segbase); 952 } 953 else 954 #endif 955 { 956 #ifndef UNW_LOCAL_ONLY 957 segbase = di->u.rti.segbase; 958 if ((ret = remote_lookup (as, (uintptr_t) table, table_len, 959 ip - segbase, &ent, arg)) < 0) 960 return ret; 961 if (ret) 962 e = &ent; 963 else 964 e = NULL; /* no info found */ 965 #endif 966 } 967 if (!e) 968 { 969 Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n", 970 (long) ip, (long) di->start_ip, (long) di->end_ip); 971 /* IP is inside this table's range, but there is no explicit 972 unwind info. */ 973 return -UNW_ENOINFO; 974 } 975 Debug (15, "ip=0x%lx, start_ip=0x%lx\n", 976 (long) ip, (long) (e->start_ip_offset)); 977 if (debug_frame_base) 978 fde_addr = e->fde_offset + debug_frame_base; 979 else 980 fde_addr = e->fde_offset + segbase; 981 Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, " 982 "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase, 983 (long) debug_frame_base, (long) fde_addr); 984 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi, 985 need_unwind_info, 986 debug_frame_base, arg)) < 0) 987 return ret; 988 989 /* .debug_frame uses an absolute encoding that does not know about any 990 shared library relocation. */ 991 if (di->format == UNW_INFO_FORMAT_TABLE) 992 { 993 pi->start_ip += segbase; 994 pi->end_ip += segbase; 995 pi->flags = UNW_PI_FLAG_DEBUG_FRAME; 996 } 997 998 if (ip < pi->start_ip || ip >= pi->end_ip) 999 { 1000 /* ANDROID support update. */ 1001 if (need_unwind_info && pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE) 1002 { 1003 /* Free the memory used if the call fails. Otherwise, when there 1004 * is a mix of dwarf and other unwind data, the memory allocated 1005 * will be leaked. 1006 */ 1007 mempool_free (&dwarf_cie_info_pool, pi->unwind_info); 1008 pi->unwind_info = NULL; 1009 } 1010 /* End of ANDROID support update. */ 1011 return -UNW_ENOINFO; 1012 } 1013 1014 return 0; 1015 } 1016 1017 HIDDEN void 1018 dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) 1019 { 1020 return; /* always a nop */ 1021 } 1022