1
|
1 /* Ddbg - Win32 Debugger for the D programming language
|
|
2 * Copyright (c) 2007 Jascha Wetzel
|
|
3 * All rights reserved. See LICENSE.TXT for details.
|
|
4 */
|
|
5 module dbgthread;
|
|
6
|
|
7 import util;
|
|
8
|
|
9 import win32.winbase;
|
|
10 import win32.windef;
|
|
11
|
|
12 /**************************************************************************************************
|
|
13
|
|
14 **************************************************************************************************/
|
|
15 class DbgThread
|
|
16 {
|
|
17 HANDLE handle;
|
|
18 uint id,
|
|
19 stack_base;
|
|
20
|
|
21 /**********************************************************************************************
|
|
22
|
|
23 **********************************************************************************************/
|
|
24 this(HANDLE h, uint i)
|
|
25 {
|
|
26 handle = h;
|
|
27 id = i;
|
|
28
|
|
29 // get current esp as stack base
|
|
30 CONTEXT ctx;
|
|
31 if ( getContext(ctx, CONTEXT_CONTROL) )
|
|
32 stack_base = ctx.Esp;
|
|
33 }
|
|
34
|
|
35 int priority()
|
|
36 {
|
|
37 return GetThreadPriority(handle);
|
|
38 }
|
|
39
|
|
40 bool priorityBoost()
|
|
41 {
|
|
42 int boost;
|
|
43 GetThreadPriorityBoost(handle, &boost);
|
|
44 return cast(bool)boost;
|
|
45 }
|
|
46
|
|
47 void times(out ulong creation, out ulong exit, out ulong kernel, out ulong user)
|
|
48 {
|
|
49 GetThreadTimes(handle, cast(FILETIME*)&creation, cast(FILETIME*)&exit, cast(FILETIME*)&kernel, cast(FILETIME*)&user);
|
|
50 }
|
|
51
|
|
52 uint suspendCount()
|
|
53 {
|
|
54 uint count = suspend;
|
|
55 resume;
|
|
56 return count;
|
|
57 }
|
|
58
|
|
59 uint suspend()
|
|
60 {
|
|
61 return SuspendThread(handle);
|
|
62 }
|
|
63
|
|
64 uint resume()
|
|
65 {
|
|
66 return ResumeThread(handle);
|
|
67 }
|
|
68
|
|
69 /**********************************************************************************************
|
|
70
|
|
71 **********************************************************************************************/
|
|
72 bool getContext(out CONTEXT ctx, uint flags=CONTEXT_FULL)
|
|
73 {
|
|
74 ctx.ContextFlags = flags;
|
|
75 suspend;
|
|
76 bool res = cast(bool)GetThreadContext(handle, &ctx);
|
|
77 resume;
|
|
78 return res;
|
|
79 }
|
|
80
|
|
81 /**********************************************************************************************
|
|
82
|
|
83 **********************************************************************************************/
|
|
84 bool setContext(ref CONTEXT ctx)
|
|
85 {
|
|
86 suspend;
|
|
87 auto res = cast(bool)SetThreadContext(handle, &ctx);
|
|
88 resume;
|
|
89 return res;
|
|
90 }
|
|
91
|
|
92 /**********************************************************************************************
|
|
93
|
|
94 **********************************************************************************************/
|
|
95 size_t getDsBase()
|
|
96 {
|
|
97 CONTEXT ctx;
|
|
98 getContext(ctx);
|
|
99
|
|
100 LDT_ENTRY sel_entry;
|
|
101 GetThreadSelectorEntry(handle, ctx.SegDs, &sel_entry);
|
|
102 return (cast(size_t)sel_entry.BaseHi << 24) | (cast(size_t)sel_entry.BaseMid << 16) | cast(size_t)sel_entry.BaseLow;
|
|
103 }
|
|
104
|
|
105 /**********************************************************************************************
|
|
106 Wrapper function for changing the thread's context. Calls the
|
|
107 modify(ctx) delegate that can do the actual change.
|
|
108 Returns: success
|
|
109 **********************************************************************************************/
|
|
110 bool changeContext(void delegate(ref CONTEXT ctx) modify, uint flags=CONTEXT_FULL)
|
|
111 {
|
|
112 // if ( 0 > SuspendThread(thread) )
|
|
113 // {
|
|
114 // DbgIO.println("ERROR: Couldn't SuspendThread to reset instruction pointer: %s", getLastError);
|
|
115 // return false;
|
|
116 // }
|
|
117
|
|
118 CONTEXT ctx;
|
|
119 if ( getContext(ctx, flags) )
|
|
120 {
|
|
121 modify(ctx);
|
|
122 if ( !SetThreadContext(handle, &ctx) )
|
|
123 DbgIO.println("ERROR: Couldn't SetThreadContext to reset instruction pointer: %s", lastError);
|
|
124 } else
|
|
125 DbgIO.println("ERROR: Couldn't GetThreadContext to reset instruction pointer: %s", lastError);
|
|
126
|
|
127 // if ( 0 > ResumeThread(thread) )
|
|
128 // {
|
|
129 // DbgIO.println("ERROR: Couldn't ResumeThread to reset instruction pointer: %s", getLastError);
|
|
130 // return false;
|
|
131 // }
|
|
132
|
|
133 return true;
|
|
134 }
|
|
135 }
|