mirror of
https://git.freebsd.org/ports.git
synced 2025-07-18 01:39:16 -04:00
This includes an update to the bundled libc++ pretty printers with fixes for recent changes in libc++ to std::string and std::unordered_map. PR: 272922 Sponsored by: AFRL, DARPA Differential Revision: https://reviews.freebsd.org/D46232
259 lines
8.3 KiB
C
259 lines
8.3 KiB
C
/*-
|
|
* Copyright (c) 2006 Marcel Moolenaar
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "defs.h"
|
|
#include "frame-unwind.h"
|
|
#include "gdbcore.h"
|
|
#include "osabi.h"
|
|
#include "regcache.h"
|
|
#include "solib.h"
|
|
#include "symtab.h"
|
|
#include "trad-frame.h"
|
|
#include "ppc-tdep.h"
|
|
#include "ppc64-tdep.h"
|
|
|
|
#ifdef __powerpc__
|
|
#include <machine/pcb.h>
|
|
#include <machine/frame.h>
|
|
#endif
|
|
|
|
#include "kgdb.h"
|
|
|
|
#define PCB_OFF_R12 0
|
|
#define PCB_OFF_CR 20
|
|
#define PCB_OFF_SP 21
|
|
#define PCB_OFF_TOC 22
|
|
#define PCB_OFF_LR 23
|
|
|
|
#ifdef __powerpc__
|
|
_Static_assert(offsetof(struct pcb, pcb_context)
|
|
== PCB_OFF_R12 * sizeof(register_t), "r12 offset");
|
|
_Static_assert(offsetof(struct pcb, pcb_cr) == PCB_OFF_CR * sizeof(register_t),
|
|
"cr offset");
|
|
_Static_assert(offsetof(struct pcb, pcb_sp) == PCB_OFF_SP * sizeof(register_t),
|
|
"sp offset");
|
|
_Static_assert(offsetof(struct pcb, pcb_toc) == PCB_OFF_TOC * sizeof(register_t),
|
|
"toc offset");
|
|
_Static_assert(offsetof(struct pcb, pcb_lr) == PCB_OFF_LR * sizeof(register_t),
|
|
"lr offset");
|
|
#endif
|
|
|
|
static void
|
|
ppcfbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr)
|
|
{
|
|
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (regcache->arch ());
|
|
gdb_byte buf[24 * tdep->wordsize];
|
|
int i;
|
|
|
|
/* Always give a value for PC in case the PCB isn't readable. */
|
|
regcache->raw_supply_zeroed (PPC_PC_REGNUM);
|
|
if (target_read_memory (pcb_addr, buf, sizeof buf) != 0)
|
|
return;
|
|
|
|
/* r12 - r31 */
|
|
for (i = 0; i < 20; i++)
|
|
regcache->raw_supply (tdep->ppc_gp0_regnum + 12 + i,
|
|
buf + tdep->wordsize * i);
|
|
|
|
/* r1 is saved in the sp field */
|
|
regcache->raw_supply (tdep->ppc_gp0_regnum + 1,
|
|
buf + tdep->wordsize * PCB_OFF_SP);
|
|
|
|
if (tdep->wordsize == 8)
|
|
/* r2 is saved in the toc field */
|
|
regcache->raw_supply (tdep->ppc_gp0_regnum + 2,
|
|
buf + tdep->wordsize * PCB_OFF_TOC);
|
|
|
|
regcache->raw_supply (tdep->ppc_lr_regnum, buf + tdep->wordsize * PCB_OFF_LR);
|
|
regcache->raw_supply (PPC_PC_REGNUM, buf + tdep->wordsize * PCB_OFF_LR);
|
|
regcache->raw_supply (tdep->ppc_cr_regnum, buf + tdep->wordsize * PCB_OFF_CR);
|
|
}
|
|
|
|
#define OFF_FIXREG 0
|
|
#define OFF_LR 32
|
|
#define OFF_CR 33
|
|
#define OFF_XER 34
|
|
#define OFF_CTR 35
|
|
#define OFF_SRR0 36
|
|
#define TRAPFRAME_SIZE 42
|
|
|
|
#ifdef __powerpc__
|
|
_Static_assert(sizeof(struct trapframe) == TRAPFRAME_SIZE * sizeof(register_t),
|
|
"trapframe size");
|
|
_Static_assert(offsetof(struct trapframe, fixreg)
|
|
== OFF_FIXREG * sizeof(register_t), "fixreg offset");
|
|
_Static_assert(offsetof(struct trapframe, lr) == OFF_LR * sizeof(register_t),
|
|
"lr offset");
|
|
_Static_assert(offsetof(struct trapframe, cr) == OFF_CR * sizeof(register_t),
|
|
"cr offset");
|
|
_Static_assert(offsetof(struct trapframe, xer) == OFF_XER * sizeof(register_t),
|
|
"xer offset");
|
|
_Static_assert(offsetof(struct trapframe, ctr) == OFF_CTR * sizeof(register_t),
|
|
"ctr offset");
|
|
_Static_assert(offsetof(struct trapframe, srr0)
|
|
== OFF_SRR0 * sizeof(register_t), "srr0 offset");
|
|
#endif
|
|
|
|
static struct trad_frame_cache *
|
|
ppcfbsd_trapframe_cache (const frame_info_ptr &this_frame, void **this_cache)
|
|
{
|
|
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
|
struct trad_frame_cache *cache;
|
|
CORE_ADDR base;
|
|
int i;
|
|
|
|
if (*this_cache)
|
|
return (struct trad_frame_cache *)*this_cache;
|
|
|
|
cache = trad_frame_cache_zalloc (this_frame);
|
|
*this_cache = cache;
|
|
|
|
base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
|
|
if (tdep->wordsize == 8)
|
|
base += 48;
|
|
else
|
|
base += 8;
|
|
|
|
for (i = 0; i < ppc_num_gprs; i++)
|
|
trad_frame_set_reg_addr (cache, tdep->ppc_gp0_regnum + i, base
|
|
+ (OFF_FIXREG + i) * tdep->wordsize);
|
|
trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, base
|
|
+ OFF_LR * tdep->wordsize);
|
|
trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, base
|
|
+ OFF_CR * tdep->wordsize);
|
|
trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, base
|
|
+ OFF_XER * tdep->wordsize);
|
|
trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, base
|
|
+ OFF_CTR * tdep->wordsize);
|
|
/* SRR0? */
|
|
trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), base
|
|
+ OFF_SRR0 * tdep->wordsize);
|
|
|
|
/* Construct the frame ID using the function start. */
|
|
trad_frame_set_id (cache, frame_id_build (base, get_frame_func (this_frame)));
|
|
|
|
return cache;
|
|
}
|
|
|
|
static void
|
|
ppcfbsd_trapframe_this_id (const frame_info_ptr &this_frame,
|
|
void **this_cache, struct frame_id *this_id)
|
|
{
|
|
struct trad_frame_cache *cache =
|
|
ppcfbsd_trapframe_cache (this_frame, this_cache);
|
|
|
|
trad_frame_get_id (cache, this_id);
|
|
}
|
|
|
|
static struct value *
|
|
ppcfbsd_trapframe_prev_register (const frame_info_ptr &this_frame,
|
|
void **this_cache, int regnum)
|
|
{
|
|
struct trad_frame_cache *cache =
|
|
ppcfbsd_trapframe_cache (this_frame, this_cache);
|
|
|
|
return trad_frame_get_register (cache, this_frame, regnum);
|
|
}
|
|
|
|
static int
|
|
ppcfbsd_trapframe_sniffer (const struct frame_unwind *self,
|
|
const frame_info_ptr &this_frame,
|
|
void **this_cache)
|
|
{
|
|
CORE_ADDR pc;
|
|
const char *name;
|
|
|
|
pc = get_frame_func (this_frame);
|
|
find_pc_partial_function (pc, &name, NULL, NULL);
|
|
if (name && (strcmp(name, "trapagain") == 0
|
|
|| strcmp(name, "trapexit") == 0
|
|
|| strcmp(name, "dbtrap") == 0))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct frame_unwind ppcfbsd_trapframe_unwind =
|
|
{
|
|
"ppc FreeBSD kernel trap",
|
|
SIGTRAMP_FRAME,
|
|
default_frame_unwind_stop_reason,
|
|
ppcfbsd_trapframe_this_id,
|
|
ppcfbsd_trapframe_prev_register,
|
|
NULL,
|
|
ppcfbsd_trapframe_sniffer
|
|
};
|
|
|
|
static void
|
|
ppcfbsd_kernel_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
|
|
|
frame_unwind_prepend_unwinder(gdbarch, &ppcfbsd_trapframe_unwind);
|
|
|
|
set_gdbarch_so_ops(gdbarch, &kld_so_ops);
|
|
|
|
fbsd_vmcore_set_supply_pcb(gdbarch, ppcfbsd_supply_pcb);
|
|
fbsd_vmcore_set_cpu_pcb_addr(gdbarch, kgdb_trgt_stop_pcb);
|
|
|
|
/* FreeBSD 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);
|
|
|
|
if (tdep->wordsize == 4)
|
|
{
|
|
set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
|
|
}
|
|
|
|
if (tdep->wordsize == 8)
|
|
{
|
|
set_gdbarch_convert_from_func_ptr_addr
|
|
(gdbarch, ppc64_convert_from_func_ptr_addr);
|
|
set_gdbarch_elf_make_msymbol_special (gdbarch,
|
|
ppc64_elf_make_msymbol_special);
|
|
}
|
|
}
|
|
|
|
void _initialize_ppc_kgdb_tdep ();
|
|
void
|
|
_initialize_ppc_kgdb_tdep ()
|
|
{
|
|
gdbarch_register_osabi_sniffer(bfd_arch_powerpc,
|
|
bfd_target_elf_flavour,
|
|
fbsd_kernel_osabi_sniffer);
|
|
gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc,
|
|
GDB_OSABI_FREEBSD_KERNEL, ppcfbsd_kernel_init_abi);
|
|
gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64,
|
|
GDB_OSABI_FREEBSD_KERNEL, ppcfbsd_kernel_init_abi);
|
|
|
|
/* Not sure about this one. */
|
|
gdbarch_register_osabi_sniffer(bfd_arch_rs6000,
|
|
bfd_target_elf_flavour,
|
|
fbsd_kernel_osabi_sniffer);
|
|
gdbarch_register_osabi (bfd_arch_rs6000, 0,
|
|
GDB_OSABI_FREEBSD_KERNEL, ppcfbsd_kernel_init_abi);
|
|
}
|