aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorHannes Domani <ssbssa@yahoo.de>2024-12-06 14:04:00 +0100
committerHannes Domani <ssbssa@yahoo.de>2024-12-06 14:04:04 +0100
commitb2682eade4db993bc8231007ba94aec4e4728c61 (patch)
treefab3f6098344cbdea331fabf92734d1ed66e9445 /gdb
parenta3011beced048e66d200921b2a11c836fae31abf (diff)
downloadbinutils-b2682eade4db993bc8231007ba94aec4e4728c61.zip
binutils-b2682eade4db993bc8231007ba94aec4e4728c61.tar.gz
binutils-b2682eade4db993bc8231007ba94aec4e4728c61.tar.bz2
Reduce WOW64 code duplication
Currently we have duplicate code for each place where windows_thread_info::context is touched, since for WOW64 processes it has to do the equivalent with wow64_context instead. For example this code...: #ifdef __x86_64__ if (windows_process.wow64_process) { th->wow64_context.ContextFlags = WOW64_CONTEXT_ALL; CHECK (Wow64GetThreadContext (th->h, &th->wow64_context)); ... } else #endif { th->context.ContextFlags = CONTEXT_DEBUGGER_DR; CHECK (GetThreadContext (th->h, &th->context)); ... } ...changes to look like this instead: windows_process.with_context (th, [&] (auto *context) { context->ContextFlags = WindowsContext<decltype(context)>::all; CHECK (get_thread_context (th->h, context)); ... } The actual choice if context or wow64_context are used, is handled by this new function in windows_process_info: template<typename Function> auto with_context (windows_thread_info *th, Function function) { #ifdef __x86_64__ if (wow64_process) return function (th != nullptr ? th->wow64_context : nullptr); else #endif return function (th != nullptr ? th->context : nullptr); } The other parts to make this work are the templated WindowsContext class which give the appropriate ContextFlags for both types. And there are also overloaded helper functions, like in the case of get_thread_context here, call either GetThreadContext or Wow64GetThreadContext. According git log --stat, this results in 120 lines less code. Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/nat/windows-nat.c63
-rw-r--r--gdb/nat/windows-nat.h117
-rw-r--r--gdb/windows-nat.c232
3 files changed, 190 insertions, 222 deletions
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index f9f6848..6f1ce81 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -172,23 +172,13 @@ windows_process_info::get_exec_module_filename (char *exe_name_ret,
DWORD cbNeeded;
cbNeeded = 0;
-#ifdef __x86_64__
- if (wow64_process)
- {
- if (!EnumProcessModulesEx (handle,
- &dh_buf, sizeof (HMODULE), &cbNeeded,
- LIST_MODULES_32BIT)
- || !cbNeeded)
- return 0;
- }
- else
-#endif
+ BOOL ret = with_context (nullptr, [&] (auto *context)
{
- if (!EnumProcessModules (handle,
- &dh_buf, sizeof (HMODULE), &cbNeeded)
- || !cbNeeded)
- return 0;
- }
+ return enum_process_modules (context, handle, &dh_buf,
+ sizeof (HMODULE), &cbNeeded);
+ });
+ if (!ret || !cbNeeded)
+ return 0;
/* We know the executable is always first in the list of modules,
which we just fetched. So no need to fetch more. */
@@ -523,41 +513,22 @@ windows_process_info::add_dll (LPVOID load_addr)
HMODULE *hmodules;
int i;
-#ifdef __x86_64__
- if (wow64_process)
+ BOOL ret = with_context (nullptr, [&] (auto *context)
{
- if (EnumProcessModulesEx (handle, &dummy_hmodule,
- sizeof (HMODULE), &cb_needed,
- LIST_MODULES_32BIT) == 0)
- return;
- }
- else
-#endif
- {
- if (EnumProcessModules (handle, &dummy_hmodule,
- sizeof (HMODULE), &cb_needed) == 0)
- return;
- }
-
- if (cb_needed < 1)
+ return enum_process_modules (context, handle, &dummy_hmodule,
+ sizeof (HMODULE), &cb_needed);
+ });
+ if (!ret || cb_needed < 1)
return;
hmodules = (HMODULE *) alloca (cb_needed);
-#ifdef __x86_64__
- if (wow64_process)
+ ret = with_context (nullptr, [&] (auto *context)
{
- if (EnumProcessModulesEx (handle, hmodules,
- cb_needed, &cb_needed,
- LIST_MODULES_32BIT) == 0)
- return;
- }
- else
-#endif
- {
- if (EnumProcessModules (handle, hmodules,
- cb_needed, &cb_needed) == 0)
- return;
- }
+ return enum_process_modules (context, handle, hmodules,
+ cb_needed, &cb_needed);
+ });
+ if (!ret)
+ return;
char system_dir[MAX_PATH];
char syswow_dir[MAX_PATH];
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index f2b5d77..dc637d4 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -29,6 +29,12 @@
#define STATUS_WX86_BREAKPOINT 0x4000001F
#define STATUS_WX86_SINGLE_STEP 0x4000001E
+#ifndef CONTEXT_EXTENDED_REGISTERS
+/* This macro is only defined on ia32. It only makes sense on this target,
+ so define it as zero if not already defined. */
+#define CONTEXT_EXTENDED_REGISTERS 0
+#endif
+
namespace windows_nat
{
@@ -250,6 +256,25 @@ struct windows_process_info
const char *pid_to_exec_file (int);
+ template<typename Function>
+ auto with_context (windows_thread_info *th, Function function)
+ {
+#ifdef __x86_64__
+ if (wow64_process)
+ return function (th != nullptr ? &th->wow64_context : nullptr);
+ else
+#endif
+ return function (th != nullptr ? &th->context : nullptr);
+ }
+
+ DWORD *context_flags_ptr (windows_thread_info *th)
+ {
+ return with_context (th, [] (auto *context)
+ {
+ return &context->ContextFlags;
+ });
+ }
+
private:
/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
@@ -433,6 +458,98 @@ extern DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList;
extern bool disable_randomization_available ();
+/* Helper classes to get the correct ContextFlags values based on the
+ used type (CONTEXT or WOW64_CONTEXT). */
+
+template<typename Context>
+struct WindowsContext;
+
+template<>
+struct WindowsContext<CONTEXT *>
+{
+ static constexpr DWORD control = CONTEXT_CONTROL;
+ static constexpr DWORD floating = CONTEXT_FLOATING_POINT;
+ static constexpr DWORD debug = CONTEXT_DEBUG_REGISTERS;
+ static constexpr DWORD extended = CONTEXT_EXTENDED_REGISTERS;
+ static constexpr DWORD full = CONTEXT_FULL;
+ static constexpr DWORD all = (CONTEXT_FULL
+ | CONTEXT_FLOATING_POINT
+ | CONTEXT_SEGMENTS
+ | CONTEXT_DEBUG_REGISTERS
+ | CONTEXT_EXTENDED_REGISTERS);
+};
+
+#ifdef __x86_64__
+template<>
+struct WindowsContext<WOW64_CONTEXT *>
+{
+ static constexpr DWORD control = WOW64_CONTEXT_CONTROL;
+ static constexpr DWORD floating = WOW64_CONTEXT_FLOATING_POINT;
+ static constexpr DWORD debug = WOW64_CONTEXT_DEBUG_REGISTERS;
+ static constexpr DWORD extended = WOW64_CONTEXT_EXTENDED_REGISTERS;
+ static constexpr DWORD full = WOW64_CONTEXT_FULL;
+ static constexpr DWORD all = WOW64_CONTEXT_ALL;
+};
+#endif
+
+/* Overloaded helper functions to call the correct function based on the used
+ type (CONTEXT or WOW64_CONTEXT). */
+
+static inline BOOL
+get_thread_context (HANDLE h, CONTEXT *context)
+{
+ return GetThreadContext (h, context);
+}
+
+static inline BOOL
+set_thread_context (HANDLE h, CONTEXT *context)
+{
+ return SetThreadContext (h, context);
+}
+
+static inline BOOL
+get_thread_selector_entry (CONTEXT *, HANDLE thread, DWORD sel,
+ LDT_ENTRY *info)
+{
+ return GetThreadSelectorEntry (thread, sel, info);
+}
+
+static inline BOOL
+enum_process_modules (CONTEXT *, HANDLE process,
+ HMODULE *modules, DWORD size, LPDWORD needed)
+{
+ return EnumProcessModules (process, modules, size, needed);
+}
+
+#ifdef __x86_64__
+static inline BOOL
+get_thread_context (HANDLE h, WOW64_CONTEXT *context)
+{
+ return Wow64GetThreadContext (h, context);
+}
+
+static inline BOOL
+set_thread_context (HANDLE h, WOW64_CONTEXT *context)
+{
+ return Wow64SetThreadContext (h, context);
+}
+
+static inline BOOL
+get_thread_selector_entry (WOW64_CONTEXT *, HANDLE thread, DWORD sel,
+ LDT_ENTRY *info)
+{
+ return Wow64GetThreadSelectorEntry (thread, sel, info);
+}
+
+static inline BOOL
+enum_process_modules (WOW64_CONTEXT *, HANDLE process,
+ HMODULE *modules, DWORD size, LPDWORD needed)
+{
+ return EnumProcessModulesEx (process, modules, size, needed,
+ LIST_MODULES_32BIT);
+}
+#endif
+
/* Load any functions which may not be available in ancient versions
of Windows. */
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index abacafe..f2d0633 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -166,16 +166,6 @@ enum
};
#endif
-#ifndef CONTEXT_EXTENDED_REGISTERS
-/* This macro is only defined on ia32. It only makes sense on this target,
- so define it as zero if not already defined. */
-#define CONTEXT_EXTENDED_REGISTERS 0
-#endif
-
-#define CONTEXT_DEBUGGER_DR CONTEXT_FULL | CONTEXT_FLOATING_POINT \
- | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS \
- | CONTEXT_EXTENDED_REGISTERS
-
#define DR6_CLEAR_VALUE 0xffff0ff0
/* The string sent by cygwin when it processes a signal.
@@ -657,11 +647,10 @@ windows_fetch_one_register (struct regcache *regcache,
gdb_assert (r >= 0);
gdb_assert (!th->reload_context);
- char *context_ptr = (char *) &th->context;
-#ifdef __x86_64__
- if (windows_process.wow64_process)
- context_ptr = (char *) &th->wow64_context;
-#endif
+ char *context_ptr = windows_process.with_context (th, [] (auto *context)
+ {
+ return (char *) context;
+ });
char *context_offset = context_ptr + windows_process.mappings[r];
struct gdbarch *gdbarch = regcache->arch ();
@@ -727,42 +716,24 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r)
if (th->reload_context)
{
-#ifdef __x86_64__
- if (windows_process.wow64_process)
+ windows_process.with_context (th, [&] (auto *context)
{
- th->wow64_context.ContextFlags = WOW64_CONTEXT_ALL;
- CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
+ context->ContextFlags = WindowsContext<decltype(context)>::all;
+ CHECK (get_thread_context (th->h, context));
/* Copy dr values from that thread.
But only if there were not modified since last stop.
PR gdb/2388 */
if (!th->debug_registers_changed)
{
- windows_process.dr[0] = th->wow64_context.Dr0;
- windows_process.dr[1] = th->wow64_context.Dr1;
- windows_process.dr[2] = th->wow64_context.Dr2;
- windows_process.dr[3] = th->wow64_context.Dr3;
- windows_process.dr[6] = th->wow64_context.Dr6;
- windows_process.dr[7] = th->wow64_context.Dr7;
+ windows_process.dr[0] = context->Dr0;
+ windows_process.dr[1] = context->Dr1;
+ windows_process.dr[2] = context->Dr2;
+ windows_process.dr[3] = context->Dr3;
+ windows_process.dr[6] = context->Dr6;
+ windows_process.dr[7] = context->Dr7;
}
- }
- else
-#endif
- {
- th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
- CHECK (GetThreadContext (th->h, &th->context));
- /* Copy dr values from that thread.
- But only if there were not modified since last stop.
- PR gdb/2388 */
- if (!th->debug_registers_changed)
- {
- windows_process.dr[0] = th->context.Dr0;
- windows_process.dr[1] = th->context.Dr1;
- windows_process.dr[2] = th->context.Dr2;
- windows_process.dr[3] = th->context.Dr3;
- windows_process.dr[6] = th->context.Dr6;
- windows_process.dr[7] = th->context.Dr7;
- }
- }
+ });
+
th->reload_context = false;
}
@@ -785,11 +756,10 @@ windows_store_one_register (const struct regcache *regcache,
{
gdb_assert (r >= 0);
- char *context_ptr = (char *) &th->context;
-#ifdef __x86_64__
- if (windows_process.wow64_process)
- context_ptr = (char *) &th->wow64_context;
-#endif
+ char *context_ptr = windows_process.with_context (th, [] (auto *context)
+ {
+ return (char *) context;
+ });
struct gdbarch *gdbarch = regcache->arch ();
i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
@@ -1086,13 +1056,10 @@ static int
display_selector (HANDLE thread, DWORD sel)
{
LDT_ENTRY info;
- BOOL ret;
-#ifdef __x86_64__
- if (windows_process.wow64_process)
- ret = Wow64GetThreadSelectorEntry (thread, sel, &info);
- else
-#endif
- ret = GetThreadSelectorEntry (thread, sel, &info);
+ BOOL ret = windows_process.with_context (nullptr, [&] (auto *context)
+ {
+ return get_thread_selector_entry (context, thread, sel, &info);
+ });
if (ret)
{
int base, limit;
@@ -1181,50 +1148,21 @@ display_selectors (const char * args, int from_tty)
if (!args)
{
-#ifdef __x86_64__
- if (windows_process.wow64_process)
- {
- gdb_puts ("Selector $cs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegCs);
- gdb_puts ("Selector $ds\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegDs);
- gdb_puts ("Selector $es\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegEs);
- gdb_puts ("Selector $ss\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegSs);
- gdb_puts ("Selector $fs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegFs);
- gdb_puts ("Selector $gs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->wow64_context.SegGs);
- }
- else
-#endif
+ windows_process.with_context (current_windows_thread, [&] (auto *context)
{
gdb_puts ("Selector $cs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegCs);
+ display_selector (current_windows_thread->h, context->SegCs);
gdb_puts ("Selector $ds\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegDs);
+ display_selector (current_windows_thread->h, context->SegDs);
gdb_puts ("Selector $es\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegEs);
+ display_selector (current_windows_thread->h, context->SegEs);
gdb_puts ("Selector $ss\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegSs);
+ display_selector (current_windows_thread->h, context->SegSs);
gdb_puts ("Selector $fs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegFs);
+ display_selector (current_windows_thread->h, context->SegFs);
gdb_puts ("Selector $gs\n");
- display_selector (current_windows_thread->h,
- current_windows_thread->context.SegGs);
- }
+ display_selector (current_windows_thread->h, context->SegGs);
+ });
}
else
{
@@ -1285,65 +1223,36 @@ windows_nat_target::windows_continue (DWORD continue_status, int id,
for (auto &th : windows_process.thread_list)
if (id == -1 || id == (int) th->tid)
{
-#ifdef __x86_64__
- if (windows_process.wow64_process)
+ windows_process.with_context (th.get (), [&] (auto *context)
{
if (th->debug_registers_changed)
{
- th->wow64_context.ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS;
- th->wow64_context.Dr0 = windows_process.dr[0];
- th->wow64_context.Dr1 = windows_process.dr[1];
- th->wow64_context.Dr2 = windows_process.dr[2];
- th->wow64_context.Dr3 = windows_process.dr[3];
- th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
- th->wow64_context.Dr7 = windows_process.dr[7];
+ context->ContextFlags
+ |= WindowsContext<decltype(context)>::debug;
+ context->Dr0 = windows_process.dr[0];
+ context->Dr1 = windows_process.dr[1];
+ context->Dr2 = windows_process.dr[2];
+ context->Dr3 = windows_process.dr[3];
+ context->Dr6 = DR6_CLEAR_VALUE;
+ context->Dr7 = windows_process.dr[7];
th->debug_registers_changed = false;
}
- if (th->wow64_context.ContextFlags)
+ if (context->ContextFlags)
{
DWORD ec = 0;
if (GetExitCodeThread (th->h, &ec)
&& ec == STILL_ACTIVE)
{
- BOOL status = Wow64SetThreadContext (th->h,
- &th->wow64_context);
+ BOOL status = set_thread_context (th->h, context);
if (!killed)
CHECK (status);
}
- th->wow64_context.ContextFlags = 0;
- }
- }
- else
-#endif
- {
- if (th->debug_registers_changed)
- {
- th->context.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
- th->context.Dr0 = windows_process.dr[0];
- th->context.Dr1 = windows_process.dr[1];
- th->context.Dr2 = windows_process.dr[2];
- th->context.Dr3 = windows_process.dr[3];
- th->context.Dr6 = DR6_CLEAR_VALUE;
- th->context.Dr7 = windows_process.dr[7];
- th->debug_registers_changed = false;
+ context->ContextFlags = 0;
}
- if (th->context.ContextFlags)
- {
- DWORD ec = 0;
-
- if (GetExitCodeThread (th->h, &ec)
- && ec == STILL_ACTIVE)
- {
- BOOL status = SetThreadContext (th->h, &th->context);
+ });
- if (!killed)
- CHECK (status);
- }
- th->context.ContextFlags = 0;
- }
- }
th->resume ();
}
else
@@ -1454,8 +1363,7 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
th = windows_process.thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
if (th)
{
-#ifdef __x86_64__
- if (windows_process.wow64_process)
+ windows_process.with_context (th, [&] (auto *context)
{
if (step)
{
@@ -1463,53 +1371,25 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
regcache *regcache = get_thread_regcache (inferior_thread ());
struct gdbarch *gdbarch = regcache->arch ();
fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
- th->wow64_context.EFlags |= FLAG_TRACE_BIT;
+ context->EFlags |= FLAG_TRACE_BIT;
}
- if (th->wow64_context.ContextFlags)
+ if (context->ContextFlags)
{
if (th->debug_registers_changed)
{
- th->wow64_context.Dr0 = windows_process.dr[0];
- th->wow64_context.Dr1 = windows_process.dr[1];
- th->wow64_context.Dr2 = windows_process.dr[2];
- th->wow64_context.Dr3 = windows_process.dr[3];
- th->wow64_context.Dr6 = DR6_CLEAR_VALUE;
- th->wow64_context.Dr7 = windows_process.dr[7];
+ context->Dr0 = windows_process.dr[0];
+ context->Dr1 = windows_process.dr[1];
+ context->Dr2 = windows_process.dr[2];
+ context->Dr3 = windows_process.dr[3];
+ context->Dr6 = DR6_CLEAR_VALUE;
+ context->Dr7 = windows_process.dr[7];
th->debug_registers_changed = false;
}
- CHECK (Wow64SetThreadContext (th->h, &th->wow64_context));
- th->wow64_context.ContextFlags = 0;
+ CHECK (set_thread_context (th->h, context));
+ context->ContextFlags = 0;
}
- }
- else
-#endif
- {
- if (step)
- {
- /* Single step by setting t bit. */
- regcache *regcache = get_thread_regcache (inferior_thread ());
- struct gdbarch *gdbarch = regcache->arch ();
- fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
- th->context.EFlags |= FLAG_TRACE_BIT;
- }
-
- if (th->context.ContextFlags)
- {
- if (th->debug_registers_changed)
- {
- th->context.Dr0 = windows_process.dr[0];
- th->context.Dr1 = windows_process.dr[1];
- th->context.Dr2 = windows_process.dr[2];
- th->context.Dr3 = windows_process.dr[3];
- th->context.Dr6 = DR6_CLEAR_VALUE;
- th->context.Dr7 = windows_process.dr[7];
- th->debug_registers_changed = false;
- }
- CHECK (SetThreadContext (th->h, &th->context));
- th->context.ContextFlags = 0;
- }
- }
+ });
}
/* Allow continuing with the same signal that interrupted us.