/* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
- Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
This file is part of GDB.
extern struct obstack frame_cache_obstack;
\f
-/* Forward declarations. */
+/* Prototypes for local functions. */
+
+static alpha_extra_func_info_t push_sigtramp_desc PARAMS ((CORE_ADDR low_addr));
static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
} *linked_proc_desc_table = NULL;
\f
-/* Under Linux, signal handler invocations can be identified by the
+/* Under GNU/Linux, signal handler invocations can be identified by the
designated code sequence that is used to return from a signal
handler. In particular, the return address of a signal handler
points to the following sequence (the first instruction is quadword
guarantee that we are in the middle of a sigreturn syscall. Don't
think this will be a problem in praxis, though.
*/
+
long
alpha_linux_sigtramp_offset (CORE_ADDR pc)
{
unsigned int i[3], w;
- long off, res;
+ long off;
if (read_memory_nobpt(pc, (char *) &w, 4) != 0)
return -1;
the signal-handler return code starting at address LOW_ADDR. The
descriptor is added to the linked_proc_desc_table. */
-alpha_extra_func_info_t
-push_sigtramp_desc (CORE_ADDR low_addr)
+static alpha_extra_func_info_t
+push_sigtramp_desc (low_addr)
+ CORE_ADDR low_addr;
{
struct linked_proc_info *link;
alpha_extra_func_info_t proc_desc;
PROC_PC_REG (proc_desc) = 26;
PROC_LOCALOFF (proc_desc) = 0;
SET_PROC_DESC_IS_DYN_SIGTRAMP (proc_desc);
+ return (proc_desc);
}
\f
static struct alpha_extra_func_info temp_proc_desc;
static struct frame_saved_regs temp_saved_regs;
+/* Nonzero if instruction at PC is a return instruction. "ret
+ $zero,($ra),1" on alpha. */
+
+static int
+alpha_about_to_return (pc)
+ CORE_ADDR pc;
+{
+ return read_memory_integer (pc, 4) == 0x6bfa8001;
+}
+
+
+
/* This fencepost looks highly suspicious to me. Removing it also
seems suspicious as it could affect remote debugging across serial
lines. */
return 0;
}
- else if (ABOUT_TO_RETURN(start_pc))
- break;
+ else if (alpha_about_to_return (start_pc))
+ break;
start_pc += 4; /* skip return */
return start_pc;
word = extract_unsigned_integer (buf, 4);
if ((word & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
- frame_size += (-word) & 0xffff;
+ {
+ if (word & 0x8000)
+ frame_size += (-word) & 0xffff;
+ else
+ /* Exit loop if a positive stack adjustment is found, which
+ usually means that the stack cleanup code in the function
+ epilogue is reached. */
+ break;
+ }
else if ((word & 0xfc1f0000) == 0xb41e0000 /* stq reg,n($sp) */
&& (word & 0xffff0000) != 0xb7fe0000) /* reg != $zero */
{
rearrange the register saves.
So we recognize only a few registers (t7, t9, ra) within
the procedure prologue as valid return address registers.
+ If we encounter a return instruction, we extract the
+ the return address register from it.
FIXME: Rewriting GDB to access the procedure descriptors,
e.g. via the minimal symbol table, might obviate this hack. */
if (pcreg == -1
- && cur_pc < (start_pc + 20)
+ && cur_pc < (start_pc + 80)
&& (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM))
pcreg = reg;
}
+ else if ((word & 0xffe0ffff) == 0x6be08001) /* ret zero,reg,1 */
+ pcreg = (word >> 16) & 0x1f;
else if (word == 0x47de040f) /* bis sp,sp fp */
has_frame_reg = 1;
}
{
/* If we haven't found a valid return address register yet,
keep searching in the procedure prologue. */
- while (cur_pc < (limit_pc + 20) && cur_pc < (start_pc + 20))
+ while (cur_pc < (limit_pc + 80) && cur_pc < (start_pc + 80))
{
char buf[4];
unsigned long word;
- int status;
- status = read_memory_nobpt (cur_pc, buf, 4);
- if (status)
- memory_error (status, cur_pc);
+ if (read_memory_nobpt (cur_pc, buf, 4))
+ break;
cur_pc += 4;
word = extract_unsigned_integer (buf, 4);
break;
}
}
+ else if ((word & 0xffe0ffff) == 0x6be08001) /* ret zero,reg,1 */
+ {
+ pcreg = (word >> 16) & 0x1f;
+ break;
+ }
}
}
if (offset >= 0)
return push_sigtramp_desc (pc - offset);
- if (startaddr == 0)
+ /* If heuristic_fence_post is non-zero, determine the procedure
+ start address by examining the instructions.
+ This allows us to find the start address of static functions which
+ have no symbolic information, as startaddr would have been set to
+ the preceding global function start address by the
+ find_pc_partial_function call above. */
+ if (startaddr == 0 || heuristic_fence_post != 0)
startaddr = heuristic_proc_start (pc);
proc_desc =
*/
/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
-#define MASK(i,j) (((1L << ((j)+1)) - 1) ^ ((1L << (i)) - 1))
+#define MASK(i,j) ((((LONGEST)1 << ((j)+1)) - 1) ^ (((LONGEST)1 << (i)) - 1))
#define GEN_REG_SAVE_MASK (MASK(0,8) | MASK(16,29))
#define GEN_REG_SAVE_COUNT 24
#define FLOAT_REG_SAVE_MASK (MASK(0,1) | MASK(10,30))
}
else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
{
- unsigned LONGEST l;
+ ULONGEST l;
l = extract_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum));
l = ((l >> 32) & 0xc0000000) | ((l >> 29) & 0x3fffffff);
store_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype), l);
}
else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
{
- unsigned LONGEST l;
+ ULONGEST l;
if (TYPE_UNSIGNED (valtype))
l = extract_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype));
else