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