summaryrefslogtreecommitdiff
path: root/i386
diff options
context:
space:
mode:
Diffstat (limited to 'i386')
-rw-r--r--i386/i386/db_interface.c93
-rw-r--r--i386/i386/db_machdep.h1
2 files changed, 94 insertions, 0 deletions
diff --git a/i386/i386/db_interface.c b/i386/i386/db_interface.c
index be0c893..d149adc 100644
--- a/i386/i386/db_interface.c
+++ b/i386/i386/db_interface.c
@@ -520,6 +520,53 @@ db_search_null(
return FALSE;
}
+#define GNU
+
+#ifdef GNU
+static boolean_t
+looks_like_command(
+ task_t task,
+ char* kaddr)
+{
+ char *c;
+
+ assert(!((vm_offset_t) kaddr & (INTEL_PGBYTES-1)));
+
+ /*
+ * Must be the environment.
+ */
+ if (!memcmp(kaddr, "PATH=", 5) || !memcmp(kaddr, "TERM=", 5) || !memcmp(kaddr, "SHELL=", 6) || !memcmp(kaddr, "LOCAL_PART=", 11) || !memcmp(kaddr, "LC_ALL=", 7))
+ return FALSE;
+
+ /*
+ * This is purely heuristical but works quite nicely.
+ * We know that it should look like words separated by \0, and
+ * eventually only \0s.
+ */
+ c = kaddr;
+ while (c < kaddr + INTEL_PGBYTES) {
+ if (!*c) {
+ if (c == kaddr)
+ /* Starts by \0. */
+ return FALSE;
+ break;
+ }
+ while (c < kaddr + INTEL_PGBYTES && *c)
+ c++;
+ if (c < kaddr + INTEL_PGBYTES)
+ c++; /* Skip \0 */
+ }
+ /*
+ * Check that the remainder is just \0s.
+ */
+ while (c < kaddr + INTEL_PGBYTES)
+ if (*c++)
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
void
db_task_name(
task_t task)
@@ -527,7 +574,46 @@ db_task_name(
register char *p;
register int n;
unsigned vaddr, kaddr;
+ unsigned sp;
+ if (task->map->pmap == kernel_pmap) {
+ db_printf(DB_GNUMACH_TASK_NAME);
+ return;
+ }
+
+#ifdef GNU
+ /*
+ * GNU Hurd-specific heuristics.
+ */
+
+ /* Heuristical address first. */
+ vaddr = 0x1026000;
+ if (db_user_to_kernel_address(task, vaddr, &kaddr, 0) >= 0 &&
+ looks_like_command(task, (char*) kaddr))
+ goto ok;
+
+ /* Try to catch SP of the main thread. */
+ thread_t thread;
+
+ task_lock(task);
+ thread = (thread_t) queue_first(&task->thread_list);
+ if (!thread) {
+ task_unlock(task);
+ db_printf(DB_NULL_TASK_NAME);
+ return;
+ }
+ sp = thread->pcb->iss.uesp;
+ task_unlock(task);
+
+ vaddr = (sp & ~(INTEL_PGBYTES - 1)) + INTEL_PGBYTES;
+ while (1) {
+ if (db_user_to_kernel_address(task, vaddr, &kaddr, 0) < 0)
+ return FALSE;
+ if (looks_like_command(task, (char*) kaddr))
+ break;
+ vaddr += INTEL_PGBYTES;
+ }
+#else
vaddr = DB_USER_STACK_ADDR;
kaddr = 0;
@@ -545,11 +631,18 @@ db_task_name(
db_printf(DB_NULL_TASK_NAME);
return;
}
+#endif
+ok:
n = DB_TASK_NAME_LEN-1;
+#ifdef GNU
+ p = (char *)kaddr;
+ for (; n > 0; vaddr++, p++, n--) {
+#else
p = (char *)kaddr + sizeof(unsigned);
for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0;
vaddr++, p++, n--) {
+#endif
if (vaddr % INTEL_PGBYTES == 0) {
(void)db_user_to_kernel_address(task, vaddr, &kaddr, 0);
p = (char*)kaddr;
diff --git a/i386/i386/db_machdep.h b/i386/i386/db_machdep.h
index cba259c..95e3797 100644
--- a/i386/i386/db_machdep.h
+++ b/i386/i386/db_machdep.h
@@ -94,6 +94,7 @@ db_regs_t ddb_regs; /* register state */
#define DB_TASK_NAME_TITLE "COMMAND "
#define DB_TASK_NAME_LEN 23
#define DB_NULL_TASK_NAME "? "
+#define DB_GNUMACH_TASK_NAME "gnumach "
/* macro for checking if a thread has used floating-point */