diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/gdbserver/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/gdbserver/win32-low.c | 90 |
2 files changed, 61 insertions, 46 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 21c73b2..1111aae 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,20 @@ +2014-02-26 Joel Brobecker <brobecker@adacore.com> + + * win32-low.c (win32_add_all_dlls): Renames + win32_ensure_ntdll_loaded. Rewrite function documentation. + Adjust implementation to always load all DLLs. + Add 0x1000 offset to DLL base address when calling + win32_add_one_solib. + (child_initialization_done): New static global. + (do_initial_child_stuff): Set child_initialization_done to + zero during child initialization, and 1 after. Replace call + to win32_ensure_ntdll_loaded by call to win32_add_all_dlls. + Add comment. + (match_dll_by_basename, dll_is_loaded_by_basename): Delete. + (handle_unload_dll): Add function documentation. + (get_child_debug_event): Ignore load and unload DLL events + during child initialization. + 2014-02-20 Doug Evans <dje@google.com> Remove global all_lwps. diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index e84306d..74ac83f 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -106,7 +106,7 @@ static ptid_t win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options); static void win32_resume (struct thread_resume *resume_info, size_t n); #ifndef _WIN32_WCE -static void win32_ensure_ntdll_loaded (void); +static void win32_add_all_dlls (void); #endif /* Get the thread ID from the current selected inferior (the current @@ -324,6 +324,10 @@ child_init_thread_list (void) for_each_inferior (&all_threads, delete_thread_info); } +/* Zero during the child initialization phase, and nonzero otherwise. */ + +static int child_initialization_done = 0; + static void do_initial_child_stuff (HANDLE proch, DWORD pid, int attached) { @@ -343,6 +347,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached) proc = add_process (pid, attached); proc->tdesc = win32_tdesc; child_init_thread_list (); + child_initialization_done = 0; if (the_low_target.initial_stuff != NULL) (*the_low_target.initial_stuff) (); @@ -376,8 +381,25 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached) } #ifndef _WIN32_WCE - win32_ensure_ntdll_loaded (); + /* Now that the inferior has been started and all DLLs have been mapped, + we can iterate over all DLLs and load them in. + + We avoid doing it any earlier because, on certain versions of Windows, + LOAD_DLL_DEBUG_EVENTs are sometimes not complete. In particular, + we have seen on Windows 8.1 that the ntdll.dll load event does not + include the DLL name, preventing us from creating an associated SO. + A possible explanation is that ntdll.dll might be mapped before + the SO info gets created by the Windows system -- ntdll.dll is + the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs + do not seem to suffer from that problem. + + Rather than try to work around this sort of issue, it is much + simpler to just ignore DLL load/unload events during the startup + phase, and then process them all in one batch now. */ + win32_add_all_dlls (); #endif + + child_initialization_done = 1; } /* Resume all artificially suspended threads if we are continuing @@ -1143,42 +1165,11 @@ failed: #ifndef _WIN32_WCE -/* Helper routine for dll_is_loaded_by_basename. - Return non-zero if the basename in ARG matches the DLL in INF. */ - -static int -match_dll_by_basename (struct inferior_list_entry *inf, void *arg) -{ - struct dll_info *iter = (void *) inf; - const char *basename = arg; - - return strcasecmp (lbasename (iter->name), basename) == 0; -} - -/* Return non-zero if the DLL specified by BASENAME is loaded. */ - -static int -dll_is_loaded_by_basename (const char *basename) -{ - return find_inferior (&all_dlls, match_dll_by_basename, - (void *) basename) != NULL; -} - -/* On certain versions of Windows, the information about ntdll.dll - is not available yet at the time we get the LOAD_DLL_DEBUG_EVENT, - thus preventing us from reporting this DLL as an SO. This has been - witnessed on Windows 8.1, for instance. A possible explanation - is that ntdll.dll might be mapped before the SO info gets created - by the Windows system -- ntdll.dll is the first DLL to be reported - via LOAD_DLL_DEBUG_EVENT and other DLLs do not seem to suffer from - that problem. - - If we indeed are missing ntdll.dll, this function tries to recover - from this issue, after the fact. Do nothing if we encounter any - issue trying to locate that DLL. */ +/* Iterate over all DLLs currently mapped by our inferior, and + add them to our list of solibs. */ static void -win32_ensure_ntdll_loaded (void) +win32_add_all_dlls (void) { size_t i; HMODULE dh_buf[1]; @@ -1186,9 +1177,6 @@ win32_ensure_ntdll_loaded (void) DWORD cbNeeded; BOOL ok; - if (dll_is_loaded_by_basename ("ntdll.dll")) - return; - if (!load_psapi ()) return; @@ -1212,7 +1200,7 @@ win32_ensure_ntdll_loaded (void) if (!ok) return; - for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++) + for (i = 1; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++) { MODULEINFO mi; char dll_name[MAX_PATH]; @@ -1227,12 +1215,11 @@ win32_ensure_ntdll_loaded (void) dll_name, MAX_PATH) == 0) continue; - if (strcasecmp (lbasename (dll_name), "ntdll.dll") == 0) - { - win32_add_one_solib (dll_name, - (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll); - return; - } + /* The symbols in a dll are offset by 0x1000, which is the + offset from 0 of the first byte in an image - because + of the file header and the section alignment. */ + win32_add_one_solib (dll_name, + (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll + 0x1000); } } #endif @@ -1361,6 +1348,13 @@ handle_load_dll (void) win32_add_one_solib (dll_name, load_addr); } +/* Handle a DLL unload event. + + This function assumes that this event did not occur during inferior + initialization, where their event info may be incomplete (see + do_initial_child_stuff and win32_add_one_solib for more info + on how we handle DLL loading during that phase). */ + static void handle_unload_dll (void) { @@ -1675,6 +1669,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus) (unsigned) current_event.dwProcessId, (unsigned) current_event.dwThreadId)); CloseHandle (current_event.u.LoadDll.hFile); + if (! child_initialization_done) + break; handle_load_dll (); ourstatus->kind = TARGET_WAITKIND_LOADED; @@ -1686,6 +1682,8 @@ get_child_debug_event (struct target_waitstatus *ourstatus) "for pid=%u tid=%x\n", (unsigned) current_event.dwProcessId, (unsigned) current_event.dwThreadId)); + if (! child_initialization_done) + break; handle_unload_dll (); ourstatus->kind = TARGET_WAITKIND_LOADED; ourstatus->value.sig = GDB_SIGNAL_TRAP; |