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 - + Aug-2007 - Updated by + Jose Flavio Aguilar Paulino 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 + Jose Flavio Aguilar Paulino + +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 + Jose Flavio Aguilar Paulino + +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; + +}