binutils-gdb/gdb/sparc64-sol2-tdep.c
Joel Brobecker a9762ec78a Switch the license of all .c files to GPLv3.
Switch the license of all .h files to GPLv3.
        Switch the license of all .cc files to GPLv3.
2007-08-23 18:08:50 +00:00

184 lines
5.5 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Target-dependent code for Solaris UltraSPARC.
Copyright (C) 2003, 2004, 2006, 2007 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 "frame.h"
#include "frame-unwind.h"
#include "gdbarch.h"
#include "symtab.h"
#include "objfiles.h"
#include "osabi.h"
#include "trad-frame.h"
#include "gdb_assert.h"
#include "sol2-tdep.h"
#include "sparc64-tdep.h"
#include "solib-svr4.h"
/* From <sys/regset.h>. */
const struct sparc_gregset sparc64_sol2_gregset =
{
32 * 8, /* "tstate" */
33 * 8, /* %pc */
34 * 8, /* %npc */
35 * 8, /* %y */
-1, /* %wim */
-1, /* %tbr */
1 * 8, /* %g1 */
16 * 8, /* %l0 */
8 /* sizeof (%y) */
};
static struct sparc_frame_cache *
sparc64_sol2_sigtramp_frame_cache (struct frame_info *next_frame,
void **this_cache)
{
struct sparc_frame_cache *cache;
CORE_ADDR mcontext_addr, addr;
int regnum;
if (*this_cache)
return *this_cache;
cache = sparc_frame_cache (next_frame, this_cache);
gdb_assert (cache == *this_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
/* The third argument is a pointer to an instance of `ucontext_t',
which has a member `uc_mcontext' that contains the saved
registers. */
regnum = (cache->frameless_p ? SPARC_O2_REGNUM : SPARC_I2_REGNUM);
mcontext_addr = frame_unwind_register_unsigned (next_frame, regnum) + 64;
cache->saved_regs[SPARC64_CCR_REGNUM].addr = mcontext_addr + 0 * 8;
cache->saved_regs[SPARC64_PC_REGNUM].addr = mcontext_addr + 1 * 8;
cache->saved_regs[SPARC64_NPC_REGNUM].addr = mcontext_addr + 2 * 8;
cache->saved_regs[SPARC64_Y_REGNUM].addr = mcontext_addr + 3 * 8;
cache->saved_regs[SPARC64_ASI_REGNUM].addr = mcontext_addr + 19 * 8;
cache->saved_regs[SPARC64_FPRS_REGNUM].addr = mcontext_addr + 20 * 8;
/* Since %g0 is always zero, keep the identity encoding. */
for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 4 * 8;
regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
cache->saved_regs[regnum].addr = addr;
if (get_frame_memory_unsigned (next_frame, mcontext_addr + 21 * 8, 8))
{
/* The register windows haven't been flushed. */
for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
trad_frame_set_unknown (cache->saved_regs, regnum);
}
else
{
CORE_ADDR sp;
addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
sp = get_frame_memory_unsigned (next_frame, addr, 8);
for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
cache->saved_regs[regnum].addr = addr;
}
return cache;
}
static void
sparc64_sol2_sigtramp_frame_this_id (struct frame_info *next_frame,
void **this_cache,
struct frame_id *this_id)
{
struct sparc_frame_cache *cache =
sparc64_sol2_sigtramp_frame_cache (next_frame, this_cache);
(*this_id) = frame_id_build (cache->base, cache->pc);
}
static void
sparc64_sol2_sigtramp_frame_prev_register (struct frame_info *next_frame,
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp,
CORE_ADDR *addrp,
int *realnump, gdb_byte *valuep)
{
struct sparc_frame_cache *cache =
sparc64_sol2_sigtramp_frame_cache (next_frame, this_cache);
trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
}
static const struct frame_unwind sparc64_sol2_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
sparc64_sol2_sigtramp_frame_this_id,
sparc64_sol2_sigtramp_frame_prev_register
};
static const struct frame_unwind *
sparc64_sol2_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
char *name;
find_pc_partial_function (pc, &name, NULL, NULL);
if (sparc_sol2_pc_in_sigtramp (pc, name))
return &sparc64_sol2_sigtramp_frame_unwind;
return NULL;
}
void
sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
frame_unwind_append_sniffer (gdbarch, sparc64_sol2_sigtramp_frame_sniffer);
sparc64_init_abi (info, gdbarch);
/* Solaris has SVR4-style shared libraries... */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_gdbarch_skip_solib_resolver (gdbarch, sol2_skip_solib_resolver);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
/* ...which means that we need some special handling when doing
prologue analysis. */
tdep->plt_entry_size = 16;
/* Solaris has kernel-assisted single-stepping support. */
set_gdbarch_software_single_step (gdbarch, NULL);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_sparc64_sol2_tdep (void);
void
_initialize_sparc64_sol2_tdep (void)
{
gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
GDB_OSABI_SOLARIS, sparc64_sol2_init_abi);
}