]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix disassembly of C64 instructions in GDB
authorLuis Machado <luis.machado@linaro.org>
Tue, 9 Mar 2021 17:56:15 +0000 (14:56 -0300)
committerLuis Machado <luis.machado@linaro.org>
Wed, 17 Mar 2021 13:37:59 +0000 (10:37 -0300)
Disassembling of C64 instructions in GDB does not work correctly. It needs
to pass the proper information to opcodes.

This patch accomplishes that.

gdb/ChangeLog:

2021-03-17  Luis Machado  <luis.machado@arm.com>

* aarch64-tdep.c (aarch64_find_mapping_symbol, aarch64_pc_is_c64): New
functions.
(aarch64_gdb_print_insn): Pass map type to disassembler.

include/ChangeLog:

2021-03-17  Luis Machado  <luis.machado@arm.com>

* opcode/aarch64.h (enum map_type): Moved from opcodes/aarch64-dis.c.
Renamed fields.
(struct aarch64_private_data): New struct.

opcodes/ChangeLog:

2021-03-17  Luis Machado  <luis.machado@arm.com>

* aarch64-dis.c (enum map_type): Moved to include/opcode/aarch64.h.
(MAYBE_C64): Adjust.
(get_sym_code_type): Adjust.
(print_insn_aarch64): Use private data when available.

gdb/ChangeLog
gdb/aarch64-tdep.c
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-dis.c

index 2e26c87d20c4d5129ce3331c469aff68307476d8..97addfc322bd1ef7aa6f4d3f0fc80675064d1d90 100644 (file)
@@ -1,3 +1,9 @@
+2021-03-17  Luis Machado  <luis.machado@arm.com>
+
+       * aarch64-tdep.c (aarch64_find_mapping_symbol, aarch64_pc_is_c64): New
+       functions.
+       (aarch64_gdb_print_insn): Pass map type to disassembler.
+
 2021-01-15  Luis Machado  <luis.machado@arm.com>
 
        * aarch64-linux-nat.c (store_cregs_to_thread): Implement.
index edbafb04f8670290c7c01a007cfcb313f5181222..9d11cba958bdd6f749fea9b7a11de7e606968aa7 100644 (file)
@@ -2602,12 +2602,113 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   return -1;
 }
 
+/* Search for the mapping symbol covering MEMADDR.  If one is found,
+   return its type.  Otherwise, return 0.  If START is non-NULL,
+   set *START to the location of the mapping symbol.  */
+
+static char
+aarch64_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
+{
+  struct obj_section *sec;
+
+  /* If there are mapping symbols, consult them.  */
+  sec = find_pc_section (memaddr);
+  if (sec != NULL)
+    {
+      aarch64_per_bfd *data = aarch64_bfd_data_key.get (sec->objfile->obfd);
+      if (data != NULL)
+       {
+         unsigned int section_idx = sec->the_bfd_section->index;
+         aarch64_mapping_symbol_vec &map
+           = data->section_maps[section_idx];
+
+         /* Sort the vector on first use.  */
+         if (!data->section_maps_sorted[section_idx])
+           {
+             std::sort (map.begin (), map.end ());
+             data->section_maps_sorted[section_idx] = true;
+           }
+
+         struct aarch64_mapping_symbol map_key
+           = { memaddr - obj_section_addr (sec), 0 };
+         aarch64_mapping_symbol_vec::const_iterator it
+           = std::lower_bound (map.begin (), map.end (), map_key);
+
+         /* std::lower_bound finds the earliest ordered insertion
+            point.  If the symbol at this position starts at this exact
+            address, we use that; otherwise, the preceding
+            mapping symbol covers this address.  */
+         if (it < map.end ())
+           {
+             if (it->value == map_key.value)
+               {
+                 if (start)
+                   *start = it->value + obj_section_addr (sec);
+                 return it->type;
+               }
+           }
+
+         if (it > map.begin ())
+           {
+             aarch64_mapping_symbol_vec::const_iterator prev_it
+               = it - 1;
+
+             if (start)
+               *start = prev_it->value + obj_section_addr (sec);
+             return prev_it->type;
+           }
+       }
+    }
+
+  return 0;
+}
+
+/* Determine if the program counter specified in MEMADDR is in a C64
+   function.  This function should be called for addresses unrelated to
+   any executing frame.  */
+
+static bool
+aarch64_pc_is_c64 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* If we're using the AAPCS64-CAP ABI, then this is pure-cap and it is
+     always C64.  */
+  if (tdep->abi == AARCH64_ABI_AAPCS64_CAP)
+    return true;
+
+  /* If there are mapping symbols, consult them.  */
+  char type = aarch64_find_mapping_symbol (memaddr, NULL);
+  if (type)
+    return type == 'c';
+
+  /* C64 functions have a "special" bit set in minimal symbols.  */
+  struct bound_minimal_symbol sym;
+  sym = lookup_minimal_symbol_by_pc (memaddr);
+  if (sym.minsym)
+    return (MSYMBOL_IS_SPECIAL (sym.minsym));
+
+  /* Otherwise we're out of luck; we assume A64.  */
+  return false;
+}
+
 /* Implement the "print_insn" gdbarch method.  */
 
 static int
 aarch64_gdb_print_insn (bfd_vma memaddr, disassemble_info *info)
 {
+  gdb_disassembler *di
+    = static_cast<gdb_disassembler *>(info->application_data);
+  struct gdbarch *gdbarch = di->arch ();
+  struct aarch64_private_data data;
+
+  info->private_data = static_cast<void *> (&data);
+
+  if (aarch64_pc_is_c64 (gdbarch, memaddr))
+    data.instruction_type = MAP_TYPE_C64;
+
   info->symbols = NULL;
+
   return default_print_insn (memaddr, info);
 }
 
