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>
5 This file is part of libunwind.
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:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
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. */
26 /* Locate an FDE via the ELF data-structures defined by LSB v1.3
27 (http://www.linuxbase.org/spec/). */
35 #include "libunwind_i.h"
39 int32_t start_ip_offset;
43 #ifndef UNW_REMOTE_ONLY
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,
53 unw_proc_info_t *pi, int need_unwind_info, void *arg)
55 unw_accessors_t *a = unw_get_accessors (unw_local_addr_space);
56 unw_word_t i = 0, fde_addr, addr = eh_frame_start;
59 while (i++ < fde_count && addr < eh_frame_end)
62 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
67 if (ip >= pi->start_ip && ip < pi->end_ip)
69 if (!need_unwind_info)
72 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi,
83 #endif /* !UNW_REMOTE_ONLY */
85 #ifdef CONFIG_DEBUG_FRAME
86 /* Load .debug_frame section from FILE. Allocates and returns space
87 in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the
88 local process, in which case we can search the system debug file
89 directory; 0 for other address spaces, in which case we do not; or
90 -1 for recursive calls following .gnu_debuglink. Returns 0 on
91 success, 1 on error. Succeeds even if the file contains no
93 /* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */
96 load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local)
100 Elf_W (Half) shstrndx;
101 Elf_W (Shdr) *sec_hdrs = NULL;
102 char *stringtab = NULL;
105 char *linkbuf = NULL;
110 f = fopen (file, "r");
115 if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1)
118 shstrndx = ehdr.e_shstrndx;
120 Debug (4, "opened file '%s'. Section header at offset %d\n",
121 file, (int) ehdr.e_shoff);
123 fseek (f, ehdr.e_shoff, SEEK_SET);
124 sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr)));
125 if (fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum)
128 Debug (4, "loading string table of size %zd\n",
129 sec_hdrs[shstrndx].sh_size);
130 stringtab = malloc (sec_hdrs[shstrndx].sh_size);
131 fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET);
132 if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size)
135 for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++)
137 char *secname = &stringtab[sec_hdrs[i].sh_name];
139 if (strcmp (secname, ".debug_frame") == 0)
141 *bufsize = sec_hdrs[i].sh_size;
142 *buf = malloc (*bufsize);
144 fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
145 if (fread (*buf, 1, *bufsize, f) != *bufsize)
148 Debug (4, "read %zd bytes of .debug_frame from offset %zd\n",
149 *bufsize, sec_hdrs[i].sh_offset);
151 else if (strcmp (secname, ".gnu_debuglink") == 0)
153 linksize = sec_hdrs[i].sh_size;
154 linkbuf = malloc (linksize);
156 fseek (f, sec_hdrs[i].sh_offset, SEEK_SET);
157 if (fread (linkbuf, 1, linksize, f) != linksize)
160 Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n",
161 linksize, sec_hdrs[i].sh_offset);
170 /* Ignore separate debug files which contain a .gnu_debuglink section. */
171 if (linkbuf && is_local == -1)
177 if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
179 char *newname, *basedir, *p;
180 static const char *debugdir = "/usr/lib/debug";
183 /* XXX: Don't bother with the checksum; just search for the file. */
184 basedir = malloc (strlen (file) + 1);
185 newname = malloc (strlen (linkbuf) + strlen (debugdir)
186 + strlen (file) + 9);
188 p = strrchr (file, '/');
191 memcpy (basedir, file, p - file);
192 basedir[p - file] = '\0';
197 strcpy (newname, basedir);
198 strcat (newname, "/");
199 strcat (newname, linkbuf);
200 ret = load_debug_frame (newname, buf, bufsize, -1);
204 strcpy (newname, basedir);
205 strcat (newname, "/.debug/");
206 strcat (newname, linkbuf);
207 ret = load_debug_frame (newname, buf, bufsize, -1);
210 if (ret == 1 && is_local == 1)
212 strcpy (newname, debugdir);
213 strcat (newname, basedir);
214 strcat (newname, "/");
215 strcat (newname, linkbuf);
216 ret = load_debug_frame (newname, buf, bufsize, -1);
226 /* An error reading image file. Release resources and return error code */
236 /* Locate the binary which originated the contents of address ADDR. Return
237 the name of the binary in *name (space is allocated by the caller)
238 Returns 0 if a binary is successfully found, or 1 if an error occurs. */
241 find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
243 #if defined(__linux) && (!UNW_REMOTE_ONLY)
244 struct map_iterator mi;
247 unsigned long segbase, mapoff, hi;
249 maps_init (&mi, pid);
250 while (maps_next (&mi, &segbase, &hi, &mapoff))
251 if (ip >= segbase && ip < hi)
253 size_t len = strlen (mi.path);
255 if (len + 1 <= name_size)
257 memcpy (name, mi.path, len + 1);
269 /* Locate and/or try to load a debug_frame section for address ADDR. Return
270 pointer to debug frame descriptor, or zero if not found. */
272 static struct unw_debug_frame_list *
273 locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
274 unw_word_t start, unw_word_t end)
276 struct unw_debug_frame_list *w, *fdesc = 0;
283 /* First, see if we loaded this frame already. */
285 for (w = as->debug_frames; w; w = w->next)
287 Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
288 if (addr >= w->start && addr < w->end)
292 /* If the object name we receive is blank, there's still a chance of locating
293 the file by parsing /proc/self/maps. */
295 if (strcmp (dlname, "") == 0)
297 err = find_binary_for_address (addr, name, sizeof(path));
300 Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
306 name = (char*) dlname;
308 err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
312 fdesc = malloc (sizeof (struct unw_debug_frame_list));
314 fdesc->start = start;
316 fdesc->debug_frame = buf;
317 fdesc->debug_frame_size = bufsize;
319 fdesc->next = as->debug_frames;
321 as->debug_frames = fdesc;
327 struct debug_frame_tab
329 struct table_entry *tab;
335 debug_frame_tab_append (struct debug_frame_tab *tab,
336 unw_word_t fde_offset, unw_word_t start_ip)
338 unsigned int length = tab->length;
340 if (length == tab->size)
343 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
346 tab->tab[length].fde_offset = fde_offset;
347 tab->tab[length].start_ip_offset = start_ip;
349 tab->length = length + 1;
353 debug_frame_tab_shrink (struct debug_frame_tab *tab)
355 if (tab->size > tab->length)
357 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
358 tab->size = tab->length;
363 debug_frame_tab_compare (const void *a, const void *b)
365 const struct table_entry *fa = a, *fb = b;
367 if (fa->start_ip_offset > fb->start_ip_offset)
369 else if (fa->start_ip_offset < fb->start_ip_offset)
376 dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
377 unw_word_t segbase, const char* obj_name,
378 unw_word_t start, unw_word_t end)
381 struct unw_debug_frame_list *fdesc = 0;
385 Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
388 fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
392 Debug (15, "couldn't load .debug_frame\n");
399 unw_word_t item_start, item_end = 0;
402 struct debug_frame_tab tab;
404 Debug (15, "loaded .debug_frame\n");
406 buf = fdesc->debug_frame;
407 bufsize = fdesc->debug_frame_size;
411 Debug (15, "zero-length .debug_frame\n");
415 /* Now create a binary-search table, if it does not already exist. */
418 addr = (unw_word_t) (uintptr_t) buf;
420 a = unw_get_accessors (unw_local_addr_space);
422 /* Find all FDE entries in debug_frame, and make into a sorted
427 tab.tab = calloc (tab.size, sizeof (struct table_entry));
429 while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
434 dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
438 else if (u32val != 0xffffffff)
440 uint32_t cie_id32 = 0;
441 item_end = addr + u32val;
442 dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
445 id_for_cie = 0xffffffff;
450 /* Extended length. */
451 dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
452 item_end = addr + u64val;
454 dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
455 id_for_cie = 0xffffffffffffffffull;
458 /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
460 if (cie_id == id_for_cie)
462 /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
465 unw_word_t fde_addr = item_start;
466 unw_proc_info_t this_pi;
469 /*Debug (1, "Found FDE at %.8x\n", item_start);*/
471 err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
474 (uintptr_t) buf, 0, 1,
478 Debug (15, "start_ip = %lx, end_ip = %lx\n",
479 (long) this_pi.start_ip, (long) this_pi.end_ip);
480 debug_frame_tab_append (&tab,
481 item_start - (unw_word_t) (uintptr_t) buf,
485 Debug (1, "FDE parse failed\n");*/
491 debug_frame_tab_shrink (&tab);
492 qsort (tab.tab, tab.length, sizeof (struct table_entry),
493 debug_frame_tab_compare);
494 /* for (i = 0; i < tab.length; i++)
496 fprintf (stderr, "ip %x, fde offset %x\n",
497 (int) tab.tab[i].start_ip_offset,
498 (int) tab.tab[i].fde_offset);
500 fdesc->index = tab.tab;
501 fdesc->index_size = tab.length;
504 di->format = UNW_INFO_FORMAT_TABLE;
505 di->start_ip = fdesc->start;
506 di->end_ip = fdesc->end;
507 di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
508 di->u.ti.table_data = (unw_word_t *) fdesc;
509 di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
510 di->u.ti.segbase = segbase;
513 Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
514 "gp=0x%lx, table_data=0x%lx\n",
515 (char *) (uintptr_t) di->u.ti.name_ptr,
516 (long) di->u.ti.segbase, (long) di->u.ti.table_len,
517 (long) di->gp, (long) di->u.ti.table_data);
522 #endif /* CONFIG_DEBUG_FRAME */
524 #ifndef UNW_REMOTE_ONLY
526 /* ptr is a pointer to a dwarf_callback_data structure and, on entry,
527 member ip contains the instruction-pointer we're looking
530 dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
532 struct dwarf_callback_data *cb_data = ptr;
533 unw_dyn_info_t *di = &cb_data->di;
534 const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
535 unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
536 Elf_W(Addr) load_base, max_load_addr = 0;
537 int ret, need_unwind_info = cb_data->need_unwind_info;
538 unw_proc_info_t *pi = cb_data->pi;
539 struct dwarf_eh_frame_hdr *hdr;
543 #ifdef CONFIG_DEBUG_FRAME
544 unw_word_t start, end;
545 #endif /* CONFIG_DEBUG_FRAME*/
549 /* Make sure struct dl_phdr_info is at least as big as we need. */
550 if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
551 + sizeof (info->dlpi_phnum))
554 Debug (15, "checking %s, base=0x%lx)\n",
555 info->dlpi_name, (long) info->dlpi_addr);
557 phdr = info->dlpi_phdr;
558 load_base = info->dlpi_addr;
563 /* See if PC falls into one of the loaded segments. Find the
564 eh-header segment at the same time. */
565 for (n = info->dlpi_phnum; --n >= 0; phdr++)
567 if (phdr->p_type == PT_LOAD)
569 Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
571 if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
574 if (vaddr + phdr->p_filesz > max_load_addr)
575 max_load_addr = vaddr + phdr->p_filesz;
577 else if (phdr->p_type == PT_GNU_EH_FRAME)
579 else if (phdr->p_type == PT_DYNAMIC)
590 /* For dynamicly linked executables and shared libraries,
591 DT_PLTGOT is the value that data-relative addresses are
592 relative to for that object. We call this the "gp". */
593 Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
594 for (; dyn->d_tag != DT_NULL; ++dyn)
595 if (dyn->d_tag == DT_PLTGOT)
597 /* Assume that _DYNAMIC is writable and GLIBC has
598 relocated it (true for x86 at least). */
599 di->gp = dyn->d_un.d_ptr;
604 /* Otherwise this is a static executable with no _DYNAMIC. Assume
605 that data-relative addresses are relative to 0, i.e.,
610 hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
611 if (hdr->version != DW_EH_VERSION)
613 Debug (1, "table `%s' has unexpected version %d\n",
614 info->dlpi_name, hdr->version);
618 a = unw_get_accessors (unw_local_addr_space);
619 addr = (unw_word_t) (uintptr_t) (hdr + 1);
621 /* (Optionally) read eh_frame_ptr: */
622 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
623 &addr, hdr->eh_frame_ptr_enc, pi,
624 &eh_frame_start, NULL)) < 0)
627 /* (Optionally) read fde_count: */
628 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
629 &addr, hdr->fde_count_enc, pi,
630 &fde_count, NULL)) < 0)
633 if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
635 /* If there is no search table or it has an unsupported
636 encoding, fall back on linear search. */
637 if (hdr->table_enc == DW_EH_PE_omit)
638 Debug (4, "table `%s' lacks search table; doing linear search\n",
641 Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
642 info->dlpi_name, hdr->table_enc);
644 eh_frame_end = max_load_addr; /* XXX can we do better? */
646 if (hdr->fde_count_enc == DW_EH_PE_omit)
648 if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
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);
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;
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);
682 #ifdef CONFIG_DEBUG_FRAME
683 /* Find the start/end of the described region by parsing the phdr_info
685 start = (unw_word_t) -1;
688 for (n = 0; n < info->dlpi_phnum; n++)
690 if (info->dlpi_phdr[n].p_type == PT_LOAD)
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;
695 if (seg_start < start)
703 found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
704 info->dlpi_addr, info->dlpi_name, start,
706 #endif /* CONFIG_DEBUG_FRAME */
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)
715 struct dwarf_callback_data cb_data;
716 intrmask_t saved_mask;
719 Debug (14, "looking for IP=0x%lx\n", (long) ip);
721 memset (&cb_data, 0, sizeof (cb_data));
724 cb_data.need_unwind_info = need_unwind_info;
725 cb_data.di.format = -1;
726 cb_data.di_debug.format = -1;
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);
734 Debug (14, "IP=0x%lx not found\n", (long) ip);
738 if (cb_data.single_fde)
739 /* already got the result in *pi */
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);
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);
755 static inline const struct table_entry *
756 lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
758 unsigned long table_len = table_size / sizeof (struct table_entry);
759 const struct table_entry *e = NULL;
760 unsigned long lo, hi, mid;
762 /* do a binary search for right entry: */
763 for (lo = 0, hi = table_len; lo < hi;)
767 Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
768 if (rel_ip < e->start_ip_offset)
779 #endif /* !UNW_REMOTE_ONLY */
781 #ifndef UNW_LOCAL_ONLY
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. */
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)
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;
798 /* do a binary search for right entry: */
799 for (lo = 0, hi = table_len; lo < hi;)
802 e_addr = table + mid * sizeof (struct table_entry);
803 if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 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)
820 #endif /* !UNW_LOCAL_ONLY */
822 static int is_remote_table(int format)
824 return (format == UNW_INFO_FORMAT_REMOTE_TABLE ||
825 format == UNW_INFO_FORMAT_IP_OFFSET);
829 dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
830 unw_dyn_info_t *di, unw_proc_info_t *pi,
831 int need_unwind_info, void *arg)
833 const struct table_entry *e = NULL, *table;
834 unw_word_t ip_base = 0, segbase = 0, fde_addr;
836 #ifndef UNW_LOCAL_ONLY
837 struct table_entry ent;
840 unw_word_t debug_frame_base;
843 #ifdef UNW_REMOTE_ONLY
844 assert (is_remote_table(di->format));
846 assert (is_remote_table(di->format)
847 || di->format == UNW_INFO_FORMAT_TABLE);
849 assert (ip >= di->start_ip && ip < di->end_ip);
851 if (is_remote_table(di->format))
853 table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
854 table_len = di->u.rti.table_len * sizeof (unw_word_t);
855 debug_frame_base = 0;
859 assert(di->format == UNW_INFO_FORMAT_TABLE);
860 #ifndef UNW_REMOTE_ONLY
861 struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
863 /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
864 space. Both the index and the unwind tables live in local memory, but
865 the address space to check for properties like the address size and
866 endianness is the target one. */
867 as = unw_local_addr_space;
868 table = fdesc->index;
869 table_len = fdesc->index_size * sizeof (struct table_entry);
870 debug_frame_base = (uintptr_t) fdesc->debug_frame;
874 a = unw_get_accessors (as);
876 segbase = di->u.rti.segbase;
877 if (di->format == UNW_INFO_FORMAT_IP_OFFSET) {
878 ip_base = di->start_ip;
883 #ifndef UNW_REMOTE_ONLY
884 if (as == unw_local_addr_space)
886 e = lookup (table, table_len, ip - ip_base);
891 #ifndef UNW_LOCAL_ONLY
892 segbase = di->u.rti.segbase;
893 if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
894 ip - ip_base, &ent, arg)) < 0)
899 e = NULL; /* no info found */
904 Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
905 (long) ip, (long) di->start_ip, (long) di->end_ip);
906 /* IP is inside this table's range, but there is no explicit
910 Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
911 (long) ip, (long) (e->start_ip_offset));
912 if (debug_frame_base)
913 fde_addr = e->fde_offset + debug_frame_base;
915 fde_addr = e->fde_offset + segbase;
916 Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
917 "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
918 (long) debug_frame_base, (long) fde_addr);
919 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
921 debug_frame_base : segbase,
923 debug_frame_base != 0, arg)) < 0)
926 /* .debug_frame uses an absolute encoding that does not know about any
927 shared library relocation. */
928 if (di->format == UNW_INFO_FORMAT_TABLE)
930 pi->start_ip += segbase;
931 pi->end_ip += segbase;
932 pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
935 if (ip < pi->start_ip || ip >= pi->end_ip)
942 dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
944 return; /* always a nop */