summaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c593
1 files changed, 280 insertions, 313 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 3f2f13c3bb6..3ba072d1ff8 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -34,6 +34,9 @@
#include "value.h"
#include "arch-utils.h"
#include "osabi.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
#include "arm-tdep.h"
#include "gdb/sim-arm.h"
@@ -155,17 +158,26 @@ static void convert_from_extended (const struct floatformat *, const void *,
static void convert_to_extended (const struct floatformat *, void *,
const void *);
-/* Define other aspects of the stack frame. We keep the offsets of
- all saved registers, 'cause we need 'em a lot! We also keep the
- current size of the stack frame, and the offset of the frame
- pointer from the stack pointer (for frameless functions, and when
- we're still in the prologue of a function with a frame). */
-
-struct frame_extra_info
+struct arm_prologue_cache
{
+ /* The stack pointer at the time this frame was created; i.e. the
+ caller's stack pointer when this function was called. It is used
+ to identify this frame. */
+ CORE_ADDR prev_sp;
+
+ /* The frame base for this frame is just prev_sp + frame offset -
+ frame size. FRAMESIZE is the size of this stack frame, and
+ FRAMEOFFSET if the initial offset from the stack pointer (this
+ frame's stack pointer, not PREV_SP) to the frame base. */
+
int framesize;
int frameoffset;
+
+ /* The register used to hold the frame pointer for this frame. */
int framereg;
+
+ /* Saved register offsets. */
+ struct trad_frame_saved_reg *saved_regs;
};
/* Addresses for calling Thumb functions have the bit 0 set.
@@ -174,12 +186,6 @@ struct frame_extra_info
#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
-static int
-arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
- return (DEPRECATED_FRAME_SAVED_PC (thisframe) >= LOWEST_PC);
-}
-
/* Set to true if the 32-bit mode is in use. */
int arm_apcs_32 = 1;
@@ -502,7 +508,6 @@ arm_skip_prologue (CORE_ADDR pc)
2) which registers are saved on it
3) the offsets of saved regs
4) the offset from the stack pointer to the frame pointer
- This information is stored in the "extra" fields of the frame_info.
A typical Thumb function prologue would create this stack frame
(offsets relative to FP)
@@ -519,7 +524,7 @@ arm_skip_prologue (CORE_ADDR pc)
/* *INDENT-ON* */
static void
-thumb_scan_prologue (struct frame_info *fi)
+thumb_scan_prologue (CORE_ADDR prev_pc, struct arm_prologue_cache *cache)
{
CORE_ADDR prologue_start;
CORE_ADDR prologue_end;
@@ -534,17 +539,12 @@ thumb_scan_prologue (struct frame_info *fi)
int findmask = 0;
int i;
- /* Don't try to scan dummy frames. */
- if (fi != NULL
- && DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
- return;
-
- if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
+ if (find_pc_partial_function (prev_pc, NULL, &prologue_start, &prologue_end))
{
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
- prologue_end = get_frame_pc (fi);
+ prologue_end = prev_pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
prologue_end = sal.end; /* (probably means no prologue) */
}
@@ -553,7 +553,7 @@ thumb_scan_prologue (struct frame_info *fi)
16 pushes, an add, and "mv fp,sp". */
prologue_end = prologue_start + 40;
- prologue_end = min (prologue_end, get_frame_pc (fi));
+ prologue_end = min (prologue_end, prev_pc);
/* Initialize the saved register map. When register H is copied to
register L, we will put H in saved_reg[L]. */
@@ -564,7 +564,7 @@ thumb_scan_prologue (struct frame_info *fi)
frame pointer, adjust the stack pointer, and save registers.
Do this until all basic prolog instructions are found. */
- get_frame_extra_info (fi)->framesize = 0;
+ cache->framesize = 0;
for (current_pc = prologue_start;
(current_pc < prologue_end) && ((findmask & 7) != 7);
current_pc += 2)
@@ -587,9 +587,8 @@ thumb_scan_prologue (struct frame_info *fi)
for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
if (mask & (1 << regno))
{
- get_frame_extra_info (fi)->framesize += 4;
- get_frame_saved_regs (fi)[saved_reg[regno]] =
- -(get_frame_extra_info (fi)->framesize);
+ cache->framesize += 4;
+ cache->saved_regs[saved_reg[regno]].addr = -cache->framesize;
/* Reset saved register map. */
saved_reg[regno] = regno;
}
@@ -605,23 +604,23 @@ thumb_scan_prologue (struct frame_info *fi)
offset = (insn & 0x7f) << 2; /* get scaled offset */
if (insn & 0x80) /* is it signed? (==subtracting) */
{
- get_frame_extra_info (fi)->frameoffset += offset;
+ cache->frameoffset += offset;
offset = -offset;
}
- get_frame_extra_info (fi)->framesize -= offset;
+ cache->framesize -= offset;
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
findmask |= 2; /* setting of r7 found */
- get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
+ cache->framereg = THUMB_FP_REGNUM;
/* get scaled offset */
- get_frame_extra_info (fi)->frameoffset = (insn & 0xff) << 2;
+ cache->frameoffset = (insn & 0xff) << 2;
}
else if (insn == 0x466f) /* mov r7, sp */
{
findmask |= 2; /* setting of r7 found */
- get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
- get_frame_extra_info (fi)->frameoffset = 0;
+ cache->framereg = THUMB_FP_REGNUM;
+ cache->frameoffset = 0;
saved_reg[THUMB_FP_REGNUM] = ARM_SP_REGNUM;
}
else if ((insn & 0xffc0) == 0x4640) /* mov r0-r7, r8-r15 */
@@ -706,27 +705,27 @@ thumb_scan_prologue (struct frame_info *fi)
*/
static void
-arm_scan_prologue (struct frame_info *fi)
+arm_scan_prologue (struct frame_info *next_frame, struct arm_prologue_cache *cache)
{
int regno, sp_offset, fp_offset;
- LONGEST return_value;
CORE_ADDR prologue_start, prologue_end, current_pc;
+ CORE_ADDR prev_pc = frame_pc_unwind (next_frame);
/* Assume there is no frame until proven otherwise. */
- get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
- get_frame_extra_info (fi)->framesize = 0;
- get_frame_extra_info (fi)->frameoffset = 0;
+ cache->framereg = ARM_SP_REGNUM;
+ cache->framesize = 0;
+ cache->frameoffset = 0;
/* Check for Thumb prologue. */
- if (arm_pc_is_thumb (get_frame_pc (fi)))
+ if (arm_pc_is_thumb (prev_pc))
{
- thumb_scan_prologue (fi);
+ thumb_scan_prologue (prev_pc, cache);
return;
}
/* Find the function prologue. If we can't find the function in
the symbol table, peek in the stack frame to find the PC. */
- if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
+ if (find_pc_partial_function (prev_pc, NULL, &prologue_start, &prologue_end))
{
/* One way to find the end of the prologue (which works well
for unoptimized code) is to do the following:
@@ -734,7 +733,7 @@ arm_scan_prologue (struct frame_info *fi)
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0)
- prologue_end = get_frame_pc (fi);
+ prologue_end = prev_pc;
else if (sal.end < prologue_end)
prologue_end = sal.end;
@@ -767,9 +766,16 @@ arm_scan_prologue (struct frame_info *fi)
}
else
{
- /* Get address of the stmfd in the prologue of the callee;
- the saved PC is the address of the stmfd + 8. */
- if (!safe_read_memory_integer (get_frame_base (fi), 4, &return_value))
+ /* We have no symbol information. Our only option is to assume this
+ function has a standard stack frame and the normal frame register.
+ Then, we can find the value of our frame pointer on entrance to
+ the callee (or at the present moment if this is the innermost frame).
+ The value stored there should be the address of the stmfd + 8. */
+ CORE_ADDR frame_loc;
+ LONGEST return_value;
+
+ frame_loc = frame_unwind_register_unsigned (next_frame, ARM_FP_REGNUM);
+ if (!safe_read_memory_integer (frame_loc, 4, &return_value))
return;
else
{
@@ -778,6 +784,9 @@ arm_scan_prologue (struct frame_info *fi)
}
}
+ if (prev_pc < prologue_end)
+ prologue_end = prev_pc;
+
/* Now search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers.
@@ -828,7 +837,7 @@ arm_scan_prologue (struct frame_info *fi)
if (mask & (1 << regno))
{
sp_offset -= 4;
- get_frame_saved_regs (fi)[regno] = sp_offset;
+ cache->saved_regs[regno].addr = sp_offset;
}
}
else if ((insn & 0xffffc000) == 0xe54b0000 || /* strb rx,[r11,#-n] */
@@ -851,7 +860,7 @@ arm_scan_prologue (struct frame_info *fi)
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
fp_offset = -imm;
- get_frame_extra_info (fi)->framereg = ARM_FP_REGNUM;
+ cache->framereg = ARM_FP_REGNUM;
}
else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
{
@@ -864,7 +873,7 @@ arm_scan_prologue (struct frame_info *fi)
{
sp_offset -= 12;
regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
- get_frame_saved_regs (fi)[regno] = sp_offset;
+ cache->saved_regs[regno].addr = sp_offset;
}
else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
{
@@ -891,7 +900,7 @@ arm_scan_prologue (struct frame_info *fi)
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
sp_offset -= 12;
- get_frame_saved_regs (fi)[fp_start_reg++] = sp_offset;
+ cache->saved_regs[fp_start_reg++].addr = sp_offset;
}
}
else if ((insn & 0xf0000000) != 0xe0000000)
@@ -907,266 +916,260 @@ arm_scan_prologue (struct frame_info *fi)
/* The frame size is just the negative of the offset (from the
original SP) of the last thing thing we pushed on the stack.
The frame offset is [new FP] - [new SP]. */
- get_frame_extra_info (fi)->framesize = -sp_offset;
- if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM)
- get_frame_extra_info (fi)->frameoffset = fp_offset - sp_offset;
+ cache->framesize = -sp_offset;
+ if (cache->framereg == ARM_FP_REGNUM)
+ cache->frameoffset = fp_offset - sp_offset;
else
- get_frame_extra_info (fi)->frameoffset = 0;
+ cache->frameoffset = 0;
}
-/* Find REGNUM on the stack. Otherwise, it's in an active register.
- One thing we might want to do here is to check REGNUM against the
- clobber mask, and somehow flag it as invalid if it isn't saved on
- the stack somewhere. This would provide a graceful failure mode
- when trying to get the value of caller-saves registers for an inner
- frame. */
-
-static CORE_ADDR
-arm_find_callers_reg (struct frame_info *fi, int regnum)
+static struct arm_prologue_cache *
+arm_make_prologue_cache (struct frame_info *next_frame)
{
- /* NOTE: cagney/2002-05-03: This function really shouldn't be
- needed. Instead the (still being written) register unwind
- function could be called directly. */
- for (; fi; fi = get_next_frame (fi))
- {
- if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
- {
- return deprecated_read_register_dummy (get_frame_pc (fi),
- get_frame_base (fi), regnum);
- }
- else if (get_frame_saved_regs (fi)[regnum] != 0)
- {
- /* NOTE: cagney/2002-05-03: This would normally need to
- handle ARM_SP_REGNUM as a special case as, according to
- the frame.h comments, saved_regs[SP_REGNUM] contains the
- SP value not its address. It appears that the ARM isn't
- doing this though. */
- return read_memory_integer (get_frame_saved_regs (fi)[regnum],
- REGISTER_RAW_SIZE (regnum));
- }
- }
- return read_register (regnum);
+ int reg;
+ struct arm_prologue_cache *cache;
+ CORE_ADDR unwound_fp;
+
+ cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
+ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+ arm_scan_prologue (next_frame, cache);
+
+ unwound_fp = frame_unwind_register_unsigned (next_frame, cache->framereg);
+ if (unwound_fp == 0)
+ return cache;
+
+ cache->prev_sp = unwound_fp + cache->framesize - cache->frameoffset;
+
+ /* Calculate actual addresses of saved registers using offsets
+ determined by arm_scan_prologue. */
+ for (reg = 0; reg < NUM_REGS; reg++)
+ if (cache->saved_regs[reg].addr != 0)
+ cache->saved_regs[reg].addr += cache->prev_sp;
+
+ return cache;
}
-/* Function: frame_chain Given a GDB frame, determine the address of
- the calling function's frame. This will be used to create a new
- GDB frame struct, and then DEPRECATED_INIT_EXTRA_FRAME_INFO and
- DEPRECATED_INIT_FRAME_PC will be called for the new frame. For
- ARM, we save the frame size when we initialize the frame_info. */
-static CORE_ADDR
-arm_frame_chain (struct frame_info *fi)
+/* Our frame ID for a normal frame is the current function's starting PC
+ and the caller's SP when we were called. */
+
+static void
+arm_prologue_this_id (struct frame_info *next_frame,
+ void **this_cache,
+ struct frame_id *this_id)
{
- CORE_ADDR caller_pc;
- int framereg = get_frame_extra_info (fi)->framereg;
+ struct arm_prologue_cache *cache;
+ struct frame_id id;
+ CORE_ADDR func;
- if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
- /* A generic call dummy's frame is the same as caller's. */
- return get_frame_base (fi);
+ if (*this_cache == NULL)
+ *this_cache = arm_make_prologue_cache (next_frame);
+ cache = *this_cache;
- if (get_frame_pc (fi) < LOWEST_PC)
- return 0;
+ func = frame_func_unwind (next_frame);
+
+ /* This is meant to halt the backtrace at "_start". Make sure we
+ don't halt it at a generic dummy frame. */
+ if (func <= LOWEST_PC || deprecated_inside_entry_file (func))
+ return;
- /* If the caller is the startup code, we're at the end of the chain. */
- caller_pc = DEPRECATED_FRAME_SAVED_PC (fi);
+ /* If we've hit a wall, stop. */
+ if (cache->prev_sp == 0)
+ return;
+
+ id = frame_id_build (cache->prev_sp, func);
+
+ /* Check that we're not going round in circles with the same frame
+ ID (but avoid applying the test to sentinel frames which do go
+ round in circles). */
+ if (frame_relative_level (next_frame) >= 0
+ && get_frame_type (next_frame) == NORMAL_FRAME
+ && frame_id_eq (get_frame_id (next_frame), id))
+ return;
- /* If the caller is Thumb and the caller is ARM, or vice versa,
- the frame register of the caller is different from ours.
- So we must scan the prologue of the caller to determine its
- frame register number. */
- /* XXX Fixme, we should try to do this without creating a temporary
- caller_fi. */
- if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (fi)))
+ *this_id = id;
+}
+
+static void
+arm_prologue_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int prev_regnum,
+ int *optimized,
+ enum lval_type *lvalp,
+ CORE_ADDR *addrp,
+ int *realnump,
+ void *valuep)
+{
+ struct arm_prologue_cache *cache;
+
+ if (*this_cache == NULL)
+ *this_cache = arm_make_prologue_cache (next_frame);
+ cache = *this_cache;
+
+ /* If we are asked to unwind the PC, then we need to return the LR
+ instead. The saved value of PC points into this frame's
+ prologue, not the next frame's resume location. */
+ if (prev_regnum == ARM_PC_REGNUM)
+ prev_regnum = ARM_LR_REGNUM;
+
+ /* SP is generally not saved to the stack, but this frame is
+ identified by NEXT_FRAME's stack pointer at the time of the call.
+ The value was already reconstructed into PREV_SP. */
+ if (prev_regnum == ARM_SP_REGNUM)
{
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- struct frame_info *caller_fi =
- deprecated_frame_xmalloc_with_cleanup (SIZEOF_FRAME_SAVED_REGS,
- sizeof (struct frame_extra_info));
-
- /* Now, scan the prologue and obtain the frame register. */
- deprecated_update_frame_pc_hack (caller_fi, caller_pc);
- arm_scan_prologue (caller_fi);
- framereg = get_frame_extra_info (caller_fi)->framereg;
-
- /* Deallocate the storage associated with the temporary frame
- created above. */
- do_cleanups (old_chain);
+ *lvalp = not_lval;
+ if (valuep)
+ store_unsigned_integer (valuep, 4, cache->prev_sp);
+ return;
}
- /* If the caller used a frame register, return its value.
- Otherwise, return the caller's stack pointer. */
- if (framereg == ARM_FP_REGNUM || framereg == THUMB_FP_REGNUM)
- return arm_find_callers_reg (fi, framereg);
- else
- return get_frame_base (fi) + get_frame_extra_info (fi)->framesize;
+ trad_frame_prev_register (next_frame, cache->saved_regs, prev_regnum,
+ optimized, lvalp, addrp, realnump, valuep);
}
-/* This function actually figures out the frame address for a given pc
- and sp. This is tricky because we sometimes don't use an explicit
- frame pointer, and the previous stack pointer isn't necessarily
- recorded on the stack. The only reliable way to get this info is
- to examine the prologue. FROMLEAF is a little confusing, it means
- this is the next frame up the chain AFTER a frameless function. If
- this is true, then the frame value for this frame is still in the
- fp register. */
+struct frame_unwind arm_prologue_unwind = {
+ NORMAL_FRAME,
+ arm_prologue_this_id,
+ arm_prologue_prev_register
+};
-static void
-arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+static const struct frame_unwind *
+arm_prologue_unwind_sniffer (struct frame_info *next_frame)
{
- int reg;
- CORE_ADDR sp;
+ return &arm_prologue_unwind;
+}
- if (get_frame_saved_regs (fi) == NULL)
- frame_saved_regs_zalloc (fi);
+static CORE_ADDR
+arm_normal_frame_base (struct frame_info *next_frame, void **this_cache)
+{
+ struct arm_prologue_cache *cache;
- frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
+ if (*this_cache == NULL)
+ *this_cache = arm_make_prologue_cache (next_frame);
+ cache = *this_cache;
- get_frame_extra_info (fi)->framesize = 0;
- get_frame_extra_info (fi)->frameoffset = 0;
- get_frame_extra_info (fi)->framereg = 0;
+ return cache->prev_sp + cache->frameoffset - cache->framesize;
+}
- if (get_next_frame (fi))
- deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
+struct frame_base arm_normal_base = {
+ &arm_prologue_unwind,
+ arm_normal_frame_base,
+ arm_normal_frame_base,
+ arm_normal_frame_base
+};
- memset (get_frame_saved_regs (fi), '\000', sizeof get_frame_saved_regs (fi));
+static struct arm_prologue_cache *
+arm_make_sigtramp_cache (struct frame_info *next_frame)
+{
+ struct arm_prologue_cache *cache;
+ int reg;
- /* Compute stack pointer for this frame. We use this value for both
- the sigtramp and call dummy cases. */
- if (!get_next_frame (fi))
- sp = read_sp();
- else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
- /* For generic dummy frames, pull the value direct from the frame.
- Having an unwind function to do this would be nice. */
- sp = deprecated_read_register_dummy (get_frame_pc (get_next_frame (fi)),
- get_frame_base (get_next_frame (fi)),
- ARM_SP_REGNUM);
- else
- sp = (get_frame_base (get_next_frame (fi))
- - get_frame_extra_info (get_next_frame (fi))->frameoffset
- + get_frame_extra_info (get_next_frame (fi))->framesize);
-
- /* Determine whether or not we're in a sigtramp frame.
- Unfortunately, it isn't sufficient to test (get_frame_type (fi)
- == SIGTRAMP_FRAME) because this value is sometimes set after
- invoking DEPRECATED_INIT_EXTRA_FRAME_INFO. So we test *both*
- (get_frame_type (fi) == SIGTRAMP_FRAME) and PC_IN_SIGTRAMP to
- determine if we need to use the sigcontext addresses for the
- saved registers.
-
- Note: If an ARM PC_IN_SIGTRAMP method ever needs to compare
- against the name of the function, the code below will have to be
- changed to first fetch the name of the function and then pass
- this name to PC_IN_SIGTRAMP. */
+ cache = frame_obstack_zalloc (sizeof (struct arm_prologue_cache));
- /* FIXME: cagney/2002-11-18: This problem will go away once
- frame.c:get_prev_frame() is modified to set the frame's type
- before calling functions like this. */
+ cache->prev_sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
- if (SIGCONTEXT_REGISTER_ADDRESS_P ()
- && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (get_frame_pc (fi), (char *)0)))
- {
- for (reg = 0; reg < NUM_REGS; reg++)
- get_frame_saved_regs (fi)[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, get_frame_pc (fi), reg);
+ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
- /* FIXME: What about thumb mode? */
- get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
- deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (fi)[get_frame_extra_info (fi)->framereg], REGISTER_RAW_SIZE (get_frame_extra_info (fi)->framereg)));
- get_frame_extra_info (fi)->framesize = 0;
- get_frame_extra_info (fi)->frameoffset = 0;
+ for (reg = 0; reg < NUM_REGS; reg++)
+ cache->saved_regs[reg].addr
+ = SIGCONTEXT_REGISTER_ADDRESS (cache->prev_sp,
+ frame_pc_unwind (next_frame), reg);
- }
- else
- {
- arm_scan_prologue (fi);
-
- if (!get_next_frame (fi))
- /* This is the innermost frame? */
- deprecated_update_frame_base_hack (fi, read_register (get_frame_extra_info (fi)->framereg));
- else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
- /* Next inner most frame is a dummy, just grab its frame.
- Dummy frames always have the same FP as their caller. */
- deprecated_update_frame_base_hack (fi, get_frame_base (get_next_frame (fi)));
- else if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM
- || get_frame_extra_info (fi)->framereg == THUMB_FP_REGNUM)
- {
- /* not the innermost frame */
- /* If we have an FP, the callee saved it. */
- if (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg] != 0)
- deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg], 4));
- else if (fromleaf)
- /* If we were called by a frameless fn. then our frame is
- still in the frame pointer register on the board... */
- deprecated_update_frame_base_hack (fi, deprecated_read_fp ());
- }
+ /* FIXME: What about thumb mode? */
+ cache->framereg = ARM_SP_REGNUM;
+ cache->prev_sp
+ = read_memory_integer (cache->saved_regs[cache->framereg].addr,
+ REGISTER_RAW_SIZE (cache->framereg));
- /* Calculate actual addresses of saved registers using offsets
- determined by arm_scan_prologue. */
- for (reg = 0; reg < NUM_REGS; reg++)
- if (get_frame_saved_regs (fi)[reg] != 0)
- get_frame_saved_regs (fi)[reg]
- += (get_frame_base (fi)
- + get_frame_extra_info (fi)->framesize
- - get_frame_extra_info (fi)->frameoffset);
- }
+ return cache;
}
+static void
+arm_sigtramp_this_id (struct frame_info *next_frame,
+ void **this_cache,
+ struct frame_id *this_id)
+{
+ struct arm_prologue_cache *cache;
-/* Find the caller of this frame. We do this by seeing if ARM_LR_REGNUM
- is saved in the stack anywhere, otherwise we get it from the
- registers.
+ if (*this_cache == NULL)
+ *this_cache = arm_make_sigtramp_cache (next_frame);
+ cache = *this_cache;
- The old definition of this function was a macro:
- #define FRAME_SAVED_PC(FRAME) \
- ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4)) */
+ /* FIXME drow/2003-07-07: This isn't right if we single-step within
+ the sigtramp frame; the PC should be the beginning of the trampoline. */
+ *this_id = frame_id_build (cache->prev_sp, frame_pc_unwind (next_frame));
+}
-static CORE_ADDR
-arm_frame_saved_pc (struct frame_info *fi)
+static void
+arm_sigtramp_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int prev_regnum,
+ int *optimized,
+ enum lval_type *lvalp,
+ CORE_ADDR *addrp,
+ int *realnump,
+ void *valuep)
{
- /* If a dummy frame, pull the PC out of the frame's register buffer. */
- if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
- return deprecated_read_register_dummy (get_frame_pc (fi),
- get_frame_base (fi), ARM_PC_REGNUM);
+ struct arm_prologue_cache *cache;
- if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
- (get_frame_base (fi)
- - get_frame_extra_info (fi)->frameoffset),
- get_frame_base (fi)))
- {
- return read_memory_integer (get_frame_saved_regs (fi)[ARM_PC_REGNUM],
- REGISTER_RAW_SIZE (ARM_PC_REGNUM));
- }
- else
- {
- CORE_ADDR pc = arm_find_callers_reg (fi, ARM_LR_REGNUM);
- return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
- }
+ if (*this_cache == NULL)
+ *this_cache = arm_make_sigtramp_cache (next_frame);
+ cache = *this_cache;
+
+ trad_frame_prev_register (next_frame, cache->saved_regs, prev_regnum,
+ optimized, lvalp, addrp, realnump, valuep);
}
-/* Return the frame address. On ARM, it is R11; on Thumb it is R7.
- Examine the Program Status Register to decide which state we're in. */
+struct frame_unwind arm_sigtramp_unwind = {
+ SIGTRAMP_FRAME,
+ arm_sigtramp_this_id,
+ arm_sigtramp_prev_register
+};
-static CORE_ADDR
-arm_read_fp (void)
+static const struct frame_unwind *
+arm_sigtramp_unwind_sniffer (struct frame_info *next_frame)
{
- if (read_register (ARM_PS_REGNUM) & 0x20) /* Bit 5 is Thumb state bit */
- return read_register (THUMB_FP_REGNUM); /* R7 if Thumb */
- else
- return read_register (ARM_FP_REGNUM); /* R11 if ARM */
+ /* Note: If an ARM PC_IN_SIGTRAMP method ever needs to compare
+ against the name of the function, the code below will have to be
+ changed to first fetch the name of the function and then pass
+ this name to PC_IN_SIGTRAMP. */
+
+ if (SIGCONTEXT_REGISTER_ADDRESS_P ()
+ && PC_IN_SIGTRAMP (frame_pc_unwind (next_frame), (char *) 0))
+ return &arm_sigtramp_unwind;
+
+ return NULL;
}
-/* Store into a struct frame_saved_regs the addresses of the saved
- registers of frame described by FRAME_INFO. This includes special
- registers such as PC and FP saved in special ways in the stack
- frame. SP is even more special: the address we return for it IS
- the sp for the next frame. */
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+ dummy frame. The frame ID's base needs to match the TOS value
+ saved by save_dummy_frame_tos() and returned from
+ arm_push_dummy_call, and the PC needs to match the dummy frame's
+ breakpoint. */
-static void
-arm_frame_init_saved_regs (struct frame_info *fip)
+static struct frame_id
+arm_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
+ return frame_id_build (frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM),
+ frame_pc_unwind (next_frame));
+}
- if (get_frame_saved_regs (fip))
- return;
+/* Given THIS_FRAME, find the previous frame's resume PC (which will
+ be used to construct the previous frame's ID, after looking up the
+ containing function). */
- arm_init_extra_frame_info (0, fip);
+static CORE_ADDR
+arm_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR pc;
+ pc = frame_unwind_register_unsigned (this_frame, ARM_PC_REGNUM);
+ return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
+}
+
+static CORE_ADDR
+arm_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ return frame_unwind_register_unsigned (this_frame, ARM_SP_REGNUM);
}
/* Set the return address for a generic dummy frame. ARM uses the
@@ -1175,7 +1178,7 @@ arm_frame_init_saved_regs (struct frame_info *fip)
static CORE_ADDR
arm_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
- write_register (ARM_LR_REGNUM, CALL_DUMMY_ADDRESS ());
+ write_register (ARM_LR_REGNUM, entry_point_address ());
return sp;
}
@@ -1311,40 +1314,6 @@ arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
write_register (4, fun);
}
-/* Pop the current frame. So long as the frame info has been
- initialized properly (see arm_init_extra_frame_info), this code
- works for dummy frames as well as regular frames. I.e, there's no
- need to have a special case for dummy frames. */
-static void
-arm_pop_frame (void)
-{
- int regnum;
- struct frame_info *frame = get_current_frame ();
- CORE_ADDR old_SP = (get_frame_base (frame)
- - get_frame_extra_info (frame)->frameoffset
- + get_frame_extra_info (frame)->framesize);
-
- if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
- get_frame_base (frame),
- get_frame_base (frame)))
- {
- generic_pop_dummy_frame ();
- flush_cached_frames ();
- return;
- }
-
- for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (get_frame_saved_regs (frame)[regnum] != 0)
- write_register (regnum,
- read_memory_integer (get_frame_saved_regs (frame)[regnum],
- REGISTER_RAW_SIZE (regnum)));
-
- write_register (ARM_PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
- write_register (ARM_SP_REGNUM, old_SP);
-
- flush_cached_frames ();
-}
-
/* When arguments must be pushed onto the stack, they go on in reverse
order. The code below implements a FILO (stack) to do this. */
@@ -1523,7 +1492,7 @@ static void
arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, const char *args)
{
- register unsigned long status = read_register (ARM_FPS_REGNUM);
+ unsigned long status = read_register (ARM_FPS_REGNUM);
int type;
type = (status >> 24) & 127;
@@ -2283,7 +2252,7 @@ static int
arm_use_struct_convention (int gcc_p, struct type *type)
{
int nRc;
- register enum type_code code;
+ enum type_code code;
/* In the ARM ABI, "integer" like aggregate types are returned in
registers. For an aggregate type to be integer like, its size
@@ -2825,10 +2794,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
- /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
- ready to unwind the PC first (see frame.c:get_prev_frame()). */
- set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
-
/* We used to default to FPA for generic ARM, but almost nobody uses that
now, and we now provide a way for the user to force the model. So
default to the most useful variant. */
@@ -2871,16 +2836,15 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
/* Frame handling. */
- set_gdbarch_deprecated_frame_chain_valid (gdbarch, arm_frame_chain_valid);
- set_gdbarch_deprecated_init_extra_frame_info (gdbarch, arm_init_extra_frame_info);
- set_gdbarch_deprecated_target_read_fp (gdbarch, arm_read_fp);
- set_gdbarch_deprecated_frame_chain (gdbarch, arm_frame_chain);
+ set_gdbarch_unwind_dummy_id (gdbarch, arm_unwind_dummy_id);
+ set_gdbarch_unwind_pc (gdbarch, arm_unwind_pc);
+ set_gdbarch_unwind_sp (gdbarch, arm_unwind_sp);
+
set_gdbarch_frameless_function_invocation
(gdbarch, arm_frameless_function_invocation);
- set_gdbarch_deprecated_frame_saved_pc (gdbarch, arm_frame_saved_pc);
set_gdbarch_frame_args_skip (gdbarch, 0);
- set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs);
- set_gdbarch_deprecated_pop_frame (gdbarch, arm_pop_frame);
+
+ frame_base_set_default (gdbarch, &arm_normal_base);
/* Address manipulation. */
set_gdbarch_smash_text_address (gdbarch, arm_smash_text_address);
@@ -2948,6 +2912,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Hook in the ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
+ /* Add some default predicates. */
+ frame_unwind_append_sniffer (gdbarch, arm_sigtramp_unwind_sniffer);
+ frame_unwind_append_sniffer (gdbarch, arm_prologue_unwind_sniffer);
+
/* Now we have tuned the configuration, set a few final things,
based on what the OS ABI has told us. */
@@ -3024,8 +2992,7 @@ _initialize_arm_tdep (void)
int numregs, i, j;
static char *helptext;
- if (GDB_MULTI_ARCH)
- gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
+ gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
/* Register an ELF OS ABI sniffer for ARM binaries. */
gdbarch_register_osabi_sniffer (bfd_arch_arm,