From patchwork Wed Mar 23 15:55:01 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ken Werner X-Patchwork-Id: 757 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:45:30 -0000 Delivered-To: patches@linaro.org Received: by 10.220.180.8 with SMTP id bs8cs11681vcb; Wed, 23 Mar 2011 08:55:11 -0700 (PDT) Received: by 10.213.103.74 with SMTP id j10mr31314ebo.7.1300895710450; Wed, 23 Mar 2011 08:55:10 -0700 (PDT) Received: from mtagate1.uk.ibm.com (mtagate1.uk.ibm.com [194.196.100.161]) by mx.google.com with ESMTPS id k50si12045733eei.100.2011.03.23.08.55.09 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 23 Mar 2011 08:55:10 -0700 (PDT) Received-SPF: neutral (google.com: 194.196.100.161 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) client-ip=194.196.100.161; Authentication-Results: mx.google.com; spf=neutral (google.com: 194.196.100.161 is neither permitted nor denied by best guess record for domain of ken.werner@linaro.org) smtp.mail=ken.werner@linaro.org Received: from d06nrmr1307.portsmouth.uk.ibm.com (d06nrmr1307.portsmouth.uk.ibm.com [9.149.38.129]) by mtagate1.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p2NFt951003968 for ; Wed, 23 Mar 2011 15:55:09 GMT Received: from d06av11.portsmouth.uk.ibm.com (d06av11.portsmouth.uk.ibm.com [9.149.37.252]) by d06nrmr1307.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p2NFtbr21896662 for ; Wed, 23 Mar 2011 15:55:37 GMT 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 p2NFt94R022426 for ; Wed, 23 Mar 2011 09:55:09 -0600 Received: from localhost.localdomain (dyn-9-152-224-51.boeblingen.de.ibm.com [9.152.224.51]) by d06av11.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p2NFt7Tu022296; Wed, 23 Mar 2011 09:55:08 -0600 From: Ken Werner To: libunwind-devel@nongnu.org Subject: [PATCH 3/8] ARM extbl cleanup. Date: Wed, 23 Mar 2011 15:55:01 +0000 Message-Id: <1300895706-5424-4-git-send-email-ken.werner@linaro.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1300895706-5424-1-git-send-email-ken.werner@linaro.org> References: <1300895706-5424-1-git-send-email-ken.werner@linaro.org> Move code that does not necessarily need to reside in the ex_tables.h header file into ex_tables.c. Add comments and remove unused code. Signed-off-by: Ken Werner --- include/tdep-arm/ex_tables.h | 37 +------- src/arm/ex_tables.c | 196 ++++++++--------------------------------- 2 files changed, 44 insertions(+), 189 deletions(-) diff --git a/include/tdep-arm/ex_tables.h b/include/tdep-arm/ex_tables.h index 7369b35..698792f 100644 --- a/include/tdep-arm/ex_tables.h +++ b/include/tdep-arm/ex_tables.h @@ -41,7 +41,6 @@ struct arm_exidx_table { #endif }; - typedef enum arm_exbuf_cmd { ARM_EXIDX_CMD_FINISH, ARM_EXIDX_CMD_DATA_PUSH, @@ -55,47 +54,21 @@ typedef enum arm_exbuf_cmd { ARM_EXIDX_CMD_REFUSED, } arm_exbuf_cmd_t; -enum arm_exbuf_cmd_flags { - ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, - ARM_EXIDX_VFP_DOUBLE = 1 << 17, -}; - -#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) -#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) -#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) - struct arm_exbuf_data { arm_exbuf_cmd_t cmd; uint32_t data; }; -static inline void * -prel31_to_addr (void *addr) -{ - uint32_t offset = ((long)*(uint32_t *)addr << 1) >> 1; - return (char *)addr + offset; -} int arm_exidx_init_local (const char *appname); - -int arm_exidx_table_add (const char *name, - struct arm_exidx_entry *start, struct arm_exidx_entry *end); +int arm_exidx_table_add (const char *name, struct arm_exidx_entry *start, + struct arm_exidx_entry *end); struct arm_exidx_table *arm_exidx_table_find (void *pc); -struct arm_exidx_entry *arm_exidx_table_lookup ( - struct arm_exidx_table *table, void *pc); - -void arm_exidx_section_find (struct elf_image *ei, - Elf_W (Shdr) **exidx, Elf_W (Shdr) **extbl); -int arm_exidx_entry_lookup (struct elf_image *ei, - Elf_W (Shdr) *exidx, uint32_t ip); -int arm_exidx_entry_extract (struct elf_image *ei, - Elf_W (Shdr) *exidx, Elf_W (Shdr) *extbl, - unsigned i, uint8_t *buf); +struct arm_exidx_entry *arm_exidx_table_lookup (struct arm_exidx_table *table, + void *pc); int arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf); - -int arm_exidx_decode (const uint8_t *buf, uint8_t len, - struct dwarf_cursor *c); +int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c); int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c); #endif // ARM_EX_TABLES_H diff --git a/src/arm/ex_tables.c b/src/arm/ex_tables.c index 6fe2947..abe9a77 100644 --- a/src/arm/ex_tables.c +++ b/src/arm/ex_tables.c @@ -24,11 +24,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libunwind_i.h" +#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) +#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) +#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) + #define ARM_EXIDX_CANT_UNWIND 0x00000001 #define ARM_EXIDX_COMPACT 0x80000000 #define ARM_EXTBL_OP_FINISH 0xb0 +enum arm_exbuf_cmd_flags { + ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, + ARM_EXIDX_VFP_DOUBLE = 1 << 17, +}; + #ifdef ARM_EXIDX_TABLE_MALLOC static struct arm_exidx_table *arm_exidx_table_list; #else @@ -38,6 +47,19 @@ static unsigned arm_exidx_table_count = 0; #endif static const char *arm_exidx_appname; +static inline uint32_t +prel31_read (uint32_t prel31) +{ + return ((int32_t)prel31 << 1) >> 1; +} + +static inline void * +prel31_to_addr (void *addr) +{ + uint32_t offset = ((long)*(uint32_t *)addr << 1) >> 1; + return (char *)addr + offset; +} + static void arm_exidx_table_reset_all (void) { @@ -79,7 +101,7 @@ arm_exidx_table_add (const char *name, } /** - * Located the appropriate unwind table + * Locate the appropriate unwind table from the given PC. */ HIDDEN struct arm_exidx_table * arm_exidx_table_find (void *pc) @@ -100,7 +122,9 @@ arm_exidx_table_find (void *pc) return NULL; } -/* Based on Linux arm/arm/kernel/unwind.c:search_index() */ +/** + * Finds the corresponding arm_exidx_entry from a given index table and PC. + */ HIDDEN struct arm_exidx_entry * arm_exidx_table_lookup (struct arm_exidx_table *table, void *pc) { @@ -190,7 +214,10 @@ arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c) return ret; } - +/** + * Decodes the given unwind instructions into arm_exbuf_data and calls + * arm_exidx_apply_cmd that applies the command onto the dwarf_cursor. + */ HIDDEN int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c) { @@ -323,59 +350,11 @@ arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c) return 0; } -static inline uint32_t -prel31_read (uint32_t prel31) -{ - return ((int32_t)prel31 << 1) >> 1; -} - -/** - * Finds the index of the table entry for the given address - * using a binary search. - * @returns The table index (or -1 if not found). - */ -HIDDEN int -arm_exidx_lookup (uint32_t *exidx_data, uint32_t exidx_size, uint32_t ip) -{ - unsigned lo = 0, hi = exidx_size / 8; - while (lo < hi) - { - unsigned mid = (lo + hi) / 2; - uint32_t base = (uint32_t)(exidx_data + mid * 2); - uint32_t addr = base + prel31_read (exidx_data[mid * 2]); - if (ip < addr) - hi = mid; - else - lo = mid + 1; - } - return hi - 1; -} - -HIDDEN int -arm_exidx_entry_lookup (struct elf_image *ei, - Elf_W (Shdr) *exidx, uint32_t ip) -{ -#if 1 - return arm_exidx_lookup (ei->image + exidx->sh_offset, exidx->sh_size, ip); -#else - unsigned n_entries = exidx->sh_size / 8; - uint32_t *exidx_data = ei->image + exidx->sh_offset; - unsigned lo = 0, hi = n_entries; - - while (lo < hi) - { - unsigned mid = (lo + hi) / 2; - uint32_t base = exidx->sh_addr + mid * 8; - uint32_t addr = base + prel31_read (exidx_data[mid * 2]); - if (ip < addr) - hi = mid; - else - lo = mid + 1; - } - return hi - 1; -#endif -} - +/** + * Reads the given entry and extracts the unwind instructions into buf. + * Returns the number of the extracted unwind insns or -UNW_ESTOPUNWIND + * if the special bit pattern ARM_EXIDX_CANT_UNWIND (0x1) was found. + */ HIDDEN int arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf) { @@ -417,7 +396,7 @@ arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf) else { void *pers = prel31_to_addr (extbl_data); - Debug (2, "%p Personality routine: %8.8x\n", addr, pers); + Debug (2, "%p Personality routine: %8p\n", addr, pers); n_table_words = extbl_data[1] >> 24; buf[nbuf++] = extbl_data[1] >> 16; buf[nbuf++] = extbl_data[1] >> 8; @@ -442,105 +421,8 @@ arm_exidx_extract (struct arm_exidx_entry *entry, uint8_t *buf) return nbuf; } -HIDDEN int -arm_exidx_entry_extract (struct elf_image *ei, - Elf_W (Shdr) *exidx, Elf_W (Shdr) *extbl, - unsigned i, uint8_t *buf) -{ - int nbuf = 0; - uint32_t *exidx_data = ei->image + exidx->sh_offset; - uint32_t base = exidx->sh_addr + i * 8; - uint32_t one = base + prel31_read (exidx_data[i * 2]); - - uint32_t two = exidx_data[i * 2 + 1]; - if (two == ARM_EXIDX_CANT_UNWIND) - printf ("0x1 [can't unwind]\n"); - else if (two & ARM_EXIDX_COMPACT) - { - printf ("compact model %d [%8.8x]\n", (two >> 24) & 0x7f, two); - buf[nbuf++] = two >> 16; - buf[nbuf++] = two >> 8; - buf[nbuf++] = two; - } - else - { - assert (NULL != extbl); - two = base + prel31_read (two) + 4; - uint32_t *extbl_data = ei->image + extbl->sh_offset - + (two - extbl->sh_addr); - two = extbl_data[0]; - unsigned int n_table_words = 0; - if (two & ARM_EXIDX_COMPACT) - { - int pers = (two >> 24) & 0x0f; - printf ("compact model %d [%8.8x]\n", pers, two); - if (pers == 1 || pers == 2) - { - n_table_words = (two >> 16) & 0xff; - extbl_data += 1; - } - else - buf[nbuf++] = two >> 16; - buf[nbuf++] = two >> 8; - buf[nbuf++] = two; - } - else - { - uint32_t pers = prel31_read (extbl_data[0]); - pers += extbl->sh_addr + i * 8 + 4; - printf ("Personality routine: %8.8x\n", pers); - n_table_words = extbl_data[1] >> 24; - buf[nbuf++] = extbl_data[1] >> 16; - buf[nbuf++] = extbl_data[1] >> 8; - buf[nbuf++] = extbl_data[1]; - extbl_data += 2; - } - assert (n_table_words <= 5); - unsigned j; - for (j = 0; j < n_table_words; j++) - { - two = *extbl_data++; - buf[nbuf++] = two >> 24; - buf[nbuf++] = two >> 16; - buf[nbuf++] = two >> 8; - buf[nbuf++] = two >> 0; - } - } - - if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH) - buf[nbuf++] = ARM_EXTBL_OP_FINISH; - - return nbuf; -} - -HIDDEN void -arm_exidx_section_find (struct elf_image *ei, - Elf_W (Shdr) **exidx, Elf_W (Shdr) **extbl) -{ - Elf_W (Ehdr) *ehdr = ei->image; - Elf_W (Shdr) *shdr; - shdr = (Elf_W (Shdr) *)((char *)ei->image + ehdr->e_shoff); - char *names = (char *)ei->image + shdr[ehdr->e_shstrndx].sh_offset; - int i = 0; - for (i = 0; i < ehdr->e_shnum; i++) - { - char *name = names + shdr[i].sh_name; - switch (shdr[i].sh_type) - { - case SHT_ARM_EXIDX: - *exidx = shdr + i; - break; - case SHT_PROGBITS: - if (strcmp (name, ".ARM.extab") != 0) - break; - *extbl = shdr + i; - break; - } - } -} - /** - * Callback to dl_iterate_phr to find each library's unwind table. + * Callback to dl_iterate_phdr to find the unwind tables. * If found, calls arm_exidx_table_add to remember it for later lookups. */ static int @@ -570,13 +452,13 @@ arm_exidx_init_local_cb (struct dl_phdr_info *info, size_t size, void *data) } /** - * Must be called for local process lookups. + * Traverse the program headers of the executable and its loaded + * shared objects to collect the unwind tables. */ HIDDEN int arm_exidx_init_local (const char *appname) { arm_exidx_appname = appname; - // traverse all libraries and find unwind tables arm_exidx_table_reset_all(); return dl_iterate_phdr (&arm_exidx_init_local_cb, NULL); }