#include "runtime.h"
#include "alloc.h"
#include "genesis/primitive-objects.h"
+#include "dynbind.h"
#include <sys/types.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>
-/* KLUDGE: Avoid double definition of boolean by rpcndr.h included via
- * shlobj.h.
- *
- * FIXME: We should probably arrange to use the rpcndr.h boolean on Windows,
- * or get rid of our own boolean type.
- */
-#define boolean rpcndr_boolean
-#include <shlobj.h>
-#undef boolean
-
#include <math.h>
#include <float.h>
return 0;
}
- if ((mem_info.State == MEM_RESERVE) && (mem_info.RegionSize >=len)) return addr;
+ if ((mem_info.State == MEM_RESERVE) && (mem_info.RegionSize >=len)) {
+ /* It would be correct to return here. However, support for Wine
+ * is beneficial, and Wine has a strange behavior in this
+ * department. It reports all memory below KERNEL32.DLL as
+ * reserved, but disallows MEM_COMMIT.
+ *
+ * Let's work around it: reserve the region we need for a second
+ * time. The second reservation is documented to fail on normal NT
+ * family, but it will succeed on Wine if this region is
+ * actually free.
+ */
+ VirtualAlloc(addr, len, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ /* If it is wine, the second call has succeded, and now the region
+ * is really reserved. */
+ return addr;
+ }
if (mem_info.State == MEM_RESERVE) {
fprintf(stderr, "validation of reserved space too short.\n");
return 0;
}
-/*
- * any OS-dependent special low-level handling for signals
- */
-
/* A tiny bit of interrupt.c state we want our paws on. */
extern boolean internal_errors_enabled;
+#ifdef LISP_FEATURE_UD2_BREAKPOINTS
+#define IS_TRAP_EXCEPTION(exception_record, context) \
+ (((exception_record)->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) && \
+ (((unsigned short *)((context)->Eip))[0] == 0x0b0f))
+#define TRAP_CODE_WIDTH 2
+#else
+#define IS_TRAP_EXCEPTION(exception_record, context) \
+ ((exception_record)->ExceptionCode == EXCEPTION_BREAKPOINT)
+#define TRAP_CODE_WIDTH 1
+#endif
+
/*
* A good explanation of the exception handling semantics is
* http://win32assembly.online.fr/Exceptionhandling.html .
handle_exception(EXCEPTION_RECORD *exception_record,
struct lisp_exception_frame *exception_frame,
CONTEXT *context,
- void *dc) /* FIXME: What's dc again? */
+ void *dispatcher_context)
{
+ if (exception_record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) {
+ /* If we're being unwound, be graceful about it. */
+
+ /* Undo any dynamic bindings. */
+ unbind_to_here(exception_frame->bindstack_pointer,
+ arch_os_get_current_thread());
+
+ return ExceptionContinueSearch;
+ }
+
/* For EXCEPTION_ACCESS_VIOLATION only. */
void *fault_address = (void *)exception_record->ExceptionInformation[1];
return ExceptionContinueExecution;
}
- if (exception_record->ExceptionCode == EXCEPTION_BREAKPOINT) {
- /* Pick off sigtrap case first. */
-
- extern void sigtrap_handler(int signal, siginfo_t *info, void *context);
- /*
- * Unlike some other operating systems, Win32 leaves EIP
- * pointing to the breakpoint instruction.
- */
- context->Eip++;
-
- sigtrap_handler(0, NULL, context);
-
- return ExceptionContinueExecution;
+ if (IS_TRAP_EXCEPTION(exception_record, context)) {
+ unsigned char trap;
+ /* This is just for info in case the monitor wants to print an
+ * approximation. */
+ current_control_stack_pointer =
+ (lispobj *)*os_context_sp_addr(context);
+ /* Unlike some other operating systems, Win32 leaves EIP
+ * pointing to the breakpoint instruction. */
+ context->Eip += TRAP_CODE_WIDTH;
+ /* Now EIP points just after the INT3 byte and aims at the
+ * 'kind' value (eg trap_Cerror). */
+ trap = *(unsigned char *)(*os_context_pc_addr(context));
+ handle_trap(context, trap);
+ /* Done, we're good to go! */
+ return ExceptionContinueExecution;
}
else if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
(is_valid_lisp_addr(fault_address) ||
*/
if (internal_errors_enabled) {
- lispobj context_sap;
- lispobj exception_record_sap;
+ lispobj context_sap;
+ lispobj exception_record_sap;
/* We're making the somewhat arbitrary decision that having
* internal errors enabled means that lisp has sufficient
* aren't supposed to happen during cold init or reinit
* anyway. */
- fake_foreign_function_call(context);
+ fake_foreign_function_call(context);
- /* Allocate the SAP objects while the "interrupts" are still
- * disabled. */
- context_sap = alloc_sap(context);
- exception_record_sap = alloc_sap(exception_record);
+ /* Allocate the SAP objects while the "interrupts" are still
+ * disabled. */
+ context_sap = alloc_sap(context);
+ exception_record_sap = alloc_sap(exception_record);
- /* The exception system doesn't automatically clear pending
- * exceptions, so we lose as soon as we execute any FP
- * instruction unless we do this first. */
- _clearfp();
+ /* The exception system doesn't automatically clear pending
+ * exceptions, so we lose as soon as we execute any FP
+ * instruction unless we do this first. */
+ _clearfp();
- /* Call into lisp to handle things. */
- funcall2(SymbolFunction(HANDLE_WIN32_EXCEPTION), context_sap,
- exception_record_sap);
+ /* Call into lisp to handle things. */
+ funcall2(StaticSymbolFunction(HANDLE_WIN32_EXCEPTION), context_sap,
+ exception_record_sap);
- /* If Lisp doesn't nlx, we need to put things back. */
- undo_fake_foreign_function_call(context);
+ /* If Lisp doesn't nlx, we need to put things back. */
+ undo_fake_foreign_function_call(context);
/* FIXME: HANDLE-WIN32-EXCEPTION should be allowed to decline */
return ExceptionContinueExecution;
fflush(stderr);
fake_foreign_function_call(context);
- lose("fake_foreign_function_call fell through");
+ lose("Exception too early in cold init, cannot continue.");
/* FIXME: WTF? How are we supposed to end up here? */
return ExceptionContinueSearch;
Sleep(0);
WriteFile(0, 0, 0, 0, 0);
_get_osfhandle(0);
+ _rmdir(0);
_pipe(0,0,0);
access(0,0);
- acos(0);
- asin(0);
close(0);
- cosh(0);
dup(0);
- hypot(0, 0);
isatty(0);
- sinh(0);
strerror(42);
write(0, 0, 0);
RtlUnwind(0, 0, 0, 0);
+ MapViewOfFile(0,0,0,0,0);
+ UnmapViewOfFile(0);
+ FlushViewOfFile(0,0);
#ifndef LISP_FEATURE_SB_UNICODE
CreateDirectoryA(0,0);
+ CreateFileMappingA(0,0,0,0,0,0);
+ CreateFileA(0,0,0,0,0,0,0);
GetComputerNameA(0, 0);
GetCurrentDirectoryA(0,0);
GetEnvironmentVariableA(0, 0, 0);
+ GetFileAttributesA(0);
GetVersionExA(0);
MoveFileA(0,0);
SHGetFolderPathA(0, 0, 0, 0, 0);
SetEnvironmentVariableA(0, 0);
#else
CreateDirectoryW(0,0);
+ CreateFileMappingW(0,0,0,0,0,0);
+ CreateFileW(0,0,0,0,0,0,0);
FormatMessageW(0, 0, 0, 0, 0, 0, 0);
GetComputerNameW(0, 0);
GetCurrentDirectoryW(0,0);
GetEnvironmentVariableW(0, 0, 0);
+ GetFileAttributesW(0);
GetVersionExW(0);
MoveFileW(0,0);
SHGetFolderPathW(0, 0, 0, 0, 0);
}
char *
-os_get_runtime_executable_path()
+os_get_runtime_executable_path(int external)
{
char path[MAX_PATH + 1];
DWORD bufsize = sizeof(path);