| author | |
| committer | |
| log | 09ff03a57a9f2144f0d3e9b0173bac7035d3629b |
| tree | c498aa8f839458e5558f8344893579d16a5954ae |
| parent | a3e2ee091139740d076da1176ac8c487ca20a9a6 |
| signature |
windows: add RtlCaptureContext, RtlLookupFunctionEntry, RtlVirtualUnwind and supporting types
windows: fix alignment of CONTEXT structs to match winnt.h as required by RtlCaptureContext (fxsave instr)
windows aarch64: fix __chkstk being defined twice if libc is not linked on msvc
Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>4 files changed, 211 insertions(+), 13 deletions(-)
lib/std/debug.zig+45-8| ... | @@ -206,17 +206,12 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT | ... | @@ -206,17 +206,12 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT |
| 206 | if (native_os == .windows) { | 206 | if (native_os == .windows) { |
| 207 | const addrs = stack_trace.instruction_addresses; | 207 | const addrs = stack_trace.instruction_addresses; |
| 208 | const first_addr = first_address orelse { | 208 | const first_addr = first_address orelse { |
| 209 | stack_trace.index = windows.ntdll.RtlCaptureStackBackTrace( | 209 | stack_trace.index = walkStackWindows(addrs[0..]); |
| 210 | 0, | ||
| 211 | @intCast(u32, addrs.len), | ||
| 212 | @ptrCast(**anyopaque, addrs.ptr), | ||
| 213 | null, | ||
| 214 | ); | ||
| 215 | return; | 210 | return; |
| 216 | }; | 211 | }; |
| 217 | var addr_buf_stack: [32]usize = undefined; | 212 | var addr_buf_stack: [32]usize = undefined; |
| 218 | const addr_buf = if (addr_buf_stack.len > addrs.len) addr_buf_stack[0..] else addrs; | 213 | const addr_buf = if (addr_buf_stack.len > addrs.len) addr_buf_stack[0..] else addrs; |
| 219 | const n = windows.ntdll.RtlCaptureStackBackTrace(0, @intCast(u32, addr_buf.len), @ptrCast(**anyopaque, addr_buf.ptr), null); | 214 | const n = walkStackWindows(addr_buf[0..]); |
| 220 | const first_index = for (addr_buf[0..n]) |addr, i| { | 215 | const first_index = for (addr_buf[0..n]) |addr, i| { |
| 221 | if (addr == first_addr) { | 216 | if (addr == first_addr) { |
| 222 | break i; | 217 | break i; |
| ... | @@ -573,6 +568,48 @@ pub fn writeCurrentStackTrace( | ... | @@ -573,6 +568,48 @@ pub fn writeCurrentStackTrace( |
| 573 | } | 568 | } |
| 574 | } | 569 | } |
| 575 | 570 | ||
| 571 | pub noinline fn walkStackWindows(addresses: []usize) usize { | ||
| 572 | if (builtin.cpu.arch == .x86) { | ||
| 573 | // RtlVirtualUnwind doesn't exist on x86 | ||
| 574 | return windows.ntdll.RtlCaptureStackBackTrace(0, addresses.len, @ptrCast(**anyopaque, addresses.ptr), null); | ||
| 575 | } | ||
| 576 | |||
| 577 | const tib = @ptrCast(*const windows.NT_TIB, &windows.teb().Reserved1); | ||
| 578 | |||
| 579 | var context: windows.CONTEXT = std.mem.zeroes(windows.CONTEXT); | ||
| 580 | windows.ntdll.RtlCaptureContext(&context); | ||
| 581 | |||
| 582 | var i: usize = 0; | ||
| 583 | var image_base: usize = undefined; | ||
| 584 | var history_table: windows.UNWIND_HISTORY_TABLE = std.mem.zeroes(windows.UNWIND_HISTORY_TABLE); | ||
| 585 | |||
| 586 | while (i < addresses.len) : (i += 1) { | ||
| 587 | const current_regs = context.getRegs(); | ||
| 588 | if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &history_table)) |runtime_function| { | ||
| 589 | var handler_data: ?*anyopaque = null; | ||
| 590 | var establisher_frame: u64 = undefined; | ||
| 591 | _ = windows.ntdll.RtlVirtualUnwind(windows.UNW_FLAG_NHANDLER, image_base, current_regs.ip, runtime_function, &context, &handler_data, &establisher_frame, null); | ||
| 592 | } else { | ||
| 593 | // leaf function | ||
| 594 | context.setIp(@intToPtr(*u64, current_regs.sp).*); | ||
| 595 | context.setSp(current_regs.sp + @sizeOf(usize)); | ||
| 596 | } | ||
| 597 | |||
| 598 | const next_regs = context.getRegs(); | ||
| 599 | if (next_regs.sp < @ptrToInt(tib.StackLimit) or next_regs.sp > @ptrToInt(tib.StackBase)) { | ||
| 600 | break; | ||
| 601 | } | ||
| 602 | |||
| 603 | if (next_regs.ip == 0) { | ||
| 604 | break; | ||
| 605 | } | ||
| 606 | |||
| 607 | addresses[i] = next_regs.ip; | ||
| 608 | } | ||
| 609 | |||
| 610 | return i; | ||
| 611 | } | ||
| 612 | |||
| 576 | pub fn writeCurrentStackTraceWindows( | 613 | pub fn writeCurrentStackTraceWindows( |
| 577 | out_stream: anytype, | 614 | out_stream: anytype, |
| 578 | debug_info: *DebugInfo, | 615 | debug_info: *DebugInfo, |
| ... | @@ -580,7 +617,7 @@ pub fn writeCurrentStackTraceWindows( | ... | @@ -580,7 +617,7 @@ pub fn writeCurrentStackTraceWindows( |
| 580 | start_addr: ?usize, | 617 | start_addr: ?usize, |
| 581 | ) !void { | 618 | ) !void { |
| 582 | var addr_buf: [1024]usize = undefined; | 619 | var addr_buf: [1024]usize = undefined; |
| 583 | const n = windows.ntdll.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**anyopaque, &addr_buf), null); | 620 | const n = walkStackWindows(addr_buf[0..]); |
| 584 | const addrs = addr_buf[0..n]; | 621 | const addrs = addr_buf[0..n]; |
| 585 | var start_i: usize = if (start_addr) |saddr| blk: { | 622 | var start_i: usize = if (start_addr) |saddr| blk: { |
| 586 | for (addrs) |addr, i| { | 623 | for (addrs) |addr, i| { |
lib/std/os/windows.zig+119-5| ... | @@ -31,6 +31,8 @@ pub const winmm = @import("windows/winmm.zig"); | ... | @@ -31,6 +31,8 @@ pub const winmm = @import("windows/winmm.zig"); |
| 31 | 31 | ||
| 32 | pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize)); | 32 | pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize)); |
| 33 | 33 | ||
| 34 | const Self = @This(); | ||
| 35 | |||
| 34 | pub const OpenError = error{ | 36 | pub const OpenError = error{ |
| 35 | IsDir, | 37 | IsDir, |
| 36 | NotDir, | 38 | NotDir, |
| ... | @@ -3282,7 +3284,7 @@ pub usingnamespace switch (native_arch) { | ... | @@ -3282,7 +3284,7 @@ pub usingnamespace switch (native_arch) { |
| 3282 | }; | 3284 | }; |
| 3283 | 3285 | ||
| 3284 | pub const CONTEXT = extern struct { | 3286 | pub const CONTEXT = extern struct { |
| 3285 | P1Home: DWORD64, | 3287 | P1Home: DWORD64 align(16), |
| 3286 | P2Home: DWORD64, | 3288 | P2Home: DWORD64, |
| 3287 | P3Home: DWORD64, | 3289 | P3Home: DWORD64, |
| 3288 | P4Home: DWORD64, | 3290 | P4Home: DWORD64, |
| ... | @@ -3352,9 +3354,28 @@ pub usingnamespace switch (native_arch) { | ... | @@ -3352,9 +3354,28 @@ pub usingnamespace switch (native_arch) { |
| 3352 | LastExceptionToRip: DWORD64, | 3354 | LastExceptionToRip: DWORD64, |
| 3353 | LastExceptionFromRip: DWORD64, | 3355 | LastExceptionFromRip: DWORD64, |
| 3354 | 3356 | ||
| 3355 | pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } { | 3357 | pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize, sp: usize } { |
| 3356 | return .{ .bp = ctx.Rbp, .ip = ctx.Rip }; | 3358 | return .{ .bp = ctx.Rbp, .ip = ctx.Rip, .sp = ctx.Rsp }; |
| 3359 | } | ||
| 3360 | |||
| 3361 | pub fn setIp(ctx: *CONTEXT, ip: usize) void { | ||
| 3362 | ctx.Rip = ip; | ||
| 3357 | } | 3363 | } |
| 3364 | |||
| 3365 | pub fn setSp(ctx: *CONTEXT, sp: usize) void { | ||
| 3366 | ctx.Rsp = sp; | ||
| 3367 | } | ||
| 3368 | }; | ||
| 3369 | |||
| 3370 | pub const RUNTIME_FUNCTION = extern struct { | ||
| 3371 | BeginAddress: DWORD, | ||
| 3372 | EndAddress: DWORD, | ||
| 3373 | UnwindData: DWORD, | ||
| 3374 | }; | ||
| 3375 | |||
| 3376 | pub const KNONVOLATILE_CONTEXT_POINTERS = extern struct { | ||
| 3377 | FloatingContext: [16]?*M128A, | ||
| 3378 | IntegerContext: [16]?*ULONG64, | ||
| 3358 | }; | 3379 | }; |
| 3359 | }, | 3380 | }, |
| 3360 | .aarch64 => struct { | 3381 | .aarch64 => struct { |
| ... | @@ -3370,7 +3391,7 @@ pub usingnamespace switch (native_arch) { | ... | @@ -3370,7 +3391,7 @@ pub usingnamespace switch (native_arch) { |
| 3370 | }; | 3391 | }; |
| 3371 | 3392 | ||
| 3372 | pub const CONTEXT = extern struct { | 3393 | pub const CONTEXT = extern struct { |
| 3373 | ContextFlags: ULONG, | 3394 | ContextFlags: ULONG align(16), |
| 3374 | Cpsr: ULONG, | 3395 | Cpsr: ULONG, |
| 3375 | DUMMYUNIONNAME: extern union { | 3396 | DUMMYUNIONNAME: extern union { |
| 3376 | DUMMYSTRUCTNAME: extern struct { | 3397 | DUMMYSTRUCTNAME: extern struct { |
| ... | @@ -3418,12 +3439,60 @@ pub usingnamespace switch (native_arch) { | ... | @@ -3418,12 +3439,60 @@ pub usingnamespace switch (native_arch) { |
| 3418 | Wcr: [2]DWORD, | 3439 | Wcr: [2]DWORD, |
| 3419 | Wvr: [2]DWORD64, | 3440 | Wvr: [2]DWORD64, |
| 3420 | 3441 | ||
| 3421 | pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } { | 3442 | pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize, sp: usize } { |
| 3422 | return .{ | 3443 | return .{ |
| 3423 | .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, | 3444 | .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, |
| 3424 | .ip = ctx.Pc, | 3445 | .ip = ctx.Pc, |
| 3446 | .sp = ctx.Sp, | ||
| 3425 | }; | 3447 | }; |
| 3426 | } | 3448 | } |
| 3449 | |||
| 3450 | pub fn setIp(ctx: *CONTEXT, ip: usize) void { | ||
| 3451 | ctx.Pc = ip; | ||
| 3452 | } | ||
| 3453 | |||
| 3454 | pub fn setSp(ctx: *CONTEXT, sp: usize) void { | ||
| 3455 | ctx.Sp = sp; | ||
| 3456 | } | ||
| 3457 | }; | ||
| 3458 | |||
| 3459 | pub const RUNTIME_FUNCTION = extern struct { | ||
| 3460 | BeginAddress: DWORD, | ||
| 3461 | DUMMYUNIONNAME: extern union { | ||
| 3462 | UnwindData: DWORD, | ||
| 3463 | DUMMYSTRUCTNAME: packed struct { | ||
| 3464 | Flag: u2, | ||
| 3465 | FunctionLength: u11, | ||
| 3466 | RegF: u3, | ||
| 3467 | RegI: u4, | ||
| 3468 | H: u1, | ||
| 3469 | CR: u2, | ||
| 3470 | FrameSize: u9, | ||
| 3471 | }, | ||
| 3472 | }, | ||
| 3473 | }; | ||
| 3474 | |||
| 3475 | pub const KNONVOLATILE_CONTEXT_POINTERS = extern struct { | ||
| 3476 | X19: ?*DWORD64, | ||
| 3477 | X20: ?*DWORD64, | ||
| 3478 | X21: ?*DWORD64, | ||
| 3479 | X22: ?*DWORD64, | ||
| 3480 | X23: ?*DWORD64, | ||
| 3481 | X24: ?*DWORD64, | ||
| 3482 | X25: ?*DWORD64, | ||
| 3483 | X26: ?*DWORD64, | ||
| 3484 | X27: ?*DWORD64, | ||
| 3485 | X28: ?*DWORD64, | ||
| 3486 | Fp: ?*DWORD64, | ||
| 3487 | Lr: ?*DWORD64, | ||
| 3488 | D8: ?*DWORD64, | ||
| 3489 | D9: ?*DWORD64, | ||
| 3490 | D10: ?*DWORD64, | ||
| 3491 | D11: ?*DWORD64, | ||
| 3492 | D12: ?*DWORD64, | ||
| 3493 | D13: ?*DWORD64, | ||
| 3494 | D14: ?*DWORD64, | ||
| 3495 | D15: ?*DWORD64, | ||
| 3427 | }; | 3496 | }; |
| 3428 | }, | 3497 | }, |
| 3429 | else => struct {}, | 3498 | else => struct {}, |
| ... | @@ -3436,6 +3505,36 @@ pub const EXCEPTION_POINTERS = extern struct { | ... | @@ -3436,6 +3505,36 @@ pub const EXCEPTION_POINTERS = extern struct { |
| 3436 | 3505 | ||
| 3437 | pub const VECTORED_EXCEPTION_HANDLER = *const fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(WINAPI) c_long; | 3506 | pub const VECTORED_EXCEPTION_HANDLER = *const fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(WINAPI) c_long; |
| 3438 | 3507 | ||
| 3508 | pub const EXCEPTION_DISPOSITION = i32; | ||
| 3509 | pub const EXCEPTION_ROUTINE = *const fn ( | ||
| 3510 | ExceptionRecord: ?*EXCEPTION_RECORD, | ||
| 3511 | EstablisherFrame: PVOID, | ||
| 3512 | ContextRecord: *(Self.CONTEXT), | ||
| 3513 | DispatcherContext: PVOID, | ||
| 3514 | ) callconv(WINAPI) EXCEPTION_DISPOSITION; | ||
| 3515 | |||
| 3516 | pub const UNWIND_HISTORY_TABLE_SIZE = 12; | ||
| 3517 | pub const UNWIND_HISTORY_TABLE_ENTRY = extern struct { | ||
| 3518 | ImageBase: ULONG64, | ||
| 3519 | FunctionEntry: *Self.RUNTIME_FUNCTION, | ||
| 3520 | }; | ||
| 3521 | |||
| 3522 | pub const UNWIND_HISTORY_TABLE = extern struct { | ||
| 3523 | Count: ULONG, | ||
| 3524 | LocalHint: BYTE, | ||
| 3525 | GlobalHint: BYTE, | ||
| 3526 | Search: BYTE, | ||
| 3527 | Once: BYTE, | ||
| 3528 | LowAddress: ULONG64, | ||
| 3529 | HighAddress: ULONG64, | ||
| 3530 | Entry: [UNWIND_HISTORY_TABLE_SIZE]UNWIND_HISTORY_TABLE_ENTRY, | ||
| 3531 | }; | ||
| 3532 | |||
| 3533 | pub const UNW_FLAG_NHANDLER = 0x0; | ||
| 3534 | pub const UNW_FLAG_EHANDLER = 0x1; | ||
| 3535 | pub const UNW_FLAG_UHANDLER = 0x2; | ||
| 3536 | pub const UNW_FLAG_CHAININFO = 0x4; | ||
| 3537 | |||
| 3439 | pub const OBJECT_ATTRIBUTES = extern struct { | 3538 | pub const OBJECT_ATTRIBUTES = extern struct { |
| 3440 | Length: ULONG, | 3539 | Length: ULONG, |
| 3441 | RootDirectory: ?HANDLE, | 3540 | RootDirectory: ?HANDLE, |
| ... | @@ -3494,6 +3593,21 @@ pub const TEB = extern struct { | ... | @@ -3494,6 +3593,21 @@ pub const TEB = extern struct { |
| 3494 | TlsExpansionSlots: PVOID, | 3593 | TlsExpansionSlots: PVOID, |
| 3495 | }; | 3594 | }; |
| 3496 | 3595 | ||
| 3596 | pub const EXCEPTION_REGISTRATION_RECORD = extern struct { | ||
| 3597 | Next: ?*EXCEPTION_REGISTRATION_RECORD, | ||
| 3598 | Handler: ?*EXCEPTION_DISPOSITION, | ||
| 3599 | }; | ||
| 3600 | |||
| 3601 | pub const NT_TIB = extern struct { | ||
| 3602 | ExceptionList: ?*EXCEPTION_REGISTRATION_RECORD, | ||
| 3603 | StackBase: PVOID, | ||
| 3604 | StackLimit: PVOID, | ||
| 3605 | SubSystemTib: PVOID, | ||
| 3606 | DUMMYUNIONNAME: extern union { FiberData: PVOID, Version: DWORD }, | ||
| 3607 | ArbitraryUserPointer: PVOID, | ||
| 3608 | Self: ?*@This(), | ||
| 3609 | }; | ||
| 3610 | |||
| 3497 | /// Process Environment Block | 3611 | /// Process Environment Block |
| 3498 | /// Microsoft documentation of this is incomplete, the fields here are taken from various resources including: | 3612 | /// Microsoft documentation of this is incomplete, the fields here are taken from various resources including: |
| 3499 | /// - https://github.com/wine-mirror/wine/blob/1aff1e6a370ee8c0213a0fd4b220d121da8527aa/include/winternl.h#L269 | 3613 | /// - https://github.com/wine-mirror/wine/blob/1aff1e6a370ee8c0213a0fd4b220d121da8527aa/include/winternl.h#L269 |
lib/std/os/windows/kernel32.zig+25| ... | @@ -5,8 +5,10 @@ const BOOL = windows.BOOL; | ... | @@ -5,8 +5,10 @@ const BOOL = windows.BOOL; |
| 5 | const BOOLEAN = windows.BOOLEAN; | 5 | const BOOLEAN = windows.BOOLEAN; |
| 6 | const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; | 6 | const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; |
| 7 | const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO; | 7 | const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO; |
| 8 | const CONTEXT = windows.CONTEXT; | ||
| 8 | const COORD = windows.COORD; | 9 | const COORD = windows.COORD; |
| 9 | const DWORD = windows.DWORD; | 10 | const DWORD = windows.DWORD; |
| 11 | const DWORD64 = windows.DWORD64; | ||
| 10 | const FILE_INFO_BY_HANDLE_CLASS = windows.FILE_INFO_BY_HANDLE_CLASS; | 12 | const FILE_INFO_BY_HANDLE_CLASS = windows.FILE_INFO_BY_HANDLE_CLASS; |
| 11 | const HANDLE = windows.HANDLE; | 13 | const HANDLE = windows.HANDLE; |
| 12 | const HMODULE = windows.HMODULE; | 14 | const HMODULE = windows.HMODULE; |
| ... | @@ -60,6 +62,10 @@ const INIT_ONCE_FN = windows.INIT_ONCE_FN; | ... | @@ -60,6 +62,10 @@ const INIT_ONCE_FN = windows.INIT_ONCE_FN; |
| 60 | const PMEMORY_BASIC_INFORMATION = windows.PMEMORY_BASIC_INFORMATION; | 62 | const PMEMORY_BASIC_INFORMATION = windows.PMEMORY_BASIC_INFORMATION; |
| 61 | const REGSAM = windows.REGSAM; | 63 | const REGSAM = windows.REGSAM; |
| 62 | const LSTATUS = windows.LSTATUS; | 64 | const LSTATUS = windows.LSTATUS; |
| 65 | const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; | ||
| 66 | const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION; | ||
| 67 | const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; | ||
| 68 | const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; | ||
| 63 | 69 | ||
| 64 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; | 70 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; |
| 65 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; | 71 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; |
| ... | @@ -292,6 +298,25 @@ pub extern "kernel32" fn ReadFile( | ... | @@ -292,6 +298,25 @@ pub extern "kernel32" fn ReadFile( |
| 292 | 298 | ||
| 293 | pub extern "kernel32" fn RemoveDirectoryW(lpPathName: [*:0]const u16) callconv(WINAPI) BOOL; | 299 | pub extern "kernel32" fn RemoveDirectoryW(lpPathName: [*:0]const u16) callconv(WINAPI) BOOL; |
| 294 | 300 | ||
| 301 | pub extern "kernel32" fn RtlCaptureContext(ContextRecord: *CONTEXT) callconv(WINAPI) void; | ||
| 302 | |||
| 303 | pub extern "kernel32" fn RtlLookupFunctionEntry( | ||
| 304 | ControlPc: DWORD64, | ||
| 305 | ImageBase: *DWORD64, | ||
| 306 | HistoryTable: *UNWIND_HISTORY_TABLE, | ||
| 307 | ) callconv(WINAPI) ?*RUNTIME_FUNCTION; | ||
| 308 | |||
| 309 | pub extern "kernel32" fn RtlVirtualUnwind( | ||
| 310 | HandlerType: DWORD, | ||
| 311 | ImageBase: DWORD64, | ||
| 312 | ControlPc: DWORD64, | ||
| 313 | FunctionEntry: *RUNTIME_FUNCTION, | ||
| 314 | ContextRecord: *CONTEXT, | ||
| 315 | HandlerData: *?PVOID, | ||
| 316 | EstablisherFrame: *DWORD64, | ||
| 317 | ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, | ||
| 318 | ) callconv(WINAPI) *EXCEPTION_ROUTINE; | ||
| 319 | |||
| 295 | pub extern "kernel32" fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) callconv(WINAPI) BOOL; | 320 | pub extern "kernel32" fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) callconv(WINAPI) BOOL; |
| 296 | 321 | ||
| 297 | pub extern "kernel32" fn SetConsoleCtrlHandler( | 322 | pub extern "kernel32" fn SetConsoleCtrlHandler( |
lib/std/os/windows/ntdll.zig+22| ... | @@ -3,6 +3,7 @@ const windows = std.os.windows; | ... | @@ -3,6 +3,7 @@ const windows = std.os.windows; |
| 3 | 3 | ||
| 4 | const BOOL = windows.BOOL; | 4 | const BOOL = windows.BOOL; |
| 5 | const DWORD = windows.DWORD; | 5 | const DWORD = windows.DWORD; |
| 6 | const DWORD64 = windows.DWORD64; | ||
| 6 | const ULONG = windows.ULONG; | 7 | const ULONG = windows.ULONG; |
| 7 | const WINAPI = windows.WINAPI; | 8 | const WINAPI = windows.WINAPI; |
| 8 | const NTSTATUS = windows.NTSTATUS; | 9 | const NTSTATUS = windows.NTSTATUS; |
| ... | @@ -24,6 +25,11 @@ const SIZE_T = windows.SIZE_T; | ... | @@ -24,6 +25,11 @@ const SIZE_T = windows.SIZE_T; |
| 24 | const CURDIR = windows.CURDIR; | 25 | const CURDIR = windows.CURDIR; |
| 25 | const PCWSTR = windows.PCWSTR; | 26 | const PCWSTR = windows.PCWSTR; |
| 26 | const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE; | 27 | const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE; |
| 28 | const CONTEXT = windows.CONTEXT; | ||
| 29 | const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; | ||
| 30 | const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION; | ||
| 31 | const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; | ||
| 32 | const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; | ||
| 27 | 33 | ||
| 28 | pub const THREADINFOCLASS = enum(c_int) { | 34 | pub const THREADINFOCLASS = enum(c_int) { |
| 29 | ThreadBasicInformation, | 35 | ThreadBasicInformation, |
| ... | @@ -99,6 +105,22 @@ pub extern "ntdll" fn RtlCaptureStackBackTrace( | ... | @@ -99,6 +105,22 @@ pub extern "ntdll" fn RtlCaptureStackBackTrace( |
| 99 | BackTrace: **anyopaque, | 105 | BackTrace: **anyopaque, |
| 100 | BackTraceHash: ?*DWORD, | 106 | BackTraceHash: ?*DWORD, |
| 101 | ) callconv(WINAPI) WORD; | 107 | ) callconv(WINAPI) WORD; |
| 108 | pub extern "ntdll" fn RtlCaptureContext(ContextRecord: *CONTEXT) callconv(WINAPI) void; | ||
| 109 | pub extern "ntdll" fn RtlLookupFunctionEntry( | ||
| 110 | ControlPc: DWORD64, | ||
| 111 | ImageBase: *DWORD64, | ||
| 112 | HistoryTable: *UNWIND_HISTORY_TABLE, | ||
| 113 | ) callconv(WINAPI) ?*RUNTIME_FUNCTION; | ||
| 114 | pub extern "ntdll" fn RtlVirtualUnwind( | ||
| 115 | HandlerType: DWORD, | ||
| 116 | ImageBase: DWORD64, | ||
| 117 | ControlPc: DWORD64, | ||
| 118 | FunctionEntry: *RUNTIME_FUNCTION, | ||
| 119 | ContextRecord: *CONTEXT, | ||
| 120 | HandlerData: *?PVOID, | ||
| 121 | EstablisherFrame: *DWORD64, | ||
| 122 | ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, | ||
| 123 | ) callconv(WINAPI) *EXCEPTION_ROUTINE; | ||
| 102 | pub extern "ntdll" fn NtQueryInformationFile( | 124 | pub extern "ntdll" fn NtQueryInformationFile( |
| 103 | FileHandle: HANDLE, | 125 | FileHandle: HANDLE, |
| 104 | IoStatusBlock: *IO_STATUS_BLOCK, | 126 | IoStatusBlock: *IO_STATUS_BLOCK, |