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