Fill out some gaps in ia64 DDB support. This involves generalising DDB's
breakpoint handling slightly to cope with the fact that ia64 instructions are not located on byte boundaries.
This commit is contained in:
parent
de1792cbb8
commit
3a0b4f259c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=83506
@ -48,6 +48,8 @@ extern db_regs_t ddb_regs; /* register state */
|
||||
#define BKPT_SIZE (1) /* size of breakpoint inst */
|
||||
#define BKPT_SET(inst) (BKPT_INST)
|
||||
|
||||
#define BKPT_SKIP ddb_regs.tf_eip += 1
|
||||
|
||||
#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_eip -= 1;
|
||||
|
||||
#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T)
|
||||
|
@ -165,6 +165,19 @@ db_find_breakpoint_here(addr)
|
||||
|
||||
static boolean_t db_breakpoints_inserted = TRUE;
|
||||
|
||||
#ifndef BKPT_WRITE
|
||||
#define BKPT_WRITE(addr, storage) \
|
||||
do { \
|
||||
*storage = db_get_value(addr, BKPT_SIZE, FALSE); \
|
||||
db_put_value(addr, BKPT_SIZE, BKPT_SET(*storage)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef BKPT_CLEAR
|
||||
#define BKPT_CLEAR(addr, storage) \
|
||||
db_put_value(addr, BKPT_SIZE, *storage)
|
||||
#endif
|
||||
|
||||
void
|
||||
db_set_breakpoints()
|
||||
{
|
||||
@ -172,18 +185,13 @@ db_set_breakpoints()
|
||||
|
||||
if (!db_breakpoints_inserted) {
|
||||
|
||||
for (bkpt = db_breakpoint_list;
|
||||
bkpt != 0;
|
||||
bkpt = bkpt->link)
|
||||
if (db_map_current(bkpt->map)) {
|
||||
bkpt->bkpt_inst = db_get_value(bkpt->address,
|
||||
BKPT_SIZE,
|
||||
FALSE);
|
||||
db_put_value(bkpt->address,
|
||||
BKPT_SIZE,
|
||||
BKPT_SET(bkpt->bkpt_inst));
|
||||
}
|
||||
db_breakpoints_inserted = TRUE;
|
||||
for (bkpt = db_breakpoint_list;
|
||||
bkpt != 0;
|
||||
bkpt = bkpt->link)
|
||||
if (db_map_current(bkpt->map)) {
|
||||
BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst);
|
||||
}
|
||||
db_breakpoints_inserted = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,13 +202,13 @@ db_clear_breakpoints()
|
||||
|
||||
if (db_breakpoints_inserted) {
|
||||
|
||||
for (bkpt = db_breakpoint_list;
|
||||
bkpt != 0;
|
||||
bkpt = bkpt->link)
|
||||
if (db_map_current(bkpt->map)) {
|
||||
db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
|
||||
}
|
||||
db_breakpoints_inserted = FALSE;
|
||||
for (bkpt = db_breakpoint_list;
|
||||
bkpt != 0;
|
||||
bkpt = bkpt->link)
|
||||
if (db_map_current(bkpt->map)) {
|
||||
BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst);
|
||||
}
|
||||
db_breakpoints_inserted = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,8 +236,7 @@ db_set_temp_breakpoint(addr)
|
||||
bkpt->init_count = 1;
|
||||
bkpt->count = 1;
|
||||
|
||||
bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
|
||||
db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
|
||||
BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst);
|
||||
return bkpt;
|
||||
}
|
||||
|
||||
@ -237,7 +244,7 @@ void
|
||||
db_delete_temp_breakpoint(bkpt)
|
||||
db_breakpoint_t bkpt;
|
||||
{
|
||||
db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
|
||||
BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst);
|
||||
db_breakpoint_free(bkpt);
|
||||
}
|
||||
#endif /* SOFTWARE_SSTEP */
|
||||
|
@ -37,6 +37,10 @@
|
||||
* Breakpoint.
|
||||
*/
|
||||
|
||||
#ifndef BKPT_INST_TYPE
|
||||
#define BKPT_INST_TYPE int
|
||||
#endif
|
||||
|
||||
struct db_breakpoint {
|
||||
vm_map_t map; /* in this map */
|
||||
db_addr_t address; /* set here */
|
||||
@ -45,7 +49,7 @@ struct db_breakpoint {
|
||||
int flags; /* flags: */
|
||||
#define BKPT_SINGLE_STEP 0x2 /* to simulate single step */
|
||||
#define BKPT_TEMP 0x4 /* temporary */
|
||||
int bkpt_inst; /* saved instruction at bkpt */
|
||||
BKPT_INST_TYPE bkpt_inst; /* saved instruction at bkpt */
|
||||
struct db_breakpoint *link; /* link in in-use or free chain */
|
||||
};
|
||||
typedef struct db_breakpoint *db_breakpoint_t;
|
||||
|
@ -104,8 +104,8 @@ db_stop_at_pc(is_breakpoint)
|
||||
return (TRUE); /* stop here */
|
||||
}
|
||||
} else if (*is_breakpoint) {
|
||||
#ifdef __i386__ /* XXx */
|
||||
ddb_regs.tf_eip += 1;
|
||||
#ifdef BKPT_SKIP
|
||||
BKPT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,8 @@ extern db_regs_t ddb_regs; /* register state */
|
||||
#define BKPT_SIZE (1) /* size of breakpoint inst */
|
||||
#define BKPT_SET(inst) (BKPT_INST)
|
||||
|
||||
#define BKPT_SKIP ddb_regs.tf_eip += 1
|
||||
|
||||
#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_eip -= 1;
|
||||
|
||||
#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T)
|
||||
|
@ -39,11 +39,6 @@
|
||||
|
||||
#define sign_extend(imm, w) (((int64_t)(imm) << (64 - (w))) >> (64 - (w)))
|
||||
|
||||
struct ia64_bundle {
|
||||
u_int64_t slot[3];
|
||||
int template;
|
||||
};
|
||||
|
||||
typedef void (*ia64_print_slot)(db_addr_t loc, u_int64_t slot, boolean_t showregs);
|
||||
|
||||
static void ia64_print_M(db_addr_t, u_int64_t, boolean_t);
|
||||
@ -252,20 +247,6 @@ const char *control_names[] = {
|
||||
"cr124", "cr125", "cr126", "cr127",
|
||||
};
|
||||
|
||||
static void
|
||||
ia64_fetch_bundle(db_addr_t loc, struct ia64_bundle *bp)
|
||||
{
|
||||
u_int64_t low, high;
|
||||
|
||||
db_read_bytes(loc, 8, (caddr_t) &low);
|
||||
db_read_bytes(loc+8, 8, (caddr_t) &high);
|
||||
|
||||
bp->template = low & 0x1f;
|
||||
bp->slot[0] = (low >> 5) & ((1L<<41) - 1);
|
||||
bp->slot[1] = (low >> 46) | ((high & ((1L<<23) - 1)) << 18);
|
||||
bp->slot[2] = (high >> 23);
|
||||
}
|
||||
|
||||
static void
|
||||
ia64_print_ill(const char *name, u_int64_t ins, db_addr_t loc)
|
||||
{
|
||||
@ -1640,7 +1621,7 @@ ia64_print_X1(const char *name, u_int64_t ins, db_addr_t loc)
|
||||
struct ia64_bundle b;
|
||||
union ia64_instruction u;
|
||||
u.ins = ins;
|
||||
ia64_fetch_bundle(loc, &b);
|
||||
db_read_bundle(loc, &b);
|
||||
db_printf("%s %lx",
|
||||
name,
|
||||
(b.slot[1] << 21) | (u.X1.i << 20) | u.X1.imm20a);
|
||||
@ -1652,7 +1633,7 @@ ia64_print_X2(const char *name, u_int64_t ins, db_addr_t loc)
|
||||
struct ia64_bundle b;
|
||||
union ia64_instruction u;
|
||||
u.ins = ins;
|
||||
ia64_fetch_bundle(loc, &b);
|
||||
db_read_bundle(loc, &b);
|
||||
db_printf("%s %s=%lx",
|
||||
name,
|
||||
register_names[u.X2.r1],
|
||||
@ -2848,7 +2829,7 @@ db_disasm(db_addr_t loc, boolean_t altfmt)
|
||||
*/
|
||||
slot = loc & 15;
|
||||
loc &= ~15;
|
||||
ia64_fetch_bundle(loc, &b);
|
||||
db_read_bundle(loc, &b);
|
||||
|
||||
if (b.slot[slot] & 63)
|
||||
db_printf("(p%ld) ", b.slot[slot] & 63);
|
||||
|
@ -75,11 +75,13 @@ extern int trap_types;
|
||||
int db_active;
|
||||
static u_int64_t zero;
|
||||
static int db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op);
|
||||
static int db_get_pc_reg(struct db_variable *vp, db_expr_t *valuep, int op);
|
||||
|
||||
struct db_variable db_regs[] = {
|
||||
/* Misc control/app registers */
|
||||
#define DB_MISC_REGS 14 /* make sure this is correct */
|
||||
#define DB_MISC_REGS 15 /* make sure this is correct */
|
||||
|
||||
{"pc", (db_expr_t*) 0, db_get_pc_reg},
|
||||
{"ip", (db_expr_t*) &ddb_regs.tf_cr_iip, FCN_NULL},
|
||||
{"psr", (db_expr_t*) &ddb_regs.tf_cr_ipsr, FCN_NULL},
|
||||
{"cr.isr", (db_expr_t*) &ddb_regs.tf_cr_isr, FCN_NULL},
|
||||
@ -295,6 +297,14 @@ db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
db_get_pc_reg(struct db_variable *vp, db_expr_t *valuep, int op)
|
||||
{
|
||||
/* Read only */
|
||||
if (op == DB_VAR_GET)
|
||||
*valuep = PC_REGS(DDB_REGS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print trap reason.
|
||||
*/
|
||||
@ -323,7 +333,8 @@ kdb_trap(int vector, struct trapframe *regs)
|
||||
* conditions exist, something Bad has happened.
|
||||
*/
|
||||
|
||||
if (vector != IA64_VEC_BREAK) {
|
||||
if (vector != IA64_VEC_BREAK
|
||||
&& vector != IA64_VEC_SINGLE_STEP_TRAP) {
|
||||
#if 0
|
||||
if (ddb_mode) {
|
||||
db_printf("ddbprinttrap from 0x%lx\n", /* XXX */
|
||||
@ -466,3 +477,69 @@ db_register_value(regs, regno)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
db_read_bundle(db_addr_t addr, struct ia64_bundle *bp)
|
||||
{
|
||||
u_int64_t low, high;
|
||||
|
||||
db_read_bytes(addr, 8, (caddr_t) &low);
|
||||
db_read_bytes(addr+8, 8, (caddr_t) &high);
|
||||
|
||||
bp->template = low & 0x1f;
|
||||
bp->slot[0] = (low >> 5) & ((1L<<41) - 1);
|
||||
bp->slot[1] = (low >> 46) | ((high & ((1L<<23) - 1)) << 18);
|
||||
bp->slot[2] = (high >> 23);
|
||||
}
|
||||
|
||||
void
|
||||
db_write_bundle(db_addr_t addr, struct ia64_bundle *bp)
|
||||
{
|
||||
u_int64_t low, high;
|
||||
|
||||
low = bp->template | (bp->slot[0] << 5) | (bp->slot[1] << 46);
|
||||
high = (bp->slot[1] >> 18) | (bp->slot[2] << 23);
|
||||
|
||||
db_write_bytes(addr, 8, (caddr_t) &low);
|
||||
db_write_bytes(addr+8, 8, (caddr_t) &high);
|
||||
}
|
||||
|
||||
void
|
||||
db_write_breakpoint(vm_offset_t addr, u_int64_t *storage)
|
||||
{
|
||||
struct ia64_bundle b;
|
||||
int slot;
|
||||
|
||||
slot = addr & 15;
|
||||
addr &= ~15;
|
||||
db_read_bundle(addr, &b);
|
||||
*storage = b.slot[slot];
|
||||
b.slot[slot] = 0x80100 << 6; /* break.* 0x80100 */
|
||||
db_write_bundle(addr, &b);
|
||||
}
|
||||
|
||||
void
|
||||
db_clear_breakpoint(vm_offset_t addr, u_int64_t *storage)
|
||||
{
|
||||
struct ia64_bundle b;
|
||||
int slot;
|
||||
|
||||
slot = addr & 15;
|
||||
addr &= ~15;
|
||||
db_read_bundle(addr, &b);
|
||||
b.slot[slot] = *storage;
|
||||
db_write_bundle(addr, &b);
|
||||
}
|
||||
|
||||
void
|
||||
db_skip_breakpoint(void)
|
||||
{
|
||||
/*
|
||||
* Skip past the break instruction.
|
||||
*/
|
||||
ddb_regs.tf_cr_ipsr += IA64_PSR_RI_1;
|
||||
if ((ddb_regs.tf_cr_ipsr & IA64_PSR_RI) > IA64_PSR_RI_2) {
|
||||
ddb_regs.tf_cr_ipsr &= ~IA64_PSR_RI;
|
||||
ddb_regs.tf_cr_iip += 16;
|
||||
}
|
||||
}
|
||||
|
@ -243,9 +243,6 @@ trap(int vector, int imm, struct trapframe *framep)
|
||||
/* Always fatal in kernel. Should never happen. */
|
||||
goto dopanic;
|
||||
|
||||
case IA64_VEC_BREAK:
|
||||
goto dopanic;
|
||||
|
||||
case IA64_VEC_DISABLED_FP:
|
||||
/*
|
||||
* on exit from the kernel, if thread == fpcurthread,
|
||||
@ -394,6 +391,37 @@ trap(int vector, int imm, struct trapframe *framep)
|
||||
printtrap(vector, imm, framep, 1, user);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case IA64_VEC_SINGLE_STEP_TRAP:
|
||||
/*
|
||||
* Clear single-step bit.
|
||||
*/
|
||||
framep->tf_cr_ipsr &= IA64_PSR_SS;
|
||||
/* FALLTHROUTH */
|
||||
|
||||
case IA64_VEC_DEBUG:
|
||||
case IA64_VEC_TAKEN_BRANCH_TRAP:
|
||||
case IA64_VEC_BREAK:
|
||||
/*
|
||||
* These are always fatal in kernel, and should never happen.
|
||||
*/
|
||||
if (!user) {
|
||||
#ifdef DDB
|
||||
/*
|
||||
* ...unless, of course, DDB is configured.
|
||||
*/
|
||||
if (kdb_trap(vector, framep))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we get here, DDB did _not_ handle the
|
||||
* trap, and we need to PANIC!
|
||||
*/
|
||||
#endif
|
||||
goto dopanic;
|
||||
}
|
||||
i = SIGTRAP;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -41,6 +41,11 @@
|
||||
|
||||
#define DB_NO_AOUT
|
||||
|
||||
struct ia64_bundle {
|
||||
u_int64_t slot[3];
|
||||
int template;
|
||||
};
|
||||
|
||||
typedef vm_offset_t db_addr_t; /* address - unsigned */
|
||||
typedef long db_expr_t; /* expression - signed */
|
||||
typedef struct trapframe db_regs_t;
|
||||
@ -50,16 +55,16 @@ db_regs_t ddb_regs; /* register state */
|
||||
#define PC_REGS(regs) ((db_addr_t)(regs)->tf_cr_iip \
|
||||
+ (((regs)->tf_cr_ipsr >> 41) & 3))
|
||||
|
||||
#define BKPT_INST 0x00000080 /* breakpoint instruction */
|
||||
#define BKPT_SIZE (4) /* size of breakpoint inst */
|
||||
#define BKPT_SET(inst) (BKPT_INST)
|
||||
#define BKPT_WRITE(addr, storage) db_write_breakpoint(addr, storage)
|
||||
#define BKPT_CLEAR(addr, storage) db_clear_breakpoint(addr, storage)
|
||||
#define BKPT_INST_TYPE u_int64_t
|
||||
|
||||
#define FIXUP_PC_AFTER_BREAK
|
||||
#define BKPT_SKIP db_skip_breakpoint()
|
||||
|
||||
#define db_clear_single_step(regs) 0
|
||||
#define db_set_single_step(regs) 0
|
||||
#define db_clear_single_step(regs) ddb_regs.tf_cr_ipsr &= ~IA64_PSR_SS
|
||||
#define db_set_single_step(regs) ddb_regs.tf_cr_ipsr |= IA64_PSR_SS
|
||||
|
||||
#define IS_BREAKPOINT_TRAP(type, code) 0
|
||||
#define IS_BREAKPOINT_TRAP(type, code) (type == IA64_VEC_BREAK)
|
||||
#define IS_WATCHPOINT_TRAP(type, code) 0
|
||||
|
||||
#define inst_trap_return(ins) 0
|
||||
@ -86,6 +91,12 @@ u_int64_t *db_rse_current_frame(void);
|
||||
u_int64_t *db_rse_previous_frame(u_int64_t *bsp, int sof);
|
||||
u_int64_t *db_rse_register_address(u_int64_t *bsp, int regno);
|
||||
|
||||
void db_read_bundle(db_addr_t addr, struct ia64_bundle *bp);
|
||||
void db_write_bundle(db_addr_t addr, struct ia64_bundle *bp);
|
||||
void db_write_breakpoint(db_addr_t addr, u_int64_t *storage);
|
||||
void db_clear_breakpoint(db_addr_t addr, u_int64_t *storage);
|
||||
void db_skip_breakpoint(void);
|
||||
|
||||
/*
|
||||
* Pretty arbitrary
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user