From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id oJtrDec7j1/aegAAWB0awg (envelope-from ) for ; Tue, 20 Oct 2020 15:35:03 -0400 Received: by simark.ca (Postfix, from userid 112) id 34B841EFC3; Tue, 20 Oct 2020 15:35:03 -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 E48211EFBF for ; Tue, 20 Oct 2020 15:35:01 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9E32F39450CB; Tue, 20 Oct 2020 19:35:01 +0000 (GMT) Received: from mail-gw01.fsdata.se (proxy04.fsdata.se [89.221.252.227]) by sourceware.org (Postfix) with ESMTPS id 70FBE3850414 for ; Tue, 20 Oct 2020 19:34:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 70FBE3850414 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; Tue, 20 Oct 2020 21:34:44 +0200 From: Fredrik Hederstierna To: , , , , Subject: [PATCH] gdb: Support corefiles for arm-none-eabi Date: Tue, 20 Oct 2020 21:34:26 +0200 Message-ID: <20201020193426.14715-1-fredrik@hederstierna.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: 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: Fredrik Hederstierna Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" From: Fredrik Hederstierna --- gdb/arm-none-tdep.c | 368 ++++++++++++++++++++++++++++++++++++++++++++ gdb/arm-none-tdep.h | 60 ++++++++ gdb/arm-tdep.c | 8 + gdb/configure.tgt | 6 +- gdb/none-tdep.c | 231 +++++++++++++++++++++++++++ gdb/none-tdep.h | 39 +++++ 6 files changed, 711 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/arm-none-tdep.c b/gdb/arm-none-tdep.c new file mode 100644 index 0000000000..9d83a8b913 --- /dev/null +++ b/gdb/arm-none-tdep.c @@ -0,0 +1,368 @@ +/* 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" + +/* ---- based on arm-linux-tdep.h ---- */ + +#define ARM_NONE_SIZEOF_NWFPE (8 * ARM_FP_REGISTER_SIZE \ + + 2 * ARM_INT_REGISTER_SIZE \ + + 8 + ARM_INT_REGISTER_SIZE) + +/* The index to access CSPR in user_regs defined in GLIBC. */ +#define ARM_CPSR_GREGNUM 16 + +/* Support for register format used by the NWFPE FPA emulator. Each + register takes three words, where either the first one, two, or + three hold a single, double, or extended precision value (depending + on the corresponding tag). The register set is eight registers, + followed by the fpsr and fpcr, followed by eight tag bytes, and a + final word flag which indicates whether NWFPE has been + initialized. */ + +#define NWFPE_FPSR_OFFSET (8 * ARM_FP_REGISTER_SIZE) +#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + ARM_INT_REGISTER_SIZE) +#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + ARM_INT_REGISTER_SIZE) +#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8) + +/* Reuse ARM GNU/Linux HWCAP values for none. These are in defined in + in current kernels. */ +#define HWCAP_VFP 64 +#define HWCAP_IWMMXT 512 +#define HWCAP_NEON 4096 +#define HWCAP_VFPv3 8192 +#define HWCAP_VFPv3D16 16384 + +/* Core file and register set support. */ + +#define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE) + +/* ---- based on arm-linux-tdep.c ---- */ + +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_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); + } +} + +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_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 for register format used by the NWFPE FPA emulator. */ + +#define typeNone 0x00 +#define typeSingle 0x01 +#define typeDouble 0x02 +#define typeExtended 0x03 + +void +arm_none_supply_nwfpe_register (struct regcache *regcache, int regno, + const gdb_byte *regs) +{ + const gdb_byte *reg_data; + gdb_byte reg_tag; + gdb_byte buf[ARM_FP_REGISTER_SIZE]; + + reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE; + reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET]; + memset (buf, 0, ARM_FP_REGISTER_SIZE); + + switch (reg_tag) + { + case typeSingle: + memcpy (buf, reg_data, 4); + break; + case typeDouble: + memcpy (buf, reg_data + 4, 4); + memcpy (buf + 4, reg_data, 4); + break; + case typeExtended: + /* We want sign and exponent, then least significant bits, + then most significant. NWFPE does sign, most, least. */ + memcpy (buf, reg_data, 4); + memcpy (buf + 4, reg_data + 8, 4); + memcpy (buf + 8, reg_data + 4, 4); + break; + default: + break; + } + + regcache->raw_supply (regno, buf); +} + +void +arm_none_collect_nwfpe_register (const struct regcache *regcache, int regno, + gdb_byte *regs) +{ + gdb_byte *reg_data; + gdb_byte reg_tag; + gdb_byte buf[ARM_FP_REGISTER_SIZE]; + + regcache->raw_collect (regno, buf); + + /* NOTE drow/2006-06-07: This code uses the tag already in the + register buffer. I've preserved that when moving the code + from the native file to the target file. But this doesn't + always make sense. */ + + reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE; + reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET]; + + switch (reg_tag) + { + case typeSingle: + memcpy (reg_data, buf, 4); + break; + case typeDouble: + memcpy (reg_data, buf + 4, 4); + memcpy (reg_data + 4, buf, 4); + break; + case typeExtended: + memcpy (reg_data, buf, 4); + memcpy (reg_data + 4, buf + 8, 4); + memcpy (reg_data + 8, buf + 4, 4); + break; + default: + break; + } +} + +void +arm_none_supply_nwfpe (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_FPS_REGNUM || regnum == -1) + regcache->raw_supply (ARM_FPS_REGNUM, + regs + NWFPE_FPSR_OFFSET); + + for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + arm_none_supply_nwfpe_register (regcache, regno, regs); +} + +void +arm_none_collect_nwfpe (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; + + for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + arm_none_collect_nwfpe_register (regcache, regno, regs); + + if (regnum == ARM_FPS_REGNUM || regnum == -1) + regcache->raw_collect (ARM_FPS_REGNUM, + regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM); +} + +/* Support VFP register format. */ + +#define ARM_NONE_SIZEOF_VFP (32 * 8 + 4) + +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 = + { + NULL, arm_none_supply_gregset, arm_none_collect_gregset + }; + +static const struct regset arm_none_fpregset = + { + NULL, arm_none_supply_nwfpe, arm_none_collect_nwfpe + }; + +static const struct regset arm_none_vfpregset = + { + NULL, 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, NULL, 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); + else if (tdep->have_fpa_registers) + cb (".reg2", ARM_NONE_SIZEOF_NWFPE, ARM_NONE_SIZEOF_NWFPE, + &arm_none_fpregset, "FPA floating-point", cb_data); +} + +/* Determine target description from core file. */ + +const struct target_desc * +arm_none_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + CORE_ADDR arm_hwcap = 0; + if (target_auxv_search (target, AT_HWCAP, &arm_hwcap) != 1) + return nullptr; + + if (arm_hwcap & HWCAP_VFP) + { + /* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support + Neon with VFPv3-D32. */ + if (arm_hwcap & HWCAP_NEON) + return aarch32_read_description (); + else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3) + return arm_read_description (ARM_FP_TYPE_VFPV3); + + return arm_read_description (ARM_FP_TYPE_VFPV2); + } + + return nullptr; +} diff --git a/gdb/arm-none-tdep.h b/gdb/arm-none-tdep.h new file mode 100644 index 0000000000..7927c0aff3 --- /dev/null +++ b/gdb/arm-none-tdep.h @@ -0,0 +1,60 @@ +/* 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 "gdbarch.h" +#include "target.h" +#include "bfd.h" + +struct regset; +struct regcache; + +void arm_none_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs_buf, size_t len); +void arm_none_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs_buf, size_t len); + +void arm_none_supply_nwfpe_register (struct regcache *regcache, int regno, + const gdb_byte *regs); +void arm_none_collect_nwfpe_register (const struct regcache *regcache, int regno, + gdb_byte *regs); + +void arm_none_supply_nwfpe (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *regs_buf, size_t len); +void arm_none_collect_nwfpe (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *regs_buf, size_t len); + +void +arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache); + +const struct target_desc * +arm_none_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd); + +#endif /* ARM_NONE_TDEP_H */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index a214f22d7a..be47cc2228 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,12 @@ 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); + set_gdbarch_core_read_description (gdbarch, arm_none_core_read_description); + /* 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..f4a1540464 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 @@ -798,4 +799,7 @@ for t in x ${gdb_target_obs}; do if test "$t" = linux-tdep.o; then gdb_have_gcore=true fi + if test "$t" = arm-none-tdep.o; then + gdb_have_gcore=true + fi done diff --git a/gdb/none-tdep.c b/gdb/none-tdep.c new file mode 100644 index 0000000000..8cd139c500 --- /dev/null +++ b/gdb/none-tdep.c @@ -0,0 +1,231 @@ +/* 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 "auxv.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 + +/* ---- based on linux-tdep.c ---- */ + +/* 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 != NULL + && 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 == NULL) + 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; +} + +/* Fills the "to_make_corefile_note" target vector. Builds the note + section for a corefile, and returns it in a malloc buffer. */ + +char * +none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size, + none_collect_thread_registers_ftype collect) +{ + char *note_data = NULL; + + /* 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 *) NULL); + + note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, + fname, psargs); + xfree (psargs); + } + + if (!note_data) + return NULL; + + if (note_data) + { + ptid_t ptid; + struct regcache *regcache; + process_stratum_target *targ = NULL; + int global_id = 1; + struct thread_info *info = find_thread_global_id (global_id); + if (info) + { + ptid = info->ptid; + targ = info->inf->process_target (); + } + else + ptid = minus_one_ptid; + regcache = get_thread_arch_regcache (targ, ptid, gdbarch); + + note_data = collect (regcache, + ptid, + obfd, + note_data, + note_size, + GDB_SIGNAL_0); + if (!note_data) + return NULL; + + /* Auxillary vector. */ + gdb::optional auxv = + target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL); + if (auxv && !auxv->empty ()) + { + note_data = elfcore_write_note (obfd, note_data, note_size, + "CORE", NT_AUXV, auxv->data (), + auxv->size ()); + + if (!note_data) + return NULL; + } + } + + /* make_cleanup (xfree, note_data); */ + return note_data; +} + +static char * +none_make_corefile_notes_1 (struct gdbarch *gdbarch, bfd *obfd, int *note_size) +{ + return none_make_corefile_notes (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_1); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_none_tdep; + +void +_initialize_none_tdep (void) +{ + /* No special actions. */ +} diff --git a/gdb/none-tdep.h b/gdb/none-tdep.h new file mode 100644 index 0000000000..4aea7004d8 --- /dev/null +++ b/gdb/none-tdep.h @@ -0,0 +1,39 @@ +/* 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; + +typedef char *(*none_collect_thread_registers_ftype) (const struct regcache *, + ptid_t, + bfd *, char *, int *, + enum gdb_signal); +char * +none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size, + none_collect_thread_registers_ftype collect); + +void +none_init_corefile (struct gdbarch_info info, + struct gdbarch *gdbarch); + +#endif /* none-tdep.h */ -- 2.17.1