summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2006-10-26 19:41:54 +0000
committerPaul Brook <paul@codesourcery.com>2006-10-26 19:41:54 +0000
commit969674da0df6a8242d0261412de8fbfee77ae432 (patch)
tree00f93ee6a54cf4aec782c395bce6a0034cfa21df
parent9fc11666a224d7ccf56634b13bf629baf9f58e94 (diff)
downloadbinutils-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.csl15
-rw-r--r--binutils/objdump.c4
-rw-r--r--include/dis-asm.h6
-rw-r--r--opcodes/arm-dis.c107
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);
+ }
}
}