| /* libunwind - a platform-independent unwind library |
| Copyright (C) 2003-2005 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 "_UCD_lib.h" |
| #include "_UCD_internal.h" |
| |
| #if UNW_TARGET_IA64 && defined(__linux) |
| # include "elf64.h" |
| # include "os-linux.h" |
| |
| static inline int |
| get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, |
| int *countp) |
| { |
| 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; |
| |
| maps_init (&mi, ui->pid); |
| while (maps_next (&mi, &lo, &hi, &off)) |
| { |
| if (off) |
| continue; |
| |
| invalidate_edi (&ui->edi); |
| |
| if (elf_map_image (&ui->ei, path) < 0) |
| /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ |
| continue; |
| |
| Debug (16, "checking object %s\n", path); |
| |
| di = tdep_find_unwind_table (&ui->edi, as, path, lo, off); |
| if (di) |
| { |
| res = _Uia64_find_dyn_list (as, di, arg); |
| if (res && count++ == 0) |
| { |
| Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); |
| *dil_addr = res; |
| } |
| } |
| } |
| maps_close (&mi); |
| *countp = count; |
| return 0; |
| } |
| |
| #else |
| |
| static inline int |
| get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, |
| int *countp) |
| { |
| # warning Implement get_list_addr(), please. |
| *countp = 0; |
| return 0; |
| } |
| |
| #endif |
| |
| int |
| _UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, |
| void *arg) |
| { |
| int count, ret; |
| |
| Debug (12, "looking for dyn_info list\n"); |
| |
| if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) |
| return ret; |
| |
| /* 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; |
| } |