@@ -24,28 +24,34 @@ use winapi::um::debugapi::DebugActiveProcessStop;
24
24
use winapi:: um:: debugapi:: DebugActiveProcess ;
25
25
use winapi:: um:: debugapi:: ContinueDebugEvent ;
26
26
use winapi:: um:: winbase:: InitializeContext ;
27
+ use winapi:: um:: processthreadsapi:: GetProcessId ;
27
28
use winapi:: um:: processthreadsapi:: GetCurrentProcess ;
28
29
use winapi:: um:: processthreadsapi:: SetThreadContext ;
29
30
use winapi:: um:: processthreadsapi:: GetThreadContext ;
30
31
use winapi:: um:: processthreadsapi:: FlushInstructionCache ;
31
32
use winapi:: um:: processthreadsapi:: TerminateProcess ;
32
33
use winapi:: um:: processthreadsapi:: OpenProcess ;
34
+ use winapi:: um:: processthreadsapi:: CreateProcessA ;
33
35
use winapi:: um:: wow64apiset:: IsWow64Process ;
34
36
use winapi:: um:: winnt:: PROCESS_QUERY_LIMITED_INFORMATION ;
35
37
use winapi:: um:: psapi:: GetMappedFileNameW ;
36
38
use winapi:: um:: winnt:: HANDLE ;
37
39
use winapi:: um:: minwinbase:: DEBUG_EVENT ;
40
+ use winapi:: um:: winbase:: DEBUG_PROCESS ;
41
+ use winapi:: um:: winbase:: DEBUG_ONLY_THIS_PROCESS ;
38
42
39
43
use std:: time:: { Duration , Instant } ;
40
44
use std:: collections:: { HashSet , HashMap } ;
41
45
use std:: path:: Path ;
42
46
use std:: sync:: Arc ;
43
47
use std:: fs:: File ;
48
+ use std:: ffi:: CString ;
44
49
use std:: io:: Write ;
45
50
use std:: io:: BufWriter ;
46
51
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
47
52
use winapi:: um:: consoleapi:: SetConsoleCtrlHandler ;
48
53
54
+
49
55
use crate :: minidump:: dump;
50
56
use crate :: handles:: Handle ;
51
57
@@ -201,6 +207,47 @@ macro_rules! mprint {
201
207
impl < ' a > Debugger < ' a > {
202
208
/// Create a new debugger and attach to `pid`
203
209
pub fn attach ( pid : u32 ) -> Debugger < ' a > {
210
+ Debugger :: attach_internal ( pid, false )
211
+ }
212
+
213
+ /// Create a new process argv[0], with arguments argv[1..] and attach to it
214
+ pub fn spawn_proc ( argv : & [ String ] , follow_fork : bool ) -> Debugger < ' a > {
215
+ let mut startup_info = unsafe { std:: mem:: zeroed ( ) } ;
216
+ let mut proc_info = unsafe { std:: mem:: zeroed ( ) } ;
217
+
218
+ let cmdline = CString :: new ( argv. join ( " " ) ) . unwrap ( ) ;
219
+
220
+ let cmdline_ptr = cmdline. into_raw ( ) ;
221
+
222
+ let flags = if follow_fork {
223
+ DEBUG_PROCESS
224
+ }
225
+ else {
226
+ DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS
227
+ } ;
228
+
229
+ unsafe {
230
+ assert ! ( CreateProcessA (
231
+ std:: ptr:: null_mut( ) , // lpApplicationName
232
+ cmdline_ptr, // lpCommandLine
233
+ std:: ptr:: null_mut( ) , // lpProcessAttributes
234
+ std:: ptr:: null_mut( ) , // lpThreadAttributes
235
+ 0 , // bInheritHandles
236
+ flags, // dwCreationFlags
237
+ std:: ptr:: null_mut( ) , // lpEnvironment
238
+ std:: ptr:: null_mut( ) , // lpCurrentDirectory
239
+ & mut startup_info, // lpStartupInfo
240
+ & mut proc_info) != 0 , // lpProcessInformation
241
+ "Failed to create process." ) ;
242
+ }
243
+
244
+ let pid = unsafe { GetProcessId ( proc_info. hProcess ) } ;
245
+
246
+ Debugger :: attach_internal ( pid, true )
247
+ }
248
+
249
+ /// Create a new debugger
250
+ pub fn attach_internal ( pid : u32 , attached : bool ) -> Debugger < ' a > {
204
251
// Save the start time
205
252
let start_time = Instant :: now ( ) ;
206
253
@@ -238,10 +285,12 @@ impl<'a> Debugger<'a> {
238
285
assert ! ( cur_is_wow64 == target_is_wow64,
239
286
"Target process does not match mesos bitness" ) ;
240
287
241
- // Attach to the target!
242
- assert ! ( DebugActiveProcess ( pid) != 0 ,
243
- "Failed to attach to process, is your PID valid \
244
- and do you have correct permissions?" ) ;
288
+ if !attached {
289
+ // Attach to the target!
290
+ assert ! ( DebugActiveProcess ( pid) != 0 ,
291
+ "Failed to attach to process, is your PID valid \
292
+ and do you have correct permissions?" ) ;
293
+ }
245
294
}
246
295
247
296
// Correctly initialize a context so it's aligned. We overcommit
0 commit comments