1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2025-01-22 16:20:29 +01:00

(Logical change 1.43)

This commit is contained in:
hp.com!davidm 2003-01-28 03:40:06 +00:00
parent b064eb4574
commit e9e4e5fb29
12 changed files with 1233 additions and 0 deletions

View file

@ -0,0 +1,58 @@
/* 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_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
int write, void *arg)
{
unw_word_t *wp = (unsigned long *) val;
struct UPT_info *ui = arg;
pid_t pid = ui->pid;
int i;
if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0]))
return -UNW_EBADREG;
errno = 0;
if (write)
for (i = 0; i < sizeof (*val) / sizeof (wp[i]); ++i)
{
ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg] + i * sizeof(wp[i]),
wp[i]);
if (errno)
return -UNW_EBADREG;
}
else
for (i = 0; i < sizeof (*val) / sizeof (wp[i]); ++i)
{
wp[i] = ptrace (PTRACE_PEEKUSER, pid,
_UPT_reg_offset[reg] + i * sizeof(wp[i]), 0);
if (errno)
return -UNW_EBADREG;
}
return 0;
}

View file

@ -0,0 +1,51 @@
/* 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, "_UPT_mem[%lx] <- %lx\n", __FUNCTION__, addr, *val);
ptrace (PTRACE_POKEDATA, pid, addr, *val);
if (errno)
return -UNW_EINVAL;
}
else
{
*val = ptrace (PTRACE_PEEKDATA, pid, addr, 0);
if (errno)
return -UNW_EINVAL;
debug (100, "%s: mem[%lx] -> %lx\n", __FUNCTION__, addr, *val);
}
return 0;
}

View file

@ -0,0 +1,189 @@
/* 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>
# include <asm/ptrace_offsets.h>
# 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 DEBUG
if (write)
debug (100, "%s: %s <- %lx\n", __FUNCTION__ unw_regname (reg), *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;
nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0);
if (errno)
return -UNW_EBADREG;
if (write)
{
if (*val)
nat_bits |= mask;
else
nat_bits &= ~mask;
errno = 0;
ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits);
if (errno)
return -UNW_EBADREG;
}
goto out;
}
else
switch (reg)
{
case UNW_REG_IP:
{
unsigned long ip, psr;
/* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */
errno = 0;
psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0);
if (errno)
return -UNW_EBADREG;
if (write)
{
ip = *val & ~0xfUL;
psr = (psr & ~0x3UL << 41) | (*val & 0x3);
errno = 0;
ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip);
ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr);
if (errno)
return -UNW_EBADREG;
}
else
{
errno = 0;
ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0);
if (errno)
return -UNW_EBADREG;
*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;
/* 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)
return -UNW_EBADREG;
sof = (cfm & 0x7f);
if (write)
{
bsp = ia64_rse_skip_regs (*val, sof);
errno = 0;
ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp);
if (errno)
return -UNW_EBADREG;
}
else
{
errno = 0;
bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
if (errno)
return -UNW_EBADREG;
*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;
errno = 0;
bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0);
cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0);
if (errno)
return -UNW_EBADREG;
old_sof = (cfm & 0x7f);
new_sof = (*val & 0x7f);
if (old_sof != new_sof)
{
bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof);
errno = 0;
ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0);
if (errno)
return -UNW_EBADREG;
}
errno = 0;
ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val);
if (errno)
return -UNW_EBADREG;
goto out;
}
break;
}
#endif
if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0]))
return -UNW_EBADREG;
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)
return -UNW_EBADREG;
out:
#if DEBUG
if (!write)
debug (100, "%s: %s -> %lx\n", __FUNCTION__ unw_regname (reg), *val);
#endif
return 0;
}

View file

@ -0,0 +1,39 @@
/* 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"
unw_accessors_t _UPT_accessors =
{
.find_proc_info = _UPT_find_proc_info,
.put_unwind_info = _UPT_put_unwind_info,
.get_dyn_info_list_addr = _UPT_get_dyn_info_list_addr,
.access_mem = _UPT_access_mem,
.access_reg = _UPT_access_reg,
.access_fpreg = _UPT_access_fpreg,
#if 0
.resume = _UPT_resume_single_block
#endif
};

View file

@ -0,0 +1,39 @@
/* 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"
void *
_UPT_create (pid_t pid)
{
struct UPT_info *ui = malloc (sizeof (struct UPT_info));
if (!ui)
return NULL;
memset (ui, 0, sizeof (*ui));
ui->pid = pid;
return ui;
}

View file

@ -0,0 +1,32 @@
/* 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"
void
_UPT_destroy (void *ui)
{
free (ui);
}

View file

@ -0,0 +1,225 @@
/* 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"
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->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 + ui->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->image_size)
{
debug (1, "%s: section table outside of image? (%lu > %lu)", __FUNCTION__,
soff + ehdr->e_shnum * ehdr->e_shentsize, ui->image_size);
goto done;
}
shdr = (Elf64_Shdr *) ((char *) ui->image + soff);
str_shdr = (Elf64_Shdr *) ((char *) ui->image + str_soff);
strtab = (char *) ui->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 *) (ui->image + shdr->sh_offset))[1];
goto done;
}
shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize);
}
done:
debug (100, "%s: image at %lx, gp = %lx\n", ui->image, gp);
return gp;
}
static inline int
elf64_valid_object (struct UPT_info *ui)
{
return memcmp (ui->image, ELFMAG, SELFMAG) == 0;
}
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;
struct stat stat;
Elf64_Ehdr *ehdr;
int fd, i;
if (ui->image)
{
munmap (ui->image, ui->image_size);
ui->image = NULL;
ui->image_size = 0;
/* invalidate the cache: */
ui->di_cache.start_ip = ui->di_cache.end_ip = 0;
}
fd = open (path, O_RDONLY);
if (fd < 0)
return NULL;
if (fstat (fd, &stat) < 0)
{
close (fd);
return NULL;
}
ui->image_size = stat.st_size;
ui->image = mmap (NULL, ui->image_size, PROT_READ, MAP_PRIVATE, fd, 0);
close (fd);
if (ui->image == MAP_FAILED)
return NULL;
if (!elf64_valid_object (ui))
return NULL;
ehdr = ui->image;
phdr = (Elf64_Phdr *) ((char *) ui->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->image + (punw->p_vaddr - ptxt->p_vaddr));
return &ui->di_cache;
}
static unw_dyn_info_t *
get_unwind_info (struct UPT_info *ui, unw_addr_space_t as,
unw_word_t ip, unw_proc_info_t *pi,
int need_unwind_info)
{
unsigned long segbase, hi, mapoff;
struct map_iterator mi;
char path[PATH_MAX];
#if UNW_TARGET_IA64
if (!ui->ktab.start_ip)
{
int ret = _Uia64_get_kernel_table (&ui->ktab);
if (ret < 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;
maps_init (&mi, ui->pid);
while (maps_next (&mi, &segbase, &hi, &mapoff, path))
{
if (ip >= segbase && ip < hi)
break;
}
maps_close (&mi);
if (ip < segbase || ip >= hi)
return NULL;
return _UPTi_find_unwind_table (ui, as, path, segbase, mapoff);
}
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, pi, need_unwind_info);
if (!di)
return -UNW_ENOINFO;
return _Uia64_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
}

