Home | History | Annotate | Line # | Download | only in gdb
disasm-selftests.c revision 1.1.1.3.2.1
      1          1.1  christos /* Self tests for disassembler for GDB, the GNU debugger.
      2          1.1  christos 
      3  1.1.1.3.2.1  perseant    Copyright (C) 2017-2023 Free Software Foundation, Inc.
      4          1.1  christos 
      5          1.1  christos    This file is part of GDB.
      6          1.1  christos 
      7          1.1  christos    This program is free software; you can redistribute it and/or modify
      8          1.1  christos    it under the terms of the GNU General Public License as published by
      9          1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10          1.1  christos    (at your option) any later version.
     11          1.1  christos 
     12          1.1  christos    This program is distributed in the hope that it will be useful,
     13          1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14          1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15          1.1  christos    GNU General Public License for more details.
     16          1.1  christos 
     17          1.1  christos    You should have received a copy of the GNU General Public License
     18          1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19          1.1  christos 
     20          1.1  christos #include "defs.h"
     21          1.1  christos #include "disasm.h"
     22      1.1.1.3  christos #include "gdbsupport/selftest.h"
     23          1.1  christos #include "selftest-arch.h"
     24      1.1.1.3  christos #include "gdbarch.h"
     25          1.1  christos 
     26          1.1  christos namespace selftests {
     27          1.1  christos 
     28  1.1.1.3.2.1  perseant /* Return a pointer to a buffer containing an instruction that can be
     29  1.1.1.3.2.1  perseant    disassembled for architecture GDBARCH.  *LEN will be set to the length
     30  1.1.1.3.2.1  perseant    of the returned buffer.
     31  1.1.1.3.2.1  perseant 
     32  1.1.1.3.2.1  perseant    If there's no known instruction to disassemble for GDBARCH (because we
     33  1.1.1.3.2.1  perseant    haven't figured on out, not because no instructions exist) then nullptr
     34  1.1.1.3.2.1  perseant    is returned, and *LEN is set to 0.  */
     35          1.1  christos 
     36  1.1.1.3.2.1  perseant static const gdb_byte *
     37  1.1.1.3.2.1  perseant get_test_insn (struct gdbarch *gdbarch, size_t *len)
     38          1.1  christos {
     39  1.1.1.3.2.1  perseant   *len = 0;
     40  1.1.1.3.2.1  perseant   const gdb_byte *insn = nullptr;
     41          1.1  christos 
     42          1.1  christos   switch (gdbarch_bfd_arch_info (gdbarch)->arch)
     43          1.1  christos     {
     44          1.1  christos     case bfd_arch_bfin:
     45          1.1  christos       /* M3.L = 0xe117 */
     46          1.1  christos       static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff};
     47          1.1  christos 
     48          1.1  christos       insn = bfin_insn;
     49  1.1.1.3.2.1  perseant       *len = sizeof (bfin_insn);
     50          1.1  christos       break;
     51          1.1  christos     case bfd_arch_arm:
     52          1.1  christos       /* mov     r0, #0 */
     53          1.1  christos       static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3};
     54          1.1  christos 
     55          1.1  christos       insn = arm_insn;
     56  1.1.1.3.2.1  perseant       *len = sizeof (arm_insn);
     57          1.1  christos       break;
     58          1.1  christos     case bfd_arch_ia64:
     59  1.1.1.3.2.1  perseant       /* We get:
     60  1.1.1.3.2.1  perseant 	 internal-error: gdbarch_sw_breakpoint_from_kind:
     61  1.1.1.3.2.1  perseant 	 Assertion `gdbarch->sw_breakpoint_from_kind != NULL' failed.  */
     62  1.1.1.3.2.1  perseant       return insn;
     63          1.1  christos     case bfd_arch_mep:
     64  1.1.1.3.2.1  perseant       /* Disassembles as '*unknown*' insn, then len self-check fails.  */
     65  1.1.1.3.2.1  perseant       return insn;
     66          1.1  christos     case bfd_arch_mips:
     67  1.1.1.3.2.1  perseant       if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mips16)
     68  1.1.1.3.2.1  perseant 	/* Disassembles insn, but len self-check fails.  */
     69  1.1.1.3.2.1  perseant 	return insn;
     70  1.1.1.3.2.1  perseant       goto generic_case;
     71          1.1  christos     case bfd_arch_tic6x:
     72  1.1.1.3.2.1  perseant       /* Disassembles as '<undefined instruction 0x56454314>' insn, but len
     73  1.1.1.3.2.1  perseant 	 self-check passes, so let's allow it.  */
     74  1.1.1.3.2.1  perseant       goto generic_case;
     75          1.1  christos     case bfd_arch_xtensa:
     76  1.1.1.3.2.1  perseant       /* Disassembles insn, but len self-check fails.  */
     77  1.1.1.3.2.1  perseant       return insn;
     78  1.1.1.3.2.1  perseant     case bfd_arch_or1k:
     79  1.1.1.3.2.1  perseant       /* Disassembles as '*unknown*' insn, but len self-check passes, so let's
     80  1.1.1.3.2.1  perseant 	 allow it.  */
     81  1.1.1.3.2.1  perseant       goto generic_case;
     82          1.1  christos     case bfd_arch_s390:
     83          1.1  christos       /* nopr %r7 */
     84          1.1  christos       static const gdb_byte s390_insn[] = {0x07, 0x07};
     85          1.1  christos 
     86          1.1  christos       insn = s390_insn;
     87  1.1.1.3.2.1  perseant       *len = sizeof (s390_insn);
     88          1.1  christos       break;
     89          1.1  christos     case bfd_arch_xstormy16:
     90          1.1  christos       /* nop */
     91          1.1  christos       static const gdb_byte xstormy16_insn[] = {0x0, 0x0};
     92          1.1  christos 
     93          1.1  christos       insn = xstormy16_insn;
     94  1.1.1.3.2.1  perseant       *len = sizeof (xstormy16_insn);
     95          1.1  christos       break;
     96          1.1  christos     case bfd_arch_nios2:
     97          1.1  christos     case bfd_arch_score:
     98      1.1.1.2  christos     case bfd_arch_riscv:
     99      1.1.1.2  christos       /* nios2, riscv, and score need to know the current instruction
    100      1.1.1.2  christos 	 to select breakpoint instruction.  Give the breakpoint
    101      1.1.1.2  christos 	 instruction kind explicitly.  */
    102      1.1.1.2  christos       {
    103      1.1.1.2  christos 	int bplen;
    104      1.1.1.2  christos 	insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, &bplen);
    105  1.1.1.3.2.1  perseant 	*len = bplen;
    106  1.1.1.3.2.1  perseant       }
    107  1.1.1.3.2.1  perseant       break;
    108  1.1.1.3.2.1  perseant     case bfd_arch_arc:
    109  1.1.1.3.2.1  perseant       /* PR 21003 */
    110  1.1.1.3.2.1  perseant       if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601)
    111  1.1.1.3.2.1  perseant 	return insn;
    112  1.1.1.3.2.1  perseant       goto generic_case;
    113  1.1.1.3.2.1  perseant     case bfd_arch_z80:
    114  1.1.1.3.2.1  perseant       {
    115  1.1.1.3.2.1  perseant 	int bplen;
    116  1.1.1.3.2.1  perseant 	insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 0x0008, &bplen);
    117  1.1.1.3.2.1  perseant 	*len = bplen;
    118      1.1.1.2  christos       }
    119          1.1  christos       break;
    120  1.1.1.3.2.1  perseant     case bfd_arch_i386:
    121  1.1.1.3.2.1  perseant       {
    122  1.1.1.3.2.1  perseant 	const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
    123  1.1.1.3.2.1  perseant 	/* The disassembly tests will fail on x86-linux because
    124  1.1.1.3.2.1  perseant 	   opcodes rejects an attempt to disassemble for an arch with
    125  1.1.1.3.2.1  perseant 	   a 64-bit address size when bfd_vma is 32-bit.  */
    126  1.1.1.3.2.1  perseant 	if (info->bits_per_address > sizeof (bfd_vma) * CHAR_BIT)
    127  1.1.1.3.2.1  perseant 	  return insn;
    128  1.1.1.3.2.1  perseant       }
    129  1.1.1.3.2.1  perseant       /* fall through */
    130          1.1  christos     default:
    131  1.1.1.3.2.1  perseant     generic_case:
    132          1.1  christos       {
    133          1.1  christos 	/* Test disassemble breakpoint instruction.  */
    134          1.1  christos 	CORE_ADDR pc = 0;
    135  1.1.1.3.2.1  perseant 	int kind;
    136          1.1  christos 	int bplen;
    137          1.1  christos 
    138  1.1.1.3.2.1  perseant 	struct gdbarch_info info;
    139  1.1.1.3.2.1  perseant 	info.bfd_arch_info = gdbarch_bfd_arch_info (gdbarch);
    140  1.1.1.3.2.1  perseant 
    141  1.1.1.3.2.1  perseant 	enum gdb_osabi it;
    142  1.1.1.3.2.1  perseant 	bool found = false;
    143  1.1.1.3.2.1  perseant 	for (it = GDB_OSABI_UNKNOWN; it != GDB_OSABI_INVALID;
    144  1.1.1.3.2.1  perseant 	     it = static_cast<enum gdb_osabi>(static_cast<int>(it) + 1))
    145  1.1.1.3.2.1  perseant 	  {
    146  1.1.1.3.2.1  perseant 	    if (it == GDB_OSABI_UNKNOWN)
    147  1.1.1.3.2.1  perseant 	      continue;
    148  1.1.1.3.2.1  perseant 
    149  1.1.1.3.2.1  perseant 	    info.osabi = it;
    150  1.1.1.3.2.1  perseant 
    151  1.1.1.3.2.1  perseant 	    if (it != GDB_OSABI_NONE)
    152  1.1.1.3.2.1  perseant 	      {
    153  1.1.1.3.2.1  perseant 		if (!has_gdb_osabi_handler (info))
    154  1.1.1.3.2.1  perseant 		  /* Unsupported.  Skip to prevent warnings like:
    155  1.1.1.3.2.1  perseant 		     A handler for the OS ABI <x> is not built into this
    156  1.1.1.3.2.1  perseant 		     configuration of GDB.  Attempting to continue with the
    157  1.1.1.3.2.1  perseant 		     default <y> settings.  */
    158  1.1.1.3.2.1  perseant 		  continue;
    159  1.1.1.3.2.1  perseant 	      }
    160  1.1.1.3.2.1  perseant 
    161  1.1.1.3.2.1  perseant 	    gdbarch = gdbarch_find_by_info (info);
    162  1.1.1.3.2.1  perseant 	    SELF_CHECK (gdbarch != NULL);
    163  1.1.1.3.2.1  perseant 
    164  1.1.1.3.2.1  perseant 	    try
    165  1.1.1.3.2.1  perseant 	      {
    166  1.1.1.3.2.1  perseant 		kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc);
    167  1.1.1.3.2.1  perseant 		insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen);
    168  1.1.1.3.2.1  perseant 	      }
    169  1.1.1.3.2.1  perseant 	    catch (...)
    170  1.1.1.3.2.1  perseant 	      {
    171  1.1.1.3.2.1  perseant 		continue;
    172  1.1.1.3.2.1  perseant 	      }
    173  1.1.1.3.2.1  perseant 	    found = true;
    174  1.1.1.3.2.1  perseant 	    break;
    175  1.1.1.3.2.1  perseant 	  }
    176  1.1.1.3.2.1  perseant 
    177  1.1.1.3.2.1  perseant 	/* Assert that we have found an instruction to disassemble.  */
    178  1.1.1.3.2.1  perseant 	SELF_CHECK (found);
    179          1.1  christos 
    180  1.1.1.3.2.1  perseant 	*len = bplen;
    181          1.1  christos 	break;
    182          1.1  christos       }
    183          1.1  christos     }
    184  1.1.1.3.2.1  perseant   SELF_CHECK (*len > 0);
    185  1.1.1.3.2.1  perseant 
    186  1.1.1.3.2.1  perseant   return insn;
    187  1.1.1.3.2.1  perseant }
    188  1.1.1.3.2.1  perseant 
    189  1.1.1.3.2.1  perseant /* Test disassembly of one instruction.  */
    190  1.1.1.3.2.1  perseant 
    191  1.1.1.3.2.1  perseant static void
    192  1.1.1.3.2.1  perseant print_one_insn_test (struct gdbarch *gdbarch)
    193  1.1.1.3.2.1  perseant {
    194  1.1.1.3.2.1  perseant   size_t len;
    195  1.1.1.3.2.1  perseant   const gdb_byte *insn = get_test_insn (gdbarch, &len);
    196  1.1.1.3.2.1  perseant 
    197  1.1.1.3.2.1  perseant   if (insn == nullptr)
    198  1.1.1.3.2.1  perseant     return;
    199          1.1  christos 
    200          1.1  christos   /* Test gdb_disassembler for a given gdbarch by reading data from a
    201          1.1  christos      pre-allocated buffer.  If you want to see the disassembled
    202  1.1.1.3.2.1  perseant      instruction printed to gdb_stdout, use maint selftest -verbose.  */
    203          1.1  christos 
    204          1.1  christos   class gdb_disassembler_test : public gdb_disassembler
    205          1.1  christos   {
    206          1.1  christos   public:
    207          1.1  christos 
    208          1.1  christos     explicit gdb_disassembler_test (struct gdbarch *gdbarch,
    209          1.1  christos 				    const gdb_byte *insn,
    210          1.1  christos 				    size_t len)
    211          1.1  christos       : gdb_disassembler (gdbarch,
    212  1.1.1.3.2.1  perseant 			  (run_verbose () ? gdb_stdlog : &null_stream),
    213          1.1  christos 			  gdb_disassembler_test::read_memory),
    214          1.1  christos 	m_insn (insn), m_len (len)
    215          1.1  christos     {
    216          1.1  christos     }
    217          1.1  christos 
    218          1.1  christos     int
    219          1.1  christos     print_insn (CORE_ADDR memaddr)
    220          1.1  christos     {
    221          1.1  christos       int len = gdb_disassembler::print_insn (memaddr);
    222          1.1  christos 
    223  1.1.1.3.2.1  perseant       if (run_verbose ())
    224  1.1.1.3.2.1  perseant 	debug_printf ("\n");
    225          1.1  christos 
    226          1.1  christos       return len;
    227          1.1  christos     }
    228          1.1  christos 
    229          1.1  christos   private:
    230          1.1  christos     /* A buffer contain one instruction.  */
    231          1.1  christos     const gdb_byte *m_insn;
    232          1.1  christos 
    233          1.1  christos     /* Length of the buffer.  */
    234          1.1  christos     size_t m_len;
    235          1.1  christos 
    236          1.1  christos     static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
    237  1.1.1.3.2.1  perseant 			    unsigned int len,
    238  1.1.1.3.2.1  perseant 			    struct disassemble_info *info) noexcept
    239          1.1  christos     {
    240          1.1  christos       gdb_disassembler_test *self
    241          1.1  christos 	= static_cast<gdb_disassembler_test *>(info->application_data);
    242          1.1  christos 
    243          1.1  christos       /* The disassembler in opcodes may read more data than one
    244          1.1  christos 	 instruction.  Supply infinite consecutive copies
    245          1.1  christos 	 of the same instruction.  */
    246          1.1  christos       for (size_t i = 0; i < len; i++)
    247          1.1  christos 	myaddr[i] = self->m_insn[(memaddr + i) % self->m_len];
    248          1.1  christos 
    249          1.1  christos       return 0;
    250          1.1  christos     }
    251          1.1  christos   };
    252          1.1  christos 
    253          1.1  christos   gdb_disassembler_test di (gdbarch, insn, len);
    254          1.1  christos 
    255          1.1  christos   SELF_CHECK (di.print_insn (0) == len);
    256          1.1  christos }
    257          1.1  christos 
    258  1.1.1.3.2.1  perseant /* Test the gdb_buffered_insn_length function.  */
    259  1.1.1.3.2.1  perseant 
    260  1.1.1.3.2.1  perseant static void
    261  1.1.1.3.2.1  perseant buffered_insn_length_test (struct gdbarch *gdbarch)
    262  1.1.1.3.2.1  perseant {
    263  1.1.1.3.2.1  perseant   size_t buf_len;
    264  1.1.1.3.2.1  perseant   const gdb_byte *insn = get_test_insn (gdbarch, &buf_len);
    265  1.1.1.3.2.1  perseant 
    266  1.1.1.3.2.1  perseant   if (insn == nullptr)
    267  1.1.1.3.2.1  perseant     return;
    268  1.1.1.3.2.1  perseant 
    269  1.1.1.3.2.1  perseant   /* The tic6x architecture is VLIW.  Disassembling requires that the
    270  1.1.1.3.2.1  perseant      entire instruction bundle be available.  However, the buffer we got
    271  1.1.1.3.2.1  perseant      back from get_test_insn only contains a single instruction, which is
    272  1.1.1.3.2.1  perseant      just part of an instruction bundle.  As a result, the disassemble will
    273  1.1.1.3.2.1  perseant      fail.  To avoid this, skip tic6x tests now.  */
    274  1.1.1.3.2.1  perseant   if (gdbarch_bfd_arch_info (gdbarch)->arch == bfd_arch_tic6x)
    275  1.1.1.3.2.1  perseant     return;
    276  1.1.1.3.2.1  perseant 
    277  1.1.1.3.2.1  perseant   CORE_ADDR insn_address = 0;
    278  1.1.1.3.2.1  perseant   int calculated_len = gdb_buffered_insn_length (gdbarch, insn, buf_len,
    279  1.1.1.3.2.1  perseant 						 insn_address);
    280  1.1.1.3.2.1  perseant 
    281  1.1.1.3.2.1  perseant   SELF_CHECK (calculated_len == buf_len);
    282  1.1.1.3.2.1  perseant }
    283  1.1.1.3.2.1  perseant 
    284          1.1  christos /* Test disassembly on memory error.  */
    285          1.1  christos 
    286          1.1  christos static void
    287          1.1  christos memory_error_test (struct gdbarch *gdbarch)
    288          1.1  christos {
    289          1.1  christos   class gdb_disassembler_test : public gdb_disassembler
    290          1.1  christos   {
    291          1.1  christos   public:
    292          1.1  christos     gdb_disassembler_test (struct gdbarch *gdbarch)
    293          1.1  christos       : gdb_disassembler (gdbarch, &null_stream,
    294          1.1  christos 			  gdb_disassembler_test::read_memory)
    295          1.1  christos     {
    296          1.1  christos     }
    297          1.1  christos 
    298          1.1  christos     static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
    299          1.1  christos 			    unsigned int len,
    300  1.1.1.3.2.1  perseant 			    struct disassemble_info *info) noexcept
    301          1.1  christos     {
    302          1.1  christos       /* Always return an error.  */
    303          1.1  christos       return -1;
    304          1.1  christos     }
    305          1.1  christos   };
    306          1.1  christos 
    307  1.1.1.3.2.1  perseant   if (gdbarch_bfd_arch_info (gdbarch)->arch == bfd_arch_i386)
    308  1.1.1.3.2.1  perseant     {
    309  1.1.1.3.2.1  perseant       const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
    310  1.1.1.3.2.1  perseant       /* This test will fail on x86-linux because opcodes rejects an
    311  1.1.1.3.2.1  perseant 	 attempt to disassemble for an arch with a 64-bit address size
    312  1.1.1.3.2.1  perseant 	 when bfd_vma is 32-bit.  */
    313  1.1.1.3.2.1  perseant       if (info->bits_per_address > sizeof (bfd_vma) * CHAR_BIT)
    314  1.1.1.3.2.1  perseant 	return;
    315  1.1.1.3.2.1  perseant     }
    316  1.1.1.3.2.1  perseant 
    317          1.1  christos   gdb_disassembler_test di (gdbarch);
    318          1.1  christos   bool saw_memory_error = false;
    319          1.1  christos 
    320      1.1.1.3  christos   try
    321          1.1  christos     {
    322          1.1  christos       di.print_insn (0);
    323          1.1  christos     }
    324      1.1.1.3  christos   catch (const gdb_exception_error &ex)
    325          1.1  christos     {
    326          1.1  christos       if (ex.error == MEMORY_ERROR)
    327          1.1  christos 	saw_memory_error = true;
    328          1.1  christos     }
    329          1.1  christos 
    330          1.1  christos   /* Expect MEMORY_ERROR.  */
    331          1.1  christos   SELF_CHECK (saw_memory_error);
    332          1.1  christos }
    333          1.1  christos 
    334          1.1  christos } // namespace selftests
    335          1.1  christos 
    336      1.1.1.3  christos void _initialize_disasm_selftests ();
    337          1.1  christos void
    338      1.1.1.3  christos _initialize_disasm_selftests ()
    339          1.1  christos {
    340      1.1.1.2  christos   selftests::register_test_foreach_arch ("print_one_insn",
    341      1.1.1.2  christos 					 selftests::print_one_insn_test);
    342      1.1.1.2  christos   selftests::register_test_foreach_arch ("memory_error",
    343      1.1.1.2  christos 					 selftests::memory_error_test);
    344  1.1.1.3.2.1  perseant   selftests::register_test_foreach_arch ("buffered_insn_length",
    345  1.1.1.3.2.1  perseant 					 selftests::buffered_insn_length_test);
    346          1.1  christos }
    347