Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204950
b: refs/heads/master
c: 534af10
h: refs/heads/master
v: v3
  • Loading branch information
Jason Wessel committed Aug 5, 2010
1 parent 8f1dedb commit e70fc73
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 84a0bd5b2830722cf80ff6ad33ef98101a947e14
refs/heads/master: 534af1082329392bc29f6badf815e69ae2ae0f4c
13 changes: 13 additions & 0 deletions trunk/include/linux/kgdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ struct kgdb_bkpt {
enum kgdb_bpstate state;
};

struct dbg_reg_def_t {
char *name;
int size;
int offset;
};

#ifndef DBG_MAX_REG_NUM
#define DBG_MAX_REG_NUM 0
#else
extern struct dbg_reg_def_t dbg_reg_def[];
extern char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs);
extern int dbg_set_reg(int regno, void *mem, struct pt_regs *regs);
#endif
#ifndef KGDB_MAX_BREAKPOINTS
# define KGDB_MAX_BREAKPOINTS 1000
#endif
Expand Down
26 changes: 26 additions & 0 deletions trunk/kernel/debug/gdbstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,32 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count)
return probe_kernel_write(mem, c, size);
}

#if DBG_MAX_REG_NUM > 0
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
int i;
int idx = 0;
char *ptr = (char *)gdb_regs;

for (i = 0; i < DBG_MAX_REG_NUM; i++) {
dbg_get_reg(i, ptr + idx, regs);
idx += dbg_reg_def[i].size;
}
}

void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
int i;
int idx = 0;
char *ptr = (char *)gdb_regs;

for (i = 0; i < DBG_MAX_REG_NUM; i++) {
dbg_set_reg(i, ptr + idx, regs);
idx += dbg_reg_def[i].size;
}
}
#endif /* DBG_MAX_REG_NUM > 0 */

/* Write memory due to an 'M' or 'X' packet. */
static int write_mem_msg(int binary)
{
Expand Down
132 changes: 120 additions & 12 deletions trunk/kernel/debug/kdb/kdb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ int kdbgetularg(const char *arg, unsigned long *value)

if (endp == arg) {
/*
* Try base 16, for us folks too lazy to type the
* Also try base 16, for us folks too lazy to type the
* leading 0x...
*/
val = simple_strtoul(arg, &endp, 16);
Expand All @@ -325,6 +325,25 @@ int kdbgetularg(const char *arg, unsigned long *value)
return 0;
}

int kdbgetu64arg(const char *arg, u64 *value)
{
char *endp;
u64 val;

val = simple_strtoull(arg, &endp, 0);

if (endp == arg) {

val = simple_strtoull(arg, &endp, 16);
if (endp == arg)
return KDB_BADINT;
}

*value = val;

return 0;
}

/*
* kdb_set - This function implements the 'set' command. Alter an
* existing environment variable or create a new one.
Expand Down Expand Up @@ -1770,44 +1789,133 @@ static int kdb_go(int argc, const char **argv)
*/
static int kdb_rd(int argc, const char **argv)
{
int diag = kdb_check_regs();
if (diag)
return diag;
int len = kdb_check_regs();
#if DBG_MAX_REG_NUM > 0
int i;
char *rname;
int rsize;
u64 reg64;
u32 reg32;
u16 reg16;
u8 reg8;

if (len)
return len;

for (i = 0; i < DBG_MAX_REG_NUM; i++) {
rsize = dbg_reg_def[i].size * 2;
if (rsize > 16)
rsize = 2;
if (len + strlen(dbg_reg_def[i].name) + 4 + rsize > 80) {
len = 0;
kdb_printf("\n");
}
if (len)
len += kdb_printf(" ");
switch(dbg_reg_def[i].size * 8) {
case 8:
rname = dbg_get_reg(i, &reg8, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %02x", rname, reg8);
break;
case 16:
rname = dbg_get_reg(i, &reg16, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %04x", rname, reg16);
break;
case 32:
rname = dbg_get_reg(i, &reg32, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %08x", rname, reg32);
break;
case 64:
rname = dbg_get_reg(i, &reg64, kdb_current_regs);
if (!rname)
break;
len += kdb_printf("%s: %016llx", rname, reg64);
break;
default:
len += kdb_printf("%s: ??", dbg_reg_def[i].name);
}
}
kdb_printf("\n");
#else
if (len)
return len;

kdb_dumpregs(kdb_current_regs);
#endif
return 0;
}

/*
* kdb_rm - This function implements the 'rm' (register modify) command.
* rm register-name new-contents
* Remarks:
* Currently doesn't allow modification of control or
* debug registers.
* Allows register modification with the same restrictions as gdb
*/
static int kdb_rm(int argc, const char **argv)
{
#if DBG_MAX_REG_NUM > 0
int diag;
int ind = 0;
unsigned long contents;
const char *rname;
int i;
u64 reg64;
u32 reg32;
u16 reg16;
u8 reg8;

if (argc != 2)
return KDB_ARGCOUNT;
/*
* Allow presence or absence of leading '%' symbol.
*/
if (argv[1][0] == '%')
ind = 1;
rname = argv[1];
if (*rname == '%')
rname++;

diag = kdbgetularg(argv[2], &contents);
diag = kdbgetu64arg(argv[2], &reg64);
if (diag)
return diag;

diag = kdb_check_regs();
if (diag)
return diag;

diag = KDB_BADREG;
for (i = 0; i < DBG_MAX_REG_NUM; i++) {
if (strcmp(rname, dbg_reg_def[i].name) == 0) {
diag = 0;
break;
}
}
if (!diag) {
switch(dbg_reg_def[i].size * 8) {
case 8:
reg8 = reg64;
dbg_set_reg(i, &reg8, kdb_current_regs);
break;
case 16:
reg16 = reg64;
dbg_set_reg(i, &reg16, kdb_current_regs);
break;
case 32:
reg32 = reg64;
dbg_set_reg(i, &reg32, kdb_current_regs);
break;
case 64:
dbg_set_reg(i, &reg64, kdb_current_regs);
break;
}
}
return diag;
#else
kdb_printf("ERROR: Register set currently not implemented\n");
return 0;
return 0;
#endif
}

#if defined(CONFIG_MAGIC_SYSRQ)
Expand Down

0 comments on commit e70fc73

Please sign in to comment.