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>
- Add .StaticInitializer to ValueRenderLocation to indicate that the emitted values
must be constant expressions (no function calls, struct casting).
- Add new path for special float types (nan, inf) that works in constant expressions
- Implement windows.teb() using a syscall for .stage2_c because x64 MSVC
doesn't support any kind of inline asm
The name of the game here is to avoid CreateProcessW calls at all costs,
and only ever try calling it when we have a real candidate for execution.
Secondarily, we want to minimize the number of syscalls used when checking
for each PATHEXT-appended version of the app name.
An overview of the technique used:
- Open the search directory for iteration (either cwd or a path from PATH)
- Use NtQueryDirectoryFile with a wildcard filename of `<app name>*` to
check if anything that could possibly match either the unappended version
of the app name or any of the versions with a PATHEXT value appended exists.
- If the wildcard NtQueryDirectoryFile call found nothing, we can exit early
without needing to use PATHEXT at all.
This allows us to use a <open dir, NtQueryDirectoryFile, close dir> sequence
for any directory that doesn't contain any possible matches, instead of having
to use a separate look up for each individual filename combination (unappended +
each PATHEXT appended). For directories where the wildcard *does* match something,
we only need to do a maximum of <number of supported PATHEXT extensions> more
NtQueryDirectoryFile calls.
---
In addition, we now only evaluate the extensions in PATHEXT that we know we can handle (.COM, .EXE, .BAT, .CMD) and ignore the rest.
---
This commit also makes two edge cases match Windows behavior:
- If an app name has the extension .exe and it is attempted to be executed, that is now treated as unrecoverable and InvalidExe is immediately returned no matter where the .exe is (cwd or in the PATH). This matches the behavior of the Windows cmd.exe.
- If the app name contains more than just a filename (e.g. it has path separators), then it is excluded from PATH searching and only does a cwd search. This matches the behavior of Windows cmd.exe.
This helps prevent errors related to undefined pointers being passed
through to some OS apis when slices have 0 length.
Tests have also been added to catch these cases.
There are still a few occurrences of "stage1" in the standard library
and self-hosted compiler source, however, these instances need a bit
more careful inspection to ensure no breakage.
This branch largely reverts 58f961f4cb9875bbce3070969438ecf08f392c9f. I
would like to revisit the proposal to modify the standard library in
this way and think more carefully about it before adding isAbsolute()
checks everywhere.
Ran into this when using a program that uses CreateFileMapping and then trying to call `std.fs.createFile` on the mapped file. More info can be found here:
https://stackoverflow.com/questions/41844842/when-error-1224-error-user-mapped-file-occurs
Before:
```
error.Unexpected NTSTATUS=0xc0000243
C:\Users\Ryan\Programming\Zig\zig\lib\std\os\windows.zig:138:40: 0x7ff74e957466 in OpenFile (test.exe.obj)
else => return unexpectedStatus(rc),
^
```
After:
```
FAIL (AccessDenied)
C:\Users\Ryan\Programming\Zig\zig\lib\std\os\windows.zig:137:30: 0x7ff7f5b776ea in OpenFile (test.exe.obj)
.USER_MAPPED_FILE => return error.AccessDenied,
^
```
Returning a bool allows to conveniently use it as the condition
of a while loop.
Also remove restriction that ST cannot be double-word.
While imm is only 32-bit, this value is extended into a 64-bit
memory location.