forked from Imagelibrary/binutils-gdb
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;
|
|
}
|
|
}
|