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