From 1ef980b961f19eb7bf5b18b0417a000d29e4d15e Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Mon, 11 Mar 1996 19:08:57 +0000 Subject: [PATCH] Mon Mar 11 11:02:47 1996 Steve Chamberlain With Michael Snyder: * i386-tdep.c (skip_trampoline_code): Fix strncmp length. * win32-nat.c (CHECK, DEBUG*, debug_*): New. (handle_load_dll): Don't reload symbols. (handle_exception): Use the DEBUG_* names. (child_wait): Add DEBUG_* code. (_initialize_inftarg): Add new commands to set debug_ names. --- gdb/ChangeLog | 12 +- gdb/win32-nat.c | 421 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 383 insertions(+), 50 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c714985624e..575247b3fbc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +Mon Mar 11 11:02:47 1996 Steve Chamberlain + + With Michael Snyder: + * i386-tdep.c (skip_trampoline_code): Fix strncmp length. + * win32-nat.c (CHECK, DEBUG*, debug_*): New. + (handle_load_dll): Don't reload symbols. + (handle_exception): Use the DEBUG_* names. + (child_wait): Add DEBUG_* code. + (_initialize_inftarg): Add new commands to set debug_ names. + Mon Mar 11 09:19:58 1996 Jeffrey A Law (law@cygnus.com) * From Peter Schauer: @@ -856,7 +866,7 @@ Fri Jan 12 21:41:58 1996 Jeffrey A Law (law@cygnus.com) Fri Jan 12 15:56:12 1996 Steve Chamberlain * dsrec.c (load_srec): Remove unused variable. - monitor.c (monitor_expect): Don't expect a ^C to echo. + * monitor.c (monitor_expect): Don't expect a ^C to echo. * serial.c (serial_open): Add parallel interface. * sh3-rom.c (parallel, parallel_in_use): New. (sh3_load): If parallel_in_use, download though the diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c index bd624437e5a..2b50f6d661f 100644 --- a/gdb/win32-nat.c +++ b/gdb/win32-nat.c @@ -33,13 +33,18 @@ #include #include #include "buildsym.h" +#include "symfile.h" +#include "objfiles.h" #include "gdb_string.h" #include "thread.h" #include "gdbcmd.h" #include -#define CHECK(x) check (x, __FILE__,__LINE__) -#define DEBUG(x) if (remote_debug) printf x +#define CHECK(x) check (x, __FILE__,__LINE__) +#define DEBUG_EXEC(x) if (debug_exec) printf x +#define DEBUG_EVENTS(x) if (debug_events) printf x +#define DEBUG_MEM(x) if (debug_memory) printf x +#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x /* Forward declaration */ extern struct target_ops child_ops; @@ -63,6 +68,11 @@ static int event_count = 0; /* User options. */ static int new_console = 0; static int new_group = 0; +static int dos_path_style = 0; +static int debug_exec = 0; /* show execution */ +static int debug_events = 0; /* show events from kernel */ +static int debug_memory = 0; /* show target memory accesses */ +static int debug_exceptions = 0; /* show target exceptions */ /* This vector maps GDB's idea of a register's number into an address in the win32 exception context vector. @@ -275,7 +285,9 @@ handle_load_dll (char *eventp) if (done == sizeof (dll_name_ptr) && dll_name_ptr) { - char *dll_name; + char *dll_name, *dll_basename; + struct objfile *objfile; + char unix_dll_name[MAX_PATH]; int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char); int len = 0; char b[2]; @@ -290,7 +302,6 @@ handle_load_dll (char *eventp) } while ((b[0] != 0 || b[size - 1] != 0) && done == size); - dll_name = alloca (len); if (event->u.LoadDll.fUnicode) @@ -315,10 +326,32 @@ handle_load_dll (char *eventp) &done); } + + dos_path_to_unix_path (dll_name, unix_dll_name); + /* FIXME!! It would be nice to define one symbol which pointed to the front of the dll if we can't find any symbols. */ - context.ContextFlags = CONTEXT_FULL; + if (!(dll_basename = strrchr(dll_name, '\\'))) + dll_basename = strrchr(dll_name, '/'); + + ALL_OBJFILES(objfile) + { + char *objfile_basename; + if (!(objfile_basename = strrchr(objfile->name, '\\'))) + objfile_basename = strrchr(objfile->name, '/'); + + if (dll_basename && objfile_basename && + strcmp(dll_basename+1, objfile_basename+1) == 0) + { + printf_unfiltered ("%s (symbols previously loaded)\n", + dll_basename + 1); + return 1; + } + } + + + context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT; GetThreadContext (current_thread, &context); /* The symbols in a dll are offset by 0x1000, which is the @@ -328,14 +361,11 @@ handle_load_dll (char *eventp) FIXME: Is this the real reason that we need the 0x1000 ? */ - symbol_file_add (dll_name, 0, + symbol_file_add (unix_dll_name, 0, (int) event->u.LoadDll.lpBaseOfDll + 0x1000, 0, 0, 0); - /* We strip off the path of the dll for tidiness. */ - if (strrchr (dll_name, '\\')) - dll_name = strrchr (dll_name, '\\') + 1; - - printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll, dll_name); + printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll, + unix_dll_name); } return 1; } @@ -348,23 +378,42 @@ handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus) int done = 0; ourstatus->kind = TARGET_WAITKIND_STOPPED; - for (i = 0; !done && xlate[i].us > 0; i++) - { - if (xlate[i].them == event->u.Exception.ExceptionRecord.ExceptionCode) - { - ourstatus->value.sig = xlate[i].us; - done = 1; - break; - } - } - if (!done) + switch (event->u.Exception.ExceptionRecord.ExceptionCode) { - printf_unfiltered ("Want to know about exception code %08x\n", - event->u.Exception.ExceptionRecord.ExceptionCode); + case EXCEPTION_ACCESS_VIOLATION: + DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = TARGET_SIGNAL_SEGV; + break; + case STATUS_STACK_OVERFLOW: + DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = TARGET_SIGNAL_SEGV; + break; + case EXCEPTION_BREAKPOINT: + DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = TARGET_SIGNAL_TRAP; + break; + case DBG_CONTROL_C: + DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = TARGET_SIGNAL_INT; + break; + case EXCEPTION_SINGLE_STEP: + DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionAddress)); + ourstatus->value.sig = TARGET_SIGNAL_TRAP; + break; + default: + printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n", + event->u.Exception.ExceptionRecord.ExceptionCode, + event->u.Exception.ExceptionRecord.ExceptionAddress); ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; + break; } - context.ContextFlags = CONTEXT_FULL; + context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT; GetThreadContext (current_thread, &context); exception_count++; } @@ -382,12 +431,7 @@ child_wait (int pid, struct target_waitstatus *ourstatus) { DEBUG_EVENT event; BOOL t = WaitForDebugEvent (&event, INFINITE); - - DEBUG (("%d = WaitForDebugEvent() code=%d pid=%d tid=%d)\n", - t, - event.dwDebugEventCode, - event.dwProcessId, - event.dwThreadId)); + char *p; event_count++; @@ -397,11 +441,25 @@ child_wait (int pid, struct target_waitstatus *ourstatus) switch (event.dwDebugEventCode) { case CREATE_THREAD_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "CREATE_THREAD_DEBUG_EVENT")); + break; case EXIT_THREAD_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "EXIT_THREAD_DEBUG_EVENT")); + break; case CREATE_PROCESS_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "CREATE_PROCESS_DEBUG_EVENT")); break; case EXIT_PROCESS_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "EXIT_PROCESS_DEBUG_EVENT")); ourstatus->kind = TARGET_WAITKIND_EXITED; ourstatus->value.integer = event.u.ExitProcess.dwExitCode; CloseHandle (current_process); @@ -410,22 +468,48 @@ child_wait (int pid, struct target_waitstatus *ourstatus) break; case LOAD_DLL_DEBUG_EVENT: - catch_errors (handle_load_dll, - (char*) &event, - "\n[failed reading symbols from DLL]\n", - RETURN_MASK_ALL); - registers_changed(); /* mark all regs invalid */ + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "LOAD_DLL_DEBUG_EVENT")); + catch_errors (handle_load_dll, + (char*) &event, + "\n[failed reading symbols from DLL]\n", + RETURN_MASK_ALL); + registers_changed(); /* mark all regs invalid */ break; - case EXCEPTION_DEBUG_EVENT: + case UNLOAD_DLL_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "UNLOAD_DLL_DEBUG_EVENT")); + break; /* FIXME: don't know what to do here */ + case EXCEPTION_DEBUG_EVENT: + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "EXCEPTION_DEBUG_EVENT")); handle_exception (&event, ourstatus); return current_process_id; + + case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */ + DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n", + event.dwProcessId, event.dwThreadId, + "OUTPUT_DEBUG_STRING_EVENT")); + if (target_read_string + ((CORE_ADDR) event.u.DebugString.lpDebugStringData, + &p, 1024, 0) && p && *p) + { + warning(p); + free(p); + } + break; default: - printf_unfiltered ("waitfor it %d %d %d %d\n", t, - event.dwDebugEventCode, - event.dwProcessId, - event.dwThreadId); + printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n", + event.dwProcessId, event.dwThreadId); + printf_unfiltered (" unknown event code %d\n", + event.dwDebugEventCode); break; } + DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n", + current_process_id, current_thread_id)); CHECK (ContinueDebugEvent (current_process_id, current_thread_id, DBG_CONTINUE)); @@ -433,8 +517,6 @@ child_wait (int pid, struct target_waitstatus *ourstatus) } - - /* Attach to process PID, then initialize for debugging it. */ static void @@ -516,12 +598,142 @@ child_open (arg, from_tty) } +/* Convert a unix-style set-of-paths (a colon-separated list of directory + paths with forward slashes) into the dos style (semicolon-separated + list with backward slashes), simultaneously undoing any translations + performed by the mount table. */ + +static char *buf = NULL; +static int blen = 2000; + +static char * +unix_paths_to_dos_paths(char *newenv) +{ + int ei; + char *src; + + if (buf == 0) + buf = (char *) malloc(blen); + + if (newenv == 0 || *newenv == 0 || + (src = strchr(newenv, '=')) == 0) /* find the equals sign */ + return 0; + + src++; /* now skip past it */ + + if (src[0] == '/' || /* is this a unix style path? */ + (src[0] == '.' && src[1] == '/') || + (src[0] == '.' && src[1] == '.' && src[2] == '/')) + { /* we accept that we will fail on a relative path like 'foo/mumble' */ + /* Found an env name, turn from unix style into dos style */ + int len = src - newenv; + char *dir = buf + len; + + memcpy(buf, newenv, len); + /* Split out the colons */ + while (1) + { + char *tok = strchr (src, ':'); + int doff = dir - buf; + + if (doff + MAX_PATH > blen) + { + blen *= 2; + buf = (char *) realloc((void *) buf, blen); + dir = buf + doff; + } + if (tok) + { + *tok = 0; + cygwin32_unix_path_to_dos_path_keep_rel (src, dir); + *tok = ':'; + dir += strlen(dir); + src = tok + 1; + *dir++ = ';'; + } + else + { + cygwin32_unix_path_to_dos_path_keep_rel (src, dir); + dir += strlen(dir); + *dir++ = 0; + break; + } + } + return buf; + } + return 0; +} + +/* Convert a dos-style set-of-paths (a semicolon-separated list with + backward slashes) into the dos style (colon-separated list of + directory paths with forward slashes), simultaneously undoing any + translations performed by the mount table. */ + +static char * +dos_paths_to_unix_paths(char *newenv) +{ + int ei; + char *src; + + if (buf == 0) + buf = (char *) malloc(blen); + + if (newenv == 0 || *newenv == 0 || + (src = strchr(newenv, '=')) == 0) /* find the equals sign */ + return 0; + + src++; /* now skip past it */ + + if (src[0] == '\\' || /* is this a dos style path? */ + (isalpha(src[0]) && src[1] == ':' && src[2] == '\\') || + (src[0] == '.' && src[1] == '\\') || + (src[0] == '.' && src[1] == '.' && src[2] == '\\')) + { /* we accept that we will fail on a relative path like 'foo\mumble' */ + /* Found an env name, turn from dos style into unix style */ + int len = src - newenv; + char *dir = buf + len; + + memcpy(buf, newenv, len); + /* Split out the colons */ + while (1) + { + char *tok = strchr (src, ';'); + int doff = dir - buf; + + if (doff + MAX_PATH > blen) + { + blen *= 2; + buf = (char *) realloc((void *) buf, blen); + dir = buf + doff; + } + if (tok) + { + *tok = 0; + cygwin32_dos_path_to_unix_path_keep_rel (src, dir); + *tok = ';'; + dir += strlen(dir); + src = tok + 1; + *dir++ = ':'; + } + else + { + cygwin32_dos_path_to_unix_path_keep_rel (src, dir); + dir += strlen(dir); + *dir++ = 0; + break; + } + } + return buf; + } + return 0; +} + + /* Start an inferior win32 child process and sets inferior_pid to its pid. EXEC_FILE is the file to run. ALLARGS is a string containing the arguments to the program. ENV is the environment vector to pass. Errors reported with error(). */ - static void child_create_inferior (exec_file, allargs, env) char *exec_file; @@ -551,7 +763,7 @@ child_create_inferior (exec_file, allargs, env) unix_path_to_dos_path (exec_file, real_path); - flags = DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS; + flags = DEBUG_ONLY_THIS_PROCESS; if (new_group) flags |= CREATE_NEW_PROCESS_GROUP; @@ -566,19 +778,45 @@ child_create_inferior (exec_file, allargs, env) strcat (args, " "); strcat (args, allargs); - +#if 0 /* get total size for env strings */ for (envlen = 0, i = 0; env[i] && *env[i]; i++) envlen += strlen(env[i]) + 1; +#else + /* get total size for env strings */ + for (envlen = 0, i = 0; env[i] && *env[i]; i++) + { +#if 0 + winenv = 0; +#else + winenv = unix_paths_to_dos_paths(env[i]); +#endif + envlen += winenv ? strlen(winenv) + 1 : strlen(env[i]) + 1; + } +#endif - winenv = alloca(envlen + 1); /* allocate new buffer */ + winenv = alloca(2 * envlen + 1); /* allocate new buffer */ + /* copy env strings into new buffer */ + for (temp = winenv, i = 0; env[i] && *env[i]; i++) + { +#if 0 + char *p = 0; +#else + char *p = unix_paths_to_dos_paths(env[i]); +#endif + strcpy(temp, p ? p : env[i]); + temp += strlen(temp) + 1; + } +#if 0 /* copy env strings into new buffer */ for (temp = winenv, i = 0; env[i] && *env[i]; i++) { strcpy(temp, env[i]); temp += strlen(temp) + 1; } +#endif + *temp = 0; /* final nil string to terminate new env */ ret = CreateProcess (0, @@ -629,7 +867,9 @@ child_mourn_inferior () void child_stop () { + DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n")); CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0)); + registers_changed(); /* refresh register state */ } int @@ -639,11 +879,15 @@ child_xfer_memory (CORE_ADDR memaddr, char *our, int len, DWORD done; if (write) { + DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n", + len, memaddr)); WriteProcessMemory (current_process, memaddr, our, len, &done); FlushInstructionCache (current_process, memaddr, len); } else { + DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n", + len, memaddr)); ReadProcessMemory (current_process, memaddr, our, len, &done); } return done; @@ -655,19 +899,21 @@ child_kill_inferior (void) CHECK (TerminateProcess (current_process, 0)); CHECK (CloseHandle (current_process)); CHECK (CloseHandle (current_thread)); + target_mourn_inferior(); /* or just child_mourn_inferior? */ } void child_resume (int pid, int step, enum target_signal signal) { - DEBUG (("child_resume (%d, %d, %d);\n", pid, step, signal)); + DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, signal=%d);\n", + pid, step, signal)); if (step) { #ifdef __PPC__ warning ("Single stepping not done.\n"); #endif -#ifdef __I386__ +#ifdef i386 /* Single step by setting t bit */ child_fetch_inferior_registers (PS_REGNUM); context.EFlags |= FLAG_TRACE_BIT; @@ -685,6 +931,8 @@ child_resume (int pid, int step, enum target_signal signal) fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n"); } + DEBUG_EVENTS (("gdb: ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n", + current_process_id, current_thread_id)); CHECK (ContinueDebugEvent (current_process_id, current_thread_id, DBG_CONTINUE)); @@ -705,8 +953,9 @@ child_can_run () static void child_close () { - + DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid)); } + struct target_ops child_ops = { "child", /* to_shortname */ @@ -751,9 +1000,46 @@ struct target_ops child_ops = OPS_MAGIC /* to_magic */ }; +#include "environ.h" + +static void +set_pathstyle_dos(args, from_tty, c) + char *args; + int from_tty; + struct cmd_list_element *c; +{ + char **vector = environ_vector(inferior_environ); + char *thisvar; + int dos = *(int *) c->var; + + if (info_verbose) + printf_unfiltered ("Change dos_path_style to %s\n", dos ? "true":"false"); + + while (vector && *vector) + { + if (dos) + thisvar = unix_paths_to_dos_paths(*vector); + else + thisvar = dos_paths_to_unix_paths(*vector); + + if (thisvar) + { + if (info_verbose) + printf_unfiltered ("Change %s\nto %s\n", *vector, thisvar); + free(*vector); + *vector = xmalloc(strlen(thisvar) + 1); + strcpy(*vector, thisvar); + } + vector++; + } +} + + void _initialize_inftarg () { + struct cmd_list_element *c; + add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean, (char *) &new_console, @@ -768,5 +1054,42 @@ _initialize_inftarg () &setlist), &showlist); + add_show_from_set + (c = add_set_cmd ("dos-path-style", class_support, var_boolean, + (char *) &dos_path_style, + "Set whether paths in child's environment are shown in dos style.", + &setlist), + &showlist); + + c->function.sfunc = set_pathstyle_dos; + + add_show_from_set + (add_set_cmd ("debugexec", class_support, var_boolean, + (char *) &debug_exec, + "Set whether to display execution in child process.", + &setlist), + &showlist); + + add_show_from_set + (add_set_cmd ("debugevents", class_support, var_boolean, + (char *) &debug_events, + "Set whether to display kernel events in child process.", + &setlist), + &showlist); + + add_show_from_set + (add_set_cmd ("debugmemory", class_support, var_boolean, + (char *) &debug_memory, + "Set whether to display memory accesses in child process.", + &setlist), + &showlist); + + add_show_from_set + (add_set_cmd ("debugexceptions", class_support, var_boolean, + (char *) &debug_exceptions, + "Set whether to display kernel exceptions in child process.", + &setlist), + &showlist); + add_target (&child_ops); } -- 2.30.2