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:
Doug Rabson 2001-09-15 11:06:07 +00:00
parent de1792cbb8
commit 3a0b4f259c
9 changed files with 171 additions and 59 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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;

View File

@ -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
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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
*/