diff options
author | Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> | 2007-09-12 21:52:25 -0600 |
---|---|---|
committer | David Mosberger-Tang <davidm@koala.mostang.com> | 2007-09-12 21:52:25 -0600 |
commit | 4499bb29a6214b5df5b3b21e03c6b4f3c8f26cfd (patch) | |
tree | cb0ae28cc5daff63feebb678437f76cd50e8d6a9 /include/tdep-ppc32 | |
parent | 6d75df39b5dd602be2bc3b8edc8b745d6224fd71 (diff) | |
download | libunwind-4499bb29a6214b5df5b3b21e03c6b4f3c8f26cfd.tar.gz |
[PPC32] First check-in to add preliminary support for Linux/PPC32.
Diffstat (limited to 'include/tdep-ppc32')
-rw-r--r-- | include/tdep-ppc32/dwarf-config.h | 56 | ||||
-rw-r--r-- | include/tdep-ppc32/jmpbuf.h | 37 | ||||
-rw-r--r-- | include/tdep-ppc32/libunwind_i.h | 299 |
3 files changed, 392 insertions, 0 deletions
diff --git a/include/tdep-ppc32/dwarf-config.h b/include/tdep-ppc32/dwarf-config.h new file mode 100644 index 00000000..e2676a82 --- /dev/null +++ b/include/tdep-ppc32/dwarf-config.h @@ -0,0 +1,56 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford <cjashfor@us.ibm.com> + Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com> + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com> + Will be replaced when libunwind is ready on ppc64 platform. + +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. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */ +#define DWARF_NUM_PRESERVED_REGS 115 + +#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 + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see X86_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/include/tdep-ppc32/jmpbuf.h b/include/tdep-ppc32/jmpbuf.h new file mode 100644 index 00000000..3780d5b5 --- /dev/null +++ b/include/tdep-ppc32/jmpbuf.h @@ -0,0 +1,37 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford <cjashfor@us.ibm.com> + Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com> + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com> + Will be replaced when libunwind is ready on ppc64 platform. + +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. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +#define JB_SP 6 +#define JB_RP 7 +#define JB_MASK_SAVED 8 +#define JB_MASK 9 diff --git a/include/tdep-ppc32/libunwind_i.h b/include/tdep-ppc32/libunwind_i.h new file mode 100644 index 00000000..2a9f9c1b --- /dev/null +++ b/include/tdep-ppc32/libunwind_i.h @@ -0,0 +1,299 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2006-2007 IBM + Contributed by + Corey Ashford <cjashfor@us.ibm.com> + Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com> + + Copied from libunwind-x86_64.h, modified slightly for building + frysk successfully on ppc64, by Wu Zhou <woodzltc@cn.ibm.com> + Will be replaced when libunwind is ready on ppc64 platform. + +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. */ + +#ifndef PPC32_LIBUNWIND_I_H +#define PPC32_LIBUNWIND_I_H + +/* Target-dependent definitions that are internal to libunwind but need + to be shared with target-independent code. */ + +#include <stdlib.h> +#include <libunwind.h> + +#include "elf32.h" +#include "mempool.h" +#include "dwarf.h" + +struct unw_addr_space +{ + struct unw_accessors acc; + unw_caching_policy_t caching_policy; +#ifdef HAVE_ATOMIC_OPS_H + AO_t cache_generation; +#else + uint32_t cache_generation; +#endif + unw_word_t dyn_generation; /* see dyn-common.h */ + unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ + struct dwarf_rs_cache global_cache; + int validate; +}; + +struct cursor +{ + struct dwarf_cursor dwarf; /* must be first */ + + /* Format of sigcontext structure and address at which it is + stored: */ + enum + { + PPC_SCF_NONE, /* no signal frame encountered */ + PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ + } + sigcontext_format; + unw_word_t sigcontext_addr; +}; + +#define DWARF_GET_LOC(l) ((l).val) + +#ifdef UNW_LOCAL_ONLY +# define DWARF_NULL_LOC DWARF_LOC (0, 0) +# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) +# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) +# define DWARF_IS_REG_LOC(l) 0 +# define DWARF_IS_FP_LOC(l) 0 +# define DWARF_IS_V_LOC(l) 0 +# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) +# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ + tdep_uc_addr((c)->as_arg, (r)), 0)) +# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ + tdep_uc_addr((c)->as_arg, (r)), 0)) +# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ + tdep_uc_addr((c)->as_arg, (r)), 0)) +#else /* !UNW_LOCAL_ONLY */ + +# define DWARF_LOC_TYPE_FP (1 << 0) +# define DWARF_LOC_TYPE_REG (1 << 1) +# define DWARF_LOC_TYPE_V (1 << 2) +# define DWARF_NULL_LOC DWARF_LOC (0, 0) +# define DWARF_IS_NULL_LOC(l) \ + ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) +# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) +# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) +# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) +# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0) +# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) +# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) +# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ + | DWARF_LOC_TYPE_FP)) +# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ + | DWARF_LOC_TYPE_V)) + +#endif /* !UNW_LOCAL_ONLY */ + +static inline int +dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) +{ + unw_word_t *valp = (unw_word_t *) val; + unw_word_t addr; + int ret; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + assert (DWARF_IS_V_LOC (loc)); + assert (!DWARF_IS_FP_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + val, 0, c->as_arg); + + addr = DWARF_GET_LOC (loc); + + if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, + 0, c->as_arg)) < 0) + return ret; + + return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg); +} + +static inline int +dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) +{ + unw_word_t *valp = (unw_word_t *) & val; + unw_word_t addr; + int ret; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + assert (DWARF_IS_V_LOC (loc)); + assert (!DWARF_IS_FP_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + &val, 1, c->as_arg); + + addr = DWARF_GET_LOC (loc); + if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, + 1, c->as_arg)) < 0) + return ret; + + return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg); +} + +static inline int +dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) +{ + unw_word_t *valp = (unw_word_t *) val; + unw_word_t addr; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + assert (DWARF_IS_FP_LOC (loc)); + assert (!DWARF_IS_V_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + val, 0, c->as_arg); + + addr = DWARF_GET_LOC (loc); + return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg); + +} + +static inline int +dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) +{ + unw_word_t *valp = (unw_word_t *) & val; + unw_word_t addr; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + assert (DWARF_IS_FP_LOC (loc)); + assert (!DWARF_IS_V_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + &val, 1, c->as_arg); + + addr = DWARF_GET_LOC (loc); + + return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg); +} + +static inline int +dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val) +{ + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + /* If a code-generator were to save a value of type unw_word_t in a + floating-point register, we would have to support this case. I + suppose it could happen with MMX registers, but does it really + happen? */ + assert (!DWARF_IS_FP_LOC (loc)); + assert (!DWARF_IS_V_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, + 0, c->as_arg); + else + return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, + 0, c->as_arg); +} + +static inline int +dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) +{ + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + /* If a code-generator were to save a value of type unw_word_t in a + floating-point register, we would have to support this case. I + suppose it could happen with MMX registers, but does it really + happen? */ + assert (!DWARF_IS_FP_LOC (loc)); + assert (!DWARF_IS_V_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, + 1, c->as_arg); + else + return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, + 1, c->as_arg); +} + + + +#define tdep_needs_initialization UNW_OBJ(needs_initialization) +#define tdep_init UNW_OBJ(init) +/* Platforms that support UNW_INFO_FORMAT_TABLE need to define + tdep_search_unwind_table. */ +#define tdep_search_unwind_table dwarf_search_unwind_table +#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) +#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_get_func_addr UNW_OBJ(get_func_addr) + +#ifdef UNW_LOCAL_ONLY +# define tdep_find_proc_info(c,ip,n) \ + dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ + (c)->as_arg) +# define tdep_put_unwind_info(as,pi,arg) \ + dwarf_put_unwind_info((as), (pi), (arg)) +#else +# define tdep_find_proc_info(c,ip,n) \ + (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ + (c)->as_arg) +# define tdep_put_unwind_info(as,pi,arg) \ + (*(as)->acc.put_unwind_info)((as), (pi), (arg)) +#endif + +extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip, + int need_unwind_info); + +#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 + +extern int tdep_needs_initialization; + +extern void tdep_init (void); +extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t * di, + unw_proc_info_t * pi, + int need_unwind_info, void *arg); +extern void *tdep_uc_addr (ucontext_t * uc, int reg); +extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff); +extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, + unw_word_t * valp, int write); +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 *entry_point); + +#endif /* PPC64_LIBUNWIND_I_H */ |