From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id yK0QLgfWkF+nKAAAWB0awg (envelope-from ) for ; Wed, 21 Oct 2020 20:44:55 -0400 Received: by simark.ca (Postfix, from userid 112) id B897E1EFC3; Wed, 21 Oct 2020 20:44:55 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 10BFA1E58E for ; Wed, 21 Oct 2020 20:44:55 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 937953857C7F; Thu, 22 Oct 2020 00:44:54 +0000 (GMT) Received: from mail-gw01.fsdata.se (proxy01.fsdata.se [89.221.252.211]) by sourceware.org (Postfix) with ESMTPS id 5618E3857C7F for ; Thu, 22 Oct 2020 00:44:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5618E3857C7F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=hederstierna.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=fredrik@hederstierna.com Received: from legion.sec.intra (81.236.17.7) by DAG06.HMC.local (192.168.46.16) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Thu, 22 Oct 2020 02:44:46 +0200 From: Fredrik Hederstierna To: , , , , Subject: [PATCH v3][PR gdb/14383]: Support for corefiles for arm-none-eabi target. Date: Thu, 22 Oct 2020 02:44:01 +0200 Message-ID: <20201022004401.28903-2-fredrik@hederstierna.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201022004401.28903-1-fredrik@hederstierna.com> References: <20201022004401.28903-1-fredrik@hederstierna.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [81.236.17.7] X-ClientProxiedBy: PROXY03.HMC.local (192.168.46.53) To DAG06.HMC.local (192.168.46.16) X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fredrikhederstierna Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" From: fredrikhederstierna --- gdb/Makefile.in | 6 + gdb/arm-none-tdep.c | 184 +++++++++++++++++++++++++++++ gdb/arm-none-tdep.h | 42 +++++++ gdb/arm-tdep.c | 7 ++ gdb/configure.tgt | 3 +- gdb/none-tdep.c | 276 ++++++++++++++++++++++++++++++++++++++++++++ gdb/none-tdep.h | 30 +++++ 7 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 gdb/arm-none-tdep.c create mode 100644 gdb/arm-none-tdep.h create mode 100644 gdb/none-tdep.c create mode 100644 gdb/none-tdep.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 8a160896e2..61a13312ce 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -721,6 +721,7 @@ ALL_TARGET_OBS = \ arm-fbsd-tdep.o \ arm-linux-tdep.o \ arm-netbsd-tdep.o \ + arm-none-tdep.o \ arm-obsd-tdep.o \ arm-pikeos-tdep.o \ arm-symbian-tdep.o \ @@ -788,6 +789,7 @@ ALL_TARGET_OBS = \ nds32-tdep.o \ nios2-linux-tdep.o \ nios2-tdep.o \ + none-tdep.o \ nto-tdep.o \ obsd-tdep.o \ or1k-linux-tdep.o \ @@ -1225,6 +1227,7 @@ HFILES_NO_SRCDIR = \ arch-utils.h \ arm-linux-tdep.h \ arm-netbsd-tdep.h \ + arm-none-tdep.h \ arm-tdep.h \ async-event.h \ auto-load.h \ @@ -1350,6 +1353,7 @@ HFILES_NO_SRCDIR = \ netbsd-tdep.h \ nds32-tdep.h \ nios2-tdep.h \ + none-tdep.h \ nto-tdep.h \ objc-lang.h \ objfiles.h \ @@ -2152,6 +2156,7 @@ ALLDEPFILES = \ arm-linux-tdep.c \ arm-netbsd-nat.c \ arm-netbsd-tdep.c \ + arm-none-tdep.c \ arm-obsd-tdep.c \ arm-symbian-tdep.c \ arm-tdep.c \ @@ -2238,6 +2243,7 @@ ALLDEPFILES = \ nds32-tdep.c \ nios2-linux-tdep.c \ nios2-tdep.c \ + none-tdep.c \ obsd-nat.c \ obsd-tdep.c \ posix-hdep.c \ diff --git a/gdb/arm-none-tdep.c b/gdb/arm-none-tdep.c new file mode 100644 index 0000000000..c355feff2f --- /dev/null +++ b/gdb/arm-none-tdep.c @@ -0,0 +1,184 @@ +/* none on ARM target support. + + Copyright (C) 2020 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 . */ + +#include "defs.h" +#include "target.h" +#include "value.h" +#include "gdbtypes.h" +#include "gdbcore.h" +#include "frame.h" +#include "regcache.h" +#include "solib-svr4.h" +#include "osabi.h" +#include "regset.h" +#include "trad-frame.h" +#include "tramp-frame.h" +#include "breakpoint.h" +#include "auxv.h" + +#include "aarch32-tdep.h" +#include "arch/arm.h" +#include "arm-tdep.h" +#include "arm-none-tdep.h" +#include "glibc-tdep.h" +#include "arch-utils.h" +#include "inferior.h" +#include "gdbthread.h" +#include "symfile.h" + +#include "cli/cli-utils.h" +#include "stap-probe.h" +#include "parser-defs.h" +#include "user-regs.h" +#include + +#include "elf-bfd.h" +#include "coff/internal.h" +#include "elf/arm.h" +#include "elf/common.h" + +/* The ARM none register setup is based on the ARM GNU/Linux design. */ + +static void +arm_none_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs_buf, size_t len) +{ + struct gdbarch *gdbarch = regcache->arch (); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + const gdb_byte *gregs = (const gdb_byte *) gregs_buf; + int regno; + CORE_ADDR reg_pc; + gdb_byte pc_buf[ARM_INT_REGISTER_SIZE]; + + for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno); + + if (regnum == ARM_PS_REGNUM || regnum == -1) + { + if (arm_apcs_32) + regcache->raw_supply (ARM_PS_REGNUM, + gregs + ARM_INT_REGISTER_SIZE * ARM_NONE_CPSR_GREGNUM); + else + regcache->raw_supply (ARM_PS_REGNUM, + gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); + } + + if (regnum == ARM_PC_REGNUM || regnum == -1) + { + reg_pc = extract_unsigned_integer ( + gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM, + ARM_INT_REGISTER_SIZE, byte_order); + reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc); + store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order, + reg_pc); + regcache->raw_supply (ARM_PC_REGNUM, pc_buf); + } +} + +static void +arm_none_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs_buf, size_t len) +{ + gdb_byte *gregs = (gdb_byte *) gregs_buf; + int regno; + + for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache->raw_collect (regno, + gregs + ARM_INT_REGISTER_SIZE * regno); + + if (regnum == ARM_PS_REGNUM || regnum == -1) + { + if (arm_apcs_32) + regcache->raw_collect (ARM_PS_REGNUM, + gregs + ARM_INT_REGISTER_SIZE * ARM_NONE_CPSR_GREGNUM); + else + regcache->raw_collect (ARM_PS_REGNUM, + gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); + } + + if (regnum == ARM_PC_REGNUM || regnum == -1) + regcache->raw_collect (ARM_PC_REGNUM, + gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM); +} + +/* Support VFP register format. */ + +static void +arm_none_supply_vfp (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *regs_buf, size_t len) +{ + const gdb_byte *regs = (const gdb_byte *) regs_buf; + int regno; + + if (regnum == ARM_FPSCR_REGNUM || regnum == -1) + regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8); +} + +static void +arm_none_collect_vfp (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *regs_buf, size_t len) +{ + gdb_byte *regs = (gdb_byte *) regs_buf; + int regno; + + if (regnum == ARM_FPSCR_REGNUM || regnum == -1) + regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8); +} + +static const struct regset arm_none_gregset = + { + nullptr, arm_none_supply_gregset, arm_none_collect_gregset + }; + +static const struct regset arm_none_vfpregset = + { + nullptr, arm_none_supply_vfp, arm_none_collect_vfp + }; + +/* Iterate over core file register note sections. */ + +void +arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + cb (".reg", ARM_NONE_SIZEOF_GREGSET, ARM_NONE_SIZEOF_GREGSET, + &arm_none_gregset, nullptr, cb_data); + + if (tdep->vfp_register_count > 0) + cb (".reg-arm-vfp", ARM_NONE_SIZEOF_VFP, ARM_NONE_SIZEOF_VFP, + &arm_none_vfpregset, "VFP floating-point", cb_data); +} diff --git a/gdb/arm-none-tdep.h b/gdb/arm-none-tdep.h new file mode 100644 index 0000000000..927fd91c43 --- /dev/null +++ b/gdb/arm-none-tdep.h @@ -0,0 +1,42 @@ +/* none on ARM target support, prototypes. + + Copyright (C) 2020 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 . */ + +#ifndef ARM_NONE_TDEP_H +#define ARM_NONE_TDEP_H + +#include "bfd.h" +#include "regset.h" + +struct regcache; + +/* Core file and register set support. */ +#define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE) + +/* Support VFP register format. */ +#define ARM_NONE_SIZEOF_VFP (32 * 8 + 4) + +/* The index to access CSPR in user_regs as defined in GLIBC. */ +#define ARM_NONE_CPSR_GREGNUM 16 + +void + arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache); +#endif /* ARM_NONE_TDEP_H */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index a214f22d7a..3ee444f09a 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -50,6 +50,8 @@ #include "arch/arm.h" #include "arch/arm-get-next-pcs.h" #include "arm-tdep.h" +#include "none-tdep.h" +#include "arm-none-tdep.h" #include "gdb/sim-arm.h" #include "elf-bfd.h" @@ -9453,6 +9455,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Virtual tables. */ set_gdbarch_vbit_in_delta (gdbarch, 1); + /* Default none core file support, can be overridden by osabi. */ + none_init_corefile (info, gdbarch); + set_gdbarch_iterate_over_regset_sections (gdbarch, + arm_none_iterate_over_regset_sections); + /* Hook in the ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch); diff --git a/gdb/configure.tgt b/gdb/configure.tgt index d865ecdcb6..789541d49f 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -64,7 +64,8 @@ arc*-*-*) arm*-*-*) cpu_obs="aarch32-tdep.o arch/aarch32.o arch/arm.o \ - arch/arm-get-next-pcs.o arm-tdep.o";; + arch/arm-get-next-pcs.o arm-tdep.o \ + none-tdep.o arm-none-tdep.o";; hppa*-*-*) # Target: HP PA-RISC diff --git a/gdb/none-tdep.c b/gdb/none-tdep.c new file mode 100644 index 0000000000..9a2b5b9442 --- /dev/null +++ b/gdb/none-tdep.c @@ -0,0 +1,276 @@ +/* Target-dependent code for none, architecture independent. + + Copyright (C) 2020 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 . */ + +#include "defs.h" +#include "gdbtypes.h" +#include "none-tdep.h" +#include "target.h" +#include "gdbthread.h" +#include "gdbcore.h" +#include "regcache.h" +#include "regset.h" +#include "elf/common.h" +#include "elf-bfd.h" /* for elfcore_write_* */ +#include "inferior.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "gdb_obstack.h" +#include "observable.h" +#include "objfiles.h" +#include "infcall.h" +#include "gdbcmd.h" +#include "gdb_regex.h" +#include "gdbsupport/enum-flags.h" +#include "gdbsupport/gdb_optional.h" + +#include + +typedef char *(*none_collect_thread_registers_ftype) (const struct regcache *, + ptid_t, + bfd *, char *, int *, + enum gdb_signal); + +/* The ARM none corefile setup is based on the ARM GNU/Linux design. */ + +/* Structure for passing information from + none_collect_thread_registers via an iterator to + none_collect_regset_section_cb. */ + +struct none_collect_regset_section_cb_data +{ + struct gdbarch *gdbarch; + const struct regcache *regcache; + bfd *obfd; + char *note_data; + int *note_size; + unsigned long lwp; + enum gdb_signal stop_signal; + int abort_iteration; +}; + +/* Callback for iterate_over_regset_sections that records a single + regset in the corefile note section. */ + +static void +none_collect_regset_section_cb (const char *sect_name, int supply_size, + int collect_size, const struct regset *regset, + const char *human_name, void *cb_data) +{ + struct none_collect_regset_section_cb_data *data + = (struct none_collect_regset_section_cb_data *) cb_data; + bool variable_size_section = (regset != nullptr + && regset->flags & REGSET_VARIABLE_SIZE); + + if (!variable_size_section) + gdb_assert (supply_size == collect_size); + + if (data->abort_iteration) + return; + + gdb_assert (regset && regset->collect_regset); + + /* This is intentionally zero-initialized by using std::vector, so + that any padding bytes in the core file will show as 0. */ + std::vector buf (collect_size); + + regset->collect_regset (regset, data->regcache, -1, buf.data (), + collect_size); + + /* PRSTATUS still needs to be treated specially. */ + if (strcmp (sect_name, ".reg") == 0) + data->note_data = (char *) elfcore_write_prstatus + (data->obfd, data->note_data, data->note_size, data->lwp, + gdb_signal_to_host (data->stop_signal), buf.data ()); + else + data->note_data = (char *) elfcore_write_register_note + (data->obfd, data->note_data, data->note_size, + sect_name, buf.data (), collect_size); + + if (data->note_data == nullptr) + data->abort_iteration = 1; +} + +/* Records the thread's register state for the corefile note + section. */ + +static char * +none_collect_thread_registers (const struct regcache *regcache, + ptid_t ptid, bfd *obfd, + char *note_data, int *note_size, + enum gdb_signal stop_signal) +{ + struct gdbarch *gdbarch = regcache->arch (); + struct none_collect_regset_section_cb_data data; + + data.gdbarch = gdbarch; + data.regcache = regcache; + data.obfd = obfd; + data.note_data = note_data; + data.note_size = note_size; + data.stop_signal = stop_signal; + data.abort_iteration = 0; + + /* For remote targets the LWP may not be available, so use the TID. */ + data.lwp = ptid.lwp (); + if (!data.lwp) + data.lwp = ptid.tid (); + + gdbarch_iterate_over_regset_sections (gdbarch, + none_collect_regset_section_cb, + &data, regcache); + return data.note_data; +} + +struct none_corefile_thread_data +{ + struct gdbarch *gdbarch; + bfd *obfd; + char *note_data; + int *note_size; + enum gdb_signal stop_signal; +}; + +/* Records the thread's register state for the corefile note + section. */ + +static void +none_corefile_thread (struct thread_info *info, + struct none_corefile_thread_data *args) +{ + struct regcache *regcache; + + regcache = get_thread_arch_regcache (info->inf->process_target (), + info->ptid, args->gdbarch); + + target_fetch_registers (regcache, -1); + args->note_data = none_collect_thread_registers + (regcache, info->ptid, args->obfd, args->note_data, + args->note_size, args->stop_signal); +} + +/* Find the signalled thread. In case there's more than one signalled + thread, prefer the current thread, if it is signalled. If no + thread was signalled, default to the current thread, unless it has + exited, in which case return nullptr. */ + +static thread_info * +find_signalled_thread () +{ + thread_info *curr_thr = inferior_thread (); + if (curr_thr->state != THREAD_EXITED + && curr_thr->suspend.stop_signal != GDB_SIGNAL_0) + return curr_thr; + + for (thread_info *thr : current_inferior ()->non_exited_threads ()) + if (thr->suspend.stop_signal != GDB_SIGNAL_0) + return thr; + + /* Default to the current thread, unless it has exited. */ + if (curr_thr->state != THREAD_EXITED) + return curr_thr; + + return nullptr; +} + +/* Fills the "to_make_corefile_note" target vector. Builds the note + section for a corefile, and returns it in a malloc buffer. */ + +static char * +none_make_corefile_notes_1 (struct gdbarch *gdbarch, bfd *obfd, int *note_size, + none_collect_thread_registers_ftype collect) +{ + struct none_corefile_thread_data thread_args; + char *note_data = nullptr; + + /* Process information. */ + if (get_exec_file (0)) + { + const char *fname = lbasename (get_exec_file (0)); + char *psargs = xstrdup (fname); + + if (get_inferior_args ()) + psargs = reconcat (psargs, psargs, " ", get_inferior_args (), + (char *) nullptr); + + note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, + fname, psargs); + xfree (psargs); + } + + if (!note_data) + return nullptr; + + /* Thread register information. */ + try + { + update_thread_list (); + } + catch (const gdb_exception_error &e) + { + exception_print (gdb_stderr, e); + } + + /* Like the kernel, prefer dumping the signalled thread first. + "First thread" is what tools use to infer the signalled + thread. */ + thread_info *signalled_thr = find_signalled_thread (); + + thread_args.gdbarch = gdbarch; + thread_args.obfd = obfd; + thread_args.note_data = note_data; + thread_args.note_size = note_size; + if (signalled_thr != nullptr) + thread_args.stop_signal = signalled_thr->suspend.stop_signal; + else + thread_args.stop_signal = GDB_SIGNAL_0; + + if (signalled_thr != nullptr) + none_corefile_thread (signalled_thr, &thread_args); + for (thread_info *thr : current_inferior ()->non_exited_threads ()) + { + if (thr == signalled_thr) + continue; + + none_corefile_thread (thr, &thread_args); + } + + note_data = thread_args.note_data; + if (!note_data) + return nullptr; + + return note_data; +} + +static char * +none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) +{ + return none_make_corefile_notes_1 (gdbarch, obfd, note_size, + none_collect_thread_registers); +} + +/* Setup default core file support for none targets. + Can be overridden later by OSABI. */ + +void +none_init_corefile (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + /* Default core file support. */ + set_gdbarch_make_corefile_notes (gdbarch, none_make_corefile_notes); +} diff --git a/gdb/none-tdep.h b/gdb/none-tdep.h new file mode 100644 index 0000000000..e5054189b5 --- /dev/null +++ b/gdb/none-tdep.h @@ -0,0 +1,30 @@ +/* Target-dependent code for none, architecture independent. + + Copyright (C) 2020 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 . */ + +#ifndef NONE_TDEP_H +#define NONE_TDEP_H + +#include "bfd.h" + +struct regcache; + +void none_init_corefile (struct gdbarch_info info, + struct gdbarch *gdbarch); + +#endif /* none-tdep.h */ -- 2.17.1