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