2003-06-08 Andrew Cagney <cagney@redhat.com>

* Makefile.in (d10v-tdep.o): Update dependencies.
	(SFILES): Add trad-frame.c.
	(trad_frame_h): Define.
	(COMMON_OBS): Add trad-frame.o.
	(trad-frame.o): Specify dependencies.
	* d10v-tdep.c: Include "trad-frame.h".
	(saved_regs_unwinder): Delete function.
	(d10v_frame_prev_register): Use trad_frame_prev_register.
	(struct d10v_unwind_cache): Change type of "saved_regs" to "struct
	trad_frame", delete "regs" and "prev_sp".
	(prologue_find_regs): Use trad-frame.
	* trad-frame.h, trad-frame.c: New files.
This commit is contained in:
Andrew Cagney 2003-06-08 16:09:46 +00:00
parent 0b9a4d73a8
commit a0f267c701
5 changed files with 209 additions and 97 deletions

View file

@ -1,3 +1,18 @@
2003-06-08 Andrew Cagney <cagney@redhat.com>
* Makefile.in (d10v-tdep.o): Update dependencies.
(SFILES): Add trad-frame.c.
(trad_frame_h): Define.
(COMMON_OBS): Add trad-frame.o.
(trad-frame.o): Specify dependencies.
* d10v-tdep.c: Include "trad-frame.h".
(saved_regs_unwinder): Delete function.
(d10v_frame_prev_register): Use trad_frame_prev_register.
(struct d10v_unwind_cache): Change type of "saved_regs" to "struct
trad_frame", delete "regs" and "prev_sp".
(prologue_find_regs): Use trad-frame.
* trad-frame.h, trad-frame.c: New files.
2003-06-08 Mark Kettenis <kettenis@gnu.org>
* dwarf2cfi.c, dwarf2cfi.h: Remove.

View file

