summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ddb/db_thread.c92
-rw-r--r--sys/ddb/ddb.h2
2 files changed, 94 insertions, 0 deletions
diff --git a/sys/ddb/db_thread.c b/sys/ddb/db_thread.c
index 5b50f56..a946dd8 100644
--- a/sys/ddb/db_thread.c
+++ b/sys/ddb/db_thread.c
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
+static db_expr_t hex2dec(db_expr_t expr);
+
void
db_print_thread(void)
{
@@ -108,3 +110,93 @@ db_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod)
thr = kdb_thr_next(thr);
}
}
+
+/*
+ * Take the parsed expression value from the command line that was parsed
+ * as a hexadecimal value and convert it as if the expression was parsed
+ * as a decimal value. Returns -1 if the expression was not a valid
+ * decimal value.
+ */
+static db_expr_t
+hex2dec(db_expr_t expr)
+{
+ uintptr_t x, y;
+ db_expr_t val;
+
+ y = 1;
+ val = 0;
+ x = expr;
+ while (x != 0) {
+ if (x % 16 > 9)
+ return (-1);
+ val += (x % 16) * (y);
+ x >>= 4;
+ y *= 10;
+ }
+ return (val);
+}
+
+/*
+ * Lookup a thread based on a db expression address. We assume that the
+ * address was parsed in hexadecimal. We reparse the address in decimal
+ * first and try to treat it as a thread ID to find an associated thread.
+ * If that fails and check_pid is true, we terat the decimal value as a
+ * PID. If that matches a process, we return the first thread in that
+ * process. Otherwise, we treat the addr as a pointer to a thread.
+ */
+struct thread *
+db_lookup_thread(db_expr_t addr, boolean_t check_pid)
+{
+ struct thread *td;
+ db_expr_t decaddr;
+ struct proc *p;
+
+ /*
+ * If the parsed address was not a valid decimal expression,
+ * assume it is a thread pointer.
+ */
+ decaddr = hex2dec(addr);
+ if (decaddr == -1)
+ return ((struct thread *)addr);
+
+ td = kdb_thr_lookup(decaddr);
+ if (td != NULL)
+ return (td);
+ if (check_pid) {
+ LIST_FOREACH(p, &allproc, p_list) {
+ if (p->p_pid == decaddr)
+ return (FIRST_THREAD_IN_PROC(p));
+ }
+ LIST_FOREACH(p, &zombproc, p_list) {
+ if (p->p_pid == decaddr)
+ return (FIRST_THREAD_IN_PROC(p));
+ }
+ }
+ return ((struct thread *)addr);
+}
+
+/*
+ * Lookup a process based on a db expression address. We assume that the
+ * address was parsed in hexadecimal. We reparse the address in decimal
+ * first and try to treat it as a PID to find an associated process.
+ * If that fails we treat the addr as a pointer to a process.
+ */
+struct proc *
+db_lookup_proc(db_expr_t addr)
+{
+ db_expr_t decaddr;
+ struct proc *p;
+
+ decaddr = hex2dec(addr);
+ if (decaddr != -1) {
+ LIST_FOREACH(p, &allproc, p_list) {
+ if (p->p_pid == decaddr)
+ return (p);
+ }
+ LIST_FOREACH(p, &zombproc, p_list) {
+ if (p->p_pid == decaddr)
+ return (p);
+ }
+ }
+ return ((struct proc *)addr);
+}
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index 33021c9..549e24e 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -101,6 +101,8 @@ void db_error(const char *s);
int db_expression(db_expr_t *valuep);
int db_get_variable(db_expr_t *valuep);
void db_iprintf(const char *,...) __printflike(1, 2);
+struct proc *db_lookup_proc(db_expr_t addr);
+struct thread *db_lookup_thread(db_expr_t addr, boolean_t check_pid);
struct vm_map *db_map_addr(vm_offset_t);
boolean_t db_map_current(struct vm_map *);
boolean_t db_map_equal(struct vm_map *, struct vm_map *);
OpenPOWER on IntegriCloud