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