2004-10-11 Orjan Friberg <orjanf@axis.com>
* cris-tdep.c (cris_sigtramp_start, cris_rt_sigtramp_start) (cris_sigcontext_addr, cris_sigtramp_frame_unwind_cache) (cris_sigtramp_frame_this_id, cris_sigtramp_frame_prev_register) (cris_sigtramp_frame_sniffer): New functions. (cris_gdbarch_init): Hook in signal trampoline unwinder. (cris_dwarf2_reg_to_regnum, cris_dwarf2_frame_init_reg): New functions. (cris_gdbarch_init): Hook in Dwarf-2 unwinder. (struct gdbarch_tdep, set_cris_dwarf2_cfi, cris_dump_tdep) (cris_gdbarch_init, _initialize_cris_tdep): Add CRIS Dwarf-2 CFI usage command. (cris_version_update): Remove, replace with ... (set_cris_version): New function. (struct gdbarch_tdep, cris_mode, cris_mode_update) (cris_cannot_store_register, cris_dump_tdep, cris_gdbarch_init) (_initialize_cris_tdep): Remove CRIS mode command. (cris_fpless_backtrace, _initialize_cris_tdep): Remove CRIS command for framepointer-less backtrace. (cris_scan_prologue): Fix prologue scanning limit. (cris_register_type): Update to reflect actual registers. (cris_register_bytes_ok) Remove. (cris_gdbarch_init): Remove support for CRIS v8 and v9. Remove set_gdbarch_deprecated_register_size, set_gdbarch_deprecated_register_byte, set_gdbarch_register_bytes_ok.
This commit is contained in:
parent
563f4125b7
commit
a5f6c8f5a8
2 changed files with 376 additions and 373 deletions
|
@ -1,3 +1,29 @@
|
|||
2004-10-11 Orjan Friberg <orjanf@axis.com>
|
||||
|
||||
* cris-tdep.c (cris_sigtramp_start, cris_rt_sigtramp_start)
|
||||
(cris_sigcontext_addr, cris_sigtramp_frame_unwind_cache)
|
||||
(cris_sigtramp_frame_this_id, cris_sigtramp_frame_prev_register)
|
||||
(cris_sigtramp_frame_sniffer): New functions.
|
||||
(cris_gdbarch_init): Hook in signal trampoline unwinder.
|
||||
(cris_dwarf2_reg_to_regnum, cris_dwarf2_frame_init_reg): New functions.
|
||||
(cris_gdbarch_init): Hook in Dwarf-2 unwinder.
|
||||
(struct gdbarch_tdep, set_cris_dwarf2_cfi, cris_dump_tdep)
|
||||
(cris_gdbarch_init, _initialize_cris_tdep): Add CRIS Dwarf-2 CFI usage
|
||||
command.
|
||||
(cris_version_update): Remove, replace with ...
|
||||
(set_cris_version): New function.
|
||||
(struct gdbarch_tdep, cris_mode, cris_mode_update)
|
||||
(cris_cannot_store_register, cris_dump_tdep, cris_gdbarch_init)
|
||||
(_initialize_cris_tdep): Remove CRIS mode command.
|
||||
(cris_fpless_backtrace, _initialize_cris_tdep): Remove
|
||||
cris-fpless-backtrace command.
|
||||
(cris_scan_prologue): Fix prologue scanning limit.
|
||||
(cris_register_type): Update to reflect actual registers.
|
||||
(cris_register_bytes_ok) Remove.
|
||||
(cris_gdbarch_init): Remove support for CRIS v8 and v9.
|
||||
Remove set_gdbarch_deprecated_register_size,
|
||||
set_gdbarch_deprecated_register_byte, set_gdbarch_register_bytes_ok.
|
||||
|
||||
2004-10-10 Andrew Cagney <cagney@gnu.org>
|
||||
|
||||
* ada-lang.c (lim_warning): Add ATTR_FORMAT prototype and FIXME
|
||||
|
|
721
gdb/cris-tdep.c
721
gdb/cris-tdep.c
|
@ -42,12 +42,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
/* To get entry_point_address. */
|
||||
#include "objfiles.h"
|
||||
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#include "solib-svr4.h" /* For struct link_map_offsets. */
|
||||
#include "gdb_string.h"
|
||||
#include "dis-asm.h"
|
||||
|
||||
|
||||
enum cris_num_regs
|
||||
{
|
||||
/* There are no floating point registers. Used in gdbserver low-linux.c. */
|
||||
|
@ -108,32 +107,19 @@ extern const struct cris_spec_reg cris_spec_regs[];
|
|||
|
||||
/* CRIS version, set via the user command 'set cris-version'. Affects
|
||||
register names and sizes.*/
|
||||
static int usr_cmd_cris_version;
|
||||
static unsigned int usr_cmd_cris_version;
|
||||
|
||||
/* Indicates whether to trust the above variable. */
|
||||
static int usr_cmd_cris_version_valid = 0;
|
||||
|
||||
/* CRIS mode, set via the user command 'set cris-mode'. Affects availability
|
||||
of some registers. */
|
||||
static const char *usr_cmd_cris_mode;
|
||||
|
||||
/* Indicates whether to trust the above variable. */
|
||||
static int usr_cmd_cris_mode_valid = 0;
|
||||
|
||||
static const char CRIS_MODE_USER[] = "CRIS_MODE_USER";
|
||||
static const char CRIS_MODE_SUPERVISOR[] = "CRIS_MODE_SUPERVISOR";
|
||||
static const char *cris_mode_enums[] =
|
||||
{
|
||||
CRIS_MODE_USER,
|
||||
CRIS_MODE_SUPERVISOR,
|
||||
0
|
||||
};
|
||||
/* Whether to make use of Dwarf-2 CFI (default on). */
|
||||
static int usr_cmd_cris_dwarf2_cfi = 1;
|
||||
|
||||
/* CRIS architecture specific information. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
int cris_version;
|
||||
const char *cris_mode;
|
||||
unsigned int cris_version;
|
||||
int cris_dwarf2_cfi;
|
||||
};
|
||||
|
||||
/* Functions for accessing target dependent data. */
|
||||
|
@ -144,10 +130,121 @@ cris_version (void)
|
|||
return (gdbarch_tdep (current_gdbarch)->cris_version);
|
||||
}
|
||||
|
||||
static const char *
|
||||
cris_mode (void)
|
||||
/* Sigtramp identification code copied from i386-linux-tdep.c. */
|
||||
|
||||
#define SIGTRAMP_INSN0 0x9c5f /* movu.w 0xXX, $r9 */
|
||||
#define SIGTRAMP_OFFSET0 0
|
||||
#define SIGTRAMP_INSN1 0xe93d /* break 13 */
|
||||
#define SIGTRAMP_OFFSET1 4
|
||||
|
||||
static const unsigned short sigtramp_code[] =
|
||||
{
|
||||
return (gdbarch_tdep (current_gdbarch)->cris_mode);
|
||||
SIGTRAMP_INSN0, 0x0077, /* movu.w $0x77, $r9 */
|
||||
SIGTRAMP_INSN1 /* break 13 */
|
||||
};
|
||||
|
||||
#define SIGTRAMP_LEN (sizeof sigtramp_code)
|
||||
|
||||
/* Note: same length as normal sigtramp code. */
|
||||
|
||||
static const unsigned short rt_sigtramp_code[] =
|
||||
{
|
||||
SIGTRAMP_INSN0, 0x00ad, /* movu.w $0xad, $r9 */
|
||||
SIGTRAMP_INSN1 /* break 13 */
|
||||
};
|
||||
|
||||
/* If PC is in a sigtramp routine, return the address of the start of
|
||||
the routine. Otherwise, return 0. */
|
||||
|
||||
static CORE_ADDR
|
||||
cris_sigtramp_start (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
unsigned short buf[SIGTRAMP_LEN];
|
||||
|
||||
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
|
||||
return 0;
|
||||
|
||||
if (buf[0] != SIGTRAMP_INSN0)
|
||||
{
|
||||
if (buf[0] != SIGTRAMP_INSN1)
|
||||
return 0;
|
||||
|
||||
pc -= SIGTRAMP_OFFSET1;
|
||||
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp (buf, sigtramp_code, SIGTRAMP_LEN) != 0)
|
||||
return 0;
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* If PC is in a RT sigtramp routine, return the address of the start of
|
||||
the routine. Otherwise, return 0. */
|
||||
|
||||
static CORE_ADDR
|
||||
cris_rt_sigtramp_start (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
unsigned short buf[SIGTRAMP_LEN];
|
||||
|
||||
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
|
||||
return 0;
|
||||
|
||||
if (buf[0] != SIGTRAMP_INSN0)
|
||||
{
|
||||
if (buf[0] != SIGTRAMP_INSN1)
|
||||
return 0;
|
||||
|
||||
pc -= SIGTRAMP_OFFSET1;
|
||||
if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp (buf, rt_sigtramp_code, SIGTRAMP_LEN) != 0)
|
||||
return 0;
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
|
||||
routine, return the address of the associated sigcontext structure. */
|
||||
|
||||
static CORE_ADDR
|
||||
cris_sigcontext_addr (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR pc;
|
||||
CORE_ADDR sp;
|
||||
char buf[4];
|
||||
|
||||
frame_unwind_register (next_frame, SP_REGNUM, buf);
|
||||
sp = extract_unsigned_integer (buf, 4);
|
||||
|
||||
/* Look for normal sigtramp frame first. */
|
||||
pc = cris_sigtramp_start (next_frame);
|
||||
if (pc)
|
||||
{
|
||||
/* struct signal_frame (arch/cris/kernel/signal.c) contains
|
||||
struct sigcontext as its first member, meaning the SP points to
|
||||
it already. */
|
||||
return sp;
|
||||
}
|
||||
|
||||
pc = cris_rt_sigtramp_start (next_frame);
|
||||
if (pc)
|
||||
{
|
||||
/* struct rt_signal_frame (arch/cris/kernel/signal.c) contains
|
||||
a struct ucontext, which in turn contains a struct sigcontext.
|
||||
Magic digging:
|
||||
4 + 4 + 128 to struct ucontext, then
|
||||
4 + 4 + 12 to struct sigcontext. */
|
||||
return (sp + 156);
|
||||
}
|
||||
|
||||
error ("Couldn't recognize signal trampoline.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cris_unwind_cache
|
||||
|
@ -173,6 +270,111 @@ struct cris_unwind_cache
|
|||
struct trad_frame_saved_reg *saved_regs;
|
||||
};
|
||||
|
||||
static struct cris_unwind_cache *
|
||||
cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
|
||||
void **this_cache)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||
struct cris_unwind_cache *info;
|
||||
CORE_ADDR pc;
|
||||
CORE_ADDR sp;
|
||||
CORE_ADDR addr;
|
||||
char buf[4];
|
||||
int i;
|
||||
|
||||
if ((*this_cache))
|
||||
return (*this_cache);
|
||||
|
||||
info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache);
|
||||
(*this_cache) = info;
|
||||
info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
|
||||
|
||||
/* Zero all fields. */
|
||||
info->prev_sp = 0;
|
||||
info->base = 0;
|
||||
info->size = 0;
|
||||
info->sp_offset = 0;
|
||||
info->r8_offset = 0;
|
||||
info->uses_frame = 0;
|
||||
info->return_pc = 0;
|
||||
info->leaf_function = 0;
|
||||
|
||||
frame_unwind_register (next_frame, SP_REGNUM, buf);
|
||||
info->base = extract_unsigned_integer (buf, 4);
|
||||
|
||||
addr = cris_sigcontext_addr (next_frame);
|
||||
|
||||
/* Layout of the sigcontext struct:
|
||||
struct sigcontext {
|
||||
struct pt_regs regs;
|
||||
unsigned long oldmask;
|
||||
unsigned long usp;
|
||||
}; */
|
||||
|
||||
/* R0 to R13 are stored in reverse order at offset (2 * 4) in
|
||||
struct pt_regs. */
|
||||
for (i = 0; i <= 13; i++)
|
||||
info->saved_regs[i].addr = addr + ((15 - i) * 4);
|
||||
|
||||
info->saved_regs[MOF_REGNUM].addr = addr + (16 * 4);
|
||||
info->saved_regs[DCCR_REGNUM].addr = addr + (17 * 4);
|
||||
info->saved_regs[SRP_REGNUM].addr = addr + (18 * 4);
|
||||
/* Note: IRP is off by 2 at this point. There's no point in correcting it
|
||||
though since that will mean that the backtrace will show a PC different
|
||||
from what is shown when stopped. */
|
||||
info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
|
||||
info->saved_regs[PC_REGNUM] = info->saved_regs[IRP_REGNUM];
|
||||
info->saved_regs[SP_REGNUM].addr = addr + (24 * 4);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
cris_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
|
||||
struct frame_id *this_id)
|
||||
{
|
||||
struct cris_unwind_cache *cache =
|
||||
cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
|
||||
(*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
|
||||
}
|
||||
|
||||
/* Forward declaration. */
|
||||
|
||||
static void cris_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, void *bufferp);
|
||||
static void
|
||||
cris_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, void *valuep)
|
||||
{
|
||||
/* Make sure we've initialized the cache. */
|
||||
cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
|
||||
cris_frame_prev_register (next_frame, this_cache, regnum,
|
||||
optimizedp, lvalp, addrp, realnump, valuep);
|
||||
}
|
||||
|
||||
static const struct frame_unwind cris_sigtramp_frame_unwind =
|
||||
{
|
||||
SIGTRAMP_FRAME,
|
||||
cris_sigtramp_frame_this_id,
|
||||
cris_sigtramp_frame_prev_register
|
||||
};
|
||||
|
||||
static const struct frame_unwind *
|
||||
cris_sigtramp_frame_sniffer (struct frame_info *next_frame)
|
||||
{
|
||||
if (cris_sigtramp_start (next_frame)
|
||||
|| cris_rt_sigtramp_start (next_frame))
|
||||
return &cris_sigtramp_frame_unwind;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The instruction environment needed to find single-step breakpoints. */
|
||||
typedef
|
||||
struct instruction_environment
|
||||
|
@ -345,11 +547,11 @@ static struct gdbarch *cris_gdbarch_init (struct gdbarch_info,
|
|||
|
||||
static void cris_dump_tdep (struct gdbarch *, struct ui_file *);
|
||||
|
||||
static void cris_version_update (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
static void set_cris_version (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
|
||||
static void cris_mode_update (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
static void set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
|
||||
static CORE_ADDR cris_scan_prologue (CORE_ADDR pc,
|
||||
struct frame_info *next_frame,
|
||||
|
@ -362,9 +564,8 @@ static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch,
|
|||
struct frame_info *next_frame);
|
||||
|
||||
/* When arguments must be pushed onto the stack, they go on in reverse
|
||||
order. The below implements a FILO (stack) to do this. */
|
||||
|
||||
/* Borrowed from d10v-tdep.c. */
|
||||
order. The below implements a FILO (stack) to do this.
|
||||
Copied from d10v-tdep.c. */
|
||||
|
||||
struct stack_item
|
||||
{
|
||||
|
@ -399,7 +600,7 @@ pop_stack_item (struct stack_item *si)
|
|||
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. */
|
||||
for it IS the sp for the next frame. */
|
||||
|
||||
struct cris_unwind_cache *
|
||||
cris_frame_unwind_cache (struct frame_info *next_frame,
|
||||
|
@ -531,7 +732,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
|
||||
struct stack_item *si = NULL;
|
||||
|
||||
/* Push the return address. */
|
||||
/* Push the return address. */
|
||||
regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr);
|
||||
|
||||
/* Are we returning a value using a structure return or a normal value
|
||||
|
@ -767,7 +968,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame,
|
|||
limit = next_frame ? frame_pc_unwind (next_frame) : pc + 64;
|
||||
|
||||
/* Find the prologue instructions. */
|
||||
while (pc < limit)
|
||||
while (pc > 0 && pc < limit)
|
||||
{
|
||||
insn = read_memory_unsigned_integer (pc, 2);
|
||||
pc += 2;
|
||||
|
@ -1169,13 +1370,8 @@ cris_cannot_store_register (int regno)
|
|||
/* Writing has no effect. */
|
||||
return 1;
|
||||
|
||||
else if (cris_mode () == CRIS_MODE_USER)
|
||||
{
|
||||
if (regno == IBR_REGNUM || regno == BAR_REGNUM || regno == BRP_REGNUM
|
||||
|| regno == IRP_REGNUM)
|
||||
/* Read-only in user mode. */
|
||||
return 1;
|
||||
}
|
||||
/* IBR, BAR, BRP and IRP are read-only in user mode. Let the debug
|
||||
agent decide whether they are writable. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1202,7 +1398,7 @@ cris_register_offset (int regno)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Invalid register. */
|
||||
/* Invalid register. */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1213,33 +1409,21 @@ cris_register_offset (int regno)
|
|||
static struct type *
|
||||
cris_register_type (struct gdbarch *gdbarch, int regno)
|
||||
{
|
||||
if (regno == SP_REGNUM || regno == PC_REGNUM
|
||||
|| (regno > P8_REGNUM && regno < USP_REGNUM))
|
||||
{
|
||||
/* SP, PC, IBR, IRP, SRP, BAR, DCCR, BRP */
|
||||
return lookup_pointer_type (builtin_type_void);
|
||||
}
|
||||
else if (regno == P8_REGNUM || regno == USP_REGNUM
|
||||
|| (regno >= 0 && regno < SP_REGNUM))
|
||||
{
|
||||
/* R0 - R13, P8, P15 */
|
||||
return builtin_type_unsigned_long;
|
||||
}
|
||||
else if (regno > P3_REGNUM && regno < P8_REGNUM)
|
||||
{
|
||||
/* P4, CCR, DCR0, DCR1 */
|
||||
return builtin_type_unsigned_short;
|
||||
}
|
||||
else if (regno > PC_REGNUM && regno < P4_REGNUM)
|
||||
{
|
||||
/* P0, P1, P2, P3 */
|
||||
return builtin_type_unsigned_char;
|
||||
}
|
||||
if (regno == PC_REGNUM)
|
||||
return builtin_type_void_func_ptr;
|
||||
else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM)
|
||||
return builtin_type_void_data_ptr;
|
||||
else if ((regno >= 0 && regno < SP_REGNUM)
|
||||
|| (regno >= MOF_REGNUM && regno <= USP_REGNUM))
|
||||
/* Note: R8 taken care of previous clause. */
|
||||
return builtin_type_uint32;
|
||||
else if (regno >= P4_REGNUM && regno <= CCR_REGNUM)
|
||||
return builtin_type_uint16;
|
||||
else if (regno >= P0_REGNUM && regno <= VR_REGNUM)
|
||||
return builtin_type_uint8;
|
||||
else
|
||||
{
|
||||
/* Invalid register. */
|
||||
return builtin_type_void;
|
||||
}
|
||||
/* Invalid (unimplemented) register. */
|
||||
return builtin_type_int0;
|
||||
}
|
||||
|
||||
/* Stores a function return value of type type, where valbuf is the address
|
||||
|
@ -1317,10 +1501,49 @@ cris_register_name (int regno)
|
|||
}
|
||||
}
|
||||
|
||||
/* Convert DWARF register number REG to the appropriate register
|
||||
number used by GDB. */
|
||||
|
||||
static int
|
||||
cris_register_bytes_ok (long bytes)
|
||||
cris_dwarf2_reg_to_regnum (int reg)
|
||||
{
|
||||
return (bytes == deprecated_register_bytes ());
|
||||
/* We need to re-map a couple of registers (SRP is 16 in Dwarf-2 register
|
||||
numbering, MOF is 18).
|
||||
Adapted from gcc/config/cris/cris.h. */
|
||||
static int cris_dwarf_regmap[] = {
|
||||
0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15,
|
||||
27, -1, -1, -1,
|
||||
-1, -1, -1, 23,
|
||||
-1, -1, -1, 27,
|
||||
-1, -1, -1, -1
|
||||
};
|
||||
int regnum = -1;
|
||||
|
||||
if (reg >= 0 && reg < ARRAY_SIZE (cris_dwarf_regmap))
|
||||
regnum = cris_dwarf_regmap[reg];
|
||||
|
||||
if (regnum == -1)
|
||||
warning ("Unmapped DWARF Register #%d encountered\n", reg);
|
||||
|
||||
return regnum;
|
||||
}
|
||||
|
||||
/* DWARF-2 frame support. */
|
||||
|
||||
static void
|
||||
cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
|
||||
struct dwarf2_frame_state_reg *reg)
|
||||
{
|
||||
/* The return address column. */
|
||||
if (regnum == PC_REGNUM)
|
||||
reg->how = DWARF2_FRAME_REG_RA;
|
||||
|
||||
/* The call frame address. */
|
||||
else if (regnum == SP_REGNUM)
|
||||
reg->how = DWARF2_FRAME_REG_CFA;
|
||||
}
|
||||
|
||||
/* Extract from an array regbuf containing the raw register state a function
|
||||
|
@ -1596,6 +1819,7 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
|
|||
if (status == -1)
|
||||
{
|
||||
/* Could not find a target. FIXME: Should do something. */
|
||||
warning ("cris_software_single_step: unable to find step target");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3312,7 +3536,7 @@ cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info)
|
|||
disassembler, even when there is no BFD. Does something like
|
||||
"gdb; target remote; disassmeble *0x123" work? */
|
||||
gdb_assert (exec_bfd != NULL);
|
||||
print_insn = cris_get_disassembler (exec_bfd);
|
||||
print_insn = cris_get_disassembler (exec_bfd);
|
||||
gdb_assert (print_insn != NULL);
|
||||
return print_insn (addr, info);
|
||||
}
|
||||
|
@ -3423,229 +3647,36 @@ cris_linux_svr4_fetch_link_map_offsets (void)
|
|||
return lmp;
|
||||
}
|
||||
|
||||
static void
|
||||
cris_fpless_backtrace (char *noargs, int from_tty)
|
||||
{
|
||||
/* Points at the instruction after the jsr (except when in innermost frame
|
||||
where it points at the original pc). */
|
||||
CORE_ADDR pc = 0;
|
||||
|
||||
/* Temporary variable, used for parsing from the start of the function that
|
||||
the pc is in, up to the pc. */
|
||||
CORE_ADDR tmp_pc = 0;
|
||||
CORE_ADDR sp = 0;
|
||||
|
||||
/* Information about current frame. */
|
||||
struct symtab_and_line sal;
|
||||
char* func_name;
|
||||
|
||||
/* Present instruction. */
|
||||
unsigned short insn;
|
||||
|
||||
/* Next instruction, lookahead. */
|
||||
unsigned short insn_next;
|
||||
|
||||
/* This is to store the offset between sp at start of function and until we
|
||||
reach push srp (if any). */
|
||||
int sp_add_later = 0;
|
||||
int push_srp_found = 0;
|
||||
|
||||
int val = 0;
|
||||
|
||||
/* Frame counter. */
|
||||
int frame = 0;
|
||||
|
||||
/* For the innermost frame, we want to look at srp in case it's a leaf
|
||||
function (since there's no push srp in that case). */
|
||||
int innermost_frame = 1;
|
||||
|
||||
deprecated_read_register_gen (PC_REGNUM, (char *) &pc);
|
||||
deprecated_read_register_gen (SP_REGNUM, (char *) &sp);
|
||||
|
||||
/* We make an explicit return when we can't find an outer frame. */
|
||||
while (1)
|
||||
{
|
||||
/* Get file name and line number. */
|
||||
sal = find_pc_line (pc, 0);
|
||||
|
||||
/* Get function name. */
|
||||
find_pc_partial_function (pc, &func_name, (CORE_ADDR *) NULL,
|
||||
(CORE_ADDR *) NULL);
|
||||
|
||||
/* Print information about current frame. */
|
||||
printf_unfiltered ("#%i 0x%08lx in %s", frame++, pc, func_name);
|
||||
if (sal.symtab)
|
||||
{
|
||||
printf_unfiltered (" at %s:%i", sal.symtab->filename, sal.line);
|
||||
}
|
||||
printf_unfiltered ("\n");
|
||||
|
||||
/* Get the start address of this function. */
|
||||
tmp_pc = get_pc_function_start (pc);
|
||||
|
||||
/* Mini parser, only meant to find push sp and sub ...,sp from the start
|
||||
of the function, up to the pc. */
|
||||
while (tmp_pc < pc)
|
||||
{
|
||||
insn = read_memory_unsigned_integer (tmp_pc, sizeof (short));
|
||||
tmp_pc += sizeof (short);
|
||||
if (insn == 0xE1FC)
|
||||
{
|
||||
/* push <reg> 32 bit instruction */
|
||||
insn_next = read_memory_unsigned_integer (tmp_pc,
|
||||
sizeof (short));
|
||||
tmp_pc += sizeof (short);
|
||||
|
||||
/* Recognize srp. */
|
||||
if (insn_next == 0xBE7E)
|
||||
{
|
||||
/* For subsequent (not this one though) push or sub which
|
||||
affects sp, adjust sp immediately. */
|
||||
push_srp_found = 1;
|
||||
|
||||
/* Note: this will break if we ever encounter a
|
||||
push vr (1 byte) or push ccr (2 bytes). */
|
||||
sp_add_later += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Some other register was pushed. */
|
||||
if (push_srp_found)
|
||||
{
|
||||
sp += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_add_later += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cris_get_operand2 (insn) == SP_REGNUM
|
||||
&& cris_get_mode (insn) == 0x0000
|
||||
&& cris_get_opcode (insn) == 0x000A)
|
||||
{
|
||||
/* subq <val>,sp */
|
||||
val = cris_get_quick_value (insn);
|
||||
|
||||
if (push_srp_found)
|
||||
{
|
||||
sp += val;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_add_later += val;
|
||||
}
|
||||
|
||||
}
|
||||
else if (cris_get_operand2 (insn) == SP_REGNUM
|
||||
/* Autoincrement addressing mode. */
|
||||
&& cris_get_mode (insn) == 0x0003
|
||||
/* Opcode. */
|
||||
&& ((insn) & 0x03E0) >> 5 == 0x0004)
|
||||
{
|
||||
/* subu <val>,sp */
|
||||
val = get_data_from_address (&insn, tmp_pc);
|
||||
|
||||
if (push_srp_found)
|
||||
{
|
||||
sp += val;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_add_later += val;
|
||||
}
|
||||
}
|
||||
else if (cris_get_operand2 (insn) == SP_REGNUM
|
||||
&& ((insn & 0x0F00) >> 8) == 0x0001
|
||||
&& (cris_get_signed_offset (insn) < 0))
|
||||
{
|
||||
/* Immediate byte offset addressing prefix word with sp as base
|
||||
register. Used for CRIS v8 i.e. ETRAX 100 and newer if <val>
|
||||
is between 64 and 128.
|
||||
movem r<regsave>,[sp=sp-<val>] */
|
||||
val = -cris_get_signed_offset (insn);
|
||||
insn_next = read_memory_unsigned_integer (tmp_pc,
|
||||
sizeof (short));
|
||||
tmp_pc += sizeof (short);
|
||||
|
||||
if (cris_get_mode (insn_next) == PREFIX_ASSIGN_MODE
|
||||
&& cris_get_opcode (insn_next) == 0x000F
|
||||
&& cris_get_size (insn_next) == 0x0003
|
||||
&& cris_get_operand1 (insn_next) == SP_REGNUM)
|
||||
{
|
||||
if (push_srp_found)
|
||||
{
|
||||
sp += val;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_add_later += val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (push_srp_found)
|
||||
{
|
||||
/* Reset flag. */
|
||||
push_srp_found = 0;
|
||||
|
||||
/* sp should now point at where srp is stored on the stack. Update
|
||||
the pc to the srp. */
|
||||
pc = read_memory_unsigned_integer (sp, 4);
|
||||
}
|
||||
else if (innermost_frame)
|
||||
{
|
||||
/* We couldn't find a push srp in the prologue, so this must be
|
||||
a leaf function, and thus we use the srp register directly.
|
||||
This should happen at most once, for the innermost function. */
|
||||
deprecated_read_register_gen (SRP_REGNUM, (char *) &pc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Couldn't find an outer frame. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset flag. (In case the innermost frame wasn't a leaf, we don't
|
||||
want to look at the srp register later either). */
|
||||
innermost_frame = 0;
|
||||
|
||||
/* Now, add the offset for everything up to, and including push srp,
|
||||
that was held back during the prologue parsing. */
|
||||
sp += sp_add_later;
|
||||
sp_add_later = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern initialize_file_ftype _initialize_cris_tdep; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
_initialize_cris_tdep (void)
|
||||
{
|
||||
static struct cmd_list_element *cris_set_cmdlist;
|
||||
static struct cmd_list_element *cris_show_cmdlist;
|
||||
|
||||
struct cmd_list_element *c;
|
||||
|
||||
gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
|
||||
|
||||
/* CRIS-specific user-commands. */
|
||||
c = add_set_cmd ("cris-version", class_support, var_integer,
|
||||
(char *) &usr_cmd_cris_version,
|
||||
"Set the current CRIS version.", &setlist);
|
||||
set_cmd_sfunc (c, cris_version_update);
|
||||
deprecated_add_show_from_set (c, &showlist);
|
||||
add_setshow_uinteger_cmd ("cris-version", class_support,
|
||||
&usr_cmd_cris_version,
|
||||
"Set the current CRIS version.",
|
||||
"Show the current CRIS version.",
|
||||
"Set if autodetection fails.",
|
||||
"Current CRIS version is %s.",
|
||||
set_cris_version, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
c = add_set_enum_cmd ("cris-mode", class_support, cris_mode_enums,
|
||||
&usr_cmd_cris_mode,
|
||||
"Set the current CRIS mode.", &setlist);
|
||||
set_cmd_sfunc (c, cris_mode_update);
|
||||
deprecated_add_show_from_set (c, &showlist);
|
||||
|
||||
c = add_cmd ("cris-fpless-backtrace", class_support, cris_fpless_backtrace,
|
||||
"Display call chain using the subroutine return pointer.\n"
|
||||
"Note that this displays the address after the jump to the "
|
||||
"subroutine.", &cmdlist);
|
||||
|
||||
deprecated_add_core_fns (&cris_elf_core_fns);
|
||||
add_setshow_boolean_cmd ("cris-dwarf2-cfi", class_support,
|
||||
&usr_cmd_cris_dwarf2_cfi,
|
||||
"Set the usage of Dwarf-2 CFI for CRIS.",
|
||||
"Show the usage of Dwarf-2 CFI for CRIS.",
|
||||
"Set to \"off\" if using gcc-cris < R59.",
|
||||
"Usage of Dwarf-2 CFI for CRIS is %d.",
|
||||
set_cris_dwarf2_cfi, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
}
|
||||
|
||||
|
@ -3659,65 +3690,37 @@ cris_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
|
|||
{
|
||||
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n",
|
||||
tdep->cris_version);
|
||||
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n",
|
||||
tdep->cris_mode);
|
||||
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n",
|
||||
tdep->cris_dwarf2_cfi);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cris_version_update (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
set_cris_version (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
|
||||
/* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
|
||||
function clones the set command passed as a parameter. The clone
|
||||
operation will include (BUG?) any ``set'' command callback, if
|
||||
present. Commands like ``info set'' call all the ``show''
|
||||
command callbacks. Unfortunately, for ``show'' commands cloned
|
||||
from ``set'', this includes callbacks belonging to ``set''
|
||||
commands. Making this worse, this only occures if
|
||||
deprecated_add_show_from_set() is called after add_cmd_sfunc()
|
||||
(BUG?). */
|
||||
usr_cmd_cris_version_valid = 1;
|
||||
|
||||
/* From here on, trust the user's CRIS version setting. */
|
||||
if (cmd_type (c) == set_cmd)
|
||||
{
|
||||
usr_cmd_cris_version_valid = 1;
|
||||
|
||||
/* Update the current architecture, if needed. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
|
||||
}
|
||||
/* Update the current architecture, if needed. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"cris_gdbarch_update: failed to update architecture.");
|
||||
}
|
||||
|
||||
static void
|
||||
cris_mode_update (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
|
||||
/* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
|
||||
function clones the set command passed as a parameter. The clone
|
||||
operation will include (BUG?) any ``set'' command callback, if
|
||||
present. Commands like ``info set'' call all the ``show''
|
||||
command callbacks. Unfortunately, for ``show'' commands cloned
|
||||
from ``set'', this includes callbacks belonging to ``set''
|
||||
commands. Making this worse, this only occures if
|
||||
deprecated_add_show_from_set() is called after add_cmd_sfunc()
|
||||
(BUG?). */
|
||||
|
||||
/* From here on, trust the user's CRIS mode setting. */
|
||||
if (cmd_type (c) == set_cmd)
|
||||
{
|
||||
usr_cmd_cris_mode_valid = 1;
|
||||
|
||||
/* Update the current architecture, if needed. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
|
||||
}
|
||||
/* Update the current architecture, if needed. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"cris_gdbarch_update: failed to update architecture.");
|
||||
}
|
||||
|
||||
static struct gdbarch *
|
||||
|
@ -3726,8 +3729,6 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
struct gdbarch *gdbarch;
|
||||
struct gdbarch_tdep *tdep;
|
||||
int cris_version;
|
||||
const char *cris_mode;
|
||||
int register_bytes;
|
||||
|
||||
if (usr_cmd_cris_version_valid)
|
||||
{
|
||||
|
@ -3740,26 +3741,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
cris_version = 10;
|
||||
}
|
||||
|
||||
if (usr_cmd_cris_mode_valid)
|
||||
{
|
||||
/* Trust the user's CRIS mode setting. */
|
||||
cris_mode = usr_cmd_cris_mode;
|
||||
}
|
||||
else if (cris_version == 10)
|
||||
{
|
||||
/* Assume CRIS version 10 is in user mode. */
|
||||
cris_mode = CRIS_MODE_USER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Strictly speaking, older CRIS version don't have a supervisor mode,
|
||||
but we regard its only mode as supervisor mode. */
|
||||
cris_mode = CRIS_MODE_SUPERVISOR;
|
||||
}
|
||||
|
||||
/* Make the current settings visible to the user. */
|
||||
usr_cmd_cris_version = cris_version;
|
||||
usr_cmd_cris_mode = cris_mode;
|
||||
|
||||
/* Find a candidate among the list of pre-declared architectures. Both
|
||||
CRIS version and ABI must match. */
|
||||
|
@ -3767,8 +3750,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
arches != NULL;
|
||||
arches = gdbarch_list_lookup_by_info (arches->next, &info))
|
||||
{
|
||||
if ((gdbarch_tdep (arches->gdbarch)->cris_version == cris_version)
|
||||
&& (gdbarch_tdep (arches->gdbarch)->cris_mode == cris_mode))
|
||||
if ((gdbarch_tdep (arches->gdbarch)->cris_version
|
||||
== usr_cmd_cris_version)
|
||||
&& (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi
|
||||
== usr_cmd_cris_dwarf2_cfi))
|
||||
return arches->gdbarch;
|
||||
}
|
||||
|
||||
|
@ -3776,8 +3761,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
|
||||
gdbarch = gdbarch_alloc (&info, tdep);
|
||||
|
||||
tdep->cris_version = cris_version;
|
||||
tdep->cris_mode = cris_mode;
|
||||
tdep->cris_version = usr_cmd_cris_version;
|
||||
tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi;
|
||||
|
||||
/* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */
|
||||
switch (info.byte_order)
|
||||
|
@ -3805,15 +3790,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
set_gdbarch_pc_regnum (gdbarch, 15);
|
||||
set_gdbarch_register_name (gdbarch, cris_register_name);
|
||||
|
||||
/* Length of ordinary registers used in push_word and a few other
|
||||
places. register_size() is the real way to know how big a
|
||||
register is. */
|
||||
set_gdbarch_deprecated_register_size (gdbarch, 4);
|
||||
set_gdbarch_double_bit (gdbarch, 64);
|
||||
/* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
|
||||
which means we have to set this explicitly. */
|
||||
set_gdbarch_long_double_bit (gdbarch, 64);
|
||||
set_gdbarch_register_bytes_ok (gdbarch, cris_register_bytes_ok);
|
||||
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
|
||||
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
|
||||
|
||||
|
@ -3827,33 +3807,23 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
/* Support for these may be added later. */
|
||||
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unsupported CRIS version");
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
/* CRIS v8 and v9, a.k.a. ETRAX 100. General registers R0 - R15
|
||||
(32 bits), special registers P0 - P1 (8 bits), P4 - P5 (16 bits),
|
||||
and P8 - P14 (32 bits). */
|
||||
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (7 * 4);
|
||||
/* Old versions; not supported. */
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"cris_gdbarch_init: unsupported CRIS version");
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case 11:
|
||||
/* CRIS v10 and v11, a.k.a. ETRAX 100LX. In addition to ETRAX 100,
|
||||
P7 (32 bits), and P15 (32 bits) have been implemented. */
|
||||
register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (9 * 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version");
|
||||
}
|
||||
|
||||
/* Returns the register offset for the first byte of register regno's space
|
||||
in the saved register state. */
|
||||
set_gdbarch_deprecated_register_byte (gdbarch, cris_register_offset);
|
||||
|
||||
set_gdbarch_register_type (gdbarch, cris_register_type);
|
||||
|
||||
/* Dummy frame functions. */
|
||||
|
@ -3873,9 +3843,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp);
|
||||
set_gdbarch_unwind_dummy_id (gdbarch, cris_unwind_dummy_id);
|
||||
|
||||
/* FIXME: Hook in the DWARF CFI frame unwinder.
|
||||
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
|
||||
*/
|
||||
if (tdep->cris_dwarf2_cfi == 1)
|
||||
{
|
||||
/* Hook in the Dwarf-2 frame sniffer. */
|
||||
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, cris_dwarf2_reg_to_regnum);
|
||||
dwarf2_frame_set_init_reg (gdbarch, cris_dwarf2_frame_init_reg);
|
||||
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
|
||||
}
|
||||
|
||||
frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer);
|
||||
|
||||
frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer);
|
||||
frame_base_set_default (gdbarch, &cris_frame_base);
|
||||
|
||||
|
|
Loading…
Reference in a new issue