Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac @@ -165,12 +165,6 @@ AM_CONDITIONAL(USE_DWARF, [test x$use_dwarf = xyes]) AC_MSG_RESULT([$use_dwarf]) -if test x$target_arch = xppc64; then - libdir='${exec_prefix}/lib64' - AC_MSG_NOTICE([PowerPC64 detected, lib will be installed ${libdir}]); - AC_SUBST([libdir]) -fi - AC_MSG_CHECKING([whether to restrict build to remote support]) if test x$target_arch != x$host_arch; then CPPFLAGS="${CPPFLAGS} -DUNW_REMOTE_ONLY" Index: b/src/Makefile.am =================================================================== --- a/src/Makefile.am +++ b/src/Makefile.am @@ -331,12 +331,12 @@ x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c # The list of local files that go to Power 64 and 32: -libunwind_la_SOURCES_ppc = ppc/Lcreate_addr_space.c \ +libunwind_la_SOURCES_ppc = \ ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \ ppc/Linit_remote.c ppc/Lis_signal_frame.c # The list of generic files that go to Power 64 and 32: -libunwind_ppc_la_SOURCES_ppc_generic = ppc/Gcreate_addr_space.c \ +libunwind_ppc_la_SOURCES_ppc_generic = \ ppc/Gget_proc_info.c ppc/Gget_save_loc.c ppc/Ginit_local.c \ ppc/Ginit_remote.c ppc/Gis_signal_frame.c @@ -349,6 +349,7 @@ libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ $(libunwind_la_SOURCES_local) \ $(libunwind_la_SOURCES_ppc) \ + ppc32/Lcreate_addr_space.c \ ppc32/Lglobal.c ppc32/Linit.c \ ppc32/Lregs.c ppc32/Lresume.c ppc32/Lstep.c @@ -356,6 +357,7 @@ libunwind_ppc32_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ $(libunwind_la_SOURCES_generic) \ $(libunwind_ppc_la_SOURCES_ppc_generic) \ + ppc32/Gcreate_addr_space.c \ ppc32/Gglobal.c ppc32/Ginit.c \ ppc32/Gregs.c ppc32/Gresume.c ppc32/Gstep.c @@ -368,6 +370,7 @@ libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ $(libunwind_la_SOURCES_local) \ $(libunwind_la_SOURCES_ppc) \ + ppc64/Lcreate_addr_space.c \ ppc64/Lglobal.c ppc64/Linit.c \ ppc64/Lregs.c ppc64/Lresume.c ppc64/Lstep.c @@ -375,6 +378,7 @@ libunwind_ppc64_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ $(libunwind_la_SOURCES_generic) \ $(libunwind_ppc_la_SOURCES_ppc_generic) \ + ppc64/Gcreate_addr_space.c \ ppc64/Gglobal.c ppc64/Ginit.c \ ppc64/Gregs.c ppc64/Gresume.c ppc64/Gstep.c @@ -557,6 +561,7 @@ libunwind_ppc64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) libunwind_ppc64_la_LIBADD = libunwind-dwarf-generic.la libunwind_ppc64_la_LIBADD += libunwind-elf64.la + libunwind_ppc64_la_LIBADD += $(LIBLZMA) if !REMOTE_ONLY libunwind_ppc64_la_LIBADD += libunwind.la -lc endif Index: b/tests/Makefile.am =================================================================== --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -193,3 +193,5 @@ Lia64_test_readonly_LDADD = $(LIBUNWIND_local) ia64_test_dyn1_LDADD = $(LIBUNWIND) ia64_test_sig_LDADD = $(LIBUNWIND) +ppc64_test_altivec_LDADD = $(LIBUNWIND) + Index: b/include/libunwind-ppc64.h =================================================================== --- a/include/libunwind-ppc64.h +++ b/include/libunwind-ppc64.h @@ -222,6 +222,13 @@ } ppc64_regnum_t; +typedef enum + { + UNW_PPC64_ABI_ELFv1, + UNW_PPC64_ABI_ELFv2 + } +ppc64_abi_t; + /* * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for * passing parameters to exception handlers. Index: b/include/tdep-ppc64/dwarf-config.h =================================================================== --- a/include/tdep-ppc64/dwarf-config.h +++ b/include/tdep-ppc64/dwarf-config.h @@ -38,7 +38,7 @@ #define DWARF_REGNUM_MAP_LENGTH 115 /* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 1 +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) /* Convert a pointer to a dwarf_cursor structure to a pointer to unw_cursor_t. */ Index: b/include/tdep-ppc64/libunwind_i.h =================================================================== --- a/include/tdep-ppc64/libunwind_i.h +++ b/include/tdep-ppc64/libunwind_i.h @@ -51,6 +51,8 @@ struct unw_addr_space { struct unw_accessors acc; + int big_endian; + ppc64_abi_t abi; unw_caching_policy_t caching_policy; #ifdef HAVE_ATOMIC_OPS_H AO_t cache_generation; @@ -289,7 +291,7 @@ #define tdep_get_as(c) ((c)->dwarf.as) #define tdep_get_as_arg(c) ((c)->dwarf.as_arg) #define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) 1 +#define tdep_big_endian(as) ((as)->big_endian) extern int tdep_init_done; Index: b/src/dwarf/Gexpr.c =================================================================== --- a/src/dwarf/Gexpr.c +++ b/src/dwarf/Gexpr.c @@ -212,12 +212,13 @@ }) # define push(x) \ do { \ + unw_word_t _x = (x); \ if (tos >= MAX_EXPR_STACK_SIZE) \ { \ Debug (1, "Stack overflow\n"); \ return -UNW_EINVAL; \ } \ - stack[tos++] = (x); \ + stack[tos++] = _x; \ } while (0) # define pick(n) \ ({ \ Index: b/src/elfxx.c =================================================================== --- a/src/elfxx.c +++ b/src/elfxx.c @@ -128,10 +128,11 @@ if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC && sym->st_shndx != SHN_UNDEF) { - if (tdep_get_func_addr (as, sym->st_value, &val) < 0) - continue; + val = sym->st_value; if (sym->st_shndx != SHN_ABS) val += load_offset; + if (tdep_get_func_addr (as, val, &val) < 0) + continue; Debug (16, "0x%016lx info=0x%02x %s\n", (long) val, sym->st_info, strtab + sym->st_name); Index: b/src/ppc/Gcreate_addr_space.c =================================================================== --- a/src/ppc/Gcreate_addr_space.c +++ /dev/null @@ -1,56 +0,0 @@ -/* 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 - -#include - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * Linux ppc64 supports only big-endian. - */ - if (byte_order != 0 && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - return as; -#endif -} Index: b/src/ppc/Gis_signal_frame.c =================================================================== --- a/src/ppc/Gis_signal_frame.c +++ b/src/ppc/Gis_signal_frame.c @@ -31,7 +31,7 @@ unw_is_signal_frame (unw_cursor_t * cursor) { struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, ip; + unw_word_t w0, w1, i0, i1, i2, ip; unw_addr_space_t as; unw_accessors_t *a; void *arg; @@ -60,7 +60,19 @@ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) return 0; - w1 >>= 32; - return (w0 == 0x38210080380000ac && w1 == 0x44000002); + if (tdep_big_endian (as)) + { + i0 = w0 >> 32; + i1 = w0 & 0xffffffffUL; + i2 = w1 >> 32; + } + else + { + i0 = w0 & 0xffffffffUL; + i1 = w0 >> 32; + i2 = w1 & 0xffffffffUL; + } + + return (i0 == 0x38210080 && i1 == 0x380000ac && i2 == 0x44000002); } Index: b/src/ppc/Lcreate_addr_space.c =================================================================== --- a/src/ppc/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif Index: b/src/ppc32/Gcreate_addr_space.c =================================================================== --- /dev/null +++ b/src/ppc32/Gcreate_addr_space.c @@ -0,0 +1,56 @@ +/* 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 + +#include + +PROTECTED unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * We support only big-endian on Linux ppc32. + */ + if (byte_order != 0 && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + return as; +#endif +} Index: b/src/ppc32/Lcreate_addr_space.c =================================================================== --- /dev/null +++ b/src/ppc32/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif Index: b/src/ppc64/Gcreate_addr_space.c =================================================================== --- /dev/null +++ b/src/ppc64/Gcreate_addr_space.c @@ -0,0 +1,71 @@ +/* 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 + +#include + +PROTECTED unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * We support both big- and little-endian on Linux ppc64. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + + /* FIXME! There is no way to specify the ABI. + Default to ELFv1 on big-endian and ELFv2 on little-endian. */ + if (as->big_endian) + as->abi = UNW_PPC64_ABI_ELFv1; + else + as->abi = UNW_PPC64_ABI_ELFv2; + + return as; +#endif +} Index: b/src/ppc64/Ginit.c =================================================================== --- a/src/ppc64/Ginit.c +++ b/src/ppc64/Ginit.c @@ -210,6 +210,12 @@ ppc64_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); +#if _CALL_ELF == 2 + local_addr_space.abi = UNW_PPC64_ABI_ELFv2; +#else + local_addr_space.abi = UNW_PPC64_ABI_ELFv1; +#endif local_addr_space.caching_policy = UNW_CACHE_GLOBAL; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; Index: b/src/ppc64/Lcreate_addr_space.c =================================================================== --- /dev/null +++ b/src/ppc64/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif Index: b/src/ppc64/get_func_addr.c =================================================================== --- a/src/ppc64/get_func_addr.c +++ b/src/ppc64/get_func_addr.c @@ -31,15 +31,21 @@ tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr, unw_word_t *entry_point) { - unw_accessors_t *a; - int ret; + if (as->abi == UNW_PPC64_ABI_ELFv1) + { + unw_accessors_t *a; + int ret; + + a = unw_get_accessors (as); + /* Entry-point is stored in the 1st word of the function descriptor. + In case that changes in the future, we'd have to update the line + below and read the word at addr + offset: */ + ret = (*a->access_mem) (as, addr, entry_point, 0, NULL); + if (ret < 0) + return ret; + } + else + *entry_point = addr; - a = unw_get_accessors (as); - /* Entry-point is stored in the 1st word of the function descriptor. - In case that changes in the future, we'd have to update the line - below and read the word at addr + offset: */ - ret = (*a->access_mem) (as, addr, entry_point, 0, NULL); - if (ret < 0) - return ret; return 0; }