diff options
-rw-r--r-- | binutils/ChangeLog | 5 | ||||
-rw-r--r-- | binutils/objdump.c | 4 | ||||
-rw-r--r-- | include/ChangeLog | 5 | ||||
-rw-r--r-- | include/dis-asm.h | 6 | ||||
-rw-r--r-- | opcodes/ChangeLog | 6 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 105 |
6 files changed, 126 insertions, 5 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 7b935d9..6628f14 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2006-10-30 Paul Brook <paul@codesourcery.com> + + * objdump.c (disassemble_section): Set info->symtab_pos. + (disassemble_data): Set info->symtab and info->symtab_size. + 2006-10-29 H.J. Lu <hongjiu.lu@intel.com> PR binutils/3384 diff --git a/binutils/objdump.c b/binutils/objdump.c index 809457e..661ee29 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/ChangeLog b/include/ChangeLog index 3edbe8d..b7cb681 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2006-10-30 Paul Brook <paul@codesourcery.com> + + * dis-asm.h (disassemble_info): Add symtab, symtab_pos and + symtab_size. + 2006-10-30 H.J. Lu <hongjiu.lu@intel.com> PR ld/3111 diff --git a/include/dis-asm.h b/include/dis-asm.h index cb8039b..af48e85 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -96,6 +96,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/ChangeLog b/opcodes/ChangeLog index 01613cd..31b2051 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,9 @@ +2006-10-30 Paul Brook <paul@codesourcery.com> + + * 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-31 Mei Ligang <ligang@sunnorth.com.cn> * score-dis.c (print_insn): Correct the error code to print diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 5a8d541..7a02e31 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,38 @@ 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); + + /* 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 +3934,71 @@ 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; + 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); + } } } |