/* Target-dependent mdebug code for the ALPHA architecture.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2007, 2008 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
+ 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,
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
#include "block.h"
#include "gdb_assert.h"
+#include "gdb_string.h"
+#include "trad-frame.h"
#include "alpha-tdep.h"
#include "mdebugread.h"
struct block *b = block_for_pc (pc);
struct mdebug_extra_func_info *proc_desc = NULL;
struct symbol *sym = NULL;
+ char *sh_name = NULL;
if (b)
{
CORE_ADDR startaddr;
- find_pc_partial_function (pc, NULL, &startaddr, NULL);
+ find_pc_partial_function (pc, &sh_name, &startaddr, NULL);
if (startaddr > BLOCK_START (b))
/* This is the "pathological" case referred to in a comment in
symbol reading. */
sym = NULL;
else
- sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
+ sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0);
}
if (sym)
{
proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym);
+ /* Correct incorrect setjmp procedure descriptor from the library
+ to make backtrace through setjmp work. */
+ if (proc_desc->pdr.pcreg == 0
+ && strcmp (sh_name, "setjmp") == 0)
+ {
+ proc_desc->pdr.pcreg = ALPHA_RA_REGNUM;
+ proc_desc->pdr.regmask = 0x80000000;
+ proc_desc->pdr.regoffset = -4;
+ }
+
/* If we never found a PDR for this function in symbol reading,
then examine prologues to find the information. */
if (proc_desc->pdr.framereg == -1)
{
struct mdebug_extra_func_info *proc_desc;
CORE_ADDR vfp;
- CORE_ADDR *saved_regs;
+ struct trad_frame_saved_reg *saved_regs;
};
/* Extract all of the information about the frame from PROC_DESC
and store the resulting register save locations in the structure. */
static struct alpha_mdebug_unwind_cache *
-alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame,
+alpha_mdebug_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct alpha_mdebug_unwind_cache *info;
info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
*this_prologue_cache = info;
- pc = frame_pc_unwind (next_frame);
+ pc = get_frame_pc (this_frame);
/* ??? We don't seem to be able to cache the lookup of the PDR
from alpha_mdebug_frame_p. It'd be nice if we could change
info->proc_desc = proc_desc;
gdb_assert (proc_desc != NULL);
- info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */
- frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp);
+ vfp = get_frame_register_unsigned (this_frame, PROC_FRAME_REG (proc_desc));
vfp += PROC_FRAME_OFFSET (info->proc_desc);
info->vfp = vfp;
/* Clear bit for RA so we don't save it again later. */
mask &= ~(1 << returnreg);
- info->saved_regs[returnreg] = reg_position;
+ info->saved_regs[returnreg].addr = reg_position;
reg_position += 8;
}
for (ireg = 0; ireg <= 31; ++ireg)
if (mask & (1 << ireg))
{
- info->saved_regs[ireg] = reg_position;
+ info->saved_regs[ireg].addr = reg_position;
reg_position += 8;
}
for (ireg = 0; ireg <= 31; ++ireg)
if (mask & (1 << ireg))
{
- info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
+ info->saved_regs[ALPHA_FP0_REGNUM + ireg].addr = reg_position;
reg_position += 8;
}
+ /* The stack pointer of the previous frame is computed by popping
+ the current stack frame. */
+ if (!trad_frame_addr_p (info->saved_regs, ALPHA_SP_REGNUM))
+ trad_frame_set_value (info->saved_regs, ALPHA_SP_REGNUM, vfp);
+
return info;
}
frame. This will be used to create a new GDB frame struct. */
static void
-alpha_mdebug_frame_this_id (struct frame_info *next_frame,
+alpha_mdebug_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache,
struct frame_id *this_id)
{
struct alpha_mdebug_unwind_cache *info
- = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+ = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
- *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame));
+ *this_id = frame_id_build (info->vfp, get_frame_func (this_frame));
}
/* Retrieve the value of REGNUM in FRAME. Don't give up! */
-static void
-alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *bufferp)
+static struct value *
+alpha_mdebug_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct alpha_mdebug_unwind_cache *info
- = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+ = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
/* The PC of the previous frame is stored in the link register of
the current frame. Frob regnum so that we pull the value from
if (regnum == ALPHA_PC_REGNUM)
regnum = PROC_PC_REG (info->proc_desc);
- /* For all registers known to be saved in the current frame,
- do the obvious and pull the value out. */
- if (info->saved_regs[regnum])
- {
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = info->saved_regs[regnum];
- *realnump = -1;
- if (bufferp != NULL)
- get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
- return;
- }
-
- /* The stack pointer of the previous frame is computed by popping
- the current stack frame. */
- if (regnum == ALPHA_SP_REGNUM)
- {
- *optimizedp = 0;
- *lvalp = not_lval;
- *addrp = 0;
- *realnump = -1;
- if (bufferp != NULL)
- store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
- return;
- }
-
- /* Otherwise assume the next frame has the same register value. */
- frame_register (next_frame, regnum, optimizedp, lvalp, addrp,
- realnump, bufferp);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
-static const struct frame_unwind alpha_mdebug_frame_unwind = {
- NORMAL_FRAME,
- alpha_mdebug_frame_this_id,
- alpha_mdebug_frame_prev_register
-};
-
-const struct frame_unwind *
-alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
+static int
+alpha_mdebug_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_cache)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = get_frame_address_in_block (this_frame);
struct mdebug_extra_func_info *proc_desc;
/* If this PC does not map to a PDR, then clearly this isn't an
mdebug frame. */
proc_desc = find_proc_desc (pc);
if (proc_desc == NULL)
- return NULL;
+ return 0;
/* If we're in the prologue, the PDR for this frame is not yet valid.
Say no here and we'll fall back on the heuristic unwinder. */
if (alpha_mdebug_in_prologue (pc, proc_desc))
- return NULL;
+ return 0;
- return &alpha_mdebug_frame_unwind;
+ return 1;
}
+static const struct frame_unwind alpha_mdebug_frame_unwind = {
+ NORMAL_FRAME,
+ alpha_mdebug_frame_this_id,
+ alpha_mdebug_frame_prev_register,
+ NULL,
+ alpha_mdebug_frame_sniffer
+};
+
static CORE_ADDR
-alpha_mdebug_frame_base_address (struct frame_info *next_frame,
+alpha_mdebug_frame_base_address (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct alpha_mdebug_unwind_cache *info
- = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+ = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
return info->vfp;
}
static CORE_ADDR
-alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
+alpha_mdebug_frame_locals_address (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct alpha_mdebug_unwind_cache *info
- = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+ = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
return info->vfp - PROC_LOCALOFF (info->proc_desc);
}
static CORE_ADDR
-alpha_mdebug_frame_args_address (struct frame_info *next_frame,
+alpha_mdebug_frame_args_address (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct alpha_mdebug_unwind_cache *info
- = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+ = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
return info->vfp - ALPHA_NUM_ARG_REGS * 8;
}
};
static const struct frame_base *
-alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
+alpha_mdebug_frame_base_sniffer (struct frame_info *this_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
+ CORE_ADDR pc = get_frame_address_in_block (this_frame);
struct mdebug_extra_func_info *proc_desc;
/* If this PC does not map to a PDR, then clearly this isn't an
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &alpha_mdebug_frame_unwind);
frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
}