1 /* Self tests for disassembler for GDB, the GNU debugger. 2 3 Copyright (C) 2017 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 23 #if GDB_SELF_TEST 24 #include "selftest.h" 25 #include "selftest-arch.h" 26 27 namespace selftests { 28 29 /* Test disassembly of one instruction. */ 30 31 static void 32 print_one_insn_test (struct gdbarch *gdbarch) 33 { 34 size_t len = 0; 35 const gdb_byte *insn = NULL; 36 37 switch (gdbarch_bfd_arch_info (gdbarch)->arch) 38 { 39 case bfd_arch_bfin: 40 /* M3.L = 0xe117 */ 41 static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff}; 42 43 insn = bfin_insn; 44 len = sizeof (bfin_insn); 45 break; 46 case bfd_arch_arm: 47 /* mov r0, #0 */ 48 static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3}; 49 50 insn = arm_insn; 51 len = sizeof (arm_insn); 52 break; 53 case bfd_arch_ia64: 54 case bfd_arch_mep: 55 case bfd_arch_mips: 56 case bfd_arch_tic6x: 57 case bfd_arch_xtensa: 58 return; 59 case bfd_arch_s390: 60 /* nopr %r7 */ 61 static const gdb_byte s390_insn[] = {0x07, 0x07}; 62 63 insn = s390_insn; 64 len = sizeof (s390_insn); 65 break; 66 case bfd_arch_xstormy16: 67 /* nop */ 68 static const gdb_byte xstormy16_insn[] = {0x0, 0x0}; 69 70 insn = xstormy16_insn; 71 len = sizeof (xstormy16_insn); 72 break; 73 case bfd_arch_arc: 74 /* PR 21003 */ 75 if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601) 76 return; 77 /* fall through */ 78 case bfd_arch_nios2: 79 case bfd_arch_score: 80 /* nios2 and score need to know the current instruction to select 81 breakpoint instruction. Give the breakpoint instruction kind 82 explicitly. */ 83 int bplen; 84 insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, &bplen); 85 len = bplen; 86 break; 87 default: 88 { 89 /* Test disassemble breakpoint instruction. */ 90 CORE_ADDR pc = 0; 91 int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc); 92 int bplen; 93 94 insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen); 95 len = bplen; 96 97 break; 98 } 99 } 100 SELF_CHECK (len > 0); 101 102 /* Test gdb_disassembler for a given gdbarch by reading data from a 103 pre-allocated buffer. If you want to see the disassembled 104 instruction printed to gdb_stdout, set verbose to true. */ 105 static const bool verbose = false; 106 107 class gdb_disassembler_test : public gdb_disassembler 108 { 109 public: 110 111 explicit gdb_disassembler_test (struct gdbarch *gdbarch, 112 const gdb_byte *insn, 113 size_t len) 114 : gdb_disassembler (gdbarch, 115 (verbose ? gdb_stdout : &null_stream), 116 gdb_disassembler_test::read_memory), 117 m_insn (insn), m_len (len) 118 { 119 } 120 121 int 122 print_insn (CORE_ADDR memaddr) 123 { 124 if (verbose) 125 { 126 fprintf_unfiltered (stream (), "%s ", 127 gdbarch_bfd_arch_info (arch ())->arch_name); 128 } 129 130 int len = gdb_disassembler::print_insn (memaddr); 131 132 if (verbose) 133 fprintf_unfiltered (stream (), "\n"); 134 135 return len; 136 } 137 138 private: 139 /* A buffer contain one instruction. */ 140 const gdb_byte *m_insn; 141 142 /* Length of the buffer. */ 143 size_t m_len; 144 145 static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, 146 unsigned int len, struct disassemble_info *info) 147 { 148 gdb_disassembler_test *self 149 = static_cast<gdb_disassembler_test *>(info->application_data); 150 151 /* The disassembler in opcodes may read more data than one 152 instruction. Supply infinite consecutive copies 153 of the same instruction. */ 154 for (size_t i = 0; i < len; i++) 155 myaddr[i] = self->m_insn[(memaddr + i) % self->m_len]; 156 157 return 0; 158 } 159 }; 160 161 gdb_disassembler_test di (gdbarch, insn, len); 162 163 SELF_CHECK (di.print_insn (0) == len); 164 } 165 166 /* Test disassembly on memory error. */ 167 168 static void 169 memory_error_test (struct gdbarch *gdbarch) 170 { 171 class gdb_disassembler_test : public gdb_disassembler 172 { 173 public: 174 gdb_disassembler_test (struct gdbarch *gdbarch) 175 : gdb_disassembler (gdbarch, &null_stream, 176 gdb_disassembler_test::read_memory) 177 { 178 } 179 180 static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, 181 unsigned int len, 182 struct disassemble_info *info) 183 { 184 /* Always return an error. */ 185 return -1; 186 } 187 }; 188 189 gdb_disassembler_test di (gdbarch); 190 bool saw_memory_error = false; 191 192 TRY 193 { 194 di.print_insn (0); 195 } 196 CATCH (ex, RETURN_MASK_ERROR) 197 { 198 if (ex.error == MEMORY_ERROR) 199 saw_memory_error = true; 200 } 201 END_CATCH 202 203 /* Expect MEMORY_ERROR. */ 204 SELF_CHECK (saw_memory_error); 205 } 206 207 } // namespace selftests 208 #endif /* GDB_SELF_TEST */ 209 210 /* Suppress warning from -Wmissing-prototypes. */ 211 extern initialize_file_ftype _initialize_disasm_selftests; 212 213 void 214 _initialize_disasm_selftests (void) 215 { 216 #if GDB_SELF_TEST 217 register_self_test_foreach_arch (selftests::print_one_insn_test); 218 register_self_test_foreach_arch (selftests::memory_error_test); 219 #endif 220 } 221