2006-10-26 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Thu, 26 Oct 2006 19:41:54 +0000 (19:41 +0000)
committerPaul Brook <paul@codesourcery.com>
Thu, 26 Oct 2006 19:41:54 +0000 (19:41 +0000)
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.

ChangeLog.csl
binutils/objdump.c
include/dis-asm.h
opcodes/arm-dis.c

index bc7d24d..98e6ccf 100644 (file)
@@ -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.
index 38622d7..fdfe84a 100644 (file)
@@ -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);
 
index bdbf9f8..5c488c1 100644 (file)
@@ -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.  */
index b4085c6..28b82d9 100644 (file)
@@ -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;
+
 \f
 /* 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);
+           }
        }
     }