Hi people,
This patch adds the function address needed by PowerPC64.
I tried to make a generic implementation in src/mi/get_func_addr.c
I hope that David can have an ideia of its implementation.
regards,
--
Jose Flavio Aguilar Paulino
([EMAIL PROTECTED])
System / Software Engineer
Toolchain Team
LTC, Linux Technology Center
IBM Brazil
Index: libunwind/src/elfxx.c
===================================================================
--- libunwind/src/elfxx.c.orig
+++ libunwind/src/elfxx.c
@@ -1,7 +1,8 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2003-2005 Hewlett-Packard Co
Contributed by David Mosberger-Tang <[EMAIL PROTECTED]>
-
+ Aug-2007 - Updated by
+ Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
This file is part of libunwind.
Permission is hereby granted, free of charge, to any person obtaining
@@ -39,7 +40,8 @@ elf_w (valid_object) (struct elf_image *
static int
-elf_w (lookup_symbol) (unw_word_t ip, struct elf_image *ei,
+elf_w (lookup_symbol) (unw_addr_space_t as,
+ unw_word_t ip, struct elf_image *ei,
Elf_W (Addr) load_offset,
char *buf, size_t buf_len, unw_word_t *offp)
{
@@ -48,7 +50,8 @@ elf_w (lookup_symbol) (unw_word_t ip, st
Elf_W (Sym) *sym, *symtab, *symtab_end;
Elf_W (Off) soff, str_soff;
Elf_W (Shdr) *shdr, *str_shdr;
- Elf_W (Addr) val, min_dist = ~(Elf_W (Addr))0;
+ Elf_W (Addr) func_addr, sym_val, min_dist = ~(Elf_W (Addr))0;
+ Elf_W (Addr) cur_dist;
int i, ret = 0;
char *strtab;
@@ -98,18 +101,35 @@ elf_w (lookup_symbol) (unw_word_t ip, st
if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
&& sym->st_shndx != SHN_UNDEF)
{
- val = sym->st_value;
- if (sym->st_shndx != SHN_ABS)
- val += load_offset;
- Debug (16, "0x%016lx info=0x%02x %s\n",
- (long) val, sym->st_info, strtab + sym->st_name);
+ /* On some architectures, the symbol value doesn't point
+ directly at the function, but to a function descriptor
+ in a table (TOC, opd section) instead.
+ This is true for PowerPC64. */
+ sym_val = sym->st_value;
+ ret = tdep_get_func_addr(as, sym_val, &func_addr);
+ if (ret != 0)
+ continue;
+
+ if (sym->st_shndx != SHN_ABS)
+ func_addr += load_offset;
+
+ /* Just some checks to see if the function address is
+ in a valid range */
+ cur_dist = (Elf_W (Addr)) (ip - func_addr);
+ if (unlikely (cur_dist < 0))
+ continue;
+ if (unlikely (sym->st_size && ip >= func_addr + sym->st_size))
+ continue;
+
+ Debug (16, "sym_val: 0x%016lx func_addr: 0x%016lx info=0x%02x %s\n",
+ (long) sym_val, func_addr, sym->st_info, strtab + sym->st_name);
- if ((Elf_W (Addr)) (ip - val) < min_dist)
+ if (cur_dist < min_dist)
{
- min_dist = (Elf_W (Addr)) (ip - val);
+ min_dist = cur_dist;
strncpy (buf, strtab + sym->st_name, buf_len);
buf[buf_len - 1] = '\0';
- if (strlen (strtab + sym->st_name) >= buf_len)
+ if (strlen (strtab + sym->st_name) >= buf_len)
ret = -UNW_ENOMEM;
}
}
@@ -125,6 +145,7 @@ elf_w (lookup_symbol) (unw_word_t ip, st
return -UNW_ENOINFO; /* not found */
if (offp)
*offp = min_dist;
+ //printf("buf_p: %p\n", buf);
return ret;
}
@@ -134,7 +155,8 @@ elf_w (lookup_symbol) (unw_word_t ip, st
sensitive to the performance of this routine, why bother... */
HIDDEN int
-elf_w (get_proc_name) (pid_t pid, unw_word_t ip, char *buf, size_t buf_len,
+elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip,
+ char *buf, size_t buf_len,
unw_word_t *offp)
{
unsigned long segbase, mapoff;
@@ -158,7 +180,7 @@ elf_w (get_proc_name) (pid_t pid, unw_wo
break;
}
- ret = elf_w (lookup_symbol) (ip, &ei, load_offset, buf, buf_len, offp);
+ ret = elf_w (lookup_symbol) (as, ip, &ei, load_offset, buf, buf_len, offp);
munmap (ei.image, ei.size);
ei.image = NULL;
Index: libunwind/src/ppc64/Ginit.c
===================================================================
--- libunwind/src/ppc64/Ginit.c.orig
+++ libunwind/src/ppc64/Ginit.c
@@ -208,7 +208,7 @@ get_static_proc_name (unw_addr_space_t a
char *buf, size_t buf_len, unw_word_t *offp,
void *arg)
{
- return _Uelf64_get_proc_name (getpid (), ip, buf, buf_len, offp);
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
}
HIDDEN void
Index: libunwind/src/ptrace/_UPT_get_proc_name.c
===================================================================
--- libunwind/src/ptrace/_UPT_get_proc_name.c.orig
+++ libunwind/src/ptrace/_UPT_get_proc_name.c
@@ -32,9 +32,9 @@ _UPT_get_proc_name (unw_addr_space_t as,
struct UPT_info *ui = arg;
#if ELF_CLASS == ELFCLASS64
- return _Uelf64_get_proc_name (ui->pid, ip, buf, buf_len, offp);
+ return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
#elif ELF_CLASS == ELFCLASS32
- return _Uelf32_get_proc_name (ui->pid, ip, buf, buf_len, offp);
+ return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp);
#else
return -UNW_ENOINFO;
#endif
Index: libunwind/src/elfxx.h
===================================================================
--- libunwind/src/elfxx.h.orig
+++ libunwind/src/elfxx.h
@@ -68,6 +68,7 @@ elf_map_image (struct elf_image *ei, con
}
extern int elf_w (valid_object) (struct elf_image *ei);
-extern int elf_w (get_proc_name) (pid_t pid, unw_word_t ip,
+extern int elf_w (get_proc_name) (unw_addr_space_t as,
+ pid_t pid, unw_word_t ip,
char *buf, size_t len,
unw_word_t *offp);
Index: libunwind/include/tdep-ppc64/libunwind_i.h
===================================================================
--- libunwind/include/tdep-ppc64/libunwind_i.h.orig
+++ libunwind/include/tdep-ppc64/libunwind_i.h
@@ -255,7 +255,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf
#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image)
#define tdep_access_reg UNW_OBJ(access_reg)
#define tdep_access_fpreg UNW_OBJ(access_fpreg)
-#define tdep_access_vreg UNW_OBJ(access_vreg)
+
+#define tdep_get_func_addr UNW_OBJ(get_func_addr)
#ifdef UNW_LOCAL_ONLY
# define tdep_find_proc_info(c,ip,n) \
@@ -294,4 +295,7 @@ extern int tdep_access_reg (struct curso
extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
unw_fpreg_t * valp, int write);
+extern int tdep_get_func_addr(unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *func_addr);
+
#endif /* PPC64_LIBUNWIND_I_H */
Index: libunwind/src/Makefile.am
===================================================================
--- libunwind/src/Makefile.am.orig
+++ libunwind/src/Makefile.am
@@ -154,7 +154,7 @@ libunwind_la_SOURCES_x86_common = $(libu
$(dwarf_SOURCES_common) \
elf32.c elf32.h \
x86/init.h x86/offsets.h x86/unwind_i.h \
- x86/is_fpreg.c x86/regname.c
+ x86/is_fpreg.c x86/regname.c mi/get_func_addr.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \
@@ -209,7 +209,7 @@ libunwind_la_SOURCES_ppc64_common = $(li
$(dwarf_SOURCES_common) \
elf64.c elf64.h \
ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h \
- ppc64/is_fpreg.c ppc64/regname.c
+ ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c
# The list of files that go into libunwind:
libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \
Index: libunwind/src/ppc64/get_func_addr.c
===================================================================
--- /dev/null
+++ libunwind/src/ppc64/get_func_addr.c
@@ -0,0 +1,46 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <[EMAIL PROTECTED]>
+ Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
+
+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 "unwind_i.h"
+
+int
+tdep_get_func_addr(unw_addr_space_t as, unw_word_t addr,
+ unw_word_t *func_addr)
+{
+ unw_word_t offset;
+ unw_accessors_t *a;
+
+ /*
+ * This really is a fixed offset of zero, so this code is here in the
+ * event that someone decides to change the position of the entry
+ * component within the func_descr_t structure. (very unlikely)
+ */
+ offset = 0; //((void *) &dummy.entry - (void *) &dummy);
+
+ a = unw_get_accessors (as);
+ return (a->access_mem) (as, addr + offset, func_addr, 0, NULL) < 0;
+}
Index: libunwind/src/x86/Ginit.c
===================================================================
--- libunwind/src/x86/Ginit.c.orig
+++ libunwind/src/x86/Ginit.c
@@ -186,7 +186,7 @@ get_static_proc_name (unw_addr_space_t a
char *buf, size_t buf_len, unw_word_t *offp,
void *arg)
{
- return _Uelf32_get_proc_name (getpid (), ip, buf, buf_len, offp);
+ return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
}
HIDDEN void
Index: libunwind/src/x86_64/Ginit.c
===================================================================
--- libunwind/src/x86_64/Ginit.c.orig
+++ libunwind/src/x86_64/Ginit.c
@@ -233,7 +233,7 @@ get_static_proc_name (unw_addr_space_t a
char *buf, size_t buf_len, unw_word_t *offp,
void *arg)
{
- return _Uelf64_get_proc_name (getpid (), ip, buf, buf_len, offp);
+ return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp);
}
HIDDEN void
Index: libunwind/src/mi/get_func_addr.c
===================================================================
--- /dev/null
+++ libunwind/src/mi/get_func_addr.c
@@ -0,0 +1,42 @@
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2006-2007 IBM
+ Contributed by
+ Corey Ashford <[EMAIL PROTECTED]>
+ Jose Flavio Aguilar Paulino <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
+
+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"
+
+int
+tdep_get_func_addr(unw_addr_space_t as, unw_word_t sym_value,
+ unw_word_t *func_addr)
+{
+
+ /* Trivial implementation, for many archs the address of
+ a function is just the value of the symbol */
+ *func_addr = sym_value;
+
+ /* Its always well succedd, maybe in future, some sanity check */
+ return 0;
+
+}
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel