mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-27 01:27:39 +01:00
Update.
}(Logical change 1.162)
This commit is contained in:
parent
a758c420e1
commit
410f962b8d
12 changed files with 0 additions and 1275 deletions
|
@ -1,326 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "tdep.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, i;
|
||||
unw_dyn_region_info_t *region;
|
||||
unw_word_t next_addr;
|
||||
int ret;
|
||||
|
||||
*regionp = NULL;
|
||||
|
||||
if (!*addr)
|
||||
return 0; /* NULL region-list */
|
||||
|
||||
if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0
|
||||
|| (ret = fetch32 (as, a, addr, (int32_t *) &insn_count, arg)) < 0
|
||||
|| (ret = fetch32 (as, a, addr, (int32_t *) &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 i, *data = calloc (table_len, WSIZE);
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
|
||||
case UNW_INFO_FORMAT_REMOTE_TABLE:
|
||||
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)
|
||||
{
|
||||
unw_word_t first_region;
|
||||
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,
|
||||
(int32_t *) &di->u.pi.flags, arg)) < 0)
|
||||
goto out;
|
||||
*addr += 4; /* skip over pad0 */
|
||||
if ((ret = fetchw (as, a, addr, &first_region, arg)) < 0
|
||||
|| (ret = intern_regions (as, a, &first_region, &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;
|
||||
|
||||
case UNW_INFO_FORMAT_REMOTE_TABLE:
|
||||
if ((ret = fetchw (as, a, addr, &di->u.rti.name_ptr, arg)) < 0
|
||||
|| (ret = fetchw (as, a, addr, &di->u.rti.segbase, arg)) < 0
|
||||
|| (ret = fetchw (as, a, addr, &di->u.rti.table_len, arg)) < 0
|
||||
|| (ret = fetchw (as, a, addr, &di->u.rti.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,
|
||||
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, start_ip, end_ip;
|
||||
unw_dyn_info_t *di = NULL;
|
||||
int ret;
|
||||
|
||||
if (as->dyn_info_list_addr)
|
||||
dyn_list_addr = as->dyn_info_list_addr;
|
||||
else
|
||||
{
|
||||
if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0)
|
||||
return -UNW_ENOINFO;
|
||||
if (as->caching_policy != UNW_CACHE_NONE)
|
||||
as->dyn_info_list_addr = dyn_list_addr;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
addr = dyn_list_addr;
|
||||
|
||||
ret = -UNW_ENOINFO;
|
||||
|
||||
if (fetchw (as, a, &addr, &gen1, arg) < 0
|
||||
|| fetchw (as, a, &addr, &next_addr, arg) < 0)
|
||||
return ret;
|
||||
|
||||
for (addr = next_addr; addr != 0; addr = next_addr)
|
||||
{
|
||||
if (fetchw (as, a, &addr, &next_addr, arg) < 0)
|
||||
goto recheck; /* only fail if generation # didn't change */
|
||||
|
||||
addr += WSIZE; /* skip over prev_addr */
|
||||
|
||||
if (fetchw (as, a, &addr, &start_ip, arg) < 0
|
||||
|| fetchw (as, a, &addr, &end_ip, arg) < 0)
|
||||
goto recheck; /* only fail if generation # didn't change */
|
||||
|
||||
if (ip >= start_ip && ip < end_ip)
|
||||
{
|
||||
if (!di)
|
||||
di = calloc (1, sizeof (*di));
|
||||
|
||||
di->start_ip = start_ip;
|
||||
di->end_ip = end_ip;
|
||||
|
||||
if (fetchw (as, a, &addr, &di->gp, arg) < 0
|
||||
|| fetch32 (as, a, &addr, &di->format, arg) < 0)
|
||||
goto recheck; /* only fail if generation # didn't change */
|
||||
|
||||
addr += 4; /* skip over padding */
|
||||
|
||||
if (need_unwind_info
|
||||
&& intern_dyn_info (as, a, &addr, di, arg) < 0)
|
||||
goto recheck; /* only fail if generation # didn't change */
|
||||
|
||||
if (unwi_extract_dynamic_proc_info (as, ip, pi, di,
|
||||
need_unwind_info, arg) < 0)
|
||||
{
|
||||
free_dyn_info (di);
|
||||
goto recheck; /* only fail if generation # didn't change */
|
||||
}
|
||||
ret = 0; /* OK, found it */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-check generation number to ensure the data we have is
|
||||
consistent. */
|
||||
recheck:
|
||||
addr = dyn_list_addr;
|
||||
if (fetchw (as, a, &addr, &gen2, arg) < 0)
|
||||
return ret;
|
||||
}
|
||||
while (gen1 != gen2);
|
||||
|
||||
if (ret < 0 && di)
|
||||
free (di);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
free (pi->unwind_info);
|
||||
pi->unwind_info = NULL;
|
||||
}
|
||||
|
||||
/* Returns 1 if the cache is up-to-date or -1 if the cache contained
|
||||
stale data and had to be flushed. */
|
||||
|
||||
HIDDEN int
|
||||
unwi_dyn_validate_cache (unw_addr_space_t as, void *arg)
|
||||
{
|
||||
unw_word_t addr, gen;
|
||||
unw_accessors_t *a;
|
||||
|
||||
if (!as->dyn_info_list_addr)
|
||||
/* If we don't have the dyn_info_list_addr, we don't have anything
|
||||
in the cache. */
|
||||
return 0;
|
||||
|
||||
a = unw_get_accessors (as);
|
||||
addr = as->dyn_info_list_addr;
|
||||
|
||||
if (fetchw (as, a, &addr, &gen, arg) < 0)
|
||||
return 1;
|
||||
|
||||
if (gen == as->dyn_generation)
|
||||
return 1;
|
||||
|
||||
unw_flush_cache (as, 0, 0);
|
||||
as->dyn_generation = gen;
|
||||
return -1;
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2001-2003 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"
|
||||
|
||||
static inline int
|
||||
intern_string (unw_addr_space_t as, unw_accessors_t *a,
|
||||
unw_word_t addr, char *buf, size_t buf_len, void *arg)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
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,
|
||||
char *buf, size_t buf_len, unw_word_t *offp, 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;
|
||||
|
||||
if (offp)
|
||||
*offp = ip - pi.start_ip;
|
||||
|
||||
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:
|
||||
case UNW_INFO_FORMAT_REMOTE_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, try to lookup static procedure name: */
|
||||
|
||||
if (a->get_proc_name)
|
||||
return (*a->get_proc_name) (as, ip, buf, buf_len, offp, arg);
|
||||
|
||||
return -UNW_ENOINFO;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 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 "_UPT_internal.h"
|
||||
|
||||
int
|
||||
_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
|
||||
int write, void *arg)
|
||||
{
|
||||
struct UPT_info *ui = arg;
|
||||
pid_t pid = ui->pid;
|
||||
|
||||
errno = 0;
|
||||
if (write)
|
||||
{
|
||||
debug (100, "%s: mem[%lx] <- %lx\n", __FUNCTION__,
|
||||
(long) addr, (long) *val);
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
ptrace (PTRACE_POKEDATA, pid, addr, *val);
|
||||
if (errno)
|
||||
return -UNW_EINVAL;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
*val = ptrace (PTRACE_PEEKDATA, pid, addr, 0);
|
||||
if (errno)
|
||||
return -UNW_EINVAL;
|
||||
#endif
|
||||
debug (100, "%s: mem[%lx] -> %lx\n", __FUNCTION__,
|
||||
(long) addr, (long) *val);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,253 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 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 "_UPT_internal.h"
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
# include <elf.h>
|
||||
# ifdef HAVE_ASM_PTRACE_OFFSETS_H
|
||||
# include <asm/ptrace_offsets.h>
|
||||
# endif
|
||||
# include "ia64/rse.h"
|
||||
#endif
|
||||
|
||||
int
|
||||
_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
|
||||
int write, void *arg)
|
||||
{
|
||||
struct UPT_info *ui = arg;
|
||||
pid_t pid = ui->pid;
|
||||
|
||||
#if UNW_DEBUG
|
||||
if (write)
|
||||
debug (100, "%s: %s <- %lx\n",
|
||||
__FUNCTION__, unw_regname (reg), (long) *val);
|
||||
#endif
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
if ((unsigned) reg - UNW_IA64_NAT < 32)
|
||||
{
|
||||
unsigned long nat_bits, mask;
|
||||
|
||||
/* The Linux ptrace represents the statc NaT bits as a single word. */
|
||||
mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT);
|
||||
errno = 0;
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
|
||||
if (write)
|
||||
{
|
||||
if (*val)
|
||||
nat_bits |= mask;
|
||||
else
|
||||
nat_bits &= ~mask;
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
switch (reg)
|
||||
{
|
||||
case UNW_IA64_GR + 0:
|
||||
if (write)
|
||||
goto badreg;
|
||||
*val = 0;
|
||||
return 0;
|
||||
|
||||
case UNW_REG_IP:
|
||||
{
|
||||
unsigned long ip, psr;
|
||||
|
||||
/* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
if (write)
|
||||
{
|
||||
ip = *val & ~0xfUL;
|
||||
psr = (psr & ~0x3UL << 41) | (*val & 0x3);
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip);
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
*val = ip + ((psr >> 41) & 0x3);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
case UNW_IA64_AR_BSPSTORE:
|
||||
reg = UNW_IA64_AR_BSP;
|
||||
break;
|
||||
|
||||
case UNW_IA64_AR_BSP:
|
||||
case UNW_IA64_BSP:
|
||||
{
|
||||
unsigned long sof, cfm, bsp;
|
||||
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
/* Account for the fact that ptrace() expects bsp to point
|
||||
_after_ the current register frame. */
|
||||
errno = 0;
|
||||
cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
sof = (cfm & 0x7f);
|
||||
|
||||
if (write)
|
||||
{
|
||||
bsp = ia64_rse_skip_regs (*val, sof);
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
*val = ia64_rse_skip_regs (bsp, -sof);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
case UNW_IA64_CFM:
|
||||
/* If we change CFM, we need to adjust ptrace's notion of bsp
|
||||
accordingly, so that the real bsp remains unchanged. */
|
||||
if (write)
|
||||
{
|
||||
unsigned long new_sof, old_sof, cfm, bsp;
|
||||
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
|
||||
cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
|
||||
#endif
|
||||
if (errno)
|
||||
goto badreg;
|
||||
old_sof = (cfm & 0x7f);
|
||||
new_sof = (*val & 0x7f);
|
||||
if (old_sof != new_sof)
|
||||
{
|
||||
bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof);
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0]))
|
||||
goto badreg;
|
||||
|
||||
#ifdef HAVE_TTRACE
|
||||
# warning No support for ttrace() yet.
|
||||
#else
|
||||
errno = 0;
|
||||
if (write)
|
||||
ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val);
|
||||
else
|
||||
*val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0);
|
||||
if (errno)
|
||||
goto badreg;
|
||||
#endif
|
||||
|
||||
#ifdef UNW_TARGET_IA64
|
||||
out:
|
||||
#endif
|
||||
#if UNW_DEBUG
|
||||
if (!write)
|
||||
debug (100, "%s: %s -> %lx\n",
|
||||
__FUNCTION__, unw_regname (reg), (long) *val);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
badreg:
|
||||
debug (1, "%s: bad register number %u\n", __FUNCTION__, reg);
|
||||
return -UNW_EBADREG;
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 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 <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "_UPT_internal.h"
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
|
||||
#include "elf64.h"
|
||||
|
||||
static unw_word_t
|
||||
find_gp (struct UPT_info *ui, Elf64_Phdr *pdyn, Elf64_Addr load_base)
|
||||
{
|
||||
Elf64_Off soff, str_soff;
|
||||
Elf64_Ehdr *ehdr = ui->ei.image;
|
||||
Elf64_Shdr *shdr;
|
||||
Elf64_Shdr *str_shdr;
|
||||
Elf64_Addr gp = 0;
|
||||
char *strtab;
|
||||
int i;
|
||||
|
||||
if (pdyn)
|
||||
{
|
||||
/* If we have a PT_DYNAMIC program header, fetch the gp-value
|
||||
from the DT_PLTGOT entry. */
|
||||
Elf64_Dyn *dyn = (Elf64_Dyn *) (pdyn->p_offset + (char *) ui->ei.image);
|
||||
for (; dyn->d_tag != DT_NULL; ++dyn)
|
||||
if (dyn->d_tag == DT_PLTGOT)
|
||||
{
|
||||
gp = (Elf64_Addr) dyn->d_un.d_ptr + load_base;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Without a PT_DYAMIC header, lets try to look for a non-empty .opd
|
||||
section. If there is such a section, we know it's full of
|
||||
function descriptors, and we can simply pick up the gp from the
|
||||
second word of the first entry in this table. */
|
||||
|
||||
soff = ehdr->e_shoff;
|
||||
str_soff = soff + (ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||
|
||||
if (soff + ehdr->e_shnum * ehdr->e_shentsize > ui->ei.size)
|
||||
{
|
||||
debug (1, "%s: section table outside of image? (%lu > %lu)",
|
||||
__FUNCTION__, soff + ehdr->e_shnum * ehdr->e_shentsize,
|
||||
ui->ei.size);
|
||||
goto done;
|
||||
}
|
||||
|
||||
shdr = (Elf64_Shdr *) ((char *) ui->ei.image + soff);
|
||||
str_shdr = (Elf64_Shdr *) ((char *) ui->ei.image + str_soff);
|
||||
strtab = (char *) ui->ei.image + str_shdr->sh_offset;
|
||||
for (i = 0; i < ehdr->e_shnum; ++i)
|
||||
{
|
||||
if (strcmp (strtab + shdr->sh_name, ".opd") == 0
|
||||
&& shdr->sh_size >= 16)
|
||||
{
|
||||
gp = ((Elf64_Addr *) ((char *) ui->ei.image + shdr->sh_offset))[1];
|
||||
goto done;
|
||||
}
|
||||
shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize);
|
||||
}
|
||||
|
||||
done:
|
||||
debug (100, "%s: image at %p, gp = %lx\n", __FUNCTION__, ui->ei.image, gp);
|
||||
return gp;
|
||||
}
|
||||
|
||||
HIDDEN unw_dyn_info_t *
|
||||
_UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
|
||||
char *path, unw_word_t segbase, unw_word_t mapoff)
|
||||
{
|
||||
Elf64_Phdr *phdr, *ptxt = NULL, *punw = NULL, *pdyn = NULL;
|
||||
Elf64_Ehdr *ehdr;
|
||||
int i;
|
||||
|
||||
if (!_Uelf64_valid_object (&ui->ei))
|
||||
return NULL;
|
||||
|
||||
ehdr = ui->ei.image;
|
||||
phdr = (Elf64_Phdr *) ((char *) ui->ei.image + ehdr->e_phoff);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; ++i)
|
||||
{
|
||||
switch (phdr[i].p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
if (phdr[i].p_offset == mapoff)
|
||||
ptxt = phdr + i;
|
||||
break;
|
||||
|
||||
case PT_IA_64_UNWIND:
|
||||
punw = phdr + i;
|
||||
break;
|
||||
|
||||
case PT_DYNAMIC:
|
||||
pdyn = phdr + i;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ptxt || !punw)
|
||||
return NULL;
|
||||
|
||||
ui->di_cache.start_ip = segbase;
|
||||
ui->di_cache.end_ip = ui->di_cache.start_ip + ptxt->p_memsz;
|
||||
ui->di_cache.gp = find_gp (ui, pdyn, segbase - ptxt->p_vaddr);
|
||||
ui->di_cache.format = UNW_INFO_FORMAT_TABLE;
|
||||
ui->di_cache.u.ti.name_ptr = 0;
|
||||
ui->di_cache.u.ti.segbase = segbase;
|
||||
ui->di_cache.u.ti.table_len = punw->p_memsz / sizeof (unw_word_t);
|
||||
ui->di_cache.u.ti.table_data = (unw_word_t *)
|
||||
((char *) ui->ei.image + (punw->p_vaddr - ptxt->p_vaddr));
|
||||
return &ui->di_cache;
|
||||
}
|
||||
|
||||
#elif UNW_TARGET_X86
|
||||
|
||||
HIDDEN unw_dyn_info_t *
|
||||
_UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as,
|
||||
char *path, unw_word_t segbase, unw_word_t mapoff)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* UNW_TARGET_X86 */
|
||||
|
||||
static unw_dyn_info_t *
|
||||
get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, unw_word_t ip)
|
||||
{
|
||||
unsigned long segbase, mapoff;
|
||||
char path[PATH_MAX];
|
||||
unw_dyn_info_t *di;
|
||||
|
||||
#if UNW_TARGET_IA64 && defined(__linux)
|
||||
if (!ui->ktab.start_ip && _Uia64_get_kernel_table (&ui->ktab) < 0)
|
||||
return NULL;
|
||||
|
||||
if (ip >= ui->ktab.start_ip && ip < ui->ktab.end_ip)
|
||||
return &ui->ktab;
|
||||
#endif
|
||||
|
||||
if (ip >= ui->di_cache.start_ip && ip < ui->di_cache.end_ip)
|
||||
return &ui->di_cache;
|
||||
|
||||
if (ui->ei.image)
|
||||
{
|
||||
munmap (ui->ei.image, ui->ei.size);
|
||||
ui->ei.image = NULL;
|
||||
ui->ei.size = 0;
|
||||
|
||||
/* invalidate the cache: */
|
||||
ui->di_cache.start_ip = ui->di_cache.end_ip = 0;
|
||||
}
|
||||
|
||||
if (tdep_get_elf_image (&ui->ei, ui->pid, ip, &segbase, &mapoff) < 0)
|
||||
return NULL;
|
||||
|
||||
di = _UPTi_find_unwind_table (ui, as, path, segbase, mapoff);
|
||||
if (!di
|
||||
/* This can happen in corner cases where dynamically generated
|
||||
code falls into the same page that contains the data-segment
|
||||
and the page-offset of the code is within the first page of
|
||||
the executable. */
|
||||
|| ip < di->start_ip || ip >= di->end_ip)
|
||||
return NULL;
|
||||
|
||||
return di;
|
||||
}
|
||||
|
||||
int
|
||||
_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
||||
int need_unwind_info, void *arg)
|
||||
{
|
||||
struct UPT_info *ui = arg;
|
||||
unw_dyn_info_t *di;
|
||||
|
||||
di = get_unwind_info (ui, as, ip);
|
||||
if (!di)
|
||||
return -UNW_ENOINFO;
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
if (di == &ui->ktab)
|
||||
{
|
||||
/* The kernel unwind table resides in local memory, so we have
|
||||
to use the local address space to search it. Since
|
||||
_UPT_put_unwind_info() has no easy way of detecting this
|
||||
case, we simply make a copy of the unwind-info, so
|
||||
_UPT_put_unwind_info() can always free() the unwind-info
|
||||
without ill effects. */
|
||||
int ret = tdep_search_unwind_table (unw_local_addr_space, ip, di, pi,
|
||||
need_unwind_info, arg);
|
||||
if (ret >= 0 && need_unwind_info)
|
||||
{
|
||||
void *mem = malloc (pi->unwind_info_size);
|
||||
|
||||
if (!mem)
|
||||
return -UNW_ENOMEM;
|
||||
memcpy (mem, pi->unwind_info, pi->unwind_info_size);
|
||||
pi->unwind_info = mem;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 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 "_UPT_internal.h"
|
||||
|
||||
#ifdef UNW_TARGET_IA64
|
||||
# include "elf64.h"
|
||||
# include "os-linux.h"
|
||||
#endif
|
||||
|
||||
int
|
||||
_UPT_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
|
||||
void *arg)
|
||||
{
|
||||
#if UNW_TARGET_IA64
|
||||
unsigned long lo, hi, off;
|
||||
struct UPT_info *ui = arg;
|
||||
struct map_iterator mi;
|
||||
char path[PATH_MAX];
|
||||
unw_dyn_info_t *di;
|
||||
unw_word_t res;
|
||||
#endif
|
||||
int count = 0;
|
||||
|
||||
debug (100, "%s: looking for dyn_info list\n", __FUNCTION__);
|
||||
|
||||
#if UNW_TARGET_IA64
|
||||
maps_init (&mi, ui->pid);
|
||||
while (maps_next (&mi, &lo, &hi, &off, path))
|
||||
{
|
||||
if (off)
|
||||
continue;
|
||||
|
||||
if (ui->ei.image)
|
||||
{
|
||||
munmap (ui->ei.image, ui->ei.size);
|
||||
/* invalidate the cache: */
|
||||
ui->di_cache.start_ip = ui->di_cache.end_ip = 0;
|
||||
}
|
||||
|
||||
if (elf_map_image (&ui->ei, path) < 0)
|
||||
return -UNW_ENOINFO;
|
||||
|
||||
debug (100, "%s: checking object %s\n", __FUNCTION__, path);
|
||||
|
||||
di = _UPTi_find_unwind_table (ui, as, path, lo, off);
|
||||
if (di)
|
||||
{
|
||||
res = _Uia64_find_dyn_list (as, di, arg);
|
||||
if (res && count++ == 0)
|
||||
{
|
||||
debug (100, "%s: dyn_info_list_addr = 0x%lx\n",
|
||||
__FUNCTION__, (long) res);
|
||||
*dil_addr = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
maps_close (&mi);
|
||||
#else
|
||||
# warning Implement me, please.
|
||||
#endif
|
||||
|
||||
/* If multiple dynamic-info list addresses are found, we would have
|
||||
to determine which was is the one actually in use (since the
|
||||
dynamic name resolution algorithm will pick one "winner").
|
||||
Perhaps we'd have to track them all until we find one that's
|
||||
non-empty. Hopefully, this case simply will never arise, since
|
||||
only libunwind defines the dynamic info list head. */
|
||||
assert (count <= 1);
|
||||
|
||||
return (count > 0) ? 0 : -UNW_ENOINFO;
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2003 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-internal.h"
|
||||
|
||||
PROTECTED _Unwind_Reason_Code
|
||||
_Unwind_RaiseException (struct _Unwind_Exception *exception_object)
|
||||
{
|
||||
unsigned long exception_class = exception_object->exception_class;
|
||||
_Unwind_Personality_Fn personality;
|
||||
struct _Unwind_Context context;
|
||||
_Unwind_Reason_Code reason;
|
||||
unw_proc_info_t pi;
|
||||
unw_context_t uc;
|
||||
unw_word_t ip;
|
||||
int ret;
|
||||
|
||||
debug (1, "%s(exception_object=%p)\n", __FUNCTION__, exception_object);
|
||||
|
||||
if (_Unwind_InitContext (&context, &uc) < 0)
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
|
||||
/* Phase 1 (search phase) */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((ret = unw_step (&context.cursor)) <= 0)
|
||||
{
|
||||
if (ret == 0)
|
||||
{
|
||||
debug (1, "%s: no handler found\n", __FUNCTION__);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
else
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
|
||||
if (unw_get_proc_info (&context.cursor, &pi) < 0)
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
|
||||
personality = (_Unwind_Personality_Fn) pi.handler;
|
||||
if (personality)
|
||||
{
|
||||
reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE,
|
||||
exception_class, exception_object,
|
||||
&context);
|
||||
if (reason != _URC_CONTINUE_UNWIND)
|
||||
{
|
||||
if (reason == _URC_HANDLER_FOUND)
|
||||
break;
|
||||
else
|
||||
{
|
||||
debug (1, "%s: personality returned %d\n",
|
||||
__FUNCTION__, reason);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Exceptions are associated with IP-ranges. If a given exception
|
||||
is handled at a particular IP, it will _always_ be handled at
|
||||
that IP. If this weren't true, we'd have to track the tuple
|
||||
(IP,SP,BSP) to uniquely identify the stack frame that's handling
|
||||
the exception. */
|
||||
if (unw_get_reg (&context.cursor, UNW_REG_IP, &ip) < 0)
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
exception_object->private_1 = 0; /* clear "stop" pointer */
|
||||
exception_object->private_2 = ip; /* save frame marker */
|
||||
|
||||
debug (1, "%s: found handler for IP=%lx; entering cleanup phase\n",
|
||||
__FUNCTION__, ip);
|
||||
|
||||
/* Reset the cursor to the first frame: */
|
||||
if (unw_init_local (&context.cursor, &uc) < 0)
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
|
||||
return _Unwind_Phase2 (exception_object, &context);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 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 <stdlib.h>
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
PROTECTED void
|
||||
unw_destroy_addr_space (unw_addr_space_t as)
|
||||
{
|
||||
#ifndef UNW_LOCAL_ONLY
|
||||
# if UNW_DEBUG
|
||||
memset (as, 0, sizeof (*as));
|
||||
# endif
|
||||
free (as);
|
||||
#endif
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 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"
|
||||
|
||||
PROTECTED int
|
||||
unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
return x86_access_reg (c, regnum, valp, 0);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 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"
|
||||
|
||||
PROTECTED int
|
||||
unw_set_reg (unw_cursor_t *cursor, int regnum, unw_word_t valp)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
|
||||
return x86_access_reg (c, regnum, &valp, 1);
|
||||
}
|
Loading…
Reference in a new issue