diff --git a/examples/BUILD.mk b/examples/BUILD.mk index ff8e97a79..e0318d0a7 100644 --- a/examples/BUILD.mk +++ b/examples/BUILD.mk @@ -53,6 +53,7 @@ EXAMPLES_DIRECTDEPS = \ LIBC_NEXGEN32E \ LIBC_NT_ADVAPI32 \ LIBC_NT_IPHLPAPI \ + LIBC_NT_MEMORY \ LIBC_NT_KERNEL32 \ LIBC_NT_NTDLL \ LIBC_NT_USER32 \ diff --git a/libc/nt/enum/pageflags.h b/libc/nt/enum/pageflags.h index 5cef3a2fa..40569decb 100644 --- a/libc/nt/enum/pageflags.h +++ b/libc/nt/enum/pageflags.h @@ -23,4 +23,7 @@ #define kNtSecLargePages 0x80000000 #define kNtSecWritecombine 0x40000000 +#define kNtPageTargetsInvalid 0x40000000 +#define kNtPageTargetsNoUpdate 0x40000000 + #endif /* COSMOPOLITAN_LIBC_NT_ENUM_PAGEFLAGS_H_ */ diff --git a/libc/nt/kernel32/IsWow64Process2.S b/libc/nt/kernel32/IsWow64Process2.S new file mode 100644 index 000000000..4cb92ff17 --- /dev/null +++ b/libc/nt/kernel32/IsWow64Process2.S @@ -0,0 +1,18 @@ +#include "libc/nt/codegen.h" +.imp kernel32,__imp_IsWow64Process2,IsWow64Process2 + + .text.windows + .ftrace1 +IsWow64Process2: + .ftrace2 +#ifdef __x86_64__ + push %rbp + mov %rsp,%rbp + mov __imp_IsWow64Process2(%rip),%rax + jmp __sysv2nt +#elif defined(__aarch64__) + mov x0,#0 + ret +#endif + .endfn IsWow64Process2,globl + .previous diff --git a/libc/nt/master.sh b/libc/nt/master.sh index 4f44cc057..0e8e63654 100755 --- a/libc/nt/master.sh +++ b/libc/nt/master.sh @@ -113,6 +113,7 @@ imp 'GetCurrentProcessId' GetCurrentProcessId kernel32 0 imp 'GetCurrentProcessorNumberEx' GetCurrentProcessorNumberEx kernel32 1 imp 'GetCurrentThread' GetCurrentThread kernel32 0 imp 'GetCurrentThreadId' GetCurrentThreadId kernel32 0 +imp 'GetDynamicTimeZoneInformation' GetDynamicTimeZoneInformation kernel32 1 imp 'GetEnvironmentStrings' GetEnvironmentStringsW kernel32 1 imp 'GetEnvironmentVariable' GetEnvironmentVariableW kernel32 3 imp 'GetExitCodeThread' GetExitCodeThread kernel32 2 @@ -168,8 +169,6 @@ imp 'GetSystemTimePreciseAsFileTime' GetSystemTimePreciseAsFileTime kernel3 imp 'GetSystemTimes' GetSystemTimes kernel32 3 imp 'GetTempPath' GetTempPathW kernel32 2 imp 'GetTempPathA' GetTempPathA kernel32 2 -imp 'GetDynamicTimeZoneInformation' GetDynamicTimeZoneInformation kernel32 1 -imp 'GetTimeZoneInformation' GetTimeZoneInformation kernel32 1 imp 'GetThreadContext' GetThreadContext kernel32 2 imp 'GetThreadDescription' GetThreadDescription kernel32 2 imp 'GetThreadIOPendingFlag' GetThreadIOPendingFlag kernel32 2 @@ -178,6 +177,7 @@ imp 'GetThreadPriority' GetThreadPriority kernel32 1 imp 'GetThreadPriorityBoost' GetThreadPriorityBoost kernel32 2 imp 'GetThreadTimes' GetThreadTimes kernel32 5 imp 'GetTickCount64' GetTickCount64 kernel32 0 +imp 'GetTimeZoneInformation' GetTimeZoneInformation kernel32 1 imp 'GetVersionEx' GetVersionExW kernel32 1 imp 'GetVolumeInformationByHandle' GetVolumeInformationByHandleW kernel32 8 imp 'GetVolumePathName' GetVolumePathNameW kernel32 3 @@ -197,6 +197,7 @@ imp 'InitializeCriticalSection' InitializeCriticalSection kernel32 1 imp 'InitializeCriticalSectionAndSpinCount' InitializeCriticalSectionAndSpinCount kernel32 2 imp 'InitializeProcThreadAttributeList' InitializeProcThreadAttributeList kernel32 4 imp 'InitializeSRWLock' InitializeSRWLock kernel32 1 +imp 'IsWow64Process2' IsWow64Process2 kernel32 3 imp 'LeaveCriticalSection' LeaveCriticalSection kernel32 1 imp 'LoadLibrary' LoadLibraryW kernel32 1 imp 'LoadLibraryA' LoadLibraryA kernel32 1 diff --git a/libc/nt/runtime.h b/libc/nt/runtime.h index 953e77692..5aa2df862 100644 --- a/libc/nt/runtime.h +++ b/libc/nt/runtime.h @@ -43,6 +43,8 @@ bool32 SetDefaultDllDirectories(unsigned dirflags); bool32 ProcessPrng(void *RandomBuffer, uint32_t RandomBufferLength); uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename, uint32_t nSize); +bool32 IsWow64Process2(intptr_t hProcess, uint16_t *out_pProcessMachine, + uint16_t *out_opt_pNativeMachine); #if ShouldUseMsabiAttribute() #include "libc/nt/thunk/runtime.inc" diff --git a/libc/nt/struct/arm64.h b/libc/nt/struct/arm64.h new file mode 100644 index 000000000..295da0fcd --- /dev/null +++ b/libc/nt/struct/arm64.h @@ -0,0 +1,20 @@ +#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_ARM64_H_ +#define COSMOPOLITAN_LIBC_NT_STRUCT_ARM64_H_ + +struct NtArm64RuntimeFunction { + uint32_t BeginAddress; + union { + uint32_t UnwindData; + struct { + uint32_t Flag : 2; + uint32_t FunctionLength : 11; + uint32_t RegF : 3; + uint32_t RegI : 4; + uint32_t H : 1; + uint32_t CR : 2; + uint32_t FrameSize : 9; + }; + }; +}; + +#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_ARM64_H_ */ diff --git a/libc/nt/struct/memextendedparameter.h b/libc/nt/struct/memextendedparameter.h index 6cd4d0f5d..5fdd3985c 100644 --- a/libc/nt/struct/memextendedparameter.h +++ b/libc/nt/struct/memextendedparameter.h @@ -9,26 +9,28 @@ #define kNtMemExtendedParameterPartitionHandle 3 #define kNtMemExtendedParameterUserPhysicalHandle 4 #define kNtMemExtendedParameterAttributeFlags 5 -#define kNtMemExtendedParameterMax 6 +#define kNtMemExtendedParameterImageMachine 6 +#define kNtMemExtendedParameterMax 7 #define kNtMemExtendedParameterGraphics 0x00000001 #define kNtMemExtendedParameterNonpaged 0x00000002 #define kNtMemExtendedParameterZeroPagesOptional 0x00000004 #define kNtMemExtendedParameterNonpagedLarge 0x00000008 #define kNtMemExtendedParameterNonpagedHuge 0x00000010 +#define kNtMemExtendedParameterSoftFaultPages 0x00000020 +#define kNtMemExtendedParameterEcCode 0x00000040 +#define kNtMemExtendedParameterImageNoHpat 0x00000080 struct NtMemExtendedParameter { - struct { - uint64_t Type : kNtMemExtendedParameterTypeBits; - uint64_t Reserved : 64 - kNtMemExtendedParameterTypeBits; - } DUMMYSTRUCTNAME; + uint8_t Type; + uint8_t Reserved[7]; union { uint64_t ULong64; void *Pointer; size_t Size; intptr_t Handle; unsigned ULong; - } DUMMYUNIONNAME; + }; }; #endif /* COSMOPOLITAN_LIBC_NT_STRUCT_MEMEXTENDEDPARAMETER_H_ */ diff --git a/tool/build/elf2pe.c b/tool/build/elf2pe.c index 485ada109..784525584 100644 --- a/tool/build/elf2pe.c +++ b/tool/build/elf2pe.c @@ -229,6 +229,17 @@ static struct Segment *NewSegment(void) { return s; } +static int ConvertElfMachineToPe(struct Elf *elf) { + switch (elf->ehdr->e_machine) { + case EM_NEXGEN32E: + return kNtImageFileMachineNexgen32e; + case EM_AARCH64: + return kNtImageFileMachineArm64; + default: + Die(elf->path, "unsupported e_machine"); + } +} + static Elf64_Addr RelocateVaddrWithinSegment(struct Elf *elf, Elf64_Addr vaddr_old, struct Segment *segment) { @@ -811,7 +822,17 @@ static uint32_t GetPeSectionCharacteristics(struct Segment *s) { // originally in the elf image that ld linked. in order for this to work // the executable needs to be linked in `ld -q` mode, since it'll retain // the .rela sections we'll need later to fixup the binary. -static struct ImagePointer GeneratePe(struct Elf *elf, char *fp, int64_t vp) { +static struct ImagePointer GeneratePe(struct Elf *elf, char *fp) { + + int64_t vp = 0; + Elf64_Phdr *phdr; + for (int i = 0; i < elf->ehdr->e_phnum; ++i) { + if ((phdr = GetElfProgramHeaderAddress(elf->ehdr, elf->size, i)) && + phdr->p_type == PT_LOAD) { + vp = phdr->p_vaddr; + break; + } + } Elf64_Sym *entry; if (!(entry = FindGlobal(elf, "__win32_start")) && @@ -855,7 +876,7 @@ static struct ImagePointer GeneratePe(struct Elf *elf, char *fp, int64_t vp) { struct NtImageFileHeader *filehdr; filehdr = (struct NtImageFileHeader *)fp; fp += sizeof(struct NtImageFileHeader); - filehdr->Machine = kNtImageFileMachineNexgen32e; + filehdr->Machine = ConvertElfMachineToPe(elf); filehdr->TimeDateStamp = 1690072024; filehdr->Characteristics = kNtPeFileExecutableImage | kNtImageFileLargeAddressAware | @@ -873,7 +894,9 @@ static struct ImagePointer GeneratePe(struct Elf *elf, char *fp, int64_t vp) { opthdr->FileAlignment = 512; opthdr->SectionAlignment = MAX(4096, elf->align); opthdr->MajorOperatingSystemVersion = 6; + opthdr->MinorOperatingSystemVersion = 2; opthdr->MajorSubsystemVersion = 6; + opthdr->MinorSubsystemVersion = 2; opthdr->Subsystem = kNtImageSubsystemWindowsCui; opthdr->DllCharacteristics = kNtImageDllcharacteristicsNxCompat | kNtImageDllcharacteristicsHighEntropyVa; @@ -1116,7 +1139,7 @@ int main(int argc, char *argv[]) { // translate executable struct Elf *elf = OpenElf(argv[optind]); char *buf = Memalign(MAX_ALIGN, 134217728); - struct ImagePointer ip = GeneratePe(elf, buf, 0x00400000); + struct ImagePointer ip = GeneratePe(elf, buf); if (creat(outpath, 0755) == -1) DieSys(elf->path); Pwrite(3, buf, ip.fp - buf, 0); diff --git a/tool/build/elf2pe.h b/tool/build/elf2pe.h index 53312b1a2..49cb8e71e 100644 --- a/tool/build/elf2pe.h +++ b/tool/build/elf2pe.h @@ -1,8 +1,8 @@ #ifndef COSMOPOLITAN_TOOL_BUILD_ELF2PE_H_ #define COSMOPOLITAN_TOOL_BUILD_ELF2PE_H_ -#define __dll_import(DLL, RET, FUNC, ARGS) \ - extern RET(*const __attribute__((__ms_abi__, __weak__)) FUNC) \ +#define __dll_import(DLL, RET, FUNC, ARGS) \ + extern RET(*const __msabi __attribute__((__weak__)) FUNC) \ ARGS __asm__("\"dll$" DLL "$" #FUNC "\"") #endif /* COSMOPOLITAN_TOOL_BUILD_ELF2PE_H_ */ diff --git a/tool/hello/BUILD.mk b/tool/hello/BUILD.mk index 80648401c..bb2cbb1cd 100644 --- a/tool/hello/BUILD.mk +++ b/tool/hello/BUILD.mk @@ -79,7 +79,7 @@ o/$(MODE)/tool/hello/hello-pe.ape: \ # elf2pe can generate binaries that don't have dll imports o/$(MODE)/tool/hello/life-pe.dbg: \ o/$(MODE)/tool/hello/life-pe.o - @$(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) -q -e WinMain + @$(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) -q -e WinMain #-Ttext-segment=0x140000000 o/$(MODE)/tool/hello/life-pe.ape: \ o/$(MODE)/tool/hello/life-pe.dbg \ o/$(MODE)/tool/build/elf2pe diff --git a/tool/hello/hello-pe.c b/tool/hello/hello-pe.c index c54ce5e08..47198ee76 100644 --- a/tool/hello/hello-pe.c +++ b/tool/hello/hello-pe.c @@ -7,6 +7,7 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif +#include "libc/nt/thunk/msabi.h" #include "tool/build/elf2pe.h" #define STD_OUTPUT_HANDLE -11u @@ -15,7 +16,7 @@ __dll_import("kernel32.dll", long, GetStdHandle, (unsigned)); __dll_import("kernel32.dll", int, WriteFile, (long, const void *, unsigned, unsigned *, void *)); -__attribute__((__ms_abi__)) long WinMain(void) { +__msabi long WinMain(void) { WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "hello world\n", 12, 0, 0); return 0; } diff --git a/tool/hello/life-pe.c b/tool/hello/life-pe.c index 6f6098d1d..5786749af 100644 --- a/tool/hello/life-pe.c +++ b/tool/hello/life-pe.c @@ -7,7 +7,8 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif +#include "libc/nt/thunk/msabi.h" -__attribute__((__ms_abi__)) long WinMain(void) { +__msabi long WinMain(void) { return 42 << 8; }