Since SMAP is enabled ddb(4)'s 'trace /u' and 'trace /p' for a userland
processes result, as expected, in page faults.
Diff below disable SMAP for the duration of the command. This allows us
to see any possible frame corruption.
ok?
Index: arch/amd64/amd64/db_trace.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/db_trace.c,v
retrieving revision 1.36
diff -u -p -r1.36 db_trace.c
--- arch/amd64/amd64/db_trace.c 3 Nov 2017 11:29:46 -0000 1.36
+++ arch/amd64/amd64/db_trace.c 4 Dec 2017 10:42:42 -0000
@@ -169,6 +169,7 @@ db_stack_trace_print(db_expr_t addr, boo
struct callframe *frame, *lastframe;
unsigned long *argp, *arg0;
db_addr_t callpc;
+ unsigned int cr4save;
int is_trap = 0;
boolean_t kernel_only = TRUE;
boolean_t trace_proc = FALSE;
@@ -185,6 +186,10 @@ db_stack_trace_print(db_expr_t addr, boo
}
}
+ cr4save = rcr4();
+ if (cr4save & CR4_SMAP)
+ lcr4(cr4save & ~CR4_SMAP);
+
if (!have_addr) {
frame = (struct callframe *)ddb_regs.tf_rbp;
callpc = (db_addr_t)ddb_regs.tf_rip;
@@ -193,7 +198,7 @@ db_stack_trace_print(db_expr_t addr, boo
struct proc *p = tfind((pid_t)addr);
if (p == NULL) {
(*pr) ("not found\n");
- return;
+ goto out;
}
frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp;
} else {
@@ -212,8 +217,13 @@ db_stack_trace_print(db_expr_t addr, boo
db_expr_t offset;
Elf_Sym * sym;
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
+ if (INKERNEL(frame)) {
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ } else {
+ sym = NULL;
+ name = NULL;
+ }
if (lastframe == 0 && sym == NULL) {
/* Symbol not found, peek at code */
@@ -332,6 +342,9 @@ db_stack_trace_print(db_expr_t addr, boo
db_printsym(callpc, DB_STGY_XTRN, pr);
(*pr)(":\n");
}
+
+out:
+ lcr4(cr4save);
}
void
Index: arch/i386/i386/db_trace.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/db_trace.c,v
retrieving revision 1.31
diff -u -p -r1.31 db_trace.c
--- arch/i386/i386/db_trace.c 3 Nov 2017 11:29:46 -0000 1.31
+++ arch/i386/i386/db_trace.c 4 Dec 2017 11:18:38 -0000
@@ -184,9 +184,9 @@ db_stack_trace_print(db_expr_t addr, boo
struct callframe *frame, *lastframe;
int *argp, *arg0;
db_addr_t callpc;
+ unsigned int cr4save;
int is_trap = 0;
boolean_t kernel_only = TRUE;
- boolean_t trace_thread = FALSE;
boolean_t trace_proc = FALSE;
{
@@ -194,8 +194,6 @@ db_stack_trace_print(db_expr_t addr, boo
char c;
while ((c = *cp++) != 0) {
- if (c == 't')
- trace_thread = TRUE;
if (c == 'p')
trace_proc = TRUE;
if (c == 'u')
@@ -206,16 +204,18 @@ db_stack_trace_print(db_expr_t addr, boo
if (count == -1)
count = 65535;
+ cr4save = rcr4();
+ if (cr4save & CR4_SMAP)
+ lcr4(cr4save & ~CR4_SMAP);
+
if (!have_addr) {
frame = (struct callframe *)ddb_regs.tf_ebp;
callpc = (db_addr_t)ddb_regs.tf_eip;
- } else if (trace_thread) {
- (*pr) ("%s: can't trace thread\n", __func__);
} else if (trace_proc) {
struct proc *p = tfind((pid_t)addr);
if (p == NULL) {
(*pr) ("not found\n");
- return;
+ goto out;
}
frame = (struct callframe *)p->p_addr->u_pcb.pcb_ebp;
callpc = (db_addr_t)
@@ -233,8 +233,13 @@ db_stack_trace_print(db_expr_t addr, boo
db_expr_t offset;
Elf_Sym *sym;
- sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
- db_symbol_values(sym, &name, NULL);
+ if (INKERNEL(frame)) {
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+ } else {
+ sym = NULL;
+ name = NULL;
+ }
if (lastframe == 0 && sym == NULL) {
/* Symbol not found, peek at code */
@@ -306,8 +311,10 @@ db_stack_trace_print(db_expr_t addr, boo
}
} else if (INKERNEL(lastframe)) {
/* switch from user to kernel */
- if (kernel_only)
+ if (kernel_only) {
+ (*pr)("end of kernel\n");
break; /* kernel stack only */
+ }
} else {
/* in user */
if (frame <= lastframe) {
@@ -323,6 +330,9 @@ db_stack_trace_print(db_expr_t addr, boo
db_printsym(callpc, DB_STGY_XTRN, pr);
(*pr)(":\n");
}
+
+out:
+ lcr4(cr4save);
}
void