From 0e74e583ae18d6852835f327921ee130a5fa3e6f Mon Sep 17 00:00:00 2001 From: Doug Moore Date: Tue, 20 Jun 2017 11:47:27 -0500 Subject: [PATCH] arm: Use dwarf_find_proc_info for arm dwarf processing Rather than using a copy of dwarf_find_proc_info that differs from it slightly. By using dwarf_find_proc_info, a potential search of the di table is allowed, where it is omitted now. Also, for ARM, avoid runtime checks about which kind of unwind table search to use after dl_iterate_phdr. A couple of Debug() warnings about ip lookup failure are lost here. The dwarf callback struct defintion is moved to Gfind_proc_info-lsb.c, which becomes the only source file that needs it. --- include/dwarf.h | 12 --- src/arm/Gex_tables.c | 157 ++++++++++++++------------------ src/dwarf/Gfind_proc_info-lsb.c | 42 ++++++--- 3 files changed, 94 insertions(+), 117 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index 469964e4..e8ffa66c 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -382,18 +382,6 @@ struct unw_debug_frame_list struct unw_debug_frame_list *next; }; -struct dwarf_callback_data - { - /* in: */ - unw_word_t ip; /* instruction-pointer we're looking for */ - unw_proc_info_t *pi; /* proc-info pointer */ - int need_unwind_info; - /* out: */ - int single_fde; /* did we find a single FDE? (vs. a table) */ - unw_dyn_info_t di; /* table info (if single_fde is false) */ - unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ - }; - /* Convenience macros: */ #define dwarf_init UNW_ARCH_OBJ (dwarf_init) #define dwarf_callback UNW_OBJ (dwarf_callback) diff --git a/src/arm/Gex_tables.c b/src/arm/Gex_tables.c index 9b8661af..3f6b5cfc 100644 --- a/src/arm/Gex_tables.c +++ b/src/arm/Gex_tables.c @@ -381,6 +381,69 @@ arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf) return nbuf; } +PROTECTED int +arm_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + /* The .ARM.exidx section contains a sorted list of key-value pairs - + the unwind entries. The 'key' is a prel31 offset to the start of a + function. We binary search this section in order to find the + appropriate unwind entry. */ + unw_word_t first = di->u.rti.table_data; + unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8; + unw_word_t entry, val; + + if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val) + return -UNW_ENOINFO; + + if (prel31_to_addr (as, arg, last, &val) < 0) + return -UNW_EINVAL; + + if (ip >= val) + { + entry = last; + + if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0) + return -UNW_EINVAL; + + pi->end_ip = di->end_ip -1; + } + else + { + while (first < last - 8) + { + entry = first + (((last - first) / 8 + 1) >> 1) * 8; + + if (prel31_to_addr (as, arg, entry, &val) < 0) + return -UNW_EINVAL; + + if (ip < val) + last = entry; + else + first = entry; + } + + entry = first; + + if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0) + return -UNW_EINVAL; + + if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0) + return -UNW_EINVAL; + + pi->end_ip--; + } + + if (need_unwind_info) + { + pi->unwind_info_size = 8; + pi->unwind_info = (void *) entry; + pi->format = UNW_INFO_FORMAT_ARM_EXIDX; + } + return 0; +} + PROTECTED int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, unw_dyn_info_t *di, unw_proc_info_t *pi, @@ -388,64 +451,7 @@ tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, { if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX) && di->format == UNW_INFO_FORMAT_ARM_EXIDX) - { - /* The .ARM.exidx section contains a sorted list of key-value pairs - - the unwind entries. The 'key' is a prel31 offset to the start of a - function. We binary search this section in order to find the - appropriate unwind entry. */ - unw_word_t first = di->u.rti.table_data; - unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8; - unw_word_t entry, val; - - if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val) - return -UNW_ENOINFO; - - if (prel31_to_addr (as, arg, last, &val) < 0) - return -UNW_EINVAL; - - if (ip >= val) - { - entry = last; - - if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0) - return -UNW_EINVAL; - - pi->end_ip = di->end_ip -1; - } - else - { - while (first < last - 8) - { - entry = first + (((last - first) / 8 + 1) >> 1) * 8; - - if (prel31_to_addr (as, arg, entry, &val) < 0) - return -UNW_EINVAL; - - if (ip < val) - last = entry; - else - first = entry; - } - - entry = first; - - if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0) - return -UNW_EINVAL; - - if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0) - return -UNW_EINVAL; - - pi->end_ip--; - } - - if (need_unwind_info) - { - pi->unwind_info_size = 8; - pi->unwind_info = (void *) entry; - pi->format = UNW_INFO_FORMAT_ARM_EXIDX; - } - return 0; - } + return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) && di->format != UNW_INFO_FORMAT_ARM_EXIDX) return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); @@ -509,33 +515,7 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, Debug (14, "looking for IP=0x%lx\n", (long) ip); if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) - { - struct dwarf_callback_data cb_data; - - memset (&cb_data, 0, sizeof (cb_data)); - cb_data.ip = ip; - cb_data.pi = pi; - cb_data.need_unwind_info = need_unwind_info; - cb_data.di.format = -1; - cb_data.di_debug.format = -1; - - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); - ret = dl_iterate_phdr (dwarf_callback, &cb_data); - SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - - if (ret > 0) - { - if (cb_data.single_fde) - /* already got the result in *pi */ - return 0; - - if (cb_data.di_debug.format != -1) - ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi, - need_unwind_info, arg); - else - ret = -UNW_ENOINFO; - } - } + ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg); if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) { @@ -551,15 +531,12 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); if (cb_data.di.format != -1) - ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi, - need_unwind_info, arg); + ret = arm_search_unwind_table (as, ip, &cb_data.di, pi, + need_unwind_info, arg); else ret = -UNW_ENOINFO; } - if (ret < 0) - Debug (14, "IP=0x%lx not found\n", (long) ip); - return ret; } diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 4eb80461..3e66bc1a 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -453,6 +453,18 @@ out: return eh_frame; } +struct dwarf_callback_data + { + /* in: */ + unw_word_t ip; /* instruction-pointer we're looking for */ + unw_proc_info_t *pi; /* proc-info pointer */ + int need_unwind_info; + /* out: */ + int single_fde; /* did we find a single FDE? (vs. a table) */ + unw_dyn_info_t di; /* table info (if single_fde is false) */ + unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ + }; + /* ptr is a pointer to a dwarf_callback_data structure and, on entry, member ip contains the instruction-pointer we're looking for. */ @@ -685,26 +697,26 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, ret = dl_iterate_phdr (dwarf_callback, &cb_data); SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - if (ret <= 0) + if (ret > 0) { - Debug (14, "IP=0x%lx not found\n", (long) ip); - return -UNW_ENOINFO; + if (cb_data.single_fde) + /* already got the result in *pi */ + return 0; + + /* search the table: */ + if (cb_data.di.format != -1) + ret = dwarf_search_unwind_table (as, ip, &cb_data.di, + pi, need_unwind_info, arg); + else + ret = -UNW_ENOINFO; + + if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1) + ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi, + need_unwind_info, arg); } - - if (cb_data.single_fde) - /* already got the result in *pi */ - return 0; - - /* search the table: */ - if (cb_data.di.format != -1) - ret = dwarf_search_unwind_table (as, ip, &cb_data.di, - pi, need_unwind_info, arg); else ret = -UNW_ENOINFO; - if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1) - ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi, - need_unwind_info, arg); return ret; }