From 653c9006ac876d521a4caf36de57089f0a74c6af Mon Sep 17 00:00:00 2001 From: "mostang.com!davidm" Date: Thu, 12 Dec 2002 09:17:41 +0000 Subject: [PATCH] (Logical change 1.30) --- include/internal.h | 182 +++++++++++++++++++++++ include/tdep-ia64.h | 93 ++++++++++++ src/Gput_dynamic_unwind_info.c | 47 ++++++ src/Lput_dynamic_unwind_info.c | 4 + src/dyn-cancel.c | 46 ++++++ src/dyn-extract.c | 60 ++++++++ src/dyn-remote.c | 259 +++++++++++++++++++++++++++++++++ src/get_proc_name.c | 98 +++++++++++++ src/ia64/Gget_proc_name.c | 35 +++++ src/ia64/Lget_proc_name.c | 4 + 10 files changed, 828 insertions(+) create mode 100644 include/internal.h create mode 100644 include/tdep-ia64.h create mode 100644 src/Gput_dynamic_unwind_info.c create mode 100644 src/Lput_dynamic_unwind_info.c create mode 100644 src/dyn-cancel.c create mode 100644 src/dyn-extract.c create mode 100644 src/dyn-remote.c create mode 100644 src/get_proc_name.c create mode 100644 src/ia64/Gget_proc_name.c create mode 100644 src/ia64/Lget_proc_name.c diff --git a/include/internal.h b/include/internal.h new file mode 100644 index 00000000..99c321c8 --- /dev/null +++ b/include/internal.h @@ -0,0 +1,182 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 internal_h +#define internal_h + +/* Platform-independent libunwind-internal declarations. */ + +#include +#include +#include +#include + +#ifdef __GNUC__ +# define HIDDEN __attribute__((visibility ("hidden"))) +#else +# define HIDDEN +#endif + +/* Make it easy to write thread-safe code which may or may not be + linked against libpthread. The macros below can be used + unconditionally and if -lpthread is around, they'll call the + corresponding routines otherwise, they do nothing. */ + +#pragma weak pthread_mutex_lock +#pragma weak pthread_mutex_unlock + +#define mutex_lock(l) (pthread_mutex_lock ? pthread_mutex_lock (l) : 0) +#define mutex_unlock(l) (pthread_mutex_unlock ? pthread_mutex_unlock (l) : 0) + +#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn)) +#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn) + +extern int UNWI_OBJ(find_dynamic_proc_info) (unw_addr_space_t as, + unw_word_t ip, + unw_proc_info_t *pi, + int need_unwind_info, void *arg); +extern int UNWI_ARCH_OBJ(extract_dynamic_proc_info) (unw_addr_space_t as, + unw_word_t ip, + unw_proc_info_t *pi, + unw_dyn_info_t *di, + int need_unwind_info, + void *arg); +extern void UNWI_OBJ(put_dynamic_unwind_info) (unw_addr_space_t as, + unw_proc_info_t *pi, void *arg); +extern int UNWI_ARCH_OBJ(dyn_remote_find_proc_info) (unw_addr_space_t as, + unw_word_t ip, + unw_proc_info_t *pi, + unw_word_t *generation, + int need_unwind_info, + void *arg); +extern void UNWI_ARCH_OBJ(dyn_remote_put_unwind_info) (unw_addr_space_t as, + unw_proc_info_t *pi, + void *arg); +extern int UNWI_ARCH_OBJ(get_proc_name) (unw_addr_space_t as, + unw_word_t ip, int is_local, + char *buf, size_t buf_len, void *arg); + +#define unwi_find_dynamic_proc_info(as,ip,pi,n,arg) \ + UNWI_OBJ(find_dynamic_proc_info)(as, ip, pi, n, arg) + +#define unwi_extract_dynamic_proc_info(as,ip,pi,di,n,arg) \ + UNWI_ARCH_OBJ(extract_dynamic_proc_info)(as, ip, pi, di, n, arg) + +#define unwi_put_dynamic_unwind_info(as,pi,arg) \ + UNWI_OBJ(put_dynamic_unwind_info)(as, pi, arg) + +/* These handle the remote (cross-address-space) case of accessing + dynamic unwind info. */ + +#define unwi_dyn_remote_find_proc_info(as,i,p,g,n,arg) \ + UNWI_ARCH_OBJ(dyn_remote_find_proc_info)(as, i, p, g, n, arg) + +#define unwi_dyn_remote_put_unwind_info(as,p,arg) \ + UNWI_ARCH_OBJ(dyn_remote_put_unwind_info)(as, p, arg) + +#define unwi_get_proc_name(as,ip,l,b,s,arg) \ + UNWI_ARCH_OBJ(get_proc_name)(as, ip, l, b, s, arg) + +extern unw_dyn_info_list_t _U_dyn_info_list; +extern pthread_mutex_t _U_dyn_info_list_lock; + +#define WSIZE (sizeof (unw_word_t)) + +static inline int +fetch8 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int8_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + *addr += 1; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 1 - off); +#endif + *valp = val & 0xff; + return ret; +} + +static inline int +fetch16 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int16_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + assert ((off & 0x1) == 0); + + *addr += 2; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 2 - off); +#endif + *valp = val & 0xffff; + return ret; +} + +static inline int +fetch32 (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, int32_t *valp, void *arg) +{ + unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; + int ret; + + assert ((off & 0x3) == 0); + + *addr += 4; + + ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + val >>= 8*off; +#else + val >>= 8*(WSIZE - 4 - off); +#endif + *valp = val & 0xffffffff; + return ret; +} + +static inline int +fetchw (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_word_t *valp, void *arg) +{ + int ret; + + ret = (*a->access_mem) (as, *addr, valp, 0, arg); + *addr += WSIZE; + return ret; +} + +#endif /* internal_h */ diff --git a/include/tdep-ia64.h b/include/tdep-ia64.h new file mode 100644 index 00000000..3f1c8cb0 --- /dev/null +++ b/include/tdep-ia64.h @@ -0,0 +1,93 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 TDEP_IA64_H +#define TDEP_IA64_H + +/* Target-dependent definitions that are internal to libunwind but need + to be shared with target-independent code. */ + +#include +#include + +enum ia64_pregnum + { + /* primary unat: */ + IA64_REG_PRI_UNAT_GR, + IA64_REG_PRI_UNAT_MEM, + + /* register stack */ + IA64_REG_BSP, /* register stack pointer */ + IA64_REG_BSPSTORE, + IA64_REG_PFS, /* previous function state */ + IA64_REG_RNAT, + /* memory stack */ + IA64_REG_PSP, /* previous memory stack pointer */ + /* return pointer: */ + IA64_REG_RP, + + /* preserved registers: */ + IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7, + IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7, + IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR, + IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5, + IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5, + IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19, + IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23, + IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27, + IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31, + IA64_NUM_PREGS + }; + +#include "ia64/script.h" + +struct unw_addr_space + { + struct unw_accessors acc; + int big_endian; + unw_caching_policy_t caching_policy; + uint32_t cache_generation; + unw_word_t dyn_generation; /* see dyn-common.h */ + + struct ia64_script_cache global_cache; + }; + +extern int UNW_ARCH_OBJ (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 UNW_ARCH_OBJ (put_unwind_info) (unw_addr_space_t as, + unw_proc_info_t *pi, void *arg); + +/* Platforms that support UNW_INFO_FORMAT_TABLE need to define + tdep_search_unwind_table. */ +#define tdep_search_unwind_table(a,b,c,d,e,f) \ + UNW_ARCH_OBJ(search_unwind_table) (a,b,c,d,e,f) +#define tdep_put_unwind_info(a,b,c) \ + UNW_ARCH_OBJ(put_unwind_info)(a,b,c) + +#endif /* TDEP_IA64_H */ diff --git a/src/Gput_dynamic_unwind_info.c b/src/Gput_dynamic_unwind_info.c new file mode 100644 index 00000000..c2695cc0 --- /dev/null +++ b/src/Gput_dynamic_unwind_info.c @@ -0,0 +1,47 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 "internal.h" + +HIDDEN void +unwi_put_dynamic_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, + void *arg) +{ + switch (pi->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + unwi_dyn_remote_put_unwind_info (as, pi, arg); + break; + + case UNW_INFO_FORMAT_TABLE: +#ifdef tdep_put_unwind_info + tdep_put_unwind_info (as, pi, arg); + break; +#endif + /* fall through */ + default: + break; + } +} diff --git a/src/Lput_dynamic_unwind_info.c b/src/Lput_dynamic_unwind_info.c new file mode 100644 index 00000000..b5156468 --- /dev/null +++ b/src/Lput_dynamic_unwind_info.c @@ -0,0 +1,4 @@ +#ifndef UNW_REMOTE_ONLY +#define UNW_LOCAL_ONLY +#include "Gput_dynamic_unwind_info.c" +#endif diff --git a/src/dyn-cancel.c b/src/dyn-cancel.c new file mode 100644 index 00000000..85a36458 --- /dev/null +++ b/src/dyn-cancel.c @@ -0,0 +1,46 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 "internal.h" + +void +_U_dyn_cancel (unw_dyn_info_t *di) +{ + mutex_lock (&_U_dyn_info_list_lock); + { + ++_U_dyn_info_list.generation; + + if (di->prev) + di->prev->next = di->next; + else + _U_dyn_info_list.first = di->next; + + if (di->next) + di->next->prev = di->prev; + } + mutex_unlock (&_U_dyn_info_list_lock); + + di->next = di->prev = NULL; +} diff --git a/src/dyn-extract.c b/src/dyn-extract.c new file mode 100644 index 00000000..a9f57ebb --- /dev/null +++ b/src/dyn-extract.c @@ -0,0 +1,60 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 "internal.h" +#include "tdep.h" + +HIDDEN int +unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, unw_dyn_info_t *di, + int need_unwind_info, void *arg) +{ + pi->start_ip = di->start_ip; + pi->end_ip = di->end_ip; + pi->gp = di->gp; + pi->format = di->format; + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + pi->handler = di->u.pi.handler; + pi->flags = di->u.pi.flags; + if (need_unwind_info) + pi->unwind_info = di; + else + pi->unwind_info = NULL; + return 0; + + case UNW_INFO_FORMAT_TABLE: +#ifdef tdep_search_unwind_table + /* call platform-specific search routine: */ + return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); +#else + /* fall through */ +#endif + default: + break; + } + return -UNW_EINVAL; +} diff --git a/src/dyn-remote.c b/src/dyn-remote.c new file mode 100644 index 00000000..d4d50027 --- /dev/null +++ b/src/dyn-remote.c @@ -0,0 +1,259 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 + +#include "internal.h" + +static void +free_regions (unw_dyn_region_info_t *region) +{ + if (region->next) + free_regions (region->next); + free (region); +} + +static int +intern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, + unw_dyn_op_t *op, void *arg) +{ + int ret; + + if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0 + || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0 + || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0 + || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0 + || (ret = fetchw (as, a, addr, &op->val, arg)) < 0) + return ret; + return 0; +} + +static int +intern_regions (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg) +{ + uint32_t insn_count, op_count; + unw_dyn_region_info_t *region; + unw_word_t next_addr; + int i, ret; + + *regionp = NULL; + + if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0 + || (ret = fetch32 (as, a, addr, &insn_count, arg)) < 0 + || (ret = fetch32 (as, a, addr, &op_count, arg)) < 0) + return ret; + + region = calloc (1, _U_dyn_region_info_size (op_count)); + if (!region) + { + ret = -UNW_ENOMEM; + goto out; + } + + region->insn_count = insn_count; + region->op_count = op_count; + for (i = 0; i < op_count; ++i) + if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0) + goto out; + + if (next_addr) + if ((ret = intern_regions (as, a, &next_addr, ®ion->next, arg)) < 0) + goto out; + + *regionp = region; + return 0; + + out: + if (region) + free_regions (region); + return ret; +} + +static int +intern_array (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data, + void *arg) +{ + unw_word_t *data = calloc (table_len, WSIZE); + int ret = 0, i; + + if (!data) + { + ret = -UNW_ENOMEM; + goto out; + } + + for (i = 0; i < table_len; ++i) + if (fetchw (as, a, addr, data + i, arg) < 0) + goto out; + + *table_data = data; + return 0; + + out: + if (data) + free (data); + return ret; +} + +static void +free_dyn_info (unw_dyn_info_t *di) +{ + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + if (di->u.pi.regions) + { + free_regions (di->u.pi.regions); + di->u.pi.regions = NULL; + } + break; + + case UNW_INFO_FORMAT_TABLE: + if (di->u.ti.table_data) + { + free (di->u.ti.table_data); + di->u.ti.table_data = NULL; + } + break; + + default: + break; + } +} + +static int +intern_dyn_info (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unw_dyn_info_t *di, void *arg) +{ + int ret; + + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0 + || (ret = fetch32 (as, a, addr, &di->u.pi.flags, arg)) < 0 + || (ret = fetch32 (as, a, addr, &di->u.pi.pad0, arg)) < 0 + || (ret = intern_regions (as, a, addr, &di->u.pi.regions, arg)) < 0) + goto out; + break; + + case UNW_INFO_FORMAT_TABLE: + if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0 + || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0 + || (ret = intern_array (as, a, addr, di->u.ti.table_len, + &di->u.ti.table_data, arg)) < 0) + goto out; + break; + + default: + ret = -UNW_ENOINFO; + goto out; + } + return 0; + + out: + free_dyn_info (di); + return ret; +} + +HIDDEN int +unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, unw_word_t *genp, + int need_unwind_info, void *arg) +{ + unw_accessors_t *a = unw_get_accessors (as); + unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2; + unw_word_t start_ip, end_ip; + unw_dyn_info_t di; + int32_t pad; + int ret; + + ret = (*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg); + if (ret < 0) + return ret; + + do + { + addr = dyn_list_addr; + + if ((ret = fetchw (as, a, &addr, &gen1, arg)) < 0 + || (ret = fetchw (as, a, &addr, &next_addr, arg)) < 0) + return ret; + + for (addr = next_addr; addr != 0; addr = next_addr) + { + if ((ret = fetchw (as, a, &addr, &next_addr, arg)) < 0 + || (ret = fetchw (as, a, &addr, &start_ip, arg)) < 0 + || (ret = fetchw (as, a, &addr, &end_ip, arg)) < 0) + return ret; + + if (ip >= di.start_ip && ip < di.end_ip) + { + if ((ret = fetchw (as, a, &addr, &di.gp, arg)) < 0 + || (ret = fetch32 (as, a, &addr, &di.format, arg)) < 0 + || (ret = fetch32 (as, a, &addr, &pad, arg)) < 0) + return ret; + + if (need_unwind_info) + if ((ret = intern_dyn_info (as, a, &addr, &di, arg)) < 0) + return ret; + + ret = unwi_extract_dynamic_proc_info (as, ip, pi, &di, + need_unwind_info, arg); + if (ret < 0) + { + free_dyn_info (&di); + return ret; + } + return 0; + } + } + + /* Recheck generation number to ensure things didn't change + underneath us: */ + addr = dyn_list_addr; + if ((ret = fetchw (as, a, &addr, &gen2, arg)) < 0) + return ret; + } + while (gen1 != gen2); + *genp = gen1; + return 0; +} + +HIDDEN void +unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, + void *arg) +{ + if (!pi->unwind_info) + return; + + free_dyn_info(pi->unwind_info); + pi->unwind_info = NULL; +} diff --git a/src/get_proc_name.c b/src/get_proc_name.c new file mode 100644 index 00000000..1922a78f --- /dev/null +++ b/src/get_proc_name.c @@ -0,0 +1,98 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 "internal.h" + +static int +intern_string (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t addr, char *buf, size_t buf_len, void *arg) +{ + int ret, i; + + for (i = 0; i < buf_len; ++i) + { + if ((ret = fetch8 (as, a, &addr, buf + i, arg)) < 0) + return ret; + + if (buf[i] == '\0') + return 0; /* copied full string; return success */ + } + buf[buf_len - 1] = '\0'; /* ensure string is NUL terminated */ + return -UNW_ENOMEM; +} + +HIDDEN int +unwi_get_proc_name (unw_addr_space_t as, unw_word_t ip, int is_local, + char *buf, size_t buf_len, void *arg) +{ + unw_accessors_t *a = unw_get_accessors (as); + unw_proc_info_t pi; + int ret; + + buf[0] = '\0'; /* always return a valid string, even if it's empty */ + + ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg); + if (ret == 0) + { + unw_dyn_info_t *di = pi.unwind_info; + + switch (di->format) + { + case UNW_INFO_FORMAT_DYNAMIC: + ret = intern_string (as, a, di->u.pi.name_ptr, buf, buf_len, arg); + break; + + case UNW_INFO_FORMAT_TABLE: + /* XXX should we create a fake name, e.g.: "tablenameN", + where N is the index of the function in the table??? */ + ret = -UNW_ENOINFO; + break; + + default: + ret = -UNW_EINVAL; + break; + } + unwi_put_dynamic_unwind_info (as, &pi, arg); + return ret; + } + + if (ret != -UNW_ENOINFO) + return ret; + + /* not a dynamic procedure */ + + if (!is_local) + /* It makes no sense to implement get_proc_name() for remote + address spaces because that would require a callback and in + that case, the application using libunwind needs to know how to + look up a procedure name anyhow. */ + return -UNW_ENOINFO; + + /* XXX implement me: look up ELF executable covering IP, then check + dynamic and regular symbol tables for a good name. */ + return -UNW_ENOINFO; +} diff --git a/src/ia64/Gget_proc_name.c b/src/ia64/Gget_proc_name.c new file mode 100644 index 00000000..045bbac6 --- /dev/null +++ b/src/ia64/Gget_proc_name.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 +unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len) +{ + struct ia64_cursor *c = (struct ia64_cursor *) cursor; + + return unwi_get_proc_name (c->as, c->ip, c->as == unw_local_addr_space, + buf, buf_len, c->as_arg); +} diff --git a/src/ia64/Lget_proc_name.c b/src/ia64/Lget_proc_name.c new file mode 100644 index 00000000..4c39ede8 --- /dev/null +++ b/src/ia64/Lget_proc_name.c @@ -0,0 +1,4 @@ +#ifndef UNW_REMOTE_ONLY +#define UNW_LOCAL_ONLY +#include "Gget_proc_name.c" +#endif