index 1093514929ca4d5ff368dcedb2bdb7f9d7d7457c..47bc23995874384c5a6d3b7759d1f43a9342128d 100644 (file)
@@ -1,3 +1,9 @@
+2021-03-17  Luis Machado  <luis.machado@arm.com>
+
+       * opcode/aarch64.h (enum map_type): Moved from opcodes/aarch64-dis.c.
+       Renamed fields.
+       (struct aarch64_private_data): New struct.
+
 2020-10-20  Luis Machado  <luis.machado@arm.com>
 
        * elf/common.h (NT_ARM_MORELLO): Define.
index 0568ca10973be6c841c91ef3721a69dc5de15d43..6360246c600d2efaa1a13845e3dfe6d16d4401ee 100644 (file)
@@ -1354,6 +1354,20 @@ struct aarch64_instr_sequence
   int next_insn;
 };
 
+/* Cached mapping symbol state.  */
+enum map_type
+{
+  MAP_TYPE_INSN,
+  MAP_TYPE_DATA,
+  MAP_TYPE_C64
+};
+
+/* AArch64-specific data to help proper disassembling of instructions.  */
+struct aarch64_private_data
+{
+  enum map_type instruction_type;
+};
+
 /* Encoding entrypoint.  */
 
 extern int
index 427467fe7e15526c074b753a9843cdac8b589e62..ed383afdd71dfa739b64a250edfef7e9ed294d42 100644 (file)
@@ -1,3 +1,10 @@
+2021-03-17  Luis Machado  <luis.machado@arm.com>
+
+       * aarch64-dis.c (enum map_type): Moved to include/opcode/aarch64.h.
+       (MAYBE_C64): Adjust.
+       (get_sym_code_type): Adjust.
+       (print_insn_aarch64): Use private data when available.
+
 2020-10-20  Luis Machado  <luis.machado@arm.com>
 
        * aarch64-tbl.h (aarch64_opcode_table): Update iclass field
index 24dea397e83f9b9098316d866751141b4a766a2b..a1778b4d2b42ec53a820eccf6dc74830615dd03e 100644 (file)
 
 #define INSNLEN 4
 
-/* Cached mapping symbol state.  */
-enum map_type
-{
-  MAP_INSN,
-  MAP_DATA,
-  MAP_C64
-};
-
 static aarch64_feature_set arch_variant; /* See select_aarch64_variant.  */
 static enum map_type last_type;
 static int last_mapping_sym = -1;
 static bfd_vma last_stop_offset = 0;
 static bfd_vma last_mapping_addr = 0;
 
