From patchwork Thu Oct 27 08:38:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Werner X-Patchwork-Id: 4854 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 027E423E0C for ; Thu, 27 Oct 2011 08:38:19 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id EC551A18321 for ; Thu, 27 Oct 2011 08:38:18 +0000 (UTC) Received: by mail-fx0-f52.google.com with SMTP id n26so3464822faa.11 for ; Thu, 27 Oct 2011 01:38:18 -0700 (PDT) Received: by 10.223.15.10 with SMTP id i10mr65232632faa.17.1319704698521; Thu, 27 Oct 2011 01:38:18 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.1.71 with SMTP id 7cs37913lak; Thu, 27 Oct 2011 01:38:18 -0700 (PDT) Received: by 10.213.22.3 with SMTP id l3mr664254ebb.100.1319704695189; Thu, 27 Oct 2011 01:38:15 -0700 (PDT) Received: from mtagate3.uk.ibm.com (mtagate3.uk.ibm.com. [194.196.100.163]) by mx.google.com with ESMTPS id g46si1343563eea.82.2011.10.27.01.38.14 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Oct 2011 01:38:15 -0700 (PDT) Received-SPF: neutral (google.com: 194.196.100.163 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) client-ip=194.196.100.163; Authentication-Results: mx.google.com; spf=neutral (google.com: 194.196.100.163 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) smtp.mail=ken.werner@linaro.org Received: from d06nrmr1806.portsmouth.uk.ibm.com (d06nrmr1806.portsmouth.uk.ibm.com [9.149.39.193]) by mtagate3.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p9R8cE61018279 for ; Thu, 27 Oct 2011 08:38:14 GMT Received: from d06av11.portsmouth.uk.ibm.com (d06av11.portsmouth.uk.ibm.com [9.149.37.252]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p9R8cEfA2150542 for ; Thu, 27 Oct 2011 09:38:14 +0100 Received: from d06av11.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av11.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p9R8cDvw018280 for ; Thu, 27 Oct 2011 02:38:13 -0600 Received: from kiste.boeblingen.de.ibm.com (dyn-9-152-224-38.boeblingen.de.ibm.com [9.152.224.38]) by d06av11.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p9R8cCbC018201; Thu, 27 Oct 2011 02:38:13 -0600 From: Ken Werner To: libunwind-devel@nongnu.org Subject: [PATCH 3/6] Prevent the use of struct dl_phdr_info outside of dl_iterate_phdr Date: Thu, 27 Oct 2011 10:38:09 +0200 Message-Id: <1319704692-4464-4-git-send-email-ken.werner@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1319704692-4464-1-git-send-email-ken.werner@linaro.org> References: <1319704692-4464-1-git-send-email-ken.werner@linaro.org> Since the dl_iterate_phdr is required for local unwinding only the use of struct dl_phdr_info can be eliminated in case libunwind gets compiled for remote unwinding. This enhances libunwinds portability to targets that don't provide any dl_iterate_phdr functionality. Signed-off-by: Ken Werner --- include/dwarf.h | 4 ++- src/dwarf/Gfind_proc_info-lsb.c | 73 ++++++++++++++++++-------------------- src/ptrace/_UPT_find_proc_info.c | 50 ++++++++++--------------- 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index cdf9f24..f2f8bf9 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -387,7 +387,9 @@ extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); #endif /* !UNW_REMOTE_ONLY */ extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, - struct dl_phdr_info *info, unw_word_t ip); + unw_word_t ip, unw_word_t segbase, + const char* obj_name, unw_word_t start, + unw_word_t end); extern int dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, unw_dyn_info_t *di, diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 77d1c00..ee3872e 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -26,7 +26,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Locate an FDE via the ELF data-structures defined by LSB v1.3 (http://www.linuxbase.org/spec/). */ +#ifndef UNW_REMOTE_ONLY #include +#endif /* !UNW_REMOTE_ONLY */ #include #include #include @@ -269,17 +271,15 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size) pointer to debug frame descriptor, or zero if not found. */ static struct unw_debug_frame_list * -locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info, - unw_word_t addr, const char *dlname) +locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname, + unw_word_t start, unw_word_t end) { struct unw_debug_frame_list *w, *fdesc = 0; char path[PATH_MAX]; char *name = path; int err; - uint64_t start = 0, end = 0; char *buf; size_t bufsize; - unsigned int i; /* First, see if we loaded this frame already. */ @@ -306,29 +306,6 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info, else name = (char*) dlname; - /* Find the start/end of the described region by parsing the - dl_phdr_info structure. */ - - start = info->dlpi_addr + info->dlpi_phdr[0].p_vaddr; - end = start; - - for (i = 0; i < info->dlpi_phnum; i++) - { - Elf_W (Addr) hdrbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; - Elf_W (Addr) hdrlimit = hdrbase + info->dlpi_phdr[i].p_memsz; - - if (info->dlpi_phdr[i].p_type != PT_LOAD) - continue; - - if (hdrbase < start) - start = hdrbase; - if (hdrlimit > end) - end = hdrlimit; - } - - Debug (4, "calculated bounds of %lx-%lx for '%s'\n", (long)start, (long)end, - name); - err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space); if (!err) @@ -409,19 +386,19 @@ debug_frame_tab_compare (const void *a, const void *b) } PROTECTED int -dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, - struct dl_phdr_info *info, unw_word_t ip) +dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip, + unw_word_t segbase, const char* obj_name, + unw_word_t start, unw_word_t end) { unw_dyn_info_t *di; struct unw_debug_frame_list *fdesc = 0; unw_accessors_t *a; unw_word_t addr; - Debug (15, "Trying to find .debug_frame info->dlpi_name=%s\n", - info->dlpi_name); + Debug (15, "Trying to find .debug_frame for %s\n", obj_name); di = di_debug; - fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); + fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end); if (!fdesc) { @@ -539,10 +516,10 @@ dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, di->format = UNW_INFO_FORMAT_TABLE; di->start_ip = fdesc->start; di->end_ip = fdesc->end; - di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; + di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name; di->u.ti.table_data = (unw_word_t *) fdesc; di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); - di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr; + di->u.ti.segbase = segbase; found = 1; Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " @@ -567,7 +544,7 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) struct dwarf_callback_data *cb_data = ptr; unw_dyn_info_t *di = &cb_data->di; const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text; - unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip; + unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip, start, end; Elf_W(Addr) load_base, segbase = 0, max_load_addr = 0; int ret, need_unwind_info = cb_data->need_unwind_info; unw_proc_info_t *pi = cb_data->pi; @@ -733,9 +710,29 @@ dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) } #ifdef CONFIG_DEBUG_FRAME - { - found = dwarf_find_debug_frame (found, &cb_data->di_debug, info, ip); - } + /* Find the start/end of the described region by parsing the phdr_info + structure. */ + start = (unw_word_t) -1; + end = 0; + + for (n = 0; n < info->dlpi_phnum; n++) + { + if (info->dlpi_phdr[n].p_type == PT_LOAD) + { + unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr; + unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz; + + if (seg_start < start) + start = seg_start; + + if (seg_end > end) + end = seg_end; + } + } + + found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip, + info->dlpi_addr, info->dlpi_name, start, + end); #endif /* CONFIG_DEBUG_FRAME */ return found; diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index 7aaa0c2..ee0b698 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -172,6 +172,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; unw_word_t addr, eh_frame_start, fde_count, load_base; unw_word_t max_load_addr = 0; + unw_word_t start_ip = (unw_word_t) -1; + unw_word_t end_ip = 0; struct dwarf_eh_frame_hdr *hdr; unw_proc_info_t pi; unw_accessors_t *a; @@ -194,6 +196,12 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, switch (phdr[i].p_type) { case PT_LOAD: + if (phdr[i].p_vaddr < start_ip) + start_ip = phdr[i].p_vaddr; + + if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip) + end_ip = phdr[i].p_vaddr + phdr[i].p_memsz; + if (phdr[i].p_offset == mapoff) ptxt = phdr + i; if ((uintptr_t) ui->ei.image + phdr->p_filesz > max_load_addr) @@ -222,6 +230,10 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, if (!ptxt) return 0; + load_base = segbase - ptxt->p_vaddr; + start_ip += load_base; + end_ip += load_base; + if (peh_hdr) { if (pdyn) @@ -305,10 +317,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, #endif } - load_base = segbase - ptxt->p_vaddr; - - ui->di_cache.start_ip = segbase; - ui->di_cache.end_ip = ui->di_cache.start_ip + ptxt->p_memsz; + ui->di_cache.start_ip = start_ip; + ui->di_cache.end_ip = end_ip; ui->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE; ui->di_cache.u.rti.name_ptr = 0; /* two 32-bit values (ip_offset/fde_offset) per table-entry: */ @@ -329,39 +339,19 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, if (parm_exidx) { ui->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX; - ui->di_arm.start_ip = segbase; - ui->di_arm.end_ip = ui->di_arm.start_ip + ptxt->p_memsz; + ui->di_arm.start_ip = start_ip; + ui->di_arm.end_ip = end_ip; ui->di_arm.u.rti.name_ptr = (unw_word_t) path; - ui->di_arm.u.rti.table_data = parm_exidx->p_vaddr + segbase - - ptxt->p_vaddr; + ui->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr; ui->di_arm.u.rti.table_len = parm_exidx->p_memsz; found = 1; } #endif #ifdef CONFIG_DEBUG_FRAME - { - /* Try .debug_frame. */ - struct dl_phdr_info info; - - info.dlpi_name = path; - info.dlpi_phdr = phdr; - info.dlpi_phnum = ehdr->e_phnum; - - /* Fixup segbase to match correct base address. */ - for (i = 0; i < info.dlpi_phnum; i++) - { - if (info.dlpi_phdr[i].p_type == PT_LOAD && - info.dlpi_phdr[i].p_offset == 0) - { - segbase -= info.dlpi_phdr[i].p_vaddr; - break; - } - } - info.dlpi_addr = segbase; - - found = dwarf_find_debug_frame (found, &ui->di_debug, &info, ip); - } + /* Try .debug_frame. */ + found = dwarf_find_debug_frame (found, &ui->di_debug, ip, segbase, path, + start_ip, end_ip); #endif return found;