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