View file

@ -0,0 +1,73 @@
/* 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_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr,
void *arg)
{
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;
int count = 0;
if (ui->checked_dyn_info_list_addr)
{
*dil_addr = ui->dyn_info_list_addr;
return *dil_addr ? 0 : -UNW_ENOINFO;
}
ui->checked_dyn_info_list_addr = 1;
maps_init (&mi, ui->pid);
while (maps_next (&mi, &lo, &hi, &off, path))
{
di = _UPTi_find_unwind_table (ui, as, path, lo, off);
if (di)
{
res = _Uia64_find_dyn_list (as, di->u.ti.table_data,
(di->u.ti.table_len
* sizeof (di->u.ti.table_data[0])),
di->u.ti.segbase, arg);
if (res && ++count == 0)
ui->dyn_info_list_addr = *dil_addr = res;
}
}
maps_close (&mi);
/* 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;
}

View file

@ -0,0 +1,100 @@
#ifndef _UPT_internal_h
#define _UPT_internal_h
/* 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 <errno.h>
#include <libunwind.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include "internal.h"
struct UPT_info
{
pid_t pid; /* the process-id of the child we're unwinding */
void *image; /* mmap'ped image of the child's executable */
size_t image_size; /* size of the image */
unw_dyn_info_t di_cache;
unw_word_t dyn_info_list_addr;
unsigned int checked_dyn_info_list_addr : 1;
#if UNW_TARGET_IA64
unw_dyn_info_t ktab;
#endif
};
struct map_iterator
{
FILE *fp;
};
HIDDEN int _UPT_reg_offset[UNW_REG_LAST];
extern 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);
static inline void
maps_init (struct map_iterator *mi, pid_t pid)
{
char path[PATH_MAX];
snprintf (path, sizeof (path), "/proc/%d/maps", pid);
mi->fp = fopen (path, "r");
}
static inline int
maps_next (struct map_iterator *mi,
unsigned long *low, unsigned long *high, unsigned long *offset,
char *path)
{
char line[256+PATH_MAX];
if (!mi->fp)
return 0;
while (fgets (line, sizeof (line), mi->fp))
{
if (sscanf (line, "%lx-%lx %*4c %lx %*x:%*x %*d %s\n",
low, high, offset, path) == 4)
return 1;
}
return 0;
}
static inline void
maps_close (struct map_iterator *mi)
{
fclose (mi->fp);
mi->fp = NULL;
}
#endif /* _UPT_internal_h */

View file

@ -0,0 +1,35 @@
/* 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"
void
_UPT_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg)
{
if (!pi->unwind_info)
return;
free (pi->unwind_info);
pi->unwind_info = NULL;
}

View file

@ -0,0 +1,214 @@
/* 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 <asm/ptrace_offsets.h>
#endif
int _UPT_reg_offset[UNW_REG_LAST] =
{
#if UNW_TARGET_IA64
# ifndef PT_AR_CSD
# define PT_AR_CSD -1 /* this was introduced with rev 2.1 of ia64 */
# endif
[UNW_IA64_GR + 0] = -1, [UNW_IA64_GR + 1] = PT_R1,
[UNW_IA64_GR + 2] = PT_R2, [UNW_IA64_GR + 3] = PT_R3,
[UNW_IA64_GR + 4] = PT_R4, [UNW_IA64_GR + 5] = PT_R5,
[UNW_IA64_GR + 6] = PT_R6, [UNW_IA64_GR + 7] = PT_R7,
[UNW_IA64_GR + 8] = PT_R8, [UNW_IA64_GR + 9] = PT_R9,
[UNW_IA64_GR + 10] = PT_R10, [UNW_IA64_GR + 11] = PT_R11,
[UNW_IA64_GR + 12] = PT_R12, [UNW_IA64_GR + 13] = PT_R13,
[UNW_IA64_GR + 14] = PT_R14, [UNW_IA64_GR + 15] = PT_R15,
[UNW_IA64_GR + 16] = PT_R16, [UNW_IA64_GR + 17] = PT_R17,
[UNW_IA64_GR + 18] = PT_R18, [UNW_IA64_GR + 19] = PT_R19,
[UNW_IA64_GR + 20] = PT_R20, [UNW_IA64_GR + 21] = PT_R21,
[UNW_IA64_GR + 22] = PT_R22, [UNW_IA64_GR + 23] = PT_R23,
[UNW_IA64_GR + 24] = PT_R24, [UNW_IA64_GR + 25] = PT_R25,
[UNW_IA64_GR + 26] = PT_R26, [UNW_IA64_GR + 27] = PT_R27,
[UNW_IA64_GR + 28] = PT_R28, [UNW_IA64_GR + 29] = PT_R29,
[UNW_IA64_GR + 30] = PT_R30, [UNW_IA64_GR + 31] = PT_R31,
[UNW_IA64_NAT+ 0] = -1, [UNW_IA64_NAT+ 1] = PT_NAT_BITS,
[UNW_IA64_NAT+ 2] = PT_NAT_BITS, [UNW_IA64_NAT+ 3] = PT_NAT_BITS,
[UNW_IA64_NAT+ 4] = PT_NAT_BITS, [UNW_IA64_NAT+ 5] = PT_NAT_BITS,
[UNW_IA64_NAT+ 6] = PT_NAT_BITS, [UNW_IA64_NAT+ 7] = PT_NAT_BITS,
[UNW_IA64_NAT+ 8] = PT_NAT_BITS, [UNW_IA64_NAT+ 9] = PT_NAT_BITS,
[UNW_IA64_NAT+ 10] = PT_NAT_BITS, [UNW_IA64_NAT+ 11] = PT_NAT_BITS,
[UNW_IA64_NAT+ 12] = PT_NAT_BITS, [UNW_IA64_NAT+ 13] = PT_NAT_BITS,
[UNW_IA64_NAT+ 14] = PT_NAT_BITS, [UNW_IA64_NAT+ 15] = PT_NAT_BITS,
[UNW_IA64_NAT+ 16] = PT_NAT_BITS, [UNW_IA64_NAT+ 17] = PT_NAT_BITS,
[UNW_IA64_NAT+ 18] = PT_NAT_BITS, [UNW_IA64_NAT+ 19] = PT_NAT_BITS,
[UNW_IA64_NAT+ 20] = PT_NAT_BITS, [UNW_IA64_NAT+ 21] = PT_NAT_BITS,
[UNW_IA64_NAT+ 22] = PT_NAT_BITS, [UNW_IA64_NAT+ 23] = PT_NAT_BITS,
[UNW_IA64_NAT+ 24] = PT_NAT_BITS, [UNW_IA64_NAT+ 25] = PT_NAT_BITS,
[UNW_IA64_NAT+ 26] = PT_NAT_BITS, [UNW_IA64_NAT+ 27] = PT_NAT_BITS,
[UNW_IA64_NAT+ 28] = PT_NAT_BITS, [UNW_IA64_NAT+ 29] = PT_NAT_BITS,
[UNW_IA64_NAT+ 30] = PT_NAT_BITS, [UNW_IA64_NAT+ 31] = PT_NAT_BITS,
[UNW_IA64_FR + 0] = -1, [UNW_IA64_FR + 1] = -1,
[UNW_IA64_FR + 2] = PT_F2, [UNW_IA64_FR + 3] = PT_F3,
[UNW_IA64_FR + 4] = PT_F4, [UNW_IA64_FR + 5] = PT_F5,
[UNW_IA64_FR + 6] = PT_F6, [UNW_IA64_FR + 7] = PT_F7,
[UNW_IA64_FR + 8] = PT_F8, [UNW_IA64_FR + 9] = PT_F9,
[UNW_IA64_FR + 10] = PT_F10, [UNW_IA64_FR + 11] = PT_F11,
[UNW_IA64_FR + 12] = PT_F12, [UNW_IA64_FR + 13] = PT_F13,
[UNW_IA64_FR + 14] = PT_F14, [UNW_IA64_FR + 15] = PT_F15,
[UNW_IA64_FR + 16] = PT_F16, [UNW_IA64_FR + 17] = PT_F17,
[UNW_IA64_FR + 18] = PT_F18, [UNW_IA64_FR + 19] = PT_F19,
[UNW_IA64_FR + 20] = PT_F20, [UNW_IA64_FR + 21] = PT_F21,
[UNW_IA64_FR + 22] = PT_F22, [UNW_IA64_FR + 23] = PT_F23,
[UNW_IA64_FR + 24] = PT_F24, [UNW_IA64_FR + 25] = PT_F25,
[UNW_IA64_FR + 26] = PT_F26, [UNW_IA64_FR + 27] = PT_F27,
[UNW_IA64_FR + 28] = PT_F28, [UNW_IA64_FR + 29] = PT_F29,
[UNW_IA64_FR + 30] = PT_F30, [UNW_IA64_FR + 31] = PT_F31,
[UNW_IA64_FR + 32] = PT_F32, [UNW_IA64_FR + 33] = PT_F33,
[UNW_IA64_FR + 34] = PT_F34, [UNW_IA64_FR + 35] = PT_F35,
[UNW_IA64_FR + 36] = PT_F36, [UNW_IA64_FR + 37] = PT_F37,
[UNW_IA64_FR + 38] = PT_F38, [UNW_IA64_FR + 39] = PT_F39,
[UNW_IA64_FR + 40] = PT_F40, [UNW_IA64_FR + 41] = PT_F41,
[UNW_IA64_FR + 42] = PT_F42, [UNW_IA64_FR + 43] = PT_F43,
[UNW_IA64_FR + 44] = PT_F44, [UNW_IA64_FR + 45] = PT_F45,
[UNW_IA64_FR + 46] = PT_F46, [UNW_IA64_FR + 47] = PT_F47,
[UNW_IA64_FR + 48] = PT_F48, [UNW_IA64_FR + 49] = PT_F49,
[UNW_IA64_FR + 50] = PT_F50, [UNW_IA64_FR + 51] = PT_F51,
[UNW_IA64_FR + 52] = PT_F52, [UNW_IA64_FR + 53] = PT_F53,
[UNW_IA64_FR + 54] = PT_F54, [UNW_IA64_FR + 55] = PT_F55,
[UNW_IA64_FR + 56] = PT_F56, [UNW_IA64_FR + 57] = PT_F57,
[UNW_IA64_FR + 58] = PT_F58, [UNW_IA64_FR + 59] = PT_F59,
[UNW_IA64_FR + 60] = PT_F60, [UNW_IA64_FR + 61] = PT_F61,
[UNW_IA64_FR + 62] = PT_F62, [UNW_IA64_FR + 63] = PT_F63,
[UNW_IA64_FR + 64] = PT_F64, [UNW_IA64_FR + 65] = PT_F65,
[UNW_IA64_FR + 66] = PT_F66, [UNW_IA64_FR + 67] = PT_F67,
[UNW_IA64_FR + 68] = PT_F68, [UNW_IA64_FR + 69] = PT_F69,
[UNW_IA64_FR + 70] = PT_F70, [UNW_IA64_FR + 71] = PT_F71,
[UNW_IA64_FR + 72] = PT_F72, [UNW_IA64_FR + 73] = PT_F73,
[UNW_IA64_FR + 74] = PT_F74, [UNW_IA64_FR + 75] = PT_F75,
[UNW_IA64_FR + 76] = PT_F76, [UNW_IA64_FR + 77] = PT_F77,
[UNW_IA64_FR + 78] = PT_F78, [UNW_IA64_FR + 79] = PT_F79,
[UNW_IA64_FR + 80] = PT_F80, [UNW_IA64_FR + 81] = PT_F81,
[UNW_IA64_FR + 82] = PT_F82, [UNW_IA64_FR + 83] = PT_F83,
[UNW_IA64_FR + 84] = PT_F84, [UNW_IA64_FR + 85] = PT_F85,
[UNW_IA64_FR + 86] = PT_F86, [UNW_IA64_FR + 87] = PT_F87,
[UNW_IA64_FR + 88] = PT_F88, [UNW_IA64_FR + 89] = PT_F89,
[UNW_IA64_FR + 90] = PT_F90, [UNW_IA64_FR + 91] = PT_F91,
[UNW_IA64_FR + 92] = PT_F92, [UNW_IA64_FR + 93] = PT_F93,
[UNW_IA64_FR + 94] = PT_F94, [UNW_IA64_FR + 95] = PT_F95,
[UNW_IA64_FR + 96] = PT_F96, [UNW_IA64_FR + 97] = PT_F97,
[UNW_IA64_FR + 98] = PT_F98, [UNW_IA64_FR + 99] = PT_F99,
[UNW_IA64_FR +100] = PT_F100, [UNW_IA64_FR +101] = PT_F101,
[UNW_IA64_FR +102] = PT_F102, [UNW_IA64_FR +103] = PT_F103,
[UNW_IA64_FR +104] = PT_F104, [UNW_IA64_FR +105] = PT_F105,
[UNW_IA64_FR +106] = PT_F106, [UNW_IA64_FR +107] = PT_F107,
[UNW_IA64_FR +108] = PT_F108, [UNW_IA64_FR +109] = PT_F109,
[UNW_IA64_FR +110] = PT_F110, [UNW_IA64_FR +111] = PT_F111,
[UNW_IA64_FR +112] = PT_F112, [UNW_IA64_FR +113] = PT_F113,
[UNW_IA64_FR +114] = PT_F114, [UNW_IA64_FR +115] = PT_F115,
[UNW_IA64_FR +116] = PT_F116, [UNW_IA64_FR +117] = PT_F117,
[UNW_IA64_FR +118] = PT_F118, [UNW_IA64_FR +119] = PT_F119,
[UNW_IA64_FR +120] = PT_F120, [UNW_IA64_FR +121] = PT_F121,
[UNW_IA64_FR +122] = PT_F122, [UNW_IA64_FR +123] = PT_F123,
[UNW_IA64_FR +124] = PT_F124, [UNW_IA64_FR +125] = PT_F125,
[UNW_IA64_FR +126] = PT_F126, [UNW_IA64_FR +127] = PT_F127,
[UNW_IA64_AR + 0] = -1, [UNW_IA64_AR + 1] = -1,
[UNW_IA64_AR + 2] = -1, [UNW_IA64_AR + 3] = -1,
[UNW_IA64_AR + 4] = -1, [UNW_IA64_AR + 5] = -1,
[UNW_IA64_AR + 6] = -1, [UNW_IA64_AR + 7] = -1,
[UNW_IA64_AR + 8] = -1, [UNW_IA64_AR + 9] = -1,
[UNW_IA64_AR + 10] = -1, [UNW_IA64_AR + 11] = -1,
[UNW_IA64_AR + 12] = -1, [UNW_IA64_AR + 13] = -1,
[UNW_IA64_AR + 14] = -1, [UNW_IA64_AR + 15] = -1,
[UNW_IA64_AR + 16] = PT_AR_RSC, [UNW_IA64_AR + 17] = PT_AR_BSP,
[UNW_IA64_AR + 18] = PT_AR_BSPSTORE,[UNW_IA64_AR + 19] = PT_AR_RNAT,
[UNW_IA64_AR + 20] = -1, [UNW_IA64_AR + 21] = -1,
[UNW_IA64_AR + 22] = -1, [UNW_IA64_AR + 23] = -1,
[UNW_IA64_AR + 24] = -1, [UNW_IA64_AR + 25] = PT_AR_CSD,
[UNW_IA64_AR + 26] = -1, [UNW_IA64_AR + 27] = -1,
[UNW_IA64_AR + 28] = -1, [UNW_IA64_AR + 29] = -1,
[UNW_IA64_AR + 30] = -1, [UNW_IA64_AR + 31] = -1,
[UNW_IA64_AR + 32] = PT_AR_CCV, [UNW_IA64_AR + 33] = -1,
[UNW_IA64_AR + 34] = -1, [UNW_IA64_AR + 35] = -1,
[UNW_IA64_AR + 36] = PT_AR_UNAT, [UNW_IA64_AR + 37] = -1,
[UNW_IA64_AR + 38] = -1, [UNW_IA64_AR + 39] = -1,
[UNW_IA64_AR + 40] = PT_AR_FPSR, [UNW_IA64_AR + 41] = -1,
[UNW_IA64_AR + 42] = -1, [UNW_IA64_AR + 43] = -1,
[UNW_IA64_AR + 44] = -1, [UNW_IA64_AR + 45] = -1,
[UNW_IA64_AR + 46] = -1, [UNW_IA64_AR + 47] = -1,
[UNW_IA64_AR + 48] = -1, [UNW_IA64_AR + 49] = -1,
[UNW_IA64_AR + 50] = -1, [UNW_IA64_AR + 51] = -1,
[UNW_IA64_AR + 52] = -1, [UNW_IA64_AR + 53] = -1,
[UNW_IA64_AR + 54] = -1, [UNW_IA64_AR + 55] = -1,
[UNW_IA64_AR + 56] = -1, [UNW_IA64_AR + 57] = -1,
[UNW_IA64_AR + 58] = -1, [UNW_IA64_AR + 59] = -1,
[UNW_IA64_AR + 60] = -1, [UNW_IA64_AR + 61] = -1,
[UNW_IA64_AR + 62] = -1, [UNW_IA64_AR + 63] = -1,
[UNW_IA64_AR + 64] = PT_AR_PFS, [UNW_IA64_AR + 65] = PT_AR_LC,
[UNW_IA64_AR + 66] = PT_AR_EC, [UNW_IA64_AR + 67] = -1,
[UNW_IA64_AR + 68] = -1, [UNW_IA64_AR + 69] = -1,
[UNW_IA64_AR + 70] = -1, [UNW_IA64_AR + 71] = -1,
[UNW_IA64_AR + 72] = -1, [UNW_IA64_AR + 73] = -1,
[UNW_IA64_AR + 74] = -1, [UNW_IA64_AR + 75] = -1,
[UNW_IA64_AR + 76] = -1, [UNW_IA64_AR + 77] = -1,
[UNW_IA64_AR + 78] = -1, [UNW_IA64_AR + 79] = -1,
[UNW_IA64_AR + 80] = -1, [UNW_IA64_AR + 81] = -1,
[UNW_IA64_AR + 82] = -1, [UNW_IA64_AR + 83] = -1,
[UNW_IA64_AR + 84] = -1, [UNW_IA64_AR + 85] = -1,
[UNW_IA64_AR + 86] = -1, [UNW_IA64_AR + 87] = -1,
[UNW_IA64_AR + 88] = -1, [UNW_IA64_AR + 89] = -1,
[UNW_IA64_AR + 90] = -1, [UNW_IA64_AR + 91] = -1,
[UNW_IA64_AR + 92] = -1, [UNW_IA64_AR + 93] = -1,
[UNW_IA64_AR + 94] = -1, [UNW_IA64_AR + 95] = -1,
[UNW_IA64_AR + 96] = -1, [UNW_IA64_AR + 97] = -1,
[UNW_IA64_AR + 98] = -1, [UNW_IA64_AR + 99] = -1,
[UNW_IA64_AR +100] = -1, [UNW_IA64_AR +101] = -1,
[UNW_IA64_AR +102] = -1, [UNW_IA64_AR +103] = -1,
[UNW_IA64_AR +104] = -1, [UNW_IA64_AR +105] = -1,
[UNW_IA64_AR +106] = -1, [UNW_IA64_AR +107] = -1,
[UNW_IA64_AR +108] = -1, [UNW_IA64_AR +109] = -1,
[UNW_IA64_AR +110] = -1, [UNW_IA64_AR +111] = -1,
[UNW_IA64_AR +112] = -1, [UNW_IA64_AR +113] = -1,
[UNW_IA64_AR +114] = -1, [UNW_IA64_AR +115] = -1,
[UNW_IA64_AR +116] = -1, [UNW_IA64_AR +117] = -1,
[UNW_IA64_AR +118] = -1, [UNW_IA64_AR +119] = -1,
[UNW_IA64_AR +120] = -1, [UNW_IA64_AR +121] = -1,
[UNW_IA64_AR +122] = -1, [UNW_IA64_AR +123] = -1,
[UNW_IA64_AR +124] = -1, [UNW_IA64_AR +125] = -1,
[UNW_IA64_AR +126] = -1, [UNW_IA64_AR +127] = -1,
[UNW_IA64_BR + 0] = PT_B0, [UNW_IA64_BR + 1] = PT_B1,
[UNW_IA64_BR + 2] = PT_B2, [UNW_IA64_BR + 3] = PT_B3,
[UNW_IA64_BR + 4] = PT_B4, [UNW_IA64_BR + 5] = PT_B5,
[UNW_IA64_BR + 6] = PT_B6, [UNW_IA64_BR + 7] = PT_B7,
[UNW_IA64_PR] = PT_PR,
[UNW_IA64_CFM] = PT_CFM,
[UNW_IA64_IP] = PT_CR_IIP
#else
# error Fix me.
#endif
};

