Copyright (C) 2017-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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "regcache.h"
#include "target.h"
#include <sys/types.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#include "aarch64-tdep.h"
#include "aarch64-obsd-tdep.h"
#include "inf-ptrace.h"
#include "obsd-nat.h"
struct aarch64_obsd_nat_target final : public obsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static aarch64_obsd_nat_target the_aarch64_obsd_nat_target;
/* Determine if PT_GETREGS fetches REGNUM. */
static bool
getregs_supplies (int regnum)
{
return (regnum >= AARCH64_X0_REGNUM && regnum <= AARCH64_CPSR_REGNUM);
}
/* Determine if PT_GETFPREGS fetches REGNUM. */
static bool
getfpregs_supplies (int regnum)
{
return (regnum >= AARCH64_V0_REGNUM && regnum <= AARCH64_FPCR_REGNUM);
}
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
void
aarch64_obsd_nat_target::fetch_registers (struct regcache *regcache,
int regnum)
{
pid_t pid = get_ptrace_pid (regcache->ptid ());
if (regnum == -1 || getregs_supplies (regnum))
{
struct reg regs;
if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name (_("Couldn't get registers"));
regcache->supply_regset (&aarch64_obsd_gregset, regnum, ®s,
sizeof (regs));
}
if (regnum == -1 || getfpregs_supplies (regnum))
{
struct fpreg fpregs;
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't get floating point status"));
regcache->supply_regset (&aarch64_obsd_fpregset, regnum, &fpregs,
sizeof (fpregs));
}
}
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
void
aarch64_obsd_nat_target::store_registers (struct regcache *regcache,
int regnum)
{
pid_t pid = get_ptrace_pid (regcache->ptid ());
if (regnum == -1 || getregs_supplies (regnum))
{
struct reg regs;
if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name (_("Couldn't get registers"));
regcache->collect_regset (&aarch64_obsd_gregset, regnum, ®s,
sizeof (regs));
if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name (_("Couldn't write registers"));
}
if (regnum == -1 || getfpregs_supplies (regnum))
{
struct fpreg fpregs;
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't get floating point status"));
regcache->collect_regset (&aarch64_obsd_fpregset, regnum, &fpregs,
sizeof (fpregs));
if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name (_("Couldn't write floating point status"));
}
}
void
_initialize_aarch64_obsd_nat (void)
{
add_inf_child_target (&the_aarch64_obsd_nat_target);
}
/* OpenBSD/aarch64 target support, prototypes.
Copyright (C) 2017-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 <http://www.gnu.org/licenses/>. */
#ifndef AARCH64_OBSD_TDEP_H
#define AARCH64_OBSD_TDEP_H
#include "regset.h"
extern const struct regset aarch64_obsd_gregset;
extern const struct regset aarch64_obsd_fpregset;
#endif /* AARCH64_OBSD_TDEP_H */
/* Target-dependent code for OpenBSD/aarch64.
Copyright (C) 2006-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 "gdbarch.h"
#include "frame-unwind.h"
#include "osabi.h"
#include "regset.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "aarch64-tdep.h"
#include "aarch64-obsd-tdep.h"
#include "obsd-tdep.h"
#include "solib-svr4.h"
/* 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 CORE_ADDR aarch64obsd_page_size = 4096;
/* Offset for sigreturn(2). */
static const int aarch64obsd_sigreturn_offset[] = {
0xb4, /* OpenBSD 6.2 */
0x08, /* OpenBSD 6.1 */
-1
};
static int
aarch64obsd_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 & ~(aarch64obsd_page_size - 1));
const int *offset;
const char *name;
find_pc_partial_function (pc, &name, NULL, NULL);
if (name)
return 0;
for (offset = aarch64obsd_sigreturn_offset; *offset != -1; offset++)
{
gdb_byte buf[8];
unsigned long insn;
if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
buf, sizeof buf))
continue;
/* Check for "mov x8, #SYS_sigreturn". */
insn = extract_unsigned_integer (buf, 4, byte_order);
if (insn != 0xd2800ce8)
continue;
/* Check for "svc 0". */
insn = extract_unsigned_integer (buf + 4, 4, byte_order);
if (insn != 0xd4000001)
continue;
return 1;
}
return 0;
}
/*
In 6.1 the sp points to the struct sigframe. Since 6.2 the
sigtramp routine saves floating point registers on the stack
before the struct sigframe so that needs to be skipped to look
at sigframe. A sigframe looks like this:
struct sigframe {
int sf_signum;
struct sigcontext sf_sc;
siginfo_t sf_si;
};
struct sigcontext {
int __sc_unused;
int sc_mask;
unsigned long sc_sp;
unsigned long sc_lr;
unsigned long sc_elr;
unsigned long sc_spsr;
unsigned long sc_x[30];
long sc_cookie;
};
*/
#define AARCH64_SIGCONTEXT_REG_SIZE 8
#define AARCH64_SIGFRAME_SIGCONTEXT_OFFSET 8
#define AARCH64_SIGCONTEXT_SP_OFFSET 8
#define AARCH64_SIGCONTEXT_LR_OFFSET 16
#define AARCH64_SIGCONTEXT_PC_OFFSET 24
#define AARCH64_SIGCONTEXT_SPSR_OFFSET 32
#define AARCH64_SIGCONTEXT_X0_OFFSET 40
static struct trad_frame_cache *
aarch64obsd_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 sp, sigcontext_addr, x0_addr, func;
gdb_byte buf[4];
unsigned long insn, sigframe_offset = 0;
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 &= ~(aarch64obsd_page_size - 1);
if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
return cache;
/* Calculate the offset where we can find `struct sigframe'. In 6.1
no adjustment is needed so we look at the first instruction to see
if it matches 6.2+. If it is a 'sub sp, sp, #0xNNN' instruction,
use the amount of stack space to skip from it. */
insn = extract_unsigned_integer (buf, 4, byte_order);
if ((insn & 0xffc003ff) == 0xd10003ff)
sigframe_offset += ((insn & 0x003ffc00) >> 10);
sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
sigcontext_addr = sp + sigframe_offset + AARCH64_SIGFRAME_SIGCONTEXT_OFFSET;
x0_addr = sigcontext_addr + AARCH64_SIGCONTEXT_X0_OFFSET;
trad_frame_set_reg_addr (cache, AARCH64_SP_REGNUM,
sigcontext_addr + AARCH64_SIGCONTEXT_SP_OFFSET);
trad_frame_set_reg_addr (cache, AARCH64_LR_REGNUM,
sigcontext_addr + AARCH64_SIGCONTEXT_LR_OFFSET);
trad_frame_set_reg_addr (cache, AARCH64_PC_REGNUM,
sigcontext_addr + AARCH64_SIGCONTEXT_PC_OFFSET);
trad_frame_set_reg_addr (cache, AARCH64_CPSR_REGNUM,
sigcontext_addr + AARCH64_SIGCONTEXT_SPSR_OFFSET);
for (i = 0; i < 30; i++)
{
trad_frame_set_reg_addr (cache, AARCH64_X0_REGNUM + i,
x0_addr + i * AARCH64_SIGCONTEXT_REG_SIZE);
}
trad_frame_set_id (cache, frame_id_build (sp, func));
return cache;
}
static void
aarch64obsd_sigtramp_frame_this_id (struct frame_info *this_frame,
void **this_cache,
struct frame_id *this_id)
{
struct trad_frame_cache *cache =
aarch64obsd_sigtramp_frame_cache (this_frame, this_cache);
trad_frame_get_id (cache, this_id);
}
static struct value *
aarch64obsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
void **this_cache, int regnum)
{
struct trad_frame_cache *cache =
aarch64obsd_sigtramp_frame_cache (this_frame, this_cache);
return trad_frame_get_register (cache, this_frame, regnum);
}
static const struct frame_unwind aarch64obsd_sigtramp_frame_unwind = {
SIGTRAMP_FRAME,
default_frame_unwind_stop_reason,
aarch64obsd_sigtramp_frame_this_id,
aarch64obsd_sigtramp_frame_prev_register,
NULL,
aarch64obsd_sigtramp_frame_sniffer
};
/* The general-purpose regset consists of 31 X registers, plus SP, PC,
and SPSR and TPIDR registers. */
#define AARCH64_OBSD_SIZEOF_GREGSET (35 * X_REGISTER_SIZE)
/* The fp regset consists of 32 V registers, plus FPSR and FPCR which
are 4 bytes wide each, and the whole structure is padded to 128 bit
alignment. */
#define AARCH64_OBSD_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
/* Register maps. */
static const struct regcache_map_entry aarch64_obsd_gregmap[] =
{
{ 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */
{ 1, AARCH64_SP_REGNUM, 8 },
{ 1, AARCH64_PC_REGNUM, 8 },
{ 1, AARCH64_CPSR_REGNUM, 8 },
{ 0 }
};
static const struct regcache_map_entry aarch64_obsd_fpregmap[] =
{
{ 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
{ 1, AARCH64_FPSR_REGNUM, 4 },
{ 1, AARCH64_FPCR_REGNUM, 4 },
{ 0 }
};
/* Register set definitions. */
const struct regset aarch64_obsd_gregset =
{
aarch64_obsd_gregmap,
regcache_supply_regset, regcache_collect_regset
};
const struct regset aarch64_obsd_fpregset =
{
aarch64_obsd_fpregmap,
regcache_supply_regset, regcache_collect_regset
};
static void
aarch64_obsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
iterate_over_regset_sections_cb *cb,
void *cb_data,
const struct regcache *regcache)
{
cb (".reg", AARCH64_OBSD_SIZEOF_GREGSET, AARCH64_OBSD_SIZEOF_GREGSET,
&aarch64_obsd_gregset, NULL, cb_data);
cb (".reg2", AARCH64_OBSD_SIZEOF_FPREGSET, AARCH64_OBSD_SIZEOF_FPREGSET,
&aarch64_obsd_fpregset, NULL, cb_data);
}
static void
aarch64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
obsd_init_abi (info, gdbarch);
/* OpenBSD/aarch64 uses SVR4-style shared libraries. */
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
frame_unwind_append_unwinder (gdbarch, &aarch64obsd_sigtramp_frame_unwind);
/* Enable longjmp. */
tdep->jb_pc = 13;
set_gdbarch_iterate_over_regset_sections
(gdbarch, aarch64_obsd_iterate_over_regset_sections);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_aarch64obsd_tdep;
void
_initialize_aarch64obsd_tdep (void)
{
gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_OPENBSD,
aarch64obsd_init_abi);
}
> Date: Fri, 17 Sep 2021 13:58:46 +0200 (CEST)
> From: Mark Kettenis <mark.kettenis@xs4all.nl>
>
> > From: Jeremie Courreges-Anglas <jca@wxcvbn.org>
> > Date: Fri, 17 Sep 2021 13:43:19 +0200
> >
> > On Fri, Sep 17 2021, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > >> From: Jeremie Courreges-Anglas <jca@wxcvbn.org>
> > >> Date: Fri, 17 Sep 2021 13:23:58 +0200
> > >>
> > >> On Sat, Sep 04 2021, Jeremie Courreges-Anglas <jca@wxcvbn.org> wrote:
> > >> > On Fri, Sep 03 2021, Jeremie Courreges-Anglas <jca@wxcvbn.org> wrote:
> > >> >> So here's the result of the torture I've been doing to my self during
> > >> >> this hackathon. gdb-10.x inferior target support is broken for reasons
> > >> >> I still ignore and I've been told that moving to 9.x was already nice
> > >> >> enough. :)
> > >> >>
> > >> >> Regarding the changes below:
> > >> >> - DEBUG_PACKAGES, reminded by sthen@
> > >> >> - disable mpfr, linking against libgmp.a breaks on powerpc with
> > >> >> relocation errors
> > >> >> - xxhash support added, just because it took me less time to just add
> > >> >> the dep. I didn't actually check for all possible new hidden deps
> > >> >
> > >> > To keep things simple I just force-disabled everything that seemed
> > >> > relevant.
> > >> >
> > >> >> - CFLAGS tweak maybe not needed any more? If this actually requires
> > >> >> C11 or C++11 support, COMPILER should be changed
> > >> >
> > >> > The port now requires C++11 support and thus base-clang or ports-gcc
> > >> > (tested on sparc64 with COMPILER=base-gcc). Both base-clang and
> > >> > ports-gcc default to C17 so no need to specify -std=gnu11.
> > >> >
> > >> > So along with m88k this also kills egdb support on sh (no idea whether
> > >> > it actually built/worked there, I only know that one file was patched).
> > >> > I don't consider this as a showstopper. If people care about egdb on
> > >> > those architectures it should be possible to add a devel/gdb-7 port.
> > >> >
> > >> >> - upstream moved file named <arch><system> to <arch>-<system> so I moved
> > >> >> our files too, sorry for the churn.
> > >> >> - I also had to adapt our aarch64 and powerpc64 support patches to the
> > >> >> API changes that happened upstream
> > >> >> - i386 needed special love, some changes that happened in there haven't
> > >> >> been compile tested
> > >> >> - the ptid_get_pid->get_ptrace_pid issue has been solved upstream, so
> > >> >> a bunch of patches get removed
> > >> >> - some of the configure.nat dedup changes aren't strictly needed but
> > >> >> they just seem better in the long term. For example some of our
> > >> >> architectures didn't use bsd-kvm.c/libkvm.
> > >> >> - OpenBSD/riscv64 support files shamelessly copied from the FreeBSD
> > >> >> support (thanks!). Besides mechanical renaming, I think it's the only
> > >> >> relevant change I made there. riscv64 support means we can read
> > >> >> coredumps and print backtraces. We can't do inferior process
> > >> >> debugging yet because we just don't support PT_STEP (this may also be
> > >> >> a problem on other architectures). We also need a kernel diff that
> > >> >> I haven't sent yet.
> > >> >> - m88k support has been removed, sorry aoyama@ :-/
> > >> >> - the python patch isn't needed anymore
> > >> >
> > >> > - added in the diff below: two hunks to keep building on OpenBSD/armv7,
> > >> > I had lost those bits initially present in Pascal's update to 8.2.1.
> > >> >
> > >> >> Thanks to all the folks who helped me test a previous diff on various
> > >> >> architectures! Even if there are still open questions (and I may have
> > >> >> forgotten some so reviews would be welcome), I hope we can commit this
> > >> >> update before tagging OpenBSD 7.0. Therefore I'll need another round of
> > >> >> tests!
> > >> >>
> > >> >> Things to test with -current devel/gdb *and* after applying the diff below:
> > >> >> - egdb -ex run <dynamic program> # for example du
> > >> >> - egdb -ex run <static program> # for example ls
> > >> >
> > >> > More complete/automated tests:
> > >> > - egdb -ex 'b main' -ex run -ex bt -ex continue -ex q /usr/src/usr.bin/du/obj/du
> > >> > - egdb -ex 'b main' -ex run -ex bt -ex continue -ex q /usr/src/bin/ls/obj/ls
> > >> >
> > >> >> - reading a coredump and printing a backtrace
> > >> >> - ?
> > >>
> > >> Updated diff after some tweaks and successful tests by jj@ on octeon.
> > >>
> > >> arch-specific test reports so far:
> > >> - ok: amd64, riscv64, sparc64, i386, powerpc, powerpc64, octeon
> > >> - not ok: arm64 (don't know how to run)
> > >> - unknown: alpha, armv7, hppa, loongson
> > >> - not applicable: sh, m88k
> > >>
> > >> Apart from the "unknown" architectures above, new tests on arm64 would
> > >> be sweet. The support for native inferior target should be hooked up
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >> now - but it may fail to build.
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > >>
> > >> (gdb-9.2-8.diff)
> > >
> > > Not sure what I'm doing wrong, but for me arm64 doesn't even build...
> >
> > I would suspect errors compiling aarch64-obsd-nat.c, right? If you send
> > me the error log I might be able to fix them.
>
> Yes. I can fix it myself, such that you can concentrate on the other
> missing bits. It's just that your message suggests it builds but
> doesn't run properly. So I was trying to avoid work you have already
> done ;).
The files below are what I came up with to make arm64 build. Some
light testing suggests that it actually works! I attached the files I
changed (aarch64-obsd-tdep.h is new). That should allow you to update
the diff. The files can also be found in my home dir on cvs.
No comments:
Post a Comment