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)
174 if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL)
176 char *newname, *basedir, *p;
177 static const char *debugdir = "/usr/lib/debug";
180 /* XXX: Don't bother with the checksum; just search for the file. */
181 basedir = malloc (strlen (file) + 1);
185 newname = malloc (strlen (linkbuf) + strlen (debugdir)
186 + strlen (file) + 9);
193 p = strrchr (file, '/');
196 memcpy (basedir, file, p - file);
197 basedir[p - file] = '\0';
202 strcpy (newname, basedir);
203 strcat (newname, "/");
204 strcat (newname, linkbuf);
205 ret = load_debug_frame (newname, buf, bufsize, -1);
209 strcpy (newname, basedir);
210 strcat (newname, "/.debug/");
211 strcat (newname, linkbuf);
212 ret = load_debug_frame (newname, buf, bufsize, -1);
215 if (ret == 1 && is_local == 1)
217 strcpy (newname, debugdir);
218 strcat (newname, basedir);
219 strcat (newname, "/");
220 strcat (newname, linkbuf);
221 ret = load_debug_frame (newname, buf, bufsize, -1);
231 /* An error reading image file. Release resources and return error code */
243 /* Locate the binary which originated the contents of address ADDR. Return
244 the name of the binary in *name (space is allocated by the caller)
245 Returns 0 if a binary is successfully found, or 1 if an error occurs. */
248 find_binary_for_address (unw_word_t ip, char *name, size_t name_size)
250 #if defined(__linux) && (!UNW_REMOTE_ONLY)
251 struct map_iterator mi;
254 unsigned long segbase, mapoff, hi;
256 maps_init (&mi, pid);
257 while (maps_next (&mi, &segbase, &hi, &mapoff))
258 if (ip >= segbase && ip < hi)
260 size_t len = strlen (mi.path);
262 if (len + 1 <= name_size)
264 memcpy (name, mi.path, len + 1);
276 /* Locate and/or try to load a debug_frame section for address ADDR. Return
277 pointer to debug frame descriptor, or zero if not found. */
279 static struct unw_debug_frame_list *
280 locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname,
281 unw_word_t start, unw_word_t end)
283 struct unw_debug_frame_list *w, *fdesc = 0;
290 /* First, see if we loaded this frame already. */
292 for (w = as->debug_frames; w; w = w->next)
294 Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end);
295 if (addr >= w->start && addr < w->end)
299 /* If the object name we receive is blank, there's still a chance of locating
300 the file by parsing /proc/self/maps. */
302 if (strcmp (dlname, "") == 0)
304 err = find_binary_for_address (addr, name, sizeof(path));
307 Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n",
313 name = (char*) dlname;
315 err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space);
319 fdesc = malloc (sizeof (struct unw_debug_frame_list));
321 fdesc->start = start;
323 fdesc->debug_frame = buf;
324 fdesc->debug_frame_size = bufsize;
326 fdesc->next = as->debug_frames;
328 as->debug_frames = fdesc;
334 struct debug_frame_tab
336 struct table_entry *tab;
342 debug_frame_tab_append (struct debug_frame_tab *tab,
343 unw_word_t fde_offset, unw_word_t start_ip)
345 unsigned int length = tab->length;
347 if (length == tab->size)
350 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size);
353 tab->tab[length].fde_offset = fde_offset;
354 tab->tab[length].start_ip_offset = start_ip;
356 tab->length = length + 1;
360 debug_frame_tab_shrink (struct debug_frame_tab *tab)
362 if (tab->size > tab->length)
364 tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length);
365 tab->size = tab->length;
370 debug_frame_tab_compare (const void *a, const void *b)
372 const struct table_entry *fa = a, *fb = b;
374 if (fa->start_ip_offset > fb->start_ip_offset)
376 else if (fa->start_ip_offset < fb->start_ip_offset)
383 dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip,
384 unw_word_t segbase, const char* obj_name,
385 unw_word_t start, unw_word_t end)
388 struct unw_debug_frame_list *fdesc = 0;
392 Debug (15, "Trying to find .debug_frame for %s\n", obj_name);
395 fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end);
399 Debug (15, "couldn't load .debug_frame\n");
406 unw_word_t item_start, item_end = 0;
409 struct debug_frame_tab tab;
411 Debug (15, "loaded .debug_frame\n");
413 buf = fdesc->debug_frame;
414 bufsize = fdesc->debug_frame_size;
418 Debug (15, "zero-length .debug_frame\n");
422 /* Now create a binary-search table, if it does not already exist. */
425 addr = (unw_word_t) (uintptr_t) buf;
427 a = unw_get_accessors (unw_local_addr_space);
429 /* Find all FDE entries in debug_frame, and make into a sorted
434 tab.tab = calloc (tab.size, sizeof (struct table_entry));
436 while (addr < (unw_word_t) (uintptr_t) (buf + bufsize))
441 dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL);
445 else if (u32val != 0xffffffff)
447 uint32_t cie_id32 = 0;
448 item_end = addr + u32val;
449 dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32,
452 id_for_cie = 0xffffffff;
457 /* Extended length. */
458 dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL);
459 item_end = addr + u64val;
461 dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL);
462 id_for_cie = 0xffffffffffffffffull;
465 /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/
467 if (cie_id == id_for_cie)
469 /*Debug (1, "Found CIE at %.8x.\n", item_start);*/
472 unw_word_t fde_addr = item_start;
473 unw_proc_info_t this_pi;
476 /*Debug (1, "Found FDE at %.8x\n", item_start);*/
478 err = dwarf_extract_proc_info_from_fde (unw_local_addr_space,
481 (uintptr_t) buf, 0, 1,
485 Debug (15, "start_ip = %lx, end_ip = %lx\n",
486 (long) this_pi.start_ip, (long) this_pi.end_ip);
487 debug_frame_tab_append (&tab,
488 item_start - (unw_word_t) (uintptr_t) buf,
492 Debug (1, "FDE parse failed\n");*/
498 debug_frame_tab_shrink (&tab);
499 qsort (tab.tab, tab.length, sizeof (struct table_entry),
500 debug_frame_tab_compare);
501 /* for (i = 0; i < tab.length; i++)
503 fprintf (stderr, "ip %x, fde offset %x\n",
504 (int) tab.tab[i].start_ip_offset,
505 (int) tab.tab[i].fde_offset);
507 fdesc->index = tab.tab;
508 fdesc->index_size = tab.length;
511 di->format = UNW_INFO_FORMAT_TABLE;
512 di->start_ip = fdesc->start;
513 di->end_ip = fdesc->end;
514 di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name;
515 di->u.ti.table_data = (unw_word_t *) fdesc;
516 di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t);
517 di->u.ti.segbase = segbase;
520 Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, "
521 "gp=0x%lx, table_data=0x%lx\n",
522 (char *) (uintptr_t) di->u.ti.name_ptr,
523 (long) di->u.ti.segbase, (long) di->u.ti.table_len,
524 (long) di->gp, (long) di->u.ti.table_data);
529 #endif /* CONFIG_DEBUG_FRAME */
531 #ifndef UNW_REMOTE_ONLY
533 /* ptr is a pointer to a dwarf_callback_data structure and, on entry,
534 member ip contains the instruction-pointer we're looking
537 dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr)
539 struct dwarf_callback_data *cb_data = ptr;
540 unw_dyn_info_t *di = &cb_data->di;
541 const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text;
542 unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip;
543 Elf_W(Addr) load_base, max_load_addr = 0;
544 int ret, need_unwind_info = cb_data->need_unwind_info;
545 unw_proc_info_t *pi = cb_data->pi;
546 struct dwarf_eh_frame_hdr *hdr;
550 #ifdef CONFIG_DEBUG_FRAME
551 unw_word_t start, end;
552 #endif /* CONFIG_DEBUG_FRAME*/
556 /* Make sure struct dl_phdr_info is at least as big as we need. */
557 if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
558 + sizeof (info->dlpi_phnum))
561 Debug (15, "checking %s, base=0x%lx)\n",
562 info->dlpi_name, (long) info->dlpi_addr);
564 phdr = info->dlpi_phdr;
565 load_base = info->dlpi_addr;
570 /* See if PC falls into one of the loaded segments. Find the
571 eh-header segment at the same time. */
572 for (n = info->dlpi_phnum; --n >= 0; phdr++)
574 if (phdr->p_type == PT_LOAD)
576 Elf_W(Addr) vaddr = phdr->p_vaddr + load_base;
578 if (ip >= vaddr && ip < vaddr + phdr->p_memsz)
581 if (vaddr + phdr->p_filesz > max_load_addr)
582 max_load_addr = vaddr + phdr->p_filesz;
584 else if (phdr->p_type == PT_GNU_EH_FRAME)
586 else if (phdr->p_type == PT_DYNAMIC)
597 /* For dynamicly linked executables and shared libraries,
598 DT_PLTGOT is the value that data-relative addresses are
599 relative to for that object. We call this the "gp". */
600 Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base);
601 for (; dyn->d_tag != DT_NULL; ++dyn)
602 if (dyn->d_tag == DT_PLTGOT)
604 /* Assume that _DYNAMIC is writable and GLIBC has
605 relocated it (true for x86 at least). */
606 di->gp = dyn->d_un.d_ptr;
611 /* Otherwise this is a static executable with no _DYNAMIC. Assume
612 that data-relative addresses are relative to 0, i.e.,
617 hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base);
618 if (hdr->version != DW_EH_VERSION)
620 Debug (1, "table `%s' has unexpected version %d\n",
621 info->dlpi_name, hdr->version);
625 a = unw_get_accessors (unw_local_addr_space);
626 addr = (unw_word_t) (uintptr_t) (hdr + 1);
628 /* (Optionally) read eh_frame_ptr: */
629 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
630 &addr, hdr->eh_frame_ptr_enc, pi,
631 &eh_frame_start, NULL)) < 0)
634 /* (Optionally) read fde_count: */
635 if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a,
636 &addr, hdr->fde_count_enc, pi,
637 &fde_count, NULL)) < 0)
640 if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
642 /* If there is no search table or it has an unsupported
643 encoding, fall back on linear search. */
644 if (hdr->table_enc == DW_EH_PE_omit)
645 Debug (4, "table `%s' lacks search table; doing linear search\n",
648 Debug (4, "table `%s' has encoding 0x%x; doing linear search\n",
649 info->dlpi_name, hdr->table_enc);
651 eh_frame_end = max_load_addr; /* XXX can we do better? */
653 if (hdr->fde_count_enc == DW_EH_PE_omit)
655 if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit)
658 /* XXX we know how to build a local binary search table for
659 .debug_frame, so we could do that here too. */
660 cb_data->single_fde = 1;
661 found = linear_search (unw_local_addr_space, ip,
662 eh_frame_start, eh_frame_end, fde_count,
663 pi, need_unwind_info, NULL);
669 di->format = UNW_INFO_FORMAT_REMOTE_TABLE;
670 di->start_ip = p_text->p_vaddr + load_base;
671 di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz;
672 di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name;
673 di->u.rti.table_data = addr;
674 assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0);
675 di->u.rti.table_len = (fde_count * sizeof (struct table_entry)
676 / sizeof (unw_word_t));
677 /* For the binary-search table in the eh_frame_hdr, data-relative
678 means relative to the start of that section... */
679 di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr;
682 Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, "
683 "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr,
684 (long) di->u.rti.segbase, (long) di->u.rti.table_len,
685 (long) di->gp, (long) di->u.rti.table_data);
689 #ifdef CONFIG_DEBUG_FRAME
690 /* Find the start/end of the described region by parsing the phdr_info
692 start = (unw_word_t) -1;
695 for (n = 0; n < info->dlpi_phnum; n++)
697 if (info->dlpi_phdr[n].p_type == PT_LOAD)
699 unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr;
700 unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz;
702 if (seg_start < start)
710 found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip,
711 info->dlpi_addr, info->dlpi_name, start,
713 #endif /* CONFIG_DEBUG_FRAME */
719 dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip,
720 unw_proc_info_t *pi, int need_unwind_info, void *arg)
722 struct dwarf_callback_data cb_data;
723 intrmask_t saved_mask;
726 Debug (14, "looking for IP=0x%lx\n", (long) ip);
728 memset (&cb_data, 0, sizeof (cb_data));
731 cb_data.need_unwind_info = need_unwind_info;
732 cb_data.di.format = -1;
733 cb_data.di_debug.format = -1;
735 SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
736 ret = dl_iterate_phdr (dwarf_callback, &cb_data);
737 SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
741 Debug (14, "IP=0x%lx not found\n", (long) ip);
745 if (cb_data.single_fde)
746 /* already got the result in *pi */
749 /* search the table: */
750 if (cb_data.di.format != -1)
751 ret = dwarf_search_unwind_table (as, ip, &cb_data.di,
752 pi, need_unwind_info, arg);
756 if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1)
757 ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi,
758 need_unwind_info, arg);
762 static inline const struct table_entry *
763 lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip)
765 unsigned long table_len = table_size / sizeof (struct table_entry);
766 const struct table_entry *e = NULL;
767 unsigned long lo, hi, mid;
769 /* do a binary search for right entry: */
770 for (lo = 0, hi = table_len; lo < hi;)
774 Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset);
775 if (rel_ip < e->start_ip_offset)
786 #endif /* !UNW_REMOTE_ONLY */
788 #ifndef UNW_LOCAL_ONLY
790 /* Lookup an unwind-table entry in remote memory. Returns 1 if an
791 entry is found, 0 if no entry is found, negative if an error
792 occurred reading remote memory. */
794 remote_lookup (unw_addr_space_t as,
795 unw_word_t table, size_t table_size, int32_t rel_ip,
796 struct table_entry *e, void *arg)
798 unsigned long table_len = table_size / sizeof (struct table_entry);
799 unw_accessors_t *a = unw_get_accessors (as);
800 unsigned long lo, hi, mid;
801 unw_word_t e_addr = 0;
805 /* do a binary search for right entry: */
806 for (lo = 0, hi = table_len; lo < hi;)
809 e_addr = table + mid * sizeof (struct table_entry);
810 if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0)
820 e_addr = table + (hi - 1) * sizeof (struct table_entry);
821 if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0
822 || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0)
827 #endif /* !UNW_LOCAL_ONLY */
829 static int is_remote_table(int format)
831 return (format == UNW_INFO_FORMAT_REMOTE_TABLE ||
832 format == UNW_INFO_FORMAT_IP_OFFSET);
836 dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
837 unw_dyn_info_t *di, unw_proc_info_t *pi,
838 int need_unwind_info, void *arg)
840 const struct table_entry *e = NULL, *table;
841 unw_word_t ip_base = 0, segbase = 0, fde_addr;
843 #ifndef UNW_LOCAL_ONLY
844 struct table_entry ent;
847 unw_word_t debug_frame_base;
850 #ifdef UNW_REMOTE_ONLY
851 assert (is_remote_table(di->format));
853 assert (is_remote_table(di->format)
854 || di->format == UNW_INFO_FORMAT_TABLE);
856 assert (ip >= di->start_ip && ip < di->end_ip);
858 if (is_remote_table(di->format))
860 table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data;
861 table_len = di->u.rti.table_len * sizeof (unw_word_t);
862 debug_frame_base = 0;
866 assert(di->format == UNW_INFO_FORMAT_TABLE);
867 #ifndef UNW_REMOTE_ONLY
868 struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data;
870 /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address
871 space. Both the index and the unwind tables live in local memory, but
872 the address space to check for properties like the address size and
873 endianness is the target one. */
874 as = unw_local_addr_space;
875 table = fdesc->index;
876 table_len = fdesc->index_size * sizeof (struct table_entry);
877 debug_frame_base = (uintptr_t) fdesc->debug_frame;
881 a = unw_get_accessors (as);
883 segbase = di->u.rti.segbase;
884 if (di->format == UNW_INFO_FORMAT_IP_OFFSET) {
885 ip_base = di->start_ip;
890 #ifndef UNW_REMOTE_ONLY
891 if (as == unw_local_addr_space)
893 e = lookup (table, table_len, ip - ip_base);
898 #ifndef UNW_LOCAL_ONLY
899 segbase = di->u.rti.segbase;
900 if ((ret = remote_lookup (as, (uintptr_t) table, table_len,
901 ip - ip_base, &ent, arg)) < 0)
906 e = NULL; /* no info found */
911 Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n",
912 (long) ip, (long) di->start_ip, (long) di->end_ip);
913 /* IP is inside this table's range, but there is no explicit
917 Debug (15, "ip=0x%lx, start_ip=0x%lx\n",
918 (long) ip, (long) (e->start_ip_offset));
919 if (debug_frame_base)
920 fde_addr = e->fde_offset + debug_frame_base;
922 fde_addr = e->fde_offset + segbase;
923 Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, "
924 "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase,
925 (long) debug_frame_base, (long) fde_addr);
926 if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi,
928 debug_frame_base : segbase,
930 debug_frame_base != 0, arg)) < 0)
933 /* .debug_frame uses an absolute encoding that does not know about any
934 shared library relocation. */
935 if (di->format == UNW_INFO_FORMAT_TABLE)
937 pi->start_ip += segbase;
938 pi->end_ip += segbase;
939 pi->flags = UNW_PI_FLAG_DEBUG_FRAME;
942 if (ip < pi->start_ip || ip >= pi->end_ip)
949 dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
951 return; /* always a nop */