From patchwork Thu Jul 12 18:36:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robin Haberkorn X-Patchwork-Id: 28342 Received: (qmail 108550 invoked by alias); 12 Jul 2018 18:36:59 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 107693 invoked by uid 89); 12 Jul 2018 18:36:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=consent, transferring, Searching, retrieval X-HELO: mout.kundenserver.de Received: from mout.kundenserver.de (HELO mout.kundenserver.de) (212.227.17.24) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 12 Jul 2018 18:36:56 +0000 Received: from [192.168.0.102] ([212.112.122.96]) by mrelayeu.kundenserver.de (mreue103 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MdFJL-1fLKEA3opv-00ITUq for ; Thu, 12 Jul 2018 20:36:54 +0200 To: gdb-patches@sourceware.org From: Robin Haberkorn Subject: arm-none-eabi core dump support Message-ID: <59ceb22b-2215-fb27-10c0-7a127096e37b@metratec.com> Date: Fri, 13 Jul 2018 00:36:52 +0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 X-IsSubscribed: yes Hello! I had the idea of debugging my embedded ARM project (built with the arm-none-eabi toolchain) using core dumps. Core dumps would be useful even on embedded targets for several reasons as you might guess: They can be automatically created during crashes, even if you don't have a debug probe attached, stored and later retrieved. They can be created while your firmware is running, without interrupting it. And most importantly, they allow debugging when you cannot even use a debug probe, maybe because your JTAG port is already locked. While core dump creation on an embedded target turned out to be relatively simple, I found that arm-none-eabi-gdb, at least as of embedded-gdb-7.12-branch-2017q2, does not have a core dump handler and throws the "no core file handler recognizes format" error. What other people instead do is apparently to make memory and register dumps in a custom format instead of real core dumps, transferring this file to the PC and using a custom gdb remote debug stub to feed gdb. This is at least what these guys are doing apparently: https://github.com/adamgreen/CrashDebug Searching the net, including the gdb mailing list, shows that reading core dumps on arm-none-eabi-gdb is an often asked for feature. Since I wasn't consent with inventing my own core dump format or integrating CrashDebug, I simply hacked GDB to support core dump handling via core-regset.c. See attachment. It applies on top of users/ARM/embedded-gdb-7.12-branch-2017q2, but not on top of master. Also, as I said, it's a hack. It modifies several architecture-independent files. Floating point registers are currently not supported. While this wont work for all applications, it should for most typical embedded ARM projects and IMHO it's better than nothing. I would like to improve this patch and get this upstreamed. Can you give me some pointers on where the additional patched-in definitions should be placed instead? What about core-regset.c - it seems to have been removed in the master branch? Best regards, Robin From 13b7c2d2a602c1830ad4a3f2a50a66e3c4f2f1a3 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Thu, 12 Jul 2018 17:29:04 +0600 Subject: [PATCH] added support for handling core dumps on arm-none-eabi-gdb (Embedded ARM) * this is merely a hack and not yet upstreamable, as it modifies core-regset.c, corelow.c and gregset.h with definitions taken from here and there. * core-regset.c is missing the following definitions: supply_gregset(), GDB_GREGSET_T, GDB_FPREGSET_T * probably, they should be added as a new module, but I don't know where it should be put. This should be discussed on the GDB mailing list. * also floatin point register retrieval is still missing and has simply been commented out. --- gdb/configure.tgt | 2 +- gdb/core-regset.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/corelow.c | 2 +- gdb/gregset.h | 3 +++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 7f1aac3..438f35b 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -112,7 +112,7 @@ arm*-*-symbianelf*) ;; arm*-*-*) # Target: ARM embedded system - gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o" + gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o core-regset.o" gdb_sim=../sim/arm/libsim.a ;; diff --git a/gdb/core-regset.c b/gdb/core-regset.c index 278887b..2227f5a 100644 --- a/gdb/core-regset.c +++ b/gdb/core-regset.c @@ -39,9 +39,60 @@ #include #endif +#include "arch/arm.h" + /* Prototypes for supply_gregset etc. */ #include "gregset.h" +#define ARM_CPSR_GREGNUM 16 +extern int arm_apcs_32; + +#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE) + +void +arm_linux_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs_buf, size_t len) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + 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[INT_REGISTER_SIZE]; + + for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache_raw_supply (regcache, regno, + gregs + INT_REGISTER_SIZE * regno); + + if (regnum == ARM_PS_REGNUM || regnum == -1) + { + if (arm_apcs_32) + regcache_raw_supply (regcache, ARM_PS_REGNUM, + gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM); + else + regcache_raw_supply (regcache, ARM_PS_REGNUM, + gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM); + } + + if (regnum == ARM_PC_REGNUM || regnum == -1) + { + reg_pc = extract_unsigned_integer (gregs + + INT_REGISTER_SIZE * ARM_PC_REGNUM, + INT_REGISTER_SIZE, byte_order); + reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc); + store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, byte_order, reg_pc); + regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf); + } +} + +void +supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) +{ + arm_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0); +} + /* Provide registers to GDB from a core file. CORE_REG_SECT points to an array of bytes, which are the contents @@ -84,9 +135,11 @@ fetch_core_registers (struct regcache *regcache, else { memcpy (&fpregset, core_reg_sect, sizeof (fpregset)); +#if 0 if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) >= 0) supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p); +#endif } break; diff --git a/gdb/corelow.c b/gdb/corelow.c index c46af0a..504fd26 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -541,7 +541,7 @@ get_core_register_section (struct regcache *regcache, warning (_("Section `%s' in core file too small."), section_name); return; } - if (size != min_size && !(regset->flags & REGSET_VARIABLE_SIZE)) + if (size != min_size && regset && !(regset->flags & REGSET_VARIABLE_SIZE)) { warning (_("Unexpected size of section `%s' in core file."), section_name); diff --git a/gdb/gregset.h b/gdb/gregset.h index 3101edc..ff85d46 100644 --- a/gdb/gregset.h +++ b/gdb/gregset.h @@ -23,6 +23,9 @@ #include #endif +#define GDB_GREGSET_T struct { uint32_t reg[18]; } +#define GDB_FPREGSET_T struct { uint32_t reg[18]; } + #ifndef GDB_GREGSET_T #define GDB_GREGSET_T gregset_t #endif -- 2.7.4