Hi David, this small patch adds the function that is needed for Frysk
(the code in Frysk cvs).
If you could take a look at it and say your opnion, I would be glad!
I dont know if it makes sense to you add this function, but it is needed
for Frysk.
-- José Flávio Aguilar Paulino
Index: libunwind/src/mi/Gget_unwind_table.c
===================================================================
--- /dev/null
+++ libunwind/src/mi/Gget_unwind_table.c
@@ -0,0 +1,192 @@
+// Copyright 2007, Red Hat Inc.
+
+/* This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include "libunwind_i.h"
+//#include "remote.h"
+#include "dwarf-eh.h"
+
+int
+unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *image, size_t size,
+ unsigned long segbase, unsigned long mapoff, void *arg)
+{
+ Debug(99, "Entering get_unwind_table\n");
+ Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL;
+ unw_word_t addr, eh_frame_start, fde_count, load_base;
+ struct dwarf_eh_frame_hdr *hdr;
+ Elf_W(Ehdr) *ehdr;
+ int i, ret;
+ unw_dyn_info_t di_cache;
+
+ if (size <= EI_CLASS)
+ return -1;
+
+ Debug(99, "Checking elf size\n");
+ if (!(memcmp (image, ELFMAG, SELFMAG) == 0
+ && ((uint8_t *) image)[EI_CLASS] == ELF_CLASS))
+ return -1;
+
+ Debug(99, "Checked elf class\n");
+ ehdr = image;
+ phdr = (Elf_W(Phdr) *) ((char *) image + ehdr->e_phoff);
+ for (i = 0; i < ehdr->e_phnum; ++i)
+ {
+ switch (phdr[i].p_type)
+ {
+ case PT_LOAD:
+ if (phdr[i].p_offset == mapoff)
+ ptxt = phdr + i;
+ break;
+
+ case PT_GNU_EH_FRAME:
+ peh_hdr = phdr + i;
+ break;
+
+ case PT_DYNAMIC:
+ pdyn = phdr + i;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ Debug(99, "Traversed headers\n");
+ if (!ptxt || !peh_hdr)
+ return -UNW_ENOINFO;
+
+ if (pdyn)
+ {
+ Debug(99, "Got dynamic header\n");
+ /* For dynamicly linked executables and shared libraries,
+ DT_PLTGOT is the value that data-relative addresses are
+ relative to for that object. We call this the "gp". */
+ Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset
+ + (char *) image);
+ for (; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ /* Assume that _DYNAMIC is writable and GLIBC has
+ relocated it (true for x86 at least). */
+ di_cache.gp = dyn->d_un.d_ptr;
+ break;
+ }
+ }
+ else
+ /* Otherwise this is a static executable with no _DYNAMIC. Assume
+ that data-relative addresses are relative to 0, i.e.,
+ absolute. */
+ di_cache.gp = 0;
+
+ Debug(99, "Got eh_frame_hdr\n");
+ hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset
+ + (char *) image);
+ if (hdr->version != DW_EH_VERSION)
+ {
+ Debug (1, "table has unexpected version %d\n",
+ hdr->version);
+ return 0;
+ }
+
+ Debug(99, "EH_VERSION is correct\n");
+
+ addr = (unw_word_t) (hdr + 1);
+ Debug (99, "Got addr\n");
+ /* Fill in a dummy proc_info structure. We just need to fill in
+ enough to ensure that dwarf_read_encoded_pointer() can do it's
+ job. Since we don't have a procedure-context at this point, all
+ we have to do is fill in the global-pointer. */
+ memset (pi, 0, sizeof (*pi));
+ Debug(99, "cleared pi\n");
+ pi->gp = di_cache.gp;
+
+ Debug(99, "set pi gp\n");
+
+
+//The following is a dummy local address space used by dwarf_read_encoded_pointer.
+ int
+ local_access_mem (unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *val, int write, void *arg)
+ {
+ Debug(99, "entering local_access_mem, reading addr: 0x%lx into: %p\n",
+ (long) addr, val);
+ if (write)
+ {
+ Debug (16, "mem[%x] <- %x\n", addr, *val);
+ *(unw_word_t *) addr = *val;
+ }
+ else
+ {
+ *val = *(unw_word_t *) addr;
+ Debug (16, "mem[%x] -> %x\n", addr, *val);
+ }
+ Debug(99, "leaving local_access_mem\n");
+ return 0;
+ }
+
+ unw_accessors_t temp_local_accessors = {NULL, NULL, NULL, local_access_mem,
+ NULL, NULL, NULL, NULL, NULL};
+ unw_addr_space_t temp_local_addr_space
+ = unw_create_addr_space(&temp_local_accessors, 0);
+
+ /* (Optionally) read eh_frame_ptr: */
+ if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, &temp_local_accessors,
+ &addr, hdr->eh_frame_ptr_enc, pi,
+ &eh_frame_start, NULL)) < 0)
+ return -1;
+
+ Debug(99, "read eh_frame_start: 0x%lx\n", (long) eh_frame_start);
+
+ /* (Optionally) read fde_count: */
+ if ((ret = dwarf_read_encoded_pointer (temp_local_addr_space, &temp_local_accessors,
+ &addr, hdr->fde_count_enc, pi,
+ &fde_count, NULL)) < 0)
+ return -1;
+
+ Debug(99, "read fde_count: 0x%lx\n", (long) fde_count);
+ if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+ {
+ return -1;
+ }
+
+ load_base = segbase - ptxt->p_vaddr;
+
+ di_cache.start_ip = segbase;
+ di_cache.end_ip = di_cache.start_ip + ptxt->p_memsz;
+ di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE;
+ di_cache.u.rti.name_ptr = 0;
+ /* two 32-bit values (ip_offset/fde_offset) per table-entry: */
+ di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t);
+ di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr)
+ + (addr - (unw_word_t) image
+ - peh_hdr->p_offset));
+
+ /* For the binary-search table in the eh_frame_hdr, data-relative
+ means relative to the start of that section... */
+ di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr)
+ + ((unw_word_t) hdr - (unw_word_t) image
+ - peh_hdr->p_offset));
+
+ Debug(99, "Leaving get_unwind_table\n");
+ return tdep_search_unwind_table (as, ip, &di_cache, pi, need_unwind_info, arg);
+}
Index: libunwind/include/libunwind-common.h.in
===================================================================
--- libunwind.orig/include/libunwind-common.h.in
+++ libunwind/include/libunwind-common.h.in
@@ -225,6 +225,7 @@ unw_save_loc_t;
#define unw_regname UNW_ARCH_OBJ(regname)
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
#define unw_strerror UNW_ARCH_OBJ(strerror)
+#define unw_get_unwind_table UNW_ARCH_OBJ(get_unwind_table)
extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int);
extern void unw_destroy_addr_space (unw_addr_space_t);
@@ -248,5 +249,10 @@ extern int unw_get_save_loc (unw_cursor_
extern int unw_is_signal_frame (unw_cursor_t *);
extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *);
extern const char *unw_strerror (int);
+extern int unw_get_unwind_table(unw_addr_space_t as, unw_word_t ip,
+ unw_proc_info_t *pi, int need_unwind_info,
+ void *image, size_t size,
+ unsigned long segbase, unsigned long mapoff,
+ void *arg);
extern unw_addr_space_t unw_local_addr_space;
Index: libunwind/src/Makefile.am
===================================================================
--- libunwind.orig/src/Makefile.am
+++ libunwind/src/Makefile.am
@@ -56,7 +56,7 @@ libunwind_la_SOURCES_generic = \
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
mi/Gget_reg.c mi/Gset_reg.c \
mi/Gget_fpreg.c mi/Gset_fpreg.c \
- mi/Gset_caching_policy.c
+ mi/Gset_caching_policy.c mi/Gget_unwind_table.c
# List of arch-independent files needed by local-only library (libunwind):
libunwind_la_SOURCES_local = \
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel