From e9e4e5fb29d322105e75577e11ef1cfb0dd0f9db Mon Sep 17 00:00:00 2001 From: "hp.com!davidm" Date: Tue, 28 Jan 2003 03:40:06 +0000 Subject: [PATCH] (Logical change 1.43) --- src/_UPT_access_fpreg.c | 58 ++++++++ src/_UPT_access_mem.c | 51 +++++++ src/_UPT_access_reg.c | 189 +++++++++++++++++++++++++ src/_UPT_accessors.c | 39 ++++++ src/_UPT_create.c | 39 ++++++ src/_UPT_destroy.c | 32 +++++ src/_UPT_find_proc_info.c | 225 ++++++++++++++++++++++++++++++ src/_UPT_get_dyn_info_list_addr.c | 73 ++++++++++ src/_UPT_internal.h | 100 +++++++++++++ src/_UPT_put_unwind_info.c | 35 +++++ src/_UPT_reg_offset.c | 214 ++++++++++++++++++++++++++++ tests/test-ptrace.c | 178 +++++++++++++++++++++++ 12 files changed, 1233 insertions(+) diff --git a/src/_UPT_access_fpreg.c b/src/_UPT_access_fpreg.c index e69de29b..f697b5d7 100644 --- a/src/_UPT_access_fpreg.c +++ b/src/_UPT_access_fpreg.c @@ -0,0 +1,58 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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; +} diff --git a/src/_UPT_access_mem.c b/src/_UPT_access_mem.c index e69de29b..98adf1a4 100644 --- a/src/_UPT_access_mem.c +++ b/src/_UPT_access_mem.c @@ -0,0 +1,51 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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; +} diff --git a/src/_UPT_access_reg.c b/src/_UPT_access_reg.c index e69de29b..24e25c65 100644 --- a/src/_UPT_access_reg.c +++ b/src/_UPT_access_reg.c @@ -0,0 +1,189 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 +# include +# include +# 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; +} diff --git a/src/_UPT_accessors.c b/src/_UPT_accessors.c index e69de29b..028b51d3 100644 --- a/src/_UPT_accessors.c +++ b/src/_UPT_accessors.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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 + }; diff --git a/src/_UPT_create.c b/src/_UPT_create.c index e69de29b..98118361 100644 --- a/src/_UPT_create.c +++ b/src/_UPT_create.c @@ -0,0 +1,39 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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; +} diff --git a/src/_UPT_destroy.c b/src/_UPT_destroy.c index e69de29b..52cf5434 100644 --- a/src/_UPT_destroy.c +++ b/src/_UPT_destroy.c @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +void +_UPT_destroy (void *ui) +{ + free (ui); +} diff --git a/src/_UPT_find_proc_info.c b/src/_UPT_find_proc_info.c index e69de29b..47991dfd 100644 --- a/src/_UPT_find_proc_info.c +++ b/src/_UPT_find_proc_info.c @@ -0,0 +1,225 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include + +#include + +#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); +} diff --git a/src/_UPT_get_dyn_info_list_addr.c b/src/_UPT_get_dyn_info_list_addr.c index e69de29b..1596a542 100644 --- a/src/_UPT_get_dyn_info_list_addr.c +++ b/src/_UPT_get_dyn_info_list_addr.c @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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; +} diff --git a/src/_UPT_internal.h b/src/_UPT_internal.h index e69de29b..b391fb15 100644 --- a/src/_UPT_internal.h +++ b/src/_UPT_internal.h @@ -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 + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include + +#include + +#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 */ diff --git a/src/_UPT_put_unwind_info.c b/src/_UPT_put_unwind_info.c index e69de29b..852dd868 100644 --- a/src/_UPT_put_unwind_info.c +++ b/src/_UPT_put_unwind_info.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_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; +} diff --git a/src/_UPT_reg_offset.c b/src/_UPT_reg_offset.c index e69de29b..5d009b62 100644 --- a/src/_UPT_reg_offset.c +++ b/src/_UPT_reg_offset.c @@ -0,0 +1,214 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 +# include +#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 + }; diff --git a/tests/test-ptrace.c b/tests/test-ptrace.c index e69de29b..b65b0251 100644 --- a/tests/test-ptrace.c +++ b/tests/test-ptrace.c @@ -0,0 +1,178 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +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; +}