mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-18 12:24:38 +08:00
7893943879
In the spirit of encapsulation, I'm looking to remove the need for external code to access the "ptid -> thread" map of process_info, making it an internal implementation detail. The only remaining use is in function clear_inferiors, and it led me down this rabbit hole: - clear_inferiors is really only used by the Windows port and doesn't really make sense in the grand scheme of things, I think (when would you want to remove all threads of all processes, without removing those processes?) - ok, so let's remove clear_inferiors and inline the code where it's called, in function win32_clear_inferiors - the Windows port does not support multi-process, so it's not really necessary to loop over all processes like this: for_each_process ([] (process_info *process) { process->thread_list ().clear (); process->thread_map ().clear (); }); We could just do: current_process ()->thread_list ().clear (); current_process ()->thread_map ().clear (); (or pass down the process from the caller, but it's not important right now) - so, the code that we've inlined in win32_clear_inferiors does 3 things: - clear the process' thread list and map (which deletes the thread_info objects) - clear the dll list, which just basically frees some objects - switch to no current process / no current thread - let's now look at where this win32_clear_inferiors function is used: - in win32_process_target::kill, where the process is removed just after - in win32_process_target::detach, where the process is removed just after - in win32_process_target::wait, when handling a process exit. After this returns, we could be in handle_target_event (if async) or resume (if sync), both in `server.cc`. In both of these cases, target_mourn_inferior gets called, we end up in win32_process_target::mourn, which removes the process - in all 3 cases above, we end up removing the process, which takes care of the 3 actions listed above: - the thread list and map get cleared when the process gets destroyed - same with the dll list - remove_process switches to no current process / current thread if the process being removed is the current one - I conclude that it's probably unnecessary to do the cleanup in win32_clear_inferiors, because it's going to get done right after anyway. Therefore, this patch does: - remove clear_inferiors, remove the call in win32_clear_inferiors - remove clear_dlls, which is now unused - remove process_info::thread_map, which is now unused - rename win32_clear_inferiors to win32_clear_process, which seems more accurate win32_clear_inferiors also does: for_each_thread (delete_thread_info); which also makes sure to delete all threads, but it also deletes the Windows private data object (windows_thread_info), so I'll leave this one there for now. But if we could make the thread private data destruction automatic, on thread destruction, it could be removed, I think. There should be no user-visible change with this patch. Of course, operations don't happen in the same order as before, so there might be some important detail I'm missing. I'm only able to build-test this, if someone could give it a test run on Windows, it would be appreciated. Change-Id: I4a560affe763a2c965a97754cc02f3083dbe6fbf
92 lines
2.7 KiB
C++
92 lines
2.7 KiB
C++
/* Copyright (C) 2002-2024 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "dll.h"
|
|
|
|
#include <algorithm>
|
|
|
|
/* An "unspecified" CORE_ADDR, for match_dll. */
|
|
#define UNSPECIFIED_CORE_ADDR (~(CORE_ADDR) 0)
|
|
|
|
/* Record a newly loaded DLL at BASE_ADDR for the current process. */
|
|
|
|
void
|
|
loaded_dll (const char *name, CORE_ADDR base_addr)
|
|
{
|
|
loaded_dll (current_process (), name, base_addr);
|
|
}
|
|
|
|
/* Record a newly loaded DLL at BASE_ADDR for PROC. */
|
|
|
|
void
|
|
loaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
|
|
{
|
|
gdb_assert (proc != nullptr);
|
|
proc->all_dlls.emplace_back (name != nullptr ? name : "", base_addr);
|
|
proc->dlls_changed = true;
|
|
}
|
|
|
|
/* Record that the DLL with NAME and BASE_ADDR has been unloaded
|
|
from the current process. */
|
|
|
|
void
|
|
unloaded_dll (const char *name, CORE_ADDR base_addr)
|
|
{
|
|
unloaded_dll (current_process (), name, base_addr);
|
|
}
|
|
|
|
/* Record that the DLL with NAME and BASE_ADDR has been unloaded
|
|
from PROC. */
|
|
|
|
void
|
|
unloaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
|
|
{
|
|
gdb_assert (proc != nullptr);
|
|
auto pred = [&] (const dll_info &dll)
|
|
{
|
|
if (base_addr != UNSPECIFIED_CORE_ADDR
|
|
&& base_addr == dll.base_addr)
|
|
return true;
|
|
|
|
if (name != NULL && dll.name == name)
|
|
return true;
|
|
|
|
return false;
|
|
};
|
|
|
|
auto iter = std::find_if (proc->all_dlls.begin (), proc->all_dlls.end (),
|
|
pred);
|
|
|
|
if (iter == proc->all_dlls.end ())
|
|
/* For some inferiors we might get unloaded_dll events without having
|
|
a corresponding loaded_dll. In that case, the dll cannot be found
|
|
in ALL_DLL, and there is nothing further for us to do.
|
|
|
|
This has been observed when running 32bit executables on Windows64
|
|
(i.e. through WOW64, the interface between the 32bits and 64bits
|
|
worlds). In that case, the inferior always does some strange
|
|
unloading of unnamed dll. */
|
|
return;
|
|
else
|
|
{
|
|
/* DLL has been found so remove the entry and free associated
|
|
resources. */
|
|
proc->all_dlls.erase (iter);
|
|
proc->dlls_changed = true;
|
|
}
|
|
}
|