summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-02-17 17:16:04 +0000
committerpatrick <patrick@openbsd.org>2017-02-17 17:16:04 +0000
commit9c0eaec2acf2a9cb1ba0278ad6eaa30b71cba453 (patch)
tree7deae0660fa431a05cdb1009464631ad30cf3585
parentypbind(8) is not started automatically at boot time by /etc/rc if domainname (diff)
downloadwireguard-openbsd-9c0eaec2acf2a9cb1ba0278ad6eaa30b71cba453.tar.xz
wireguard-openbsd-9c0eaec2acf2a9cb1ba0278ad6eaa30b71cba453.zip
Implement DDB backtrace support. In addition to the actual tracing,
clean up a few address types from int to vaddr_t, implement 8 byte reads and remove the unused db_fetch_reg() function. From Dale Rahn
-rw-r--r--sys/arch/arm64/arm64/db_interface.c112
-rw-r--r--sys/arch/arm64/arm64/db_trace.c84
2 files changed, 88 insertions, 108 deletions
diff --git a/sys/arch/arm64/arm64/db_interface.c b/sys/arch/arm64/arm64/db_interface.c
index 440a29729fb..1f39c3f6c24 100644
--- a/sys/arch/arm64/arm64/db_interface.c
+++ b/sys/arch/arm64/arm64/db_interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_interface.c,v 1.1 2016/12/17 23:38:33 patrick Exp $ */
+/* $OpenBSD: db_interface.c,v 1.2 2017/02/17 17:16:04 patrick Exp $ */
/* $NetBSD: db_interface.c,v 1.34 2003/10/26 23:11:15 chris Exp $ */
/*
@@ -60,7 +60,7 @@ int db_access_abt_sp (struct db_variable *, db_expr_t *, int);
int db_access_irq_sp (struct db_variable *, db_expr_t *, int);
u_int db_fetch_reg (int, db_regs_t *);
-int db_trapper (u_int, u_int, trapframe_t *, int);
+int db_trapper (vaddr_t, u_int, trapframe_t *, int);
struct db_variable db_regs[] = {
{ "x0", (long *)&DDB_REGS->tf_x[0], FCN_NULL, },
@@ -146,6 +146,8 @@ kdb_trap(int type, db_regs_t *regs)
#endif
+#define INKERNEL(va) (((vaddr_t)(va)) & (1ULL << 63))
+
static int db_validate_address(vaddr_t addr);
static int
@@ -155,12 +157,7 @@ db_validate_address(vaddr_t addr)
struct pmap *pmap;
if (!p || !p->p_vmspace || !p->p_vmspace->vm_map.pmap ||
-#ifndef ARM32_NEW_VM_LAYOUT
- addr >= VM_MAXUSER_ADDRESS
-#else
- addr >= VM_MIN_KERNEL_ADDRESS
-#endif
- )
+ INKERNEL(addr))
pmap = pmap_kernel();
else
pmap = p->p_vmspace->vm_map.pmap;
@@ -179,23 +176,28 @@ db_read_bytes(addr, size, data)
{
char *src = (char *)addr;
- if (db_validate_address((u_int)src)) {
+ if (db_validate_address((vaddr_t)src)) {
db_printf("address %p is invalid\n", src);
return;
}
- if (size == 4 && (addr & 3) == 0 && ((u_int32_t)data & 3) == 0) {
+ if (size == 8 && (addr & 7) == 0 && ((vaddr_t)data & 7) == 0) {
+ *((uint64_t*)data) = *((uint64_t*)src);
+ return;
+ }
+
+ if (size == 4 && (addr & 3) == 0 && ((vaddr_t)data & 3) == 0) {
*((int*)data) = *((int*)src);
return;
}
- if (size == 2 && (addr & 1) == 0 && ((u_int32_t)data & 1) == 0) {
+ if (size == 2 && (addr & 1) == 0 && ((vaddr_t)data & 1) == 0) {
*((short*)data) = *((short*)src);
return;
}
while (size-- > 0) {
- if (db_validate_address((u_int)src)) {
+ if (db_validate_address((vaddr_t)src)) {
db_printf("address %p is invalid\n", src);
return;
}
@@ -233,7 +235,7 @@ db_write_bytes(vaddr_t addr, size_t size, char *data)
dst = (char *)addr;
loop = size;
while (loop-- > 0) {
- if (db_validate_address((u_int)dst)) {
+ if (db_validate_address((vaddr_t)dst)) {
db_printf("address %p is invalid\n", dst);
return;
}
@@ -259,7 +261,7 @@ struct db_command db_machine_command_table[] = {
};
int
-db_trapper(u_int addr, u_int inst, trapframe_t *frame, int fault_code)
+db_trapper(vaddr_t addr, u_int inst, trapframe_t *frame, int fault_code)
{
if (fault_code == EXCP_BRK) {
@@ -270,8 +272,8 @@ db_trapper(u_int addr, u_int inst, trapframe_t *frame, int fault_code)
return (0);
}
-extern u_int esym;
-extern u_int end;
+extern vaddr_t esym;
+extern vaddr_t end;
void
db_machine_init(void)
@@ -286,84 +288,6 @@ db_machine_init(void)
db_machine_commands_install(db_machine_command_table);
}
-u_int
-db_fetch_reg(int reg, db_regs_t *db_regs)
-{
-
- switch (reg) {
- case 0:
- return (db_regs->tf_x[0]);
- case 1:
- return (db_regs->tf_x[1]);
- case 2:
- return (db_regs->tf_x[2]);
- case 3:
- return (db_regs->tf_x[3]);
- case 4:
- return (db_regs->tf_x[4]);
- case 5:
- return (db_regs->tf_x[5]);
- case 6:
- return (db_regs->tf_x[6]);
- case 7:
- return (db_regs->tf_x[7]);
- case 8:
- return (db_regs->tf_x[8]);
- case 9:
- return (db_regs->tf_x[9]);
- case 10:
- return (db_regs->tf_x[10]);
- case 11:
- return (db_regs->tf_x[11]);
- case 12:
- return (db_regs->tf_x[12]);
- case 13:
- return (db_regs->tf_x[13]);
- case 14:
- return (db_regs->tf_x[14]);
- case 15:
- return (db_regs->tf_x[15]);
- case 16:
- return (db_regs->tf_x[16]);
- case 17:
- return (db_regs->tf_x[17]);
- case 18:
- return (db_regs->tf_x[18]);
- case 19:
- return (db_regs->tf_x[19]);
- case 20:
- return (db_regs->tf_x[20]);
- case 21:
- return (db_regs->tf_x[21]);
- case 22:
- return (db_regs->tf_x[22]);
- case 23:
- return (db_regs->tf_x[23]);
- case 24:
- return (db_regs->tf_x[24]);
- case 25:
- return (db_regs->tf_x[25]);
- case 26:
- return (db_regs->tf_x[26]);
- case 27:
- return (db_regs->tf_x[27]);
- case 28:
- return (db_regs->tf_x[28]);
- case 29:
- return (db_regs->tf_x[29]);
- case 30:
- return (db_regs->tf_lr);
- case 31:
- return (db_regs->tf_sp);
- case 32:
- return (db_regs->tf_elr);
- case 33:
- return (db_regs->tf_spsr);
- default:
- panic("db_fetch_reg: botch");
- }
-}
-
db_addr_t
db_branch_taken(u_int insn, db_addr_t pc, db_regs_t *db_regs)
{
diff --git a/sys/arch/arm64/arm64/db_trace.c b/sys/arch/arm64/arm64/db_trace.c
index 3c22bf81af7..07c5ed5e0ee 100644
--- a/sys/arch/arm64/arm64/db_trace.c
+++ b/sys/arch/arm64/arm64/db_trace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_trace.c,v 1.3 2016/12/19 07:44:54 jsg Exp $ */
+/* $OpenBSD: db_trace.c,v 1.4 2017/02/17 17:16:04 patrick Exp $ */
/* $NetBSD: db_trace.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */
/*
@@ -39,12 +39,13 @@
#include <ddb/db_access.h>
#include <ddb/db_interface.h>
+#include <ddb/db_variables.h>
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
db_regs_t ddb_regs;
-#define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+#define INKERNEL(va) (((vaddr_t)(va)) & (1ULL << 63))
#ifndef __clang__
/*
@@ -55,19 +56,21 @@ db_regs_t ddb_regs;
*
*/
#define FR_RFP (0x0)
-#define FR_RLV (+0x4)
+#define FR_RLV (0x4)
#endif /* !__clang__ */
void
db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
char *modif, int (*pr)(const char *, ...))
{
- u_int32_t frame, lastframe;
+ u_int64_t frame, lastframe, lr, lastlr, sp;
char c, *cp = modif;
+ db_expr_t offset;
+ db_sym_t sym;
+ char *name;
boolean_t kernel_only = TRUE;
boolean_t trace_thread = FALSE;
//db_addr_t scp = 0;
- int scp_offset;
while ((c = *cp++) != 0) {
if (c == 'u')
@@ -77,18 +80,71 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
}
if (!have_addr) {
- // Implement
- frame = 0;
+ sp = ddb_regs.tf_sp;
+ lr = ddb_regs.tf_lr;
+ lastlr = ddb_regs.tf_elr;
+ frame = ddb_regs.tf_x[29];
} else {
- // Implement
- frame = 0;
+ if (trace_thread) {
+ struct proc *p = tfind((pid_t)addr);
+ if (p == NULL) {
+ (*pr)("not found\n");
+ return;
+ }
+ frame = p->p_addr->u_pcb.pcb_tf->tf_x[29];
+ sp = p->p_addr->u_pcb.pcb_tf->tf_sp;
+ lr = p->p_addr->u_pcb.pcb_tf->tf_lr;
+ lastlr = p->p_addr->u_pcb.pcb_tf->tf_elr;
+ } else {
+ sp = addr;
+ db_read_bytes(sp+16, sizeof(db_addr_t),
+ (char *)&frame);
+ db_read_bytes(sp + 8, sizeof(db_addr_t),
+ (char *)&lr);
+ lastlr = 0;
+ }
}
- lastframe = 0;
- //scp_offset = -get_pc_str_offset();
- scp_offset = -4;
while (count-- && frame != 0) {
- break;
- // Implement
+ lastframe = frame;
+
+ sym = db_search_symbol(lastlr, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+
+ if (name == NULL || strcmp(name, "end") == 0) {
+ (*pr)("%llx at 0x%lx", lastlr, lr - 4);
+ } else {
+ (*pr)("%s() at ", name);
+ db_printsym(lr - 4, DB_STGY_PROC, pr);
+ }
+ (*pr)("\n");
+
+ // can we detect traps ?
+ db_read_bytes(frame, sizeof(db_addr_t), (char *)&frame);
+ if (frame == 0)
+ break;
+ lastlr = lr;
+ db_read_bytes(frame + 8, sizeof(db_addr_t), (char *)&lr);
+
+ if (name != NULL) {
+ if ((strcmp (name, "handle_el0_irq") == 0) ||
+ (strcmp (name, "handle_el1_irq") == 0)) {
+ (*pr)("--- interrupt ---\n");
+ } else if (
+ (strcmp (name, "handle_el0_sync") == 0) ||
+ (strcmp (name, "handle_el1_sync") == 0)) {
+ (*pr)("--- trap ---\n");
+ }
+ }
+ if (INKERNEL(frame)) {
+ if (frame <= lastframe) {
+ (*pr)("Bad frame pointer: 0x%lx\n", frame);
+ break;
+ }
+ } else {
+ if (kernel_only)
+ break;
+ }
+ --count;
}
}