diff options
author | Paul Brook <paul@codesourcery.com> | 2006-10-26 19:41:54 +0000 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2006-10-26 19:41:54 +0000 |
commit | 969674da0df6a8242d0261412de8fbfee77ae432 (patch) | |
tree | 00f93ee6a54cf4aec782c395bce6a0034cfa21df | |
parent | 9fc11666a224d7ccf56634b13bf629baf9f58e94 (diff) | |
download | binutils-redhat-969674da0df6a8242d0261412de8fbfee77ae432.tar.gz |
2006-10-26 Paul Brook <paul@codesourcery.com>
binutils/
* objdump.c (disassemble_section): Set info->symtab_pos.
(disassemble_data): Set info->symtab and info->symtab_size.
include/
* dis-asm.h (disassemble_info): Add symtab, symtab_pos and
symtab_size.
opcodes/
* arm-dis.c (last_is_thumb, last_mapping_sym, last_mapping_addr): New.
(get_sym_code_type): New function.
(print_insn): Search for mapping symbols.
-rw-r--r-- | ChangeLog.csl | 15 | ||||
-rw-r--r-- | binutils/objdump.c | 4 | ||||
-rw-r--r-- | include/dis-asm.h | 6 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 107 |
4 files changed, 127 insertions, 5 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl index bc7d24df42..98e6ccf140 100644 --- a/ChangeLog.csl +++ b/ChangeLog.csl @@ -1,5 +1,20 @@ 2006-10-26 Paul Brook <paul@codesourcery.com> + binutils/ + * objdump.c (disassemble_section): Set info->symtab_pos. + (disassemble_data): Set info->symtab and info->symtab_size. + + include/ + * dis-asm.h (disassemble_info): Add symtab, symtab_pos and + symtab_size. + + opcodes/ + * arm-dis.c (last_is_thumb, last_mapping_sym, last_mapping_addr): New. + (get_sym_code_type): New function. + (print_insn): Search for mapping symbols. + +2006-10-26 Paul Brook <paul@codesourcery.com> + gas/ * config/tc-arm.c (arm_adjust_symtab): Don't use STT_ARM_16BIT for EABIv4. diff --git a/binutils/objdump.c b/binutils/objdump.c index 38622d7c4b..fdfe84a33c 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -1748,11 +1748,13 @@ disassemble_section (bfd *abfd, asection *section, void *info) pinfo->symbols = sorted_syms + place; pinfo->num_symbols = x - place; + pinfo->symtab_pos = place; } else { pinfo->symbols = NULL; pinfo->num_symbols = 0; + pinfo->symtab_pos = -1; } if (! prefix_addresses) @@ -1945,6 +1947,8 @@ disassemble_data (bfd *abfd) compare_relocs); } } + disasm_info.symtab = sorted_syms; + disasm_info.symtab_size = sorted_symcount; bfd_map_over_sections (abfd, disassemble_section, & disasm_info); diff --git a/include/dis-asm.h b/include/dis-asm.h index bdbf9f88c5..5c488c1ad5 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -94,6 +94,12 @@ typedef struct disassemble_info { /* Number of symbols in array. */ int num_symbols; + /* Symbol table provided for targets that want to look at it. This is + used on Arm to find mapping symbols and determine Arm/Thumb code. */ + asymbol **symtab; + int symtab_pos; + int symtab_size; + /* For use by the disassembler. The top 16 bits are reserved for public use (and are documented here). The bottom 16 bits are for the internal use of the disassembler. */ diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index b4085c64ba..28b82d9acb 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -1480,6 +1480,11 @@ static unsigned int ifthen_next_state; static bfd_vma ifthen_address; #define IFTHEN_COND ((ifthen_state >> 4) & 0xf) +/* Cached Thumb state. */ +int last_is_thumb; +int last_mapping_sym = -1; +bfd_vma last_mapping_addr = 0; + /* Functions. */ int @@ -3859,6 +3864,39 @@ find_ifthen_state (bfd_vma pc, struct disassemble_info *info, ifthen_state = 0; } +/* Try to infer the code type (Arm or Thumb) from a symbol. + Returns nonzero if is_thumb was set. */ + +static int +get_sym_code_type (struct disassemble_info *info, int n, int *is_thumb) +{ + elf_symbol_type *es; + unsigned int type; + const char *name; + + es = *(elf_symbol_type **)(info->symbols); + type = ELF_ST_TYPE (es->internal_elf_sym.st_info); + +//printf("Scan %d %s\n", n, bfd_asymbol_name(info->symtab[n])); + /* If the symbol has function type then use that. */ + if (type == STT_FUNC || type == STT_ARM_TFUNC) + { + *is_thumb = (type == STT_ARM_TFUNC); + return TRUE; + } + + /* Check for mapping symbols. */ + name = bfd_asymbol_name(info->symtab[n]); + if (name[0] == '$' && (name[1] == 'a' || name[1] == 't') + && (name[2] == 0 || name[2] == '.')) + { + *is_thumb = (name[1] == 't'); + return TRUE; + } + + return FALSE; +} + /* NOTE: There are no checks in these routines that the relevant number of data bytes exist. */ @@ -3897,13 +3935,72 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) } else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour) { - elf_symbol_type * es; - unsigned int type; + bfd_vma addr; + int n; + int last_sym; + bfd_boolean found; - es = *(elf_symbol_type **)(info->symbols); - type = ELF_ST_TYPE (es->internal_elf_sym.st_info); + if (info->symtab) + { + if (pc <= last_mapping_addr) + last_mapping_sym = -1; +//printf("Mapping %d %d %d\n", last_mapping_sym, info->symtab_pos, info->symtab_size); + is_thumb = last_is_thumb; + found = FALSE; + /* Start scanning at the start of the function, or wherever + we finished last time. */ + n = info->symtab_pos + 1; + if (n < last_mapping_sym) + n = last_mapping_sym; + + /* Scan up to the location being disassembled. */ + for (; n < info->symtab_size; n++) + { + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + break; + if (get_sym_code_type (info, n, &is_thumb)) + found = TRUE; + } + + last_sym = n; + if (!found) + { + if (last_mapping_sym == -1) + last_mapping_sym = 0; + else + found = TRUE; + + /* No mapping symbol found at this address. Look backwards + for a preceeding one. */ + for (n = info->symtab_pos; n >= last_mapping_sym; n--) + { + if (get_sym_code_type (info, n, &is_thumb)) + { + found = TRUE; + break; + } + } + } + + last_mapping_sym = last_sym; + last_is_thumb = is_thumb; + } + else + found = FALSE; - is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); + /* If no mapping symbol has been found then fall back to the type + of the function symbol. */ + if (!found) + { + elf_symbol_type * es; + unsigned int type; + + es = *(elf_symbol_type **)(info->symbols); + type = ELF_ST_TYPE (es->internal_elf_sym.st_info); + + is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); + } } } |