diff options
Diffstat (limited to 'i386')
-rw-r--r-- | i386/i386/db_interface.c | 93 | ||||
-rw-r--r-- | i386/i386/db_machdep.h | 1 |
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 */ |