@ -540,7 +540,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
sentinel-frame.c \
serial.c ser-unix.c source.c \
stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
target.c thread.c top.c tracepoint.c typeprint.c \
target.c thread.c top.c tracepoint.c \
trad-frame.c \
typeprint.c \
tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \
tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \
tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \
@ -729,6 +731,7 @@ symtab_h = symtab.h
target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h)
terminal_h = terminal.h
top_h = top.h
trad_frame_h = trad-frame.h
infttrace_h = infttrace.h
tracepoint_h = tracepoint.h
typeprint_h = typeprint.h
@ -871,7 +874,8 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
frame-base.o \
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
cp-namespace.o \
reggroups.o
reggroups.o \
trad-frame.o
OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
@ -1643,9 +1647,9 @@ cris-tdep.o: cris-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(inferior_h) \
d10v-tdep.o: d10v-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
$(frame_base_h) $(symtab_h) $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) \
$(gdb_string_h) $(value_h) $(inferior_h) $(dis_asm_h) $(symfile_h) \
$(objfiles_h) $(language_h) $(arch_utils_h) $(regcache_h) \
$(remote_h) $(floatformat_h) $(gdb_sim_d10v_h) $(sim_regno_h) \
$(gdb_assert_h) $(disasm_h)
$(objfiles_h) $(language_h) $(arch_utils_h) $(regcache_h) $(remote_h) \
$(floatformat_h) $(gdb_sim_d10v_h) $(sim_regno_h) $(disasm_h) \
$(trad_frame_h) $(gdb_assert_h)
dbug-rom.o: dbug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
$(serial_h) $(regcache_h) $(m68k_tdep_h)
dbxread.o: dbxread.c $(defs_h) $(gdb_string_h) $(gdb_obstack_h) \
@ -2309,6 +2313,7 @@ tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \
$(gdb_string_h) $(inferior_h) $(tracepoint_h) $(remote_h) \
$(linespec_h) $(regcache_h) $(completer_h) $(gdb_events_h) \
$(block_h) $(ax_h) $(ax_gdb_h) $(readline_h)
trad-frame.o: trad-frame.c $(defs_h) $(frame_h) $(trad_frame_h) $(regcache_h)
typeprint.o: typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \
$(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(command_h) \
$(gdbcmd_h) $(target_h) $(language_h) $(cp_abi_h) $(gdb_string_h)

View file

@ -44,6 +44,7 @@
#include "gdb/sim-d10v.h"
#include "sim-regno.h"
#include "disasm.h"
#include "trad-frame.h"
#include "gdb_assert.h"
@ -569,14 +570,14 @@ struct d10v_unwind_cache
/* The frame's base, optionally used by the high-level debug info. */
CORE_ADDR base;
int size;
CORE_ADDR *saved_regs;
/* How far the SP and r11 (FP) have been offset from the start of
the stack frame (as defined by the previous frame's stack
pointer). */
LONGEST sp_offset;
LONGEST r11_offset;
int uses_frame;
void **regs;
/* Table indicating the location of each and every register. */
struct trad_frame *saved_regs;
};
static int
@ -590,7 +591,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
{
n = (op & 0x1E0) >> 5;
info->sp_offset -= 2;
info->saved_regs[n] = info->sp_offset;
info->saved_regs[n].addr = info->sp_offset;
return 1;
}
@ -599,8 +600,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
{
n = (op & 0x1E0) >> 5;
info->sp_offset -= 4;
info->saved_regs[n] = info->sp_offset;
info->saved_regs[n + 1] = info->sp_offset + 2;
info->saved_regs[n + 0].addr = info->sp_offset + 0;
info->saved_regs[n + 1].addr = info->sp_offset + 2;
return 1;
}
@ -626,7 +627,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
if ((op & 0x7E1F) == 0x6816)
{
n = (op & 0x1E0) >> 5;
info->saved_regs[n] = info->r11_offset;
info->saved_regs[n].addr = info->r11_offset;
return 1;
}
@ -638,7 +639,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
if ((op & 0x7E1F) == 0x681E)
{
n = (op & 0x1E0) >> 5;
info->saved_regs[n] = info->sp_offset;
info->saved_regs[n].addr = info->sp_offset;
return 1;
}
@ -646,8 +647,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
if ((op & 0x7E3F) == 0x3A1E)
{
n = (op & 0x1E0) >> 5;
info->saved_regs[n] = info->sp_offset;
info->saved_regs[n + 1] = info->sp_offset + 2;
info->saved_regs[n + 0].addr = info->sp_offset + 0;
info->saved_regs[n + 1].addr = info->sp_offset + 2;
return 1;
}
@ -678,7 +679,7 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
info = FRAME_OBSTACK_ZALLOC (struct d10v_unwind_cache);
(*this_prologue_cache) = info;
info->saved_regs = FRAME_OBSTACK_CALLOC (NUM_REGS, CORE_ADDR);
info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
info->size = 0;
info->sp_offset = 0;
@ -703,15 +704,15 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
/* st rn, @(offset,sp) */
short offset = op & 0xFFFF;
short n = (op >> 20) & 0xF;
info->saved_regs[n] = info->sp_offset + offset;
info->saved_regs[n].addr = info->sp_offset + offset;
}
else if ((op & 0x3F1F0000) == 0x350F0000)
{
/* st2w rn, @(offset,sp) */
short offset = op & 0xFFFF;
short n = (op >> 20) & 0xF;
info->saved_regs[n] = info->sp_offset + offset;
info->saved_regs[n + 1] = info->sp_offset + offset + 2;
info->saved_regs[n + 0].addr = info->sp_offset + offset + 0;
info->saved_regs[n + 1].addr = info->sp_offset + offset + 2;
}
else
break;
@ -737,7 +738,8 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
info->size = -info->sp_offset;
/* Compute the frame's base, and the previous frame's SP. */
/* Compute the previous frame's stack pointer (which is also the
frame's ID's stack address), and this frame's base pointer. */
if (info->uses_frame)
{
/* The SP was moved to the FP. This indicates that a new frame
@ -748,16 +750,6 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
to before the first saved register giving the SP. */
prev_sp = this_base + info->size;
}
else if (info->saved_regs[D10V_SP_REGNUM])
{
/* The SP was saved (which is very unusual), the frame base is
just the PREV's frame's TOP-OF-STACK. */
this_base
= get_frame_memory_unsigned (next_frame,
info->saved_regs[D10V_SP_REGNUM],
register_size (gdbarch, D10V_SP_REGNUM));
prev_sp = this_base;
}
else
{
/* Assume that the FP is this frame's SP but with that pushed
@ -766,20 +758,28 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
prev_sp = this_base + info->size;
}
/* Convert that SP/BASE into real addresses. */
info->prev_sp = d10v_make_daddr (prev_sp);
info->base = d10v_make_daddr (this_base);
info->prev_sp = d10v_make_daddr (prev_sp);
/* Adjust all the saved registers so that they contain addresses and
not offsets. */
for (i = 0; i < NUM_REGS - 1; i++)
if (info->saved_regs[i])
if (info->saved_regs[i].addr)
{
info->saved_regs[i] = (info->prev_sp + info->saved_regs[i]);
info->saved_regs[i].addr = (info->prev_sp + info->saved_regs[i].addr);
}
/* The D10V_SP_REGNUM is special. Instead of the address of the SP, the
previous frame's SP value is saved. */
info->saved_regs[D10V_SP_REGNUM] = info->prev_sp;
/* The call instruction moves the caller's PC in the callee's LR.
Since this is an unwind, do the reverse. Copy the location of LR
into PC (the address / regnum) so that a request for PC will be
converted into a request for the LR. */
info->saved_regs[D10V_PC_REGNUM] = info->saved_regs[LR_REGNUM];
/* The previous frame's SP needed to be computed. Save the computed
value. */
trad_frame_register_value (info->saved_regs, D10V_SP_REGNUM,
d10v_make_daddr (prev_sp));
return info;
}
@ -1429,55 +1429,6 @@ d10v_frame_this_id (struct frame_info *next_frame,
(*this_id) = id;
}
static void
saved_regs_unwinder (struct frame_info *next_frame,
CORE_ADDR *this_saved_regs,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *bufferp)
{
struct gdbarch *gdbarch = get_frame_arch (next_frame);
if (this_saved_regs[regnum] != 0)
{
if (regnum == D10V_SP_REGNUM)
{
/* SP register treated specially. */
*optimizedp = 0;
*lvalp = not_lval;
*addrp = 0;
*realnump = -1;
if (bufferp != NULL)
store_unsigned_integer (bufferp,
register_size (gdbarch, regnum),
this_saved_regs[regnum]);
}
else
{
/* Any other register is saved in memory, fetch it but cache
a local copy of its value. */
*optimizedp = 0;
*lvalp = lval_memory;
*addrp = this_saved_regs[regnum];
*realnump = -1;
if (bufferp != NULL)
{
/* Read the value in from memory. */
get_frame_memory (next_frame, this_saved_regs[regnum], bufferp,
register_size (gdbarch, regnum));
}
}
return;
}
/* No luck, assume this and the next frame have the same register
value. If a value is needed, pass the request on down the chain;
otherwise just return an indication that the value is in the same
register as the next frame. */
frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp,
realnump, bufferp);
}
static void
d10v_frame_prev_register (struct frame_info *next_frame,
void **this_prologue_cache,
@ -1487,19 +1438,8 @@ d10v_frame_prev_register (struct frame_info *next_frame,
{
struct d10v_unwind_cache *info
= d10v_frame_unwind_cache (next_frame, this_prologue_cache);
if (regnum == D10V_PC_REGNUM)
{
/* The call instruction saves the caller's PC in LR. The
function prologue of the callee may then save the LR on the
stack. Find that possibly saved LR value and return it. */
saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp,
lvalp, addrp, realnump, bufferp);
}
else
{
saved_regs_unwinder (next_frame, info->saved_regs, regnum, optimizedp,
lvalp, addrp, realnump, bufferp);
}
trad_frame_prev_register (next_frame, info->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, bufferp);
}
static const struct frame_unwind d10v_frame_unwind = {

96
gdb/trad-frame.c Normal file
View file

@ -0,0 +1,96 @@
/* Traditional frame unwind support, for GDB the GNU Debugger.
Copyright 2003 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "trad-frame.h"
#include "regcache.h"
/* A traditional frame is unwound by analysing the function prologue
and using the information gathered to track registers. For
non-optimized frames, the technique is reliable (just need to check
for all potential instruction sequences). */
struct trad_frame *
trad_frame_alloc_saved_regs (struct frame_info *next_frame)
{
int i;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
int numregs = NUM_REGS + NUM_PSEUDO_REGS;
struct trad_frame *this_saved_regs
= FRAME_OBSTACK_CALLOC (numregs, struct trad_frame);
for (i = 0; i < numregs; i++)
this_saved_regs[i].regnum = i;
return this_saved_regs;
}
void
trad_frame_register_value (struct trad_frame this_saved_regs[],
int regnum, LONGEST val)
{
/* Make the REGNUM invalid, indicating that the ADDR contains the
register's value. */
this_saved_regs[regnum].regnum = -1;
this_saved_regs[regnum].addr = val;
}
void
trad_frame_prev_register (struct frame_info *next_frame,
struct trad_frame this_saved_regs[],
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *bufferp)
{
struct gdbarch *gdbarch = get_frame_arch (next_frame);
if (this_saved_regs[regnum].regnum >= 0
&& this_saved_regs[regnum].addr != 0)
{
/* The register was saved on the stack, fetch it. */
*optimizedp = 0;
*lvalp = lval_memory;
*addrp = this_saved_regs[regnum].addr;
*realnump = -1;
if (bufferp != NULL)
{
/* Read the value in from memory. */
get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
register_size (gdbarch, regnum));
}
}
else if (this_saved_regs[regnum].regnum >= 0
&& this_saved_regs[regnum].addr == 0)
{
/* As the next frame to return the value of the register. */
frame_register_unwind (next_frame, this_saved_regs[regnum].regnum,
optimizedp, lvalp, addrp, realnump, bufferp);
}
else
{
/* The register's value is available. */
*optimizedp = 0;
*lvalp = not_lval;
*addrp = 0;
*realnump = -1;
if (bufferp != NULL)
store_unsigned_integer (bufferp, register_size (gdbarch, regnum),
this_saved_regs[regnum].addr);
}
}

56
gdb/trad-frame.h Normal file
View file

@ -0,0 +1,56 @@
/* Traditional frame unwind support, for GDB the GNU Debugger.
Copyright 2003 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef TRAD_FRAME_H
#define TRAD_FRAME_H
struct trad_frame
{
/* If non-zero (and regnum >= 0), the stack address at which the
register is saved. By default, it is assumed that the register
was not saved (addr == 0). Remember, a LONGEST can always fit a
CORE_ADDR. */
LONGEST addr;
/* else, if regnum >=0 (and addr == 0), the REGNUM that contains
this registers value. By default, it is assumed that the
registers are not moved (the register's value is still in that
register and regnum == the index). */
int regnum;
/* else, if regnum < 0, ADDR is the registers value. */
};
/* Convenience function, encode the register's value in the
trad-frame. */
void trad_frame_register_value (struct trad_frame this_saved_regs[],
int regnum, LONGEST val);
/* Return a freshly allocated (and initialized) trad_frame array. */
struct trad_frame *trad_frame_alloc_saved_regs (struct frame_info *next_frame);
/* Given the trad_frame info, return the location of the specified
register. */
void trad_frame_prev_register (struct frame_info *next_frame,
struct trad_frame this_saved_regs[],
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *bufferp);
#endif