View file

@ -0,0 +1,178 @@
/* 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 <errno.h>
#include <fcntl.h>
#include <libunwind.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int nerrors;
int verbose = 1;
#define panic(args...) \
do { fprintf (stderr, args); ++nerrors; } while (0)
static unw_addr_space_t as;
void
do_backtrace (pid_t target_pid)
{
unw_proc_info_t pi;
unw_word_t ip, sp;
unw_cursor_t c;
char buf[512];
int ret;
struct UPT_info *ui;
ui = _UPT_create (target_pid);
ret = unw_init_remote (&c, as, ui);
if (ret < 0)
panic ("unw_init_remote() failed: ret=%d\n", ret);
do
{
unw_get_reg (&c, UNW_REG_IP, &ip);
unw_get_reg (&c, UNW_REG_SP, &sp);
unw_get_proc_name (&c, buf, sizeof (buf));
printf ("%016lx %-32s (sp=%016lx)\n", (long) ip, buf, (long) sp);
unw_get_proc_info (&c, &pi);
printf ("\tproc=%016lx-%016lx\n\thandler=%lx lsda=%lx",
(long) pi.start_ip, (long) pi.end_ip,
(long) pi.handler, (long) pi.lsda);
#if UNW_TARGET_IA64
{
unw_word_t bsp;
unw_get_reg (&c, UNW_IA64_BSP, &bsp);
printf (" bsp=%lx", bsp);
}
#endif
printf ("\n");
ret = unw_step (&c);
if (ret < 0)
{
unw_get_reg (&c, UNW_REG_IP, &ip);
printf ("FAILURE: unw_step() returned %d for ip=%lx\n",
ret, (long) ip);
}
}
while (ret > 0);
_UPT_destroy (ui);
if (ret < 0)
panic ("unwind failed with ret=%d\n", ret);
printf ("================\n\n");
}
int
main (int argc, char **argv)
{
int status, pid, state = 1;
pid_t target_pid;
as = unw_create_addr_space (&_UPT_accessors, 0);
if (!as)
panic ("unw_create_addr_space() failed");
if (argc == 1)
{
char *args[] = { "self", "/bin/ls", "/usr", NULL };
/* automated test case */
verbose = 0;
argv = args;
}
target_pid = fork ();
if (!target_pid)
{
/* child */
if (!verbose)
dup2 (open ("/dev/null", O_WRONLY), 1);
ptrace (PTRACE_TRACEME, 0, 0, 0);
execve (argv[1], argv + 1, environ);
_exit (-1);
}
while (1)
{
pid = wait4 (-1, &status, 0, 0);
if (pid == -1)
{
if (errno == EINTR)
continue;
panic ("wait4() failed (errno=%d)\n", errno);
}
if (WIFSIGNALED (status) || WIFEXITED (status)
|| (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP))
{
if (WIFEXITED (status))
{
if (WEXITSTATUS (status) != 0)
panic ("child's exit status %d\n", WEXITSTATUS (status));
break;
}
else if (WIFSIGNALED (status))
panic ("child terminated by signal %d\n", WTERMSIG (status));
else
panic ("child got signal %d\n", WSTOPSIG (status));
}
#if 1
if (!state)
do_backtrace (target_pid);
state ^= 1;
ptrace (PTRACE_SYSCALL, target_pid, 0, 0); /* continue */
#else
do_backtrace (target_pid);
ptrace (PTRACE_SINGLESTEP, target_pid, 0, 0); /* continue */
#endif
}
if (nerrors)
{
printf ("FAILURE: detected %d errors\n", nerrors);
exit (-1);
}
if (verbose)
printf ("SUCCESS\n");
return 0;
}