2006-10-30 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Tue, 31 Oct 2006 20:21:57 +0000 (20:21 +0000)
committerPaul Brook <paul@codesourcery.com>
Tue, 31 Oct 2006 20:21:57 +0000 (20:21 +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.

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

index 7b935d91f65df82d9324dd87a9cdf17be18d0977..6628f148eee118728c618fbe46ced47808302ce7 100644 (file)
@@ -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
index 809457ec10305e81f6fe24d22d120ee346090b62..661ee2912b833cf3694fba90c09a33f5779c16ab 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 3edbe8d069b1630df3ed2fe97155fe171c6e1297..b7cb681210c360f0130c34fc9782c42fdc8f8715 100644 (file)
@@ -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
index cb8039bf35eccc7dd48a92003a4f7a2a5f9a5e4d..af48e8528ef6bfebc48f3348c06fdab192ab1ab3 100644 (file)
@@ -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.  */
index 01613cd4b9fd85b963976687dae44f47659ff2a4..31b2051fe6b5432149cadcbe666c9c67802a0377 100644 (file)
@@ -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
index 5a8d54100d7f21495f7d79195f166c9ab49e2091..7a02e319cfbd1f64dba85c66d2f966922f13f39c 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,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);
+           }
        }
     }