-#define MAYBE_C64 (last_type == MAP_C64 ? AARCH64_FEATURE_C64 : 0)
+#define MAYBE_C64 (last_type == MAP_TYPE_C64 ? AARCH64_FEATURE_C64 : 0)
 
 /* Other options */
 static int no_aliases = 0;     /* If set disassemble as most general inst.  */
@@ -3552,7 +3544,7 @@ get_sym_code_type (struct disassemble_info *info, int n,
   if (type == STT_FUNC && !(es->symbol.flags & BSF_SYNTHETIC))
     {
       *map_type = (es->internal_elf_sym.st_target_internal & ST_BRANCH_TO_C64
-                  ? MAP_C64 : MAP_INSN);
+                  ? MAP_TYPE_C64 : MAP_TYPE_INSN);
       return TRUE;
     }
 
@@ -3565,13 +3557,13 @@ get_sym_code_type (struct disassemble_info *info, int n,
       switch (name[1])
        {
        case 'd':
-         *map_type = MAP_DATA;
+         *map_type = MAP_TYPE_DATA;
          break;
        case 'x':
-         *map_type = MAP_INSN;
+         *map_type = MAP_TYPE_INSN;
          break;
        case 'c':
-         *map_type = MAP_C64;
+         *map_type = MAP_TYPE_C64;
          break;
        default:
          abort ();
@@ -3637,17 +3629,28 @@ print_insn_aarch64 (bfd_vma pc,
   /* Aarch64 instructions are always little-endian */
   info->endian_code = BFD_ENDIAN_LITTLE;
 
-  /* Default to DATA.  A text section is required by the ABI to contain an
-     INSN mapping symbol at the start.  A data section has no such
-     requirement, hence if no mapping symbol is found the section must
-     contain only data.  This however isn't very useful if the user has
-     fully stripped the binaries.  If this is the case use the section
-     attributes to determine the default.  If we have no section default to
-     INSN as well, as we may be disassembling some raw bytes on a baremetal
-     HEX file or similar.  */
-  enum map_type type = MAP_DATA;
-  if ((info->section && info->section->flags & SEC_CODE) || !info->section)
-    type = last_type == MAP_C64 ? MAP_C64 : MAP_INSN;
+  enum map_type type;
+
+  if (info->private_data != NULL)
+    {
+      struct aarch64_private_data *aarch64_data
+       = (struct aarch64_private_data *) info->private_data;
+      type = aarch64_data->instruction_type;
+    }
+  else
+    {
+      /* Default to DATA.  A text section is required by the ABI to contain an
+        INSN mapping symbol at the start.  A data section has no such
+        requirement, hence if no mapping symbol is found the section must
+        contain only data.  This however isn't very useful if the user has
+        fully stripped the binaries.  If this is the case use the section
+        attributes to determine the default.  If we have no section default to
+        INSN as well, as we may be disassembling some raw bytes on a baremetal
+        HEX file or similar.  */
+      type = MAP_TYPE_DATA;
+      if ((info->section && info->section->flags & SEC_CODE) || !info->section)
+       type = last_type == MAP_TYPE_C64 ? MAP_TYPE_C64 : MAP_TYPE_INSN;
+    }
 
   /* First check the full symtab for a mapping symbol, even if there
      are no usable non-mapping symbols for this address.  */
@@ -3729,7 +3732,7 @@ print_insn_aarch64 (bfd_vma pc,
         less than four bytes of data.  If there's a symbol,
         mapping or otherwise, after two bytes then don't
         print more.  */
-      if (last_type == MAP_DATA)
+      if (last_type == MAP_TYPE_DATA)
        {
          size = 4 - (pc & 3);
          for (n = last_sym + 1; n < info->symtab_size; n++)
@@ -3753,7 +3756,7 @@ print_insn_aarch64 (bfd_vma pc,
     last_type = type;
 
   /* PR 10263: Disassemble data if requested to do so by the user.  */
-  if (last_type == MAP_DATA && ((info->flags & DISASSEMBLE_DATA) == 0))
+  if (last_type == MAP_TYPE_DATA && ((info->flags & DISASSEMBLE_DATA) == 0))
     {
       /* size was set above.  */
       info->bytes_per_chunk = size;