3 funcs needed for some mwcc compilers (#22)

* 3 funcs needed for some mwcc compilers

* some PR feedback

* lots more via pair programming with Simon

* cleanup, add test dir as an include dir for tests

* bugfix
This commit is contained in:
Ethan Roseman 2022-09-24 23:59:30 +09:00 committed by GitHub
parent ffe30a626b
commit 6de4e9a163
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 210 additions and 43 deletions

View File

@ -23,7 +23,7 @@ jobs:
run: |
wget https://cdn.discordapp.com/attachments/727918646525165659/917185027656286218/GC_WII_COMPILERS.zip
unzip GC_WII_COMPILERS.zip
MWCIncludes=. build/wibo GC/2.7/mwcceppc.exe -c test/test.c
MWCIncludes=. build/wibo GC/2.7/mwcceppc.exe -c test/test.c -Itest
file test.o
- name: Upload build

View File

@ -16,6 +16,7 @@ add_executable(wibo
dll/user32.cpp
dll/version.cpp
files.cpp
handles.cpp
loader.cpp
main.cpp
)

View File

@ -1,12 +1,15 @@
#include "common.h"
#include "files.h"
#include "handles.h"
#include <algorithm>
#include <ctype.h>
#include <filesystem>
#include <fnmatch.h>
#include <string>
#include <malloc.h>
#include <stdarg.h>
#include <system_error>
#include <sys/mman.h>
#include <sys/stat.h>
namespace kernel32 {
@ -85,6 +88,17 @@ namespace kernel32 {
}
}
int64_t getFileSize(void* hFile) {
FILE *fp = files::fpFromHandle(hFile);
struct stat64 st;
fflush(fp);
if (fstat64(fileno(fp), &st) == -1 || !S_ISREG(st.st_mode)) {
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND (?)
return -1; // INVALID_FILE_SIZE
}
return st.st_size;
}
uint32_t WIN_FUNC GetLastError() {
return wibo::lastError;
}
@ -384,9 +398,14 @@ namespace kernel32 {
int WIN_FUNC CloseHandle(void *hObject) {
DEBUG_LOG("CloseHandle %p\n", hObject);
FILE *fp = files::fpFromHandle(hObject, true);
if (fp && fp != stdin && fp != stdout && fp != stderr) {
fclose(fp);
auto data = handles::dataFromHandle(hObject, true);
if (data.type == handles::TYPE_FILE) {
FILE *fp = (FILE *) data.ptr;
if (!(fp == stdin || fp == stdout || fp == stderr)) {
fclose(fp);
}
} else if (data.type == handles::TYPE_MAPPED) {
munmap(data.ptr, data.size);
}
return 1;
}
@ -442,6 +461,41 @@ namespace kernel32 {
CharType cAlternateFileName[14];
};
struct FindFirstFileHandle {
std::filesystem::directory_iterator it;
std::string pattern;
};
bool findNextFile(FindFirstFileHandle *handle) {
while (handle->it != std::filesystem::directory_iterator()) {
std::filesystem::path path = *handle->it;
if (fnmatch(handle->pattern.c_str(), path.filename().c_str(), 0) == 0) {
return true;
}
handle->it++;
}
return false;
}
void setFindFileDataFromPath(WIN32_FIND_DATA<char>* data, const std::filesystem::path &path) {
auto status = std::filesystem::status(path);
uint64_t fileSize = 0;
data->dwFileAttributes = 0;
if (std::filesystem::is_directory(status)) {
data->dwFileAttributes |= 0x10;
}
if (std::filesystem::is_regular_file(status)) {
data->dwFileAttributes |= 0x80;
fileSize = std::filesystem::file_size(path);
}
data->nFileSizeHigh = (uint32_t)(fileSize >> 32);
data->nFileSizeLow = (uint32_t)fileSize;
auto fileName = path.filename().string();
assert(fileName.size() < 260);
strcpy(data->cFileName, fileName.c_str());
strcpy(data->cAlternateFileName, "8P3FMTFN.BAD");
}
void *WIN_FUNC FindFirstFileA(const char *lpFileName, WIN32_FIND_DATA<char> *lpFindFileData) {
// This should handle wildcards too, but whatever.
auto path = files::pathFromWindows(lpFileName);
@ -453,23 +507,40 @@ namespace kernel32 {
auto status = std::filesystem::status(path);
if (status.type() == std::filesystem::file_type::regular) {
lpFindFileData->dwFileAttributes = 0x80; // FILE_ATTRIBUTE_NORMAL
auto fileSize = std::filesystem::file_size(path);
lpFindFileData->nFileSizeHigh = (uint32_t)(fileSize >> 32);
lpFindFileData->nFileSizeLow = (uint32_t)fileSize;
auto fileName = path.filename().string();
assert(fileName.size() < 260);
strcpy(lpFindFileData->cFileName, fileName.c_str());
strcpy(lpFindFileData->cAlternateFileName, "8P3FMTFN.BAD");
setFindFileDataFromPath(lpFindFileData, path);
return (void *) 1;
}
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND
return (void *) 0xFFFFFFFF;
FindFirstFileHandle *handle = new FindFirstFileHandle();
std::filesystem::directory_iterator it(path.parent_path());
handle->it = it;
handle->pattern = path.filename().string();
if (!findNextFile(handle)) {
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND
delete handle;
return (void *) 0xFFFFFFFF;
}
setFindFileDataFromPath(lpFindFileData, *handle->it++);
return handle;
}
int WIN_FUNC FindNextFileA(void *hFindFile, WIN32_FIND_DATA<char> *lpFindFileData) {
FindFirstFileHandle *handle = (FindFirstFileHandle *) hFindFile;
if (!findNextFile(handle)) {
return 0;
}
setFindFileDataFromPath(lpFindFileData, *handle->it++);
return 1;
}
int WIN_FUNC FindClose(void *hFindFile) {
DEBUG_LOG("FindClose\n");
if (hFindFile != (void *) 1) {
delete (FindFirstFileHandle *)hFindFile;
}
return 1;
}
@ -580,6 +651,55 @@ namespace kernel32 {
}
}
void *WIN_FUNC CreateFileMappingA(
void *hFile,
void *lpFileMappingAttributes,
unsigned int flProtect,
unsigned int dwMaximumSizeHigh,
unsigned int dwMaximumSizeLow,
const char *lpName) {
DEBUG_LOG("CreateFileMappingA(%p, %p, %u, %u, %u, %s)\n", hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName);
int64_t size = (int64_t) dwMaximumSizeHigh << 32 | dwMaximumSizeLow;
void* mmapped;
if (hFile == (void*) -1) { // INVALID_HANDLE_VALUE
mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
} else {
int fd = fileno(files::fpFromHandle(hFile));
if (size == 0) {
size = getFileSize(hFile);
if (size == -1) {
return (void*) -1;
}
}
mmapped = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
}
assert(mmapped != MAP_FAILED);
return handles::allocDataHandle({handles::TYPE_MAPPED, mmapped, (unsigned int) size});
}
void *WIN_FUNC MapViewOfFile(
void *hFileMappingObject,
unsigned int dwDesiredAccess,
unsigned int dwFileOffsetHigh,
unsigned int dwFileOffsetLow,
unsigned int dwNumberOfBytesToMap) {
DEBUG_LOG("MapViewOfFile(%p, %u, %u, %u, %u)\n", hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
handles::Data data = handles::dataFromHandle(hFileMappingObject, false);
assert(data.type == handles::TYPE_MAPPED);
return (void*)((unsigned int) data.ptr + dwFileOffsetLow);
}
int WIN_FUNC UnmapViewOfFile(void *lpBaseAddress) {
DEBUG_LOG("UnmapViewOfFile(%p)\n", lpBaseAddress);
return 1;
}
int WIN_FUNC DeleteFileA(const char* lpFileName) {
std::string path = files::pathFromWindows(lpFileName);
DEBUG_LOG("DeleteFileA %s (%s)\n", lpFileName, path.c_str());
@ -637,18 +757,15 @@ namespace kernel32 {
unsigned int WIN_FUNC GetFileSize(void *hFile, unsigned int *lpFileSizeHigh) {
DEBUG_LOG("GetFileSize\n");
struct stat64 st;
FILE *fp = files::fpFromHandle(hFile);
fflush(fp);
if (fstat64(fileno(fp), &st) == -1 || !S_ISREG(st.st_mode)) {
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND (?)
return ~0u; // INVALID_FILE_SIZE
int64_t size = getFileSize(hFile);
if (size == -1) {
return 0xFFFFFFFF; // INVALID_FILE_SIZE
}
DEBUG_LOG("-> %ld\n", st.st_size);
DEBUG_LOG("-> %ld\n", size);
if (lpFileSizeHigh != nullptr) {
*lpFileSizeHigh = st.st_size >> 32;
*lpFileSizeHigh = size >> 32;
}
return st.st_size;
return size;
}
/*
@ -1478,11 +1595,15 @@ void *wibo::resolveKernel32(const char *name) {
// fileapi.h
if (strcmp(name, "GetFullPathNameA") == 0) return (void *) kernel32::GetFullPathNameA;
if (strcmp(name, "FindFirstFileA") == 0) return (void *) kernel32::FindFirstFileA;
if (strcmp(name, "FindNextFileA") == 0) return (void *) kernel32::FindNextFileA;
if (strcmp(name, "FindClose") == 0) return (void *) kernel32::FindClose;
if (strcmp(name, "GetFileAttributesA") == 0) return (void *) kernel32::GetFileAttributesA;
if (strcmp(name, "WriteFile") == 0) return (void *) kernel32::WriteFile;
if (strcmp(name, "ReadFile") == 0) return (void *) kernel32::ReadFile;
if (strcmp(name, "CreateFileA") == 0) return (void *) kernel32::CreateFileA;
if (strcmp(name, "CreateFileMappingA") == 0) return (void *) kernel32::CreateFileMappingA;
if (strcmp(name, "MapViewOfFile") == 0) return (void *) kernel32::MapViewOfFile;
if (strcmp(name, "UnmapViewOfFile") == 0) return (void *) kernel32::UnmapViewOfFile;
if (strcmp(name, "DeleteFileA") == 0) return (void *) kernel32::DeleteFileA;
if (strcmp(name, "SetFilePointer") == 0) return (void *) kernel32::SetFilePointer;
if (strcmp(name, "SetEndOfFile") == 0) return (void *) kernel32::SetEndOfFile;

View File

@ -1,9 +1,10 @@
#include "common.h"
#include "files.h"
#include "handles.h"
#include <algorithm>
#include <map>
namespace files {
static FILE *handleFps[0x10000];
static void *stdinHandle;
static void *stdoutHandle;
@ -68,28 +69,19 @@ namespace files {
}
FILE *fpFromHandle(void *handle, bool pop) {
uintptr_t index = (uintptr_t)handle;
if (index > 0 && index < 0x10000) {
FILE *ret = handleFps[index];
if (pop)
handleFps[index] = 0;
return ret;
}
if (pop)
handles::Data data = handles::dataFromHandle(handle, pop);
if (data.type == handles::TYPE_FILE) {
return (FILE*)data.ptr;
} else if (data.type == handles::TYPE_UNUSED && pop) {
return 0;
printf("Invalid file handle %p\n", handle);
assert(0);
} else {
printf("Invalid file handle %p\n", handle);
assert(0);
}
}
void *allocFpHandle(FILE *fp) {
for (int i = 1; i < 0x10000; i++) {
if (!handleFps[i]) {
handleFps[i] = fp;
return (void*)i;
}
}
printf("Out of file handles\n");
assert(0);
return handles::allocDataHandle(handles::Data{handles::TYPE_FILE, fp, 0});
}
void *getStdHandle(uint32_t nStdHandle) {

32
handles.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "common.h"
#include "handles.h"
#include <utility>
namespace handles {
static Data datas[0x10000];
Data dataFromHandle(void *handle, bool pop) {
uintptr_t index = (uintptr_t)handle;
if (index > 0 && index < 0x10000) {
Data ret = datas[index];
if (pop)
datas[index] = Data{};
return ret;
}
if (pop)
return Data{};
printf("Invalid file handle %p\n", handle);
assert(0);
}
void *allocDataHandle(Data data) {
for (int i = 1; i < 0x10000; i++) {
if (datas[i].type == TYPE_UNUSED) {
datas[i] = data;
return (void*)i;
}
}
printf("Out of handles\n");
assert(0);
}
}

18
handles.h Normal file
View File

@ -0,0 +1,18 @@
#include <stdlib.h>
namespace handles {
enum Type {
TYPE_UNUSED,
TYPE_FILE,
TYPE_MAPPED,
};
struct Data {
Type type = TYPE_UNUSED;
void *ptr;
size_t size;
};
Data dataFromHandle(void *handle, bool pop);
void *allocDataHandle(Data data);
}

1
test/another.inc.c Normal file
View File

@ -0,0 +1 @@
#define SOMETHING 3

View File

@ -1,6 +1,8 @@
#include "another.inc.c"
float apple = 3.0f;
float banana = 65.32f;
int something(void) {
return (int)(apple * banana) % 11;
return (int)(apple * banana) % 11 + SOMETHING;
}