1/* Self tests for disassembler for GDB, the GNU debugger. 2 3 Copyright (C) 2017-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "disasm.h" 22#include "gdbsupport/selftest.h" 23#include "selftest-arch.h" 24#include "gdbarch.h" 25 26namespace selftests { 27 28/* Test disassembly of one instruction. */ 29 30static void 31print_one_insn_test (struct gdbarch *gdbarch) 32{ 33 size_t len = 0; 34 const gdb_byte *insn = NULL; 35 36 switch (gdbarch_bfd_arch_info (gdbarch)->arch) 37 { 38 case bfd_arch_bfin: 39 /* M3.L = 0xe117 */ 40 static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff}; 41 42 insn = bfin_insn; 43 len = sizeof (bfin_insn); 44 break; 45 case bfd_arch_arm: 46 /* mov r0, #0 */ 47 static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3}; 48 49 insn = arm_insn; 50 len = sizeof (arm_insn); 51 break; 52 case bfd_arch_ia64: 53 case bfd_arch_mep: 54 case bfd_arch_mips: 55 case bfd_arch_tic6x: 56 case bfd_arch_xtensa: 57 return; 58 case bfd_arch_s390: 59 /* nopr %r7 */ 60 static const gdb_byte s390_insn[] = {0x07, 0x07}; 61 62 insn = s390_insn; 63 len = sizeof (s390_insn); 64 break; 65 case bfd_arch_xstormy16: 66 /* nop */ 67 static const gdb_byte xstormy16_insn[] = {0x0, 0x0}; 68 69 insn = xstormy16_insn; 70 len = sizeof (xstormy16_insn); 71 break; 72 case bfd_arch_arc: 73 /* PR 21003 */ 74 if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601) 75 return; 76 /* fall through */ 77 case bfd_arch_nios2: 78 case bfd_arch_score: 79 case bfd_arch_riscv: 80 /* nios2, riscv, and score need to know the current instruction 81 to select breakpoint instruction. Give the breakpoint 82 instruction kind explicitly. */ 83 { 84 int bplen; 85 insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, &bplen); 86 len = bplen; 87 } 88 break; 89 default: 90 { 91 /* Test disassemble breakpoint instruction. */ 92 CORE_ADDR pc = 0; 93 int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc); 94 int bplen; 95 96 insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen); 97 len = bplen; 98 99 break; 100 } 101 } 102 SELF_CHECK (len > 0); 103 104 /* Test gdb_disassembler for a given gdbarch by reading data from a 105 pre-allocated buffer. If you want to see the disassembled 106 instruction printed to gdb_stdout, set verbose to true. */ 107 static const bool verbose = false; 108 109 class gdb_disassembler_test : public gdb_disassembler 110 { 111 public: 112 113 explicit gdb_disassembler_test (struct gdbarch *gdbarch, 114 const gdb_byte *insn, 115 size_t len) 116 : gdb_disassembler (gdbarch, 117 (verbose ? gdb_stdout : &null_stream), 118 gdb_disassembler_test::read_memory), 119 m_insn (insn), m_len (len) 120 { 121 } 122 123 int 124 print_insn (CORE_ADDR memaddr) 125 { 126 if (verbose) 127 { 128 fprintf_unfiltered (stream (), "%s ", 129 gdbarch_bfd_arch_info (arch ())->arch_name); 130 } 131 132 int len = gdb_disassembler::print_insn (memaddr); 133 134 if (verbose) 135 fprintf_unfiltered (stream (), "\n"); 136 137 return len; 138 } 139 140 private: 141 /* A buffer contain one instruction. */ 142 const gdb_byte *m_insn; 143 144 /* Length of the buffer. */ 145 size_t m_len; 146 147 static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, 148 unsigned int len, struct disassemble_info *info) 149 { 150 gdb_disassembler_test *self 151 = static_cast<gdb_disassembler_test *>(info->application_data); 152 153 /* The disassembler in opcodes may read more data than one 154 instruction. Supply infinite consecutive copies 155 of the same instruction. */ 156 for (size_t i = 0; i < len; i++) 157 myaddr[i] = self->m_insn[(memaddr + i) % self->m_len]; 158 159 return 0; 160 } 161 }; 162 163 gdb_disassembler_test di (gdbarch, insn, len); 164 165 SELF_CHECK (di.print_insn (0) == len); 166} 167 168/* Test disassembly on memory error. */ 169 170static void 171memory_error_test (struct gdbarch *gdbarch) 172{ 173 class gdb_disassembler_test : public gdb_disassembler 174 { 175 public: 176 gdb_disassembler_test (struct gdbarch *gdbarch) 177 : gdb_disassembler (gdbarch, &null_stream, 178 gdb_disassembler_test::read_memory) 179 { 180 } 181 182 static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, 183 unsigned int len, 184 struct disassemble_info *info) 185 { 186 /* Always return an error. */ 187 return -1; 188 } 189 }; 190 191 gdb_disassembler_test di (gdbarch); 192 bool saw_memory_error = false; 193 194 try 195 { 196 di.print_insn (0); 197 } 198 catch (const gdb_exception_error &ex) 199 { 200 if (ex.error == MEMORY_ERROR) 201 saw_memory_error = true; 202 } 203 204 /* Expect MEMORY_ERROR. */ 205 SELF_CHECK (saw_memory_error); 206} 207 208} // namespace selftests 209 210void _initialize_disasm_selftests (); 211void 212_initialize_disasm_selftests () 213{ 214 selftests::register_test_foreach_arch ("print_one_insn", 215 selftests::print_one_insn_test); 216 selftests::register_test_foreach_arch ("memory_error", 217 selftests::memory_error_test); 218} 219