This adds basic powerpc64 support to the ports gdb. Only really
implements target support, so this can only really look at core dumps.
But it does a better job than base gdb.
Since the ports tree is still locked, I may actually work on improving
this a bit. But at least people have the diff if they need it.
Index: devel/gdb/patches/patch-gdb_config_powerpc_obsd64_mh
===================================================================
RCS file: devel/gdb/patches/patch-gdb_config_powerpc_obsd64_mh
diff -N devel/gdb/patches/patch-gdb_config_powerpc_obsd64_mh
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devel/gdb/patches/patch-gdb_config_powerpc_obsd64_mh 30 Sep 2020 20:18:56 -0000
@@ -0,0 +1,10 @@
+$OpenBSD$
+
+Index: gdb/config/powerpc/obsd64.mh
+--- gdb/config/powerpc/obsd64.mh.orig
++++ gdb/config/powerpc/obsd64.mh
+@@ -0,0 +1,4 @@
++# Host: OpenBSD/powerpc
++NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o ppc64obsd-nat.o bsd-kvm.o
++
++LOADLIBES= -lkvm
Index: devel/gdb/patches/patch-gdb_configure_host
===================================================================
RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_configure_host,v
retrieving revision 1.1
diff -u -p -r1.1 patch-gdb_configure_host
--- devel/gdb/patches/patch-gdb_configure_host 10 Jul 2018 11:03:46 -0000 1.1
+++ devel/gdb/patches/patch-gdb_configure_host 30 Sep 2020 20:18:56 -0000
@@ -1,6 +1,7 @@
$OpenBSD: patch-gdb_configure_host,v 1.1 2018/07/10 11:03:46 kettenis Exp $
---- gdb/configure.host.orig Sat Jan 21 05:48:42 2017
-+++ gdb/configure.host Tue Mar 7 23:52:43 2017
+Index: gdb/configure.host
+--- gdb/configure.host.orig
++++ gdb/configure.host
@@ -82,6 +82,7 @@ case "${host}" in
*-*-darwin*) gdb_host=darwin ;;
@@ -9,3 +10,11 @@ $OpenBSD: patch-gdb_configure_host,v 1.1
alpha*-*-linux*) gdb_host=alpha-linux ;;
alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
+@@ -137,6 +138,7 @@ powerpc*-*-freebsd*) gdb_host=fbsd ;;
+ powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu)
+ gdb_host=nbsd ;;
+ powerpc-*-openbsd*) gdb_host=obsd ;;
++powerpc64-*-openbsd*) gdb_host=obsd64 ;;
+
+ powerpc64*-*-linux*) gdb_host=ppc64-linux
+ # Support 'pseudo-native' debugging on the Cell BE
Index: devel/gdb/patches/patch-gdb_configure_tgt
===================================================================
RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_configure_tgt,v
retrieving revision 1.1
diff -u -p -r1.1 patch-gdb_configure_tgt
--- devel/gdb/patches/patch-gdb_configure_tgt 10 Jul 2018 11:03:46 -0000 1.1
+++ devel/gdb/patches/patch-gdb_configure_tgt 30 Sep 2020 20:18:56 -0000
@@ -16,3 +16,16 @@ Index: gdb/configure.tgt
alpha*-*-linux*)
# Target: Little-endian Alpha running Linux
gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \
+@@ -428,6 +435,12 @@ powerpc-*-openbsd*)
+ # Target: OpenBSD/powerpc
+ gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppcobsd-tdep.o \
+ solib-svr4.o \
++ ravenscar-thread.o ppc-ravenscar-thread.o"
++ ;;
++powerpc64-*-openbsd*)
++ # Target: OpenBSD/powerpc64
++ gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc64-tdep.o \
++ ppc64obsd-tdep.o obsd-tdep.o solib-svr4.o \
+ ravenscar-thread.o ppc-ravenscar-thread.o"
+ ;;
+ powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*)
Index: devel/gdb/patches/patch-gdb_ppc64obsd-nat_c
===================================================================
RCS file: devel/gdb/patches/patch-gdb_ppc64obsd-nat_c
diff -N devel/gdb/patches/patch-gdb_ppc64obsd-nat_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devel/gdb/patches/patch-gdb_ppc64obsd-nat_c 30 Sep 2020 20:18:56 -0000
@@ -0,0 +1,7 @@
+$OpenBSD$
+
+Index: gdb/ppc64obsd-nat.c
+--- gdb/ppc64obsd-nat.c.orig
++++ gdb/ppc64obsd-nat.c
+@@ -0,0 +1 @@
++/* Empty */
Index: devel/gdb/patches/patch-gdb_ppc64obsd-tdep_c
===================================================================
RCS file: devel/gdb/patches/patch-gdb_ppc64obsd-tdep_c
diff -N devel/gdb/patches/patch-gdb_ppc64obsd-tdep_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devel/gdb/patches/patch-gdb_ppc64obsd-tdep_c 30 Sep 2020 20:18:56 -0000
@@ -0,0 +1,441 @@
+$OpenBSD$
+
+Index: gdb/ppc64obsd-tdep.c
+--- gdb/ppc64obsd-tdep.c.orig
++++ gdb/ppc64obsd-tdep.c
+@@ -0,0 +1,435 @@
++/* Target-dependent code for OpenBSD/powerpc64.
++
++ Copyright (C) 2004, 2005, 2006 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 2 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, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ Boston, MA 02110-1301, USA. */
++
++#include "defs.h"
++#include "arch-utils.h"
++#include "floatformat.h"
++#include "frame.h"
++#include "frame-unwind.h"
++#include "osabi.h"
++#include "regcache.h"
++#include "regset.h"
++#include "symtab.h"
++#include "trad-frame.h"
++
++#include "obsd-tdep.h"
++#include "ppc-tdep.h"
++#include "ppc64obsd-tdep.h"
++#include "solib-svr4.h"
++
++/* Register offsets from <machine/reg.h>. */
++struct ppc_reg_offsets ppc64obsd_reg_offsets;
++struct ppc_reg_offsets ppc64obsd_fpreg_offsets;
++
++
++/* Register set support functions. */
++
++static void
++ppc64_supply_reg (struct regcache *regcache, int regnum,
++ const gdb_byte *regs, size_t offset)
++{
++ if (regnum != -1 && offset != -1)
++ regcache_raw_supply (regcache, regnum, regs + offset);
++}
++
++static void
++ppc64_collect_reg (const struct regcache *regcache, int regnum,
++ gdb_byte *regs, size_t offset)
++{
++ if (regnum != -1 && offset != -1)
++ regcache_raw_collect (regcache, regnum, regs + offset);
++}
++
++/* Supply register REGNUM in the general-purpose register set REGSET
++ from the buffer specified by GREGS and LEN to register cache
++ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
++
++void
++ppc64_supply_gregset (const struct regset *regset, struct regcache *regcache,
++ int regnum, const void *gregs, size_t len)
++{
++ struct gdbarch *gdbarch = get_regcache_arch (regcache);
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++ const struct ppc_reg_offsets *offsets
++ = (const struct ppc_reg_offsets *) regset->regmap;
++ size_t offset;
++ int i;
++
++ for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
++ i < tdep->ppc_gp0_regnum + ppc_num_gprs;
++ i++, offset += 8)
++ {
++ if (regnum == -1 || regnum == i)
++ ppc64_supply_reg (regcache, i, (const gdb_byte *) gregs, offset);
++ }
++
++ if (regnum == -1 || regnum == gdbarch_pc_regnum (gdbarch))
++ ppc64_supply_reg (regcache, gdbarch_pc_regnum (gdbarch),
++ (const gdb_byte *) gregs, offsets->pc_offset);
++ if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
++ ppc64_supply_reg (regcache, tdep->ppc_ps_regnum,
++ (const gdb_byte *) gregs, offsets->ps_offset);
++ if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
++ ppc64_supply_reg (regcache, tdep->ppc_cr_regnum,
++ (const gdb_byte *) gregs, offsets->cr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
++ ppc64_supply_reg (regcache, tdep->ppc_lr_regnum,
++ (const gdb_byte *) gregs, offsets->lr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
++ ppc64_supply_reg (regcache, tdep->ppc_ctr_regnum,
++ (const gdb_byte *) gregs, offsets->ctr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
++ ppc64_supply_reg (regcache, tdep->ppc_xer_regnum,
++ (const gdb_byte *) gregs, offsets->cr_offset);
++}
++
++/* Collect register REGNUM in the general-purpose register set
++ REGSET. from register cache REGCACHE into the buffer specified by
++ GREGS and LEN. If REGNUM is -1, do this for all registers in
++ REGSET. */
++
++void
++ppc64_collect_gregset (const struct regset *regset,
++ const struct regcache *regcache,
++ int regnum, void *gregs, size_t len)
++{
++ struct gdbarch *gdbarch = get_regcache_arch (regcache);
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++ const struct ppc_reg_offsets *offsets
++ = (const struct ppc_reg_offsets *) regset->regmap;
++ size_t offset;
++ int i;
++
++ offset = offsets->r0_offset;
++ for (i = tdep->ppc_gp0_regnum;
++ i < tdep->ppc_gp0_regnum + ppc_num_gprs;
++ i++, offset += 8)
++ {
++ if (regnum == -1 || regnum == i)
++ ppc64_collect_reg (regcache, i, (gdb_byte *) gregs, offset);
++ }
++
++ if (regnum == -1 || regnum == gdbarch_pc_regnum (gdbarch))
++ ppc64_collect_reg (regcache, gdbarch_pc_regnum (gdbarch),
++ (gdb_byte *) gregs, offsets->pc_offset);
++ if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
++ ppc64_collect_reg (regcache, tdep->ppc_ps_regnum,
++ (gdb_byte *) gregs, offsets->ps_offset);
++ if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
++ ppc64_collect_reg (regcache, tdep->ppc_cr_regnum,
++ (gdb_byte *) gregs, offsets->cr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
++ ppc64_collect_reg (regcache, tdep->ppc_lr_regnum,
++ (gdb_byte *) gregs, offsets->lr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
++ ppc64_collect_reg (regcache, tdep->ppc_ctr_regnum,
++ (gdb_byte *) gregs, offsets->ctr_offset);
++ if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
++ ppc64_collect_reg (regcache, tdep->ppc_xer_regnum,
++ (gdb_byte *) gregs, offsets->xer_offset);
++}
++
++/* Core file support. */
++
++/* Supply register REGNUM in the general-purpose register set REGSET
++ from the buffer specified by GREGS and LEN to register cache
++ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
++
++void
++ppc64obsd_supply_gregset (const struct regset *regset,
++ struct regcache *regcache, int regnum,
++ const void *gregs, size_t len)
++{
++ ppc64_supply_gregset (regset, regcache, regnum, gregs, len);
++}
++
++/* Collect register REGNUM in the general-purpose register set
++ REGSET. from register cache REGCACHE into the buffer specified by
++ GREGS and LEN. If REGNUM is -1, do this for all registers in
++ REGSET. */
++
++void
++ppc64obsd_collect_gregset (const struct regset *regset,
++ const struct regcache *regcache, int regnum,
++ void *gregs, size_t len)
++{
++ ppc64_collect_gregset (regset, regcache, regnum, gregs, len);
++}
++
++/* OpenBSD/powerpc register set. */
++
++struct regset ppc64obsd_gregset =
++{
++ &ppc64obsd_reg_offsets,
++ ppc64obsd_supply_gregset
++};
++
++struct regset ppc64obsd_fpregset =
++{
++ &ppc64obsd_fpreg_offsets,
++ ppc_supply_fpregset
++};
++
++/* Iterate over core file register note sections. */
++
++static void
++ppc64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
++ iterate_over_regset_sections_cb *cb,
++ void *cb_data,
++ const struct regcache *regcache)
++{
++ cb (".reg", 304, &ppc64obsd_gregset, NULL, cb_data);
++ // cb (".reg2", 1048, &ppc64obsd_fpregset, NULL, cb_data);
++}
++
++
++/* Signal trampolines. */
++
++/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
++ in virtual memory. The randomness makes it somewhat tricky to
++ detect it, but fortunately we can rely on the fact that the start
++ of the sigtramp routine is page-aligned. We recognize the
++ trampoline by looking for the code that invokes the sigreturn
++ system call. The offset where we can find that code varies from
++ release to release.
++
++ By the way, the mapping mentioned above is read-only, so you cannot
++ place a breakpoint in the signal trampoline. */
++
++/* Default page size. */
++static const int ppc64obsd_page_size = 4096;
++
++/* Offset for sigreturn(2). */
++static const int ppc64obsd_sigreturn_offset[] = {
++ 0x98, /* OpenBSD 3.8 */
++ 0x0c, /* OpenBSD 3.2 */
++ -1
++};
++
++static int
++ppc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
++ struct frame_info *this_frame,
++ void **this_cache)
++{
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
++ CORE_ADDR pc = get_frame_pc (this_frame);
++ CORE_ADDR start_pc = (pc & ~(ppc64obsd_page_size - 1));
++ const int *offset;
++ const char *name;
++
++ find_pc_partial_function (pc, &name, NULL, NULL);
++ if (name)
++ return 0;
++
++ for (offset = ppc64obsd_sigreturn_offset; *offset != -1; offset++)
++ {
++ gdb_byte buf[2 * PPC_INSN_SIZE];
++ unsigned long insn;
++
++ if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
++ buf, sizeof buf))
++ continue;
++
++ /* Check for "li r0,SYS_sigreturn". */
++ insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
++ if (insn != 0x38000067)
++ continue;
++
++ /* Check for "sc". */
++ insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
++ PPC_INSN_SIZE, byte_order);
++ if (insn != 0x44000002)
++ continue;
++
++ return 1;
++ }
++
++ return 0;
++}
++
++static struct trad_frame_cache *
++ppc64obsd_sigtramp_frame_cache (struct frame_info *this_frame,
++ void **this_cache)
++{
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
++ struct trad_frame_cache *cache;
++ CORE_ADDR addr, base, func;
++ gdb_byte buf[PPC_INSN_SIZE];
++ unsigned long insn, sigcontext_offset;
++ int i;
++
++ if (*this_cache)
++ return (struct trad_frame_cache *) *this_cache;
++
++ cache = trad_frame_cache_zalloc (this_frame);
++ *this_cache = cache;
++
++ func = get_frame_pc (this_frame);
++ func &= ~(ppc64obsd_page_size - 1);
++ if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
++ return cache;
++
++ /* Calculate the offset where we can find `struct sigcontext'. We
++ base our calculation on the amount of stack space reserved by the
++ first instruction of the signal trampoline. */
++ insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
++ sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;
++
++ base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
++ addr = base + sigcontext_offset + 2 * tdep->wordsize;
++ for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
++ {
++ int regnum = i + tdep->ppc_gp0_regnum;
++ trad_frame_set_reg_addr (cache, regnum, addr);
++ }
++ trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
++ addr += tdep->wordsize;
++ trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
++ addr += tdep->wordsize;
++ trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
++ addr += tdep->wordsize;
++ trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
++ addr += tdep->wordsize;
++ trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
++ /* SRR0? */
++ addr += tdep->wordsize;
++
++ /* Construct the frame ID using the function start. */
++ trad_frame_set_id (cache, frame_id_build (base, func));
++
++ return cache;
++}
++
++static void
++ppc64obsd_sigtramp_frame_this_id (struct frame_info *this_frame,
++ void **this_cache, struct frame_id *this_id)
++{
++ struct trad_frame_cache *cache =
++ ppc64obsd_sigtramp_frame_cache (this_frame, this_cache);
++
++ trad_frame_get_id (cache, this_id);
++}
++
++static struct value *
++ppc64obsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
++ void **this_cache, int regnum)
++{
++ struct trad_frame_cache *cache =
++ ppc64obsd_sigtramp_frame_cache (this_frame, this_cache);
++
++ return trad_frame_get_register (cache, this_frame, regnum);
++}
++
++static const struct frame_unwind ppc64obsd_sigtramp_frame_unwind = {
++ SIGTRAMP_FRAME,
++ default_frame_unwind_stop_reason,
++ ppc64obsd_sigtramp_frame_this_id,
++ ppc64obsd_sigtramp_frame_prev_register,
++ NULL,
++ ppc64obsd_sigtramp_frame_sniffer
++};
++
++
++static void
++ppc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
++{
++ obsd_init_abi (info, gdbarch);
++
++ /* OpenBSD doesn't support the 128-bit `long double' from the psABI. */
++ set_gdbarch_long_double_bit (gdbarch, 64);
++ set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
++
++ /* OpenBSD uses SVR4-style shared libraries. */
++ set_solib_svr4_fetch_link_map_offsets
++ (gdbarch, svr4_lp64_fetch_link_map_offsets);
++
++ set_gdbarch_iterate_over_regset_sections
++ (gdbarch, ppc64obsd_iterate_over_regset_sections);
++
++ frame_unwind_append_unwinder (gdbarch, &ppc64obsd_sigtramp_frame_unwind);
++}
++
++
++/* OpenBSD uses uses the traditional NetBSD core file format, even for
++ ports that use ELF. */
++#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
++
++static enum gdb_osabi
++ppc64obsd_core_osabi_sniffer (bfd *abfd)
++{
++ if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
++ return GDB_OSABI_NETBSD_CORE;
++
++ return GDB_OSABI_UNKNOWN;
++}
++
++
++/* Provide a prototype to silence -Wmissing-prototypes. */
++void _initialize_ppc64obsd_tdep (void);
++
++void
++_initialize_ppc64obsd_tdep (void)
++{
++ /* BFD doesn't set a flavour for NetBSD style a.out core files. */
++ gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
++ ppc64obsd_core_osabi_sniffer);
++
++#if 0
++ gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
++ ppc64obsd_init_abi);
++
No comments:
Post a Comment