diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/Makefile.in | 5 | ||||
-rw-r--r-- | gdb/disasm-selftests.c | 179 | ||||
-rw-r--r-- | gdb/selftest-arch.c | 102 | ||||
-rw-r--r-- | gdb/selftest-arch.h | 27 |
5 files changed, 322 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 246d09e..422697d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2017-01-26 Yao Qi <yao.qi@linaro.org> + * Makefile.in (SFILES): Add disasm-selftests.c and + selftest-arch.c. + (COMMON_OBS): Add disasm-selftests.o and selftest-arch.o. + * disasm-selftests.c: New file. + * selftest-arch.c: New file. + * selftest-arch.h: New file. + +2017-01-26 Yao Qi <yao.qi@linaro.org> + * mep-tdep.c (mep_gdb_print_insn): Set info->arch to bfd_arch_mep. Don't return 0 if section is not found. Call print_insn_mep. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 3ce7d69..e0fe442 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1039,6 +1039,7 @@ SFILES = \ dfp.c \ dictionary.c \ disasm.c \ + disasm-selftests.c \ doublest.c \ dtrace-probe.c \ dummy-frame.c \ @@ -1140,6 +1141,7 @@ SFILES = \ rust-exp.y \ rust-lang.c \ selftest.c \ + selftest-arch.c \ sentinel-frame.c \ ser-base.c \ ser-event.c \ @@ -1396,6 +1398,7 @@ HFILES_NO_SRCDIR = \ rs6000-tdep.h \ s390-linux-tdep.h \ score-tdep.h \ + selftest-arch.h \ sentinel-frame.h \ ser-base.h \ ser-event.h \ @@ -1643,6 +1646,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ dfp.o \ dictionary.o \ disasm.o \ + disasm-selftests.o \ doublest.o \ dummy-frame.o \ dwarf2-frame.o \ @@ -1744,6 +1748,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ run-time-clock.o \ rust-lang.o \ selftest.o \ + selftest-arch.o \ sentinel-frame.o \ ser-event.o \ serial.o \ diff --git a/gdb/disasm-selftests.c b/gdb/disasm-selftests.c new file mode 100644 index 0000000..3d68abd --- /dev/null +++ b/gdb/disasm-selftests.c @@ -0,0 +1,179 @@ +/* Self tests for disassembler for GDB, the GNU debugger. + + Copyright (C) 2017 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "disasm.h" + +#if GDB_SELF_TEST +#include "selftest.h" +#include "selftest-arch.h" + +namespace selftests { + +/* Test disassembly of one instruction. */ + +static void +print_one_insn_test (struct gdbarch *gdbarch) +{ + size_t len = 0; + const gdb_byte *insn = NULL; + + switch (gdbarch_bfd_arch_info (gdbarch)->arch) + { + case bfd_arch_bfin: + /* M3.L = 0xe117 */ + static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff}; + + insn = bfin_insn; + len = sizeof (bfin_insn); + break; + case bfd_arch_arm: + /* mov r0, #0 */ + static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3}; + + insn = arm_insn; + len = sizeof (arm_insn); + break; + case bfd_arch_ia64: + case bfd_arch_mep: + case bfd_arch_mips: + case bfd_arch_tic6x: + case bfd_arch_xtensa: + return; + case bfd_arch_s390: + /* nopr %r7 */ + static const gdb_byte s390_insn[] = {0x07, 0x07}; + + insn = s390_insn; + len = sizeof (s390_insn); + break; + case bfd_arch_xstormy16: + /* nop */ + static const gdb_byte xstormy16_insn[] = {0x0, 0x0}; + + insn = xstormy16_insn; + len = sizeof (xstormy16_insn); + break; + case bfd_arch_arc: + /* PR 21003 */ + if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601) + return; + /* fall through */ + case bfd_arch_nios2: + case bfd_arch_score: + /* nios2 and score need to know the current instruction to select + breakpoint instruction. Give the breakpoint instruction kind + explicitly. */ + int bplen; + insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, &bplen); + len = bplen; + break; + default: + { + /* Test disassemble breakpoint instruction. */ + CORE_ADDR pc = 0; + int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc); + int bplen; + + insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen); + len = bplen; + + break; + } + } + SELF_CHECK (len > 0); + + /* Test gdb_disassembler for a given gdbarch by reading data from a + pre-allocated buffer. If you want to see the disassembled + instruction printed to gdb_stdout, set verbose to true. */ + + class gdb_disassembler_test : public gdb_disassembler + { + public: + + const bool verbose = false; + + explicit gdb_disassembler_test (struct gdbarch *gdbarch, + const gdb_byte *insn, + size_t len) + : gdb_disassembler (gdbarch, + (verbose ? gdb_stdout : null_stream ()), + gdb_disassembler_test::read_memory), + m_insn (insn), m_len (len) + { + } + + int + print_insn (CORE_ADDR memaddr) + { + if (verbose) + { + fprintf_unfiltered (stream (), "%s ", + gdbarch_bfd_arch_info (arch ())->arch_name); + } + + int len = gdb_disassembler::print_insn (memaddr); + + if (verbose) + fprintf_unfiltered (stream (), "\n"); + + return len; + } + + private: + /* A buffer contain one instruction. */ + const gdb_byte *m_insn; + + /* Length of the buffer. */ + size_t m_len; + + static int read_memory (bfd_vma memaddr, gdb_byte *myaddr, + unsigned int len, struct disassemble_info *info) + { + gdb_disassembler_test *self + = static_cast<gdb_disassembler_test *>(info->application_data); + + /* The disassembler in opcodes may read more data than one + instruction. Supply infinite consecutive copies + of the same instruction. */ + for (size_t i = 0; i < len; i++) + myaddr[i] = self->m_insn[(memaddr + i) % self->m_len]; + + return 0; + } + }; + + gdb_disassembler_test di (gdbarch, insn, len); + + SELF_CHECK (di.print_insn (0) == len); +} + +} // namespace selftests +#endif /* GDB_SELF_TEST */ + +/* Suppress warning from -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_disasm_selftests; + +void +_initialize_disasm_selftests (void) +{ +#if GDB_SELF_TEST + register_self_test_foreach_arch (selftests::print_one_insn_test); +#endif +} diff --git a/gdb/selftest-arch.c b/gdb/selftest-arch.c new file mode 100644 index 0000000..cbc8c50 --- /dev/null +++ b/gdb/selftest-arch.c @@ -0,0 +1,102 @@ +/* GDB self-test for each gdbarch. + Copyright (C) 2017 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" + +#if GDB_SELF_TEST +#include "selftest.h" +#include "selftest-arch.h" +#include "arch-utils.h" + +static std::vector<self_test_foreach_arch_function *> gdbarch_tests; + +void +register_self_test_foreach_arch (self_test_foreach_arch_function *function) +{ + gdbarch_tests.push_back (function); +} + +namespace selftests { + +static void +tests_with_arch () +{ + int failed = 0; + + for (const auto &f : gdbarch_tests) + { + const char **arches = gdbarch_printable_names (); + + for (int i = 0; arches[i] != NULL; i++) + { + if (strcmp ("fr300", arches[i]) == 0) + { + /* PR 20946 */ + continue; + } + else if (strcmp ("powerpc:EC603e", arches[i]) == 0 + || strcmp ("powerpc:e500mc", arches[i]) == 0 + || strcmp ("powerpc:e500mc64", arches[i]) == 0 + || strcmp ("powerpc:titan", arches[i]) == 0 + || strcmp ("powerpc:vle", arches[i]) == 0 + || strcmp ("powerpc:e5500", arches[i]) == 0 + || strcmp ("powerpc:e6500", arches[i]) == 0) + { + /* PR 19797 */ + continue; + } + + QUIT; + + TRY + { + struct gdbarch_info info; + + gdbarch_info_init (&info); + info.bfd_arch_info = bfd_scan_arch (arches[i]); + + struct gdbarch *gdbarch = gdbarch_find_by_info (info); + SELF_CHECK (gdbarch != NULL); + f (gdbarch); + } + CATCH (ex, RETURN_MASK_ERROR) + { + ++failed; + exception_fprintf (gdb_stderr, ex, + _("Self test failed: arch %s: "), arches[i]); + } + END_CATCH + } + } + + SELF_CHECK (failed == 0); +} + +} // namespace selftests +#endif /* GDB_SELF_TEST */ + +/* Suppress warning from -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_selftests_foreach_arch; + +void +_initialize_selftests_foreach_arch () +{ +#if GDB_SELF_TEST + register_self_test (selftests::tests_with_arch); +#endif +} diff --git a/gdb/selftest-arch.h b/gdb/selftest-arch.h new file mode 100644 index 0000000..d1725cd --- /dev/null +++ b/gdb/selftest-arch.h @@ -0,0 +1,27 @@ +/* GDB self-test for each gdbarch. + Copyright (C) 2017 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SELFTEST_ARCH_H +#define SELFTEST_ARCH_H + +typedef void self_test_foreach_arch_function (struct gdbarch *); + +extern void + register_self_test_foreach_arch (self_test_foreach_arch_function *function); + +#endif /* SELFTEST_ARCH_H */ |