mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-29 10:17:38 +01:00
(Logical change 1.30)
This commit is contained in:
parent
991519dea7
commit
653c9006ac
10 changed files with 828 additions and 0 deletions
182
include/internal.h
Normal file
182
include/internal.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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 <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <libunwind.h>
|
||||
#include <tdep.h>
|
||||
|
||||
#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 */
|
93
include/tdep-ia64.h
Normal file
93
include/tdep-ia64.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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 <endian.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
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 */
|
47
src/Gput_dynamic_unwind_info.c
Normal file
47
src/Gput_dynamic_unwind_info.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
4
src/Lput_dynamic_unwind_info.c
Normal file
4
src/Lput_dynamic_unwind_info.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef UNW_REMOTE_ONLY
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include "Gput_dynamic_unwind_info.c"
|
||||
#endif
|
46
src/dyn-cancel.c
Normal file
46
src/dyn-cancel.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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;
|
||||
}
|
60
src/dyn-extract.c
Normal file
60
src/dyn-extract.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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;
|
||||
}
|
259
src/dyn-remote.c
Normal file
259
src/dyn-remote.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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 <endian.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
98
src/get_proc_name.c
Normal file
98
src/get_proc_name.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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 <endian.h>
|
||||
|
||||
#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;
|
||||
}
|
35
src/ia64/Gget_proc_name.c
Normal file
35
src/ia64/Gget_proc_name.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
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);
|
||||
}
|
4
src/ia64/Lget_proc_name.c
Normal file
4
src/ia64/Lget_proc_name.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef UNW_REMOTE_ONLY
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include "Gget_proc_name.c"
|
||||
#endif
|
Loading…
Reference in a new issue