mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
Merge pull request #171 from joshuawarner32/master
Flatten "vm" dir and split signal handling out of vm::System
This commit is contained in:
commit
3912f2c0e4
@ -11,11 +11,11 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/zone.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
@ -11,7 +11,7 @@
|
||||
#ifndef AVIAN_CODEGEN_COMPILER_H
|
||||
#define AVIAN_CODEGEN_COMPILER_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/zone.h"
|
||||
#include "assembler.h"
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef HEAP_H
|
||||
#define HEAP_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/allocator.h"
|
||||
|
||||
namespace vm {
|
82
include/avian/system/signal.h
Normal file
82
include/avian/system/signal.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef AVIAN_SYSTEM_SIGNAL_H
|
||||
#define AVIAN_SYSTEM_SIGNAL_H
|
||||
|
||||
#include <avian/common.h>
|
||||
|
||||
namespace avian {
|
||||
namespace system {
|
||||
|
||||
// Crash the process.
|
||||
// On posix, the just calls abort. On windows, we dereference a null pointer in
|
||||
// order to trigger the crash dump logic.
|
||||
NO_RETURN void crash();
|
||||
|
||||
// Registrar for unix-like "signals" (implemented with structured exceptions on windows).
|
||||
// TODO: remove dependence on generated code having a well-known "thread"
|
||||
// register. Use a thread-local variable instead.
|
||||
class SignalRegistrar {
|
||||
public:
|
||||
class Handler {
|
||||
public:
|
||||
// This function receives state information about the paused thread.
|
||||
// Returns whether to resume execution after the failure point.
|
||||
virtual bool handleSignal(void** ip,
|
||||
void** frame,
|
||||
void** stack,
|
||||
void** thread) = 0;
|
||||
};
|
||||
|
||||
enum Signal {
|
||||
// "Segmentation fault" exceptions (mostly null pointer dereference, but
|
||||
// generally access to any non-mapped memory)
|
||||
SegFault,
|
||||
|
||||
DivideByZero,
|
||||
};
|
||||
|
||||
SignalRegistrar();
|
||||
~SignalRegistrar();
|
||||
|
||||
// Register a handler for the given signal.
|
||||
// After this method call, anytime the given signal is raised, it will be
|
||||
// handled by the given handler.
|
||||
// Returns true upon success, false upon failure
|
||||
bool registerHandler(Signal signal, Handler* handler);
|
||||
|
||||
// Unregister a handler for the given signal.
|
||||
// After this method call, the given signal will no longer be handled (or,
|
||||
// rather, it go back to being handled by whatever was registered to handle it
|
||||
// before us).
|
||||
// Returns true upon success, false upon failure
|
||||
bool unregisterHandler(Signal signal);
|
||||
|
||||
// Set the directory that a crash dump will be written to should an unhandled
|
||||
// exception be thrown.
|
||||
// Note: this only currently does anything on windows.
|
||||
// TODO: move this out of this class, into a separate "CrashDumper" class or
|
||||
// somesuch.
|
||||
void setCrashDumpDirectory(const char* crashDumpDirectory);
|
||||
|
||||
// This is internal, implementation-specific data. It's declared in the
|
||||
// specific implementation.
|
||||
struct Data;
|
||||
|
||||
private:
|
||||
|
||||
Data* data;
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace avian
|
||||
|
||||
#endif
|
@ -98,12 +98,6 @@ class System : public avian::util::Aborter {
|
||||
virtual void disposeAll() = 0;
|
||||
};
|
||||
|
||||
class SignalHandler {
|
||||
public:
|
||||
virtual bool handleSignal(void** ip, void** frame, void** stack,
|
||||
void** thread) = 0;
|
||||
};
|
||||
|
||||
class MonitorResource {
|
||||
public:
|
||||
MonitorResource(System::Thread* t, System::Monitor* m): t(t), m(m) {
|
||||
@ -131,8 +125,7 @@ class System : public avian::util::Aborter {
|
||||
virtual Status make(Mutex**) = 0;
|
||||
virtual Status make(Monitor**) = 0;
|
||||
virtual Status make(Local**) = 0;
|
||||
virtual Status handleSegFault(SignalHandler* handler) = 0;
|
||||
virtual Status handleDivideByZero(SignalHandler* handler) = 0;
|
||||
|
||||
virtual Status visit(Thread* thread, Thread* target,
|
||||
ThreadVisitor* visitor) = 0;
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
@ -193,7 +186,7 @@ sysAbort(System* s)
|
||||
// #endif // not NDEBUG
|
||||
|
||||
AVIAN_EXPORT System*
|
||||
makeSystem(const char* crashDumpDirectory);
|
||||
makeSystem();
|
||||
|
||||
} // namespace vm
|
||||
|
14
makefile
14
makefile
@ -90,6 +90,12 @@ ifneq (,$(filter mingw32 cygwin,$(build-platform)))
|
||||
path-separator = ;
|
||||
endif
|
||||
|
||||
target-path-separator = :
|
||||
|
||||
ifeq ($(platform),windows)
|
||||
target-path-separator = ;
|
||||
endif
|
||||
|
||||
library-path-variable = LD_LIBRARY_PATH
|
||||
|
||||
ifeq ($(build-platform),darwin)
|
||||
@ -1108,7 +1114,8 @@ vm-depends := $(generated-code) \
|
||||
$(shell find src include -name '*.h' -or -name '*.inc.cpp')
|
||||
|
||||
vm-sources = \
|
||||
$(src)/vm/system/$(system).cpp \
|
||||
$(src)/system/$(system).cpp \
|
||||
$(src)/system/$(system)/signal.cpp \
|
||||
$(src)/finder.cpp \
|
||||
$(src)/machine.cpp \
|
||||
$(src)/util.cpp \
|
||||
@ -1239,7 +1246,8 @@ boot-object = $(build)/boot.o
|
||||
generator-depends := $(wildcard $(src)/*.h)
|
||||
generator-sources = \
|
||||
$(src)/tools/type-generator/main.cpp \
|
||||
$(src)/vm/system/$(build-system).cpp \
|
||||
$(src)/system/$(build-system).cpp \
|
||||
$(src)/system/$(build-system)/signal.cpp \
|
||||
$(src)/finder.cpp
|
||||
|
||||
ifneq ($(lzma),)
|
||||
@ -1525,7 +1533,7 @@ endif
|
||||
$(build)/run-tests.sh: $(test-classes) makefile $(build)/extra-dir/multi-classpath-test.txt $(build)/test/multi-classpath-test.txt
|
||||
echo 'cd $$(dirname $$0)' > $(@)
|
||||
echo "sh ./test.sh 2>/dev/null \\" >> $(@)
|
||||
echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test$(path-separator)extra-dir\" \\" >> $(@)
|
||||
echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test$(target-path-separator)extra-dir\" \\" >> $(@)
|
||||
echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@)
|
||||
echo "$(continuation-tests) $(tail-tests)" >> $(@)
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef VECTOR_H
|
||||
#define VECTOR_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/target.h"
|
||||
|
||||
#include <avian/util/math.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define FINDER_H
|
||||
|
||||
#include "avian/common.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/allocator.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "avian/lzma.h"
|
||||
#include "C/Types.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/allocator.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef LZMA_H
|
||||
#define LZMA_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/allocator.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -13,8 +13,9 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
#include "java-common.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/system/signal.h>
|
||||
#include <avian/heap/heap.h>
|
||||
#include "avian/finder.h"
|
||||
#include "avian/processor.h"
|
||||
#include "avian/constants.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define PROCESS_H
|
||||
|
||||
#include "avian/common.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/machine.h"
|
||||
#include "avian/constants.h"
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
||||
#define PROCESSOR_H
|
||||
|
||||
#include "avian/common.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/heap/heap.h>
|
||||
#include "bootimage.h"
|
||||
#include "avian/heapwalk.h"
|
||||
#include "avian/zone.h"
|
||||
@ -208,8 +208,10 @@ class Processor {
|
||||
}
|
||||
};
|
||||
|
||||
Processor*
|
||||
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures);
|
||||
Processor* makeProcessor(System* system,
|
||||
Allocator* allocator,
|
||||
const char* crashDumpDirectory,
|
||||
bool useNativeFeatures);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef ZONE_H
|
||||
#define ZONE_H
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/allocator.h"
|
||||
|
||||
#include <avian/util/math.h>
|
||||
|
@ -12,10 +12,10 @@
|
||||
|
||||
#include <avian/util/runtime-array.h>
|
||||
|
||||
#include <avian/vm/codegen/compiler.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/compiler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
#include "codegen/compiler/regalloc.h"
|
||||
#include "codegen/compiler/context.h"
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "codegen/compiler/context.h"
|
||||
#include "codegen/compiler/resource.h"
|
||||
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H
|
||||
#define AVIAN_CODEGEN_COMPILER_CONTEXT_H
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/compiler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/compiler.h>
|
||||
#include <avian/util/list.h>
|
||||
|
||||
#include "regalloc.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "codegen/compiler/context.h"
|
||||
#include "codegen/compiler/frame.h"
|
||||
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -13,8 +13,8 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
namespace avian {
|
||||
|
||||
@ -108,4 +108,4 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef AVIAN_CODEGEN_COMPILER_SITE_H
|
||||
#define AVIAN_CODEGEN_COMPILER_SITE_H
|
||||
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
|
||||
#include "codegen/compiler/value.h"
|
||||
#include "codegen/compiler/context.h"
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
#define AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/compiler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/compiler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
@ -81,4 +81,4 @@ Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0);
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H
|
||||
|
@ -8,7 +8,7 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -10,9 +10,9 @@
|
||||
|
||||
#include <avian/util/runtime-array.h>
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "block.h"
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include "avian/alloc-vector.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -13,8 +13,8 @@
|
||||
|
||||
#include "avian/target.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include "avian/alloc-vector.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||
|
@ -11,8 +11,8 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -8,9 +8,9 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
#include "avian/alloc-vector.h"
|
||||
#include <avian/util/abort.h>
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_CONTEXT_H
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include "avian/alloc-vector.h"
|
||||
|
||||
#ifdef powerpc
|
||||
|
@ -22,13 +22,13 @@
|
||||
#include <avian/util/abort.h>
|
||||
#include <avian/util/math.h>
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "block.h"
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "block.h"
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
#include "avian/alloc-vector.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
|
||||
namespace vm {
|
||||
class System;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H
|
||||
#define AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include <avian/util/abort.h>
|
||||
#include <avian/util/math.h>
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "encode.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
|
||||
#include "registers.h"
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "avian/zone.h"
|
||||
|
||||
#include <avian/util/abort.h>
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "fixup.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
namespace vm {
|
||||
class System;
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include <avian/util/abort.h>
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "operations.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
|
@ -15,8 +15,8 @@
|
||||
|
||||
#include <avian/util/abort.h>
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "encode.h"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
|
||||
#include "context.h"
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "avian/common.h"
|
||||
|
||||
#include <avian/vm/codegen/targets.h>
|
||||
#include <avian/codegen/targets.h>
|
||||
|
||||
#include "avian/environment.h"
|
||||
|
||||
|
@ -15,12 +15,12 @@
|
||||
#include "avian/target.h"
|
||||
#include "avian/arch.h"
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/compiler.h>
|
||||
#include <avian/vm/codegen/targets.h>
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/runtime.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/compiler.h>
|
||||
#include <avian/codegen/targets.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/runtime.h>
|
||||
|
||||
#include <avian/util/runtime-array.h>
|
||||
#include <avian/util/list.h>
|
||||
@ -43,6 +43,7 @@ vmJumpAndInvoke(void* thread, void* function, void* stack,
|
||||
unsigned frameSize);
|
||||
|
||||
using namespace avian::codegen;
|
||||
using namespace avian::system;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -8366,7 +8367,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
return r;
|
||||
}
|
||||
|
||||
class SignalHandler: public System::SignalHandler {
|
||||
class SignalHandler: public SignalRegistrar::Handler {
|
||||
public:
|
||||
SignalHandler(Machine::Type type, Machine::Root root, unsigned fixedSize):
|
||||
m(0), type(type), root(root), fixedSize(fixedSize) { }
|
||||
@ -8501,24 +8502,27 @@ class MyProcessor: public Processor {
|
||||
Thunk table;
|
||||
};
|
||||
|
||||
MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
roots(0),
|
||||
bootImage(0),
|
||||
heapImage(0),
|
||||
codeImage(0),
|
||||
codeImageSize(0),
|
||||
segFaultHandler(Machine::NullPointerExceptionType,
|
||||
Machine::NullPointerException,
|
||||
FixedSizeOfNullPointerException),
|
||||
divideByZeroHandler(Machine::ArithmeticExceptionType,
|
||||
Machine::ArithmeticException,
|
||||
FixedSizeOfArithmeticException),
|
||||
codeAllocator(s, 0, 0),
|
||||
callTableSize(0),
|
||||
useNativeFeatures(useNativeFeatures),
|
||||
compilationHandlers(0)
|
||||
MyProcessor(System* s,
|
||||
Allocator* allocator,
|
||||
const char* crashDumpDirectory,
|
||||
bool useNativeFeatures)
|
||||
: s(s),
|
||||
allocator(allocator),
|
||||
roots(0),
|
||||
bootImage(0),
|
||||
heapImage(0),
|
||||
codeImage(0),
|
||||
codeImageSize(0),
|
||||
segFaultHandler(Machine::NullPointerExceptionType,
|
||||
Machine::NullPointerException,
|
||||
FixedSizeOfNullPointerException),
|
||||
divideByZeroHandler(Machine::ArithmeticExceptionType,
|
||||
Machine::ArithmeticException,
|
||||
FixedSizeOfArithmeticException),
|
||||
codeAllocator(s, 0, 0),
|
||||
callTableSize(0),
|
||||
useNativeFeatures(useNativeFeatures),
|
||||
compilationHandlers(0)
|
||||
{
|
||||
thunkTable[compileMethodIndex] = voidPointer(local::compileMethod);
|
||||
thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod);
|
||||
@ -8540,6 +8544,8 @@ class MyProcessor: public Processor {
|
||||
// table.
|
||||
thunkTable[dummyIndex] = reinterpret_cast<void*>
|
||||
(static_cast<uintptr_t>(UINT64_C(0x5555555555555555)));
|
||||
|
||||
signals.setCrashDumpDirectory(crashDumpDirectory);
|
||||
}
|
||||
|
||||
virtual Thread*
|
||||
@ -8924,7 +8930,9 @@ class MyProcessor: public Processor {
|
||||
|
||||
compilationHandlers->dispose(allocator);
|
||||
|
||||
s->handleSegFault(0);
|
||||
signals.unregisterHandler(SignalRegistrar::SegFault);
|
||||
signals.unregisterHandler(SignalRegistrar::DivideByZero);
|
||||
signals.setCrashDumpDirectory(0);
|
||||
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
@ -9116,12 +9124,10 @@ class MyProcessor: public Processor {
|
||||
#endif
|
||||
|
||||
segFaultHandler.m = t->m;
|
||||
expect(t, t->m->system->success
|
||||
(t->m->system->handleSegFault(&segFaultHandler)));
|
||||
expect(t, signals.registerHandler(SignalRegistrar::SegFault, &segFaultHandler));
|
||||
|
||||
divideByZeroHandler.m = t->m;
|
||||
expect(t, t->m->system->success
|
||||
(t->m->system->handleDivideByZero(÷ByZeroHandler)));
|
||||
expect(t, signals.registerHandler(SignalRegistrar::DivideByZero, ÷ByZeroHandler));
|
||||
}
|
||||
|
||||
virtual void callWithCurrentContinuation(Thread* t, object receiver) {
|
||||
@ -9173,6 +9179,7 @@ class MyProcessor: public Processor {
|
||||
}
|
||||
|
||||
System* s;
|
||||
SignalRegistrar signals;
|
||||
Allocator* allocator;
|
||||
object roots;
|
||||
BootImage* bootImage;
|
||||
@ -10285,11 +10292,13 @@ codeAllocator(MyThread* t)
|
||||
|
||||
namespace vm {
|
||||
|
||||
Processor*
|
||||
makeProcessor(System* system, Allocator* allocator, bool useNativeFeatures)
|
||||
Processor* makeProcessor(System* system,
|
||||
Allocator* allocator,
|
||||
const char* crashDumpDirectory,
|
||||
bool useNativeFeatures)
|
||||
{
|
||||
return new (allocator->allocate(sizeof(local::MyProcessor)))
|
||||
local::MyProcessor(system, allocator, useNativeFeatures);
|
||||
local::MyProcessor(system, allocator, crashDumpDirectory, useNativeFeatures);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
@ -8,7 +8,7 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/util/string.h>
|
||||
#include <avian/util/runtime-array.h>
|
||||
#include <avian/util/list.h>
|
||||
|
@ -8,8 +8,8 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/heap/heap.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/common.h"
|
||||
#include "avian/arch.h"
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
details. */
|
||||
|
||||
#include "avian/common.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/system/signal.h>
|
||||
#include "avian/constants.h"
|
||||
#include "avian/machine.h"
|
||||
#include "avian/processor.h"
|
||||
@ -20,6 +21,7 @@
|
||||
#include <avian/util/list.h>
|
||||
|
||||
using namespace vm;
|
||||
using namespace avian::system;
|
||||
|
||||
namespace local {
|
||||
|
||||
@ -2959,9 +2961,11 @@ invoke(Thread* t, object method)
|
||||
|
||||
class MyProcessor: public Processor {
|
||||
public:
|
||||
MyProcessor(System* s, Allocator* allocator):
|
||||
s(s), allocator(allocator)
|
||||
{ }
|
||||
MyProcessor(System* s, Allocator* allocator, const char* crashDumpDirectory)
|
||||
: s(s), allocator(allocator)
|
||||
{
|
||||
signals.setCrashDumpDirectory(crashDumpDirectory);
|
||||
}
|
||||
|
||||
virtual vm::Thread*
|
||||
makeThread(Machine* m, object javaThread, vm::Thread* parent)
|
||||
@ -3260,21 +3264,25 @@ class MyProcessor: public Processor {
|
||||
|
||||
virtual void dispose() {
|
||||
allocator->free(this, sizeof(*this));
|
||||
signals.setCrashDumpDirectory(0);
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
SignalRegistrar signals;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Processor*
|
||||
makeProcessor(System* system, Allocator* allocator, bool)
|
||||
Processor* makeProcessor(System* system,
|
||||
Allocator* allocator,
|
||||
const char* crashDumpDirectory,
|
||||
bool)
|
||||
{
|
||||
return new (allocator->allocate(sizeof(local::MyProcessor)))
|
||||
local::MyProcessor(system, allocator);
|
||||
local::MyProcessor(system, allocator, crashDumpDirectory);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
@ -3878,7 +3878,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
|
||||
if (classpath == 0) classpath = ".";
|
||||
|
||||
System* s = makeSystem(crashDumpDirectory);
|
||||
System* s = makeSystem();
|
||||
Heap* h = makeHeap(s, heapLimit);
|
||||
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
||||
|
||||
@ -3913,7 +3913,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
Finder* af = makeFinder(s, h, classpath, bootLibrary);
|
||||
if(bootLibrary)
|
||||
free(bootLibrary);
|
||||
Processor* p = makeProcessor(s, h, true);
|
||||
Processor* p = makeProcessor(s, h, crashDumpDirectory, true);
|
||||
|
||||
const char** properties = static_cast<const char**>
|
||||
(h->allocate(sizeof(const char*) * propertyCount));
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "string.h"
|
||||
#include "jni.h"
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/finder.h"
|
||||
|
||||
#include <avian/util/runtime-array.h>
|
||||
@ -59,7 +59,7 @@ mainClass(const char* jar)
|
||||
{
|
||||
using namespace vm;
|
||||
|
||||
System* system = makeSystem(0);
|
||||
System* system = makeSystem();
|
||||
|
||||
class MyAllocator: public Allocator {
|
||||
public:
|
||||
|
@ -49,8 +49,9 @@
|
||||
#include "dirent.h"
|
||||
#include "sched.h"
|
||||
#include "avian/arch.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/system/signal.h>
|
||||
#include <avian/util/math.h>
|
||||
|
||||
|
||||
@ -78,29 +79,14 @@ class MutexResource {
|
||||
const int InvalidSignal = -1;
|
||||
const int VisitSignal = SIGUSR1;
|
||||
const unsigned VisitSignalIndex = 0;
|
||||
const int SegFaultSignal = SIGSEGV;
|
||||
const unsigned SegFaultSignalIndex = 1;
|
||||
const int InterruptSignal = SIGUSR2;
|
||||
const unsigned InterruptSignalIndex = 2;
|
||||
#ifdef __APPLE__
|
||||
const int AltSegFaultSignal = SIGBUS;
|
||||
#else
|
||||
const int AltSegFaultSignal = InvalidSignal;
|
||||
#endif
|
||||
const unsigned AltSegFaultSignalIndex = 3;
|
||||
const unsigned InterruptSignalIndex = 1;
|
||||
const int PipeSignal = SIGPIPE;
|
||||
const unsigned PipeSignalIndex = 4;
|
||||
const int DivideByZeroSignal = SIGFPE;
|
||||
const unsigned DivideByZeroSignalIndex = 5;
|
||||
const unsigned PipeSignalIndex = 2;
|
||||
|
||||
const int signals[] = { VisitSignal,
|
||||
SegFaultSignal,
|
||||
InterruptSignal,
|
||||
AltSegFaultSignal,
|
||||
PipeSignal,
|
||||
DivideByZeroSignal };
|
||||
const int signals[] = {VisitSignal, InterruptSignal, PipeSignal};
|
||||
|
||||
const unsigned SignalCount = 6;
|
||||
const unsigned SignalCount = 3;
|
||||
|
||||
class MySystem;
|
||||
MySystem* system;
|
||||
@ -123,7 +109,7 @@ pathOfExecutable(System* s, const char** retBuf, unsigned* size)
|
||||
CFURLRef url = CFBundleCopyExecutableURL(bundle);
|
||||
CFStringRef path = CFURLCopyPath(url);
|
||||
path = CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault,
|
||||
path, CFSTR(""));
|
||||
path, CFSTR(""));
|
||||
CFIndex pathSize = CFStringGetMaximumSizeOfFileSystemRepresentation(path);
|
||||
char* buffer = reinterpret_cast<char*>(allocate(s, pathSize));
|
||||
if (CFStringGetFileSystemRepresentation(path, buffer, pathSize)) {
|
||||
@ -606,32 +592,27 @@ class MySystem: public System {
|
||||
expect(this, system == 0);
|
||||
system = this;
|
||||
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
|
||||
registerHandler(&nullHandler, InterruptSignalIndex);
|
||||
registerHandler(&nullHandler, PipeSignalIndex);
|
||||
registerHandler(&nullHandler, VisitSignalIndex);
|
||||
expect(this, registerHandler(InterruptSignalIndex));
|
||||
expect(this, registerHandler(VisitSignalIndex));
|
||||
expect(this, registerHandler(PipeSignalIndex));
|
||||
|
||||
expect(this, make(&visitLock) == 0);
|
||||
}
|
||||
|
||||
int registerHandler(System::SignalHandler* handler, int index) {
|
||||
if (handler) {
|
||||
handlers[index] = handler;
|
||||
// Returns true on success, false on failure
|
||||
bool unregisterHandler(int index) {
|
||||
return sigaction(signals[index], oldHandlers + index, 0) == 0;
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = handleSignal;
|
||||
|
||||
return sigaction(signals[index], &sa, oldHandlers + index);
|
||||
} else if (handlers[index]) {
|
||||
handlers[index] = 0;
|
||||
return sigaction(signals[index], oldHandlers + index, 0);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
// Returns true on success, false on failure
|
||||
bool registerHandler(int index) {
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = handleSignal;
|
||||
|
||||
return sigaction(signals[index], &sa, oldHandlers + index) == 0;
|
||||
}
|
||||
|
||||
virtual void* tryAllocate(unsigned sizeInBytes) {
|
||||
@ -701,18 +682,6 @@ class MySystem: public System {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status handleSegFault(SignalHandler* handler) {
|
||||
Status s = registerHandler(handler, SegFaultSignalIndex);
|
||||
if (s == 0 and AltSegFaultSignal != InvalidSignal) {
|
||||
return registerHandler(handler, AltSegFaultSignalIndex);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
virtual Status handleDivideByZero(SignalHandler* handler) {
|
||||
return registerHandler(handler, DivideByZeroSignalIndex);
|
||||
}
|
||||
|
||||
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
|
||||
ThreadVisitor* visitor)
|
||||
{
|
||||
@ -931,25 +900,20 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
virtual void abort() {
|
||||
::abort();
|
||||
avian::system::crash();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
visitLock->dispose();
|
||||
|
||||
registerHandler(0, InterruptSignalIndex);
|
||||
registerHandler(0, VisitSignalIndex);
|
||||
registerHandler(0, PipeSignalIndex);
|
||||
expect(this, unregisterHandler(InterruptSignalIndex));
|
||||
expect(this, unregisterHandler(VisitSignalIndex));
|
||||
expect(this, unregisterHandler(PipeSignalIndex));
|
||||
system = 0;
|
||||
|
||||
::free(this);
|
||||
}
|
||||
|
||||
class NullSignalHandler: public SignalHandler {
|
||||
virtual bool handleSignal(void**, void**, void**, void**) { return false; }
|
||||
} nullHandler;
|
||||
|
||||
SignalHandler* handlers[SignalCount];
|
||||
struct sigaction oldHandlers[SignalCount];
|
||||
|
||||
ThreadVisitor* threadVisitor;
|
||||
@ -957,27 +921,16 @@ class MySystem: public System {
|
||||
System::Monitor* visitLock;
|
||||
};
|
||||
|
||||
void
|
||||
handleSignal(int signal, siginfo_t*, void* context)
|
||||
void handleSignal(int signal, siginfo_t*, void* context)
|
||||
{
|
||||
ucontext_t* c = static_cast<ucontext_t*>(context);
|
||||
|
||||
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
|
||||
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
|
||||
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
|
||||
void* link = reinterpret_cast<void*>(LINK_REGISTER(c));
|
||||
#ifdef FRAME_REGISTER
|
||||
void* frame = reinterpret_cast<void*>(FRAME_REGISTER(c));
|
||||
#else
|
||||
void* frame = 0;
|
||||
#endif
|
||||
|
||||
unsigned index;
|
||||
|
||||
switch (signal) {
|
||||
case VisitSignal: {
|
||||
index = VisitSignalIndex;
|
||||
|
||||
system->threadVisitor->visit(ip, stack, link);
|
||||
|
||||
System::Thread* t = system->visitTarget;
|
||||
@ -987,57 +940,6 @@ handleSignal(int signal, siginfo_t*, void* context)
|
||||
system->visitLock->notifyAll(t);
|
||||
} break;
|
||||
|
||||
case SegFaultSignal:
|
||||
case AltSegFaultSignal:
|
||||
case DivideByZeroSignal: {
|
||||
switch (signal) {
|
||||
case SegFaultSignal:
|
||||
index = SegFaultSignalIndex;
|
||||
break;
|
||||
|
||||
case AltSegFaultSignal:
|
||||
index = AltSegFaultSignalIndex;
|
||||
break;
|
||||
|
||||
case DivideByZeroSignal:
|
||||
index = DivideByZeroSignalIndex;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
bool jump = system->handlers[index]->handleSignal
|
||||
(&ip, &frame, &stack, &thread);
|
||||
|
||||
if (jump) {
|
||||
// I'd like to use setcontext here (and get rid of the
|
||||
// sigprocmask call), but it doesn't work on my Linux x86_64
|
||||
// system, and I can't tell from the documentation if it's even
|
||||
// supposed to work.
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, signal);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, 0);
|
||||
|
||||
vmJump(ip, frame, stack, thread, 0, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
case InterruptSignal: {
|
||||
index = InterruptSignalIndex;
|
||||
} break;
|
||||
|
||||
case PipeSignal: {
|
||||
index = PipeSignalIndex;
|
||||
} break;
|
||||
|
||||
default: abort();
|
||||
}
|
||||
|
||||
switch (signal) {
|
||||
case VisitSignal:
|
||||
case InterruptSignal:
|
||||
case PipeSignal:
|
||||
break;
|
||||
@ -1052,7 +954,7 @@ handleSignal(int signal, siginfo_t*, void* context)
|
||||
namespace vm {
|
||||
|
||||
AVIAN_EXPORT System*
|
||||
makeSystem(const char*)
|
||||
makeSystem()
|
||||
{
|
||||
return new (malloc(sizeof(MySystem))) MySystem();
|
||||
}
|
233
src/system/posix/signal.cpp
Normal file
233
src/system/posix/signal.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "signal.h"
|
||||
#include "sys/types.h"
|
||||
#ifdef __APPLE__
|
||||
#include "CoreFoundation/CoreFoundation.h"
|
||||
#include "sys/ucontext.h"
|
||||
#undef assert
|
||||
#elif defined(__ANDROID__)
|
||||
#include <asm/sigcontext.h> /* for sigcontext */
|
||||
#include <asm/signal.h> /* for stack_t */
|
||||
typedef struct ucontext {
|
||||
unsigned long uc_flags;
|
||||
struct ucontext* uc_link;
|
||||
stack_t uc_stack;
|
||||
struct sigcontext uc_mcontext;
|
||||
unsigned long uc_sigmask;
|
||||
} ucontext_t;
|
||||
#else
|
||||
#if defined __FreeBSD__
|
||||
#include "limits.h"
|
||||
#endif
|
||||
#include "ucontext.h"
|
||||
#endif
|
||||
|
||||
#include "avian/arch.h"
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/system/signal.h>
|
||||
|
||||
namespace avian {
|
||||
namespace system {
|
||||
|
||||
namespace posix {
|
||||
|
||||
|
||||
const int InvalidSignal = -1;
|
||||
const int SegFaultSignal = SIGSEGV;
|
||||
const unsigned SegFaultSignalIndex = 0;
|
||||
#ifdef __APPLE__
|
||||
const int AltSegFaultSignal = SIGBUS;
|
||||
#else
|
||||
const int AltSegFaultSignal = InvalidSignal;
|
||||
#endif
|
||||
const unsigned AltSegFaultSignalIndex = 1;
|
||||
const int DivideByZeroSignal = SIGFPE;
|
||||
const unsigned DivideByZeroSignalIndex = 2;
|
||||
|
||||
const int signals[]
|
||||
= {SegFaultSignal, AltSegFaultSignal, DivideByZeroSignal};
|
||||
|
||||
const unsigned SignalCount = 3;
|
||||
|
||||
}
|
||||
|
||||
struct SignalRegistrar::Data {
|
||||
Handler* handlers[posix::SignalCount];
|
||||
struct sigaction oldHandlers[posix::SignalCount];
|
||||
|
||||
bool registerHandler(Handler* handler, int index);
|
||||
|
||||
Data()
|
||||
{
|
||||
if(instance) {
|
||||
crash();
|
||||
}
|
||||
|
||||
instance = this;
|
||||
}
|
||||
|
||||
~Data()
|
||||
{
|
||||
instance = 0;
|
||||
}
|
||||
|
||||
static SignalRegistrar::Data* instance;
|
||||
};
|
||||
|
||||
SignalRegistrar::Data* SignalRegistrar::Data::instance = 0;
|
||||
|
||||
namespace posix {
|
||||
|
||||
using namespace vm;
|
||||
|
||||
void handleSignal(int signal, siginfo_t*, void* context)
|
||||
{
|
||||
ucontext_t* c = static_cast<ucontext_t*>(context);
|
||||
|
||||
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
|
||||
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
|
||||
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
|
||||
#ifdef FRAME_REGISTER
|
||||
void* frame = reinterpret_cast<void*>(FRAME_REGISTER(c));
|
||||
#else
|
||||
void* frame = 0;
|
||||
#endif
|
||||
|
||||
unsigned index;
|
||||
|
||||
switch (signal) {
|
||||
case SegFaultSignal:
|
||||
case AltSegFaultSignal:
|
||||
case DivideByZeroSignal: {
|
||||
switch (signal) {
|
||||
case SegFaultSignal:
|
||||
index = SegFaultSignalIndex;
|
||||
break;
|
||||
|
||||
case AltSegFaultSignal:
|
||||
index = AltSegFaultSignalIndex;
|
||||
break;
|
||||
|
||||
case DivideByZeroSignal:
|
||||
index = DivideByZeroSignalIndex;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash();
|
||||
}
|
||||
|
||||
bool jump
|
||||
= SignalRegistrar::Data::instance->handlers[index]->handleSignal(&ip, &frame, &stack, &thread);
|
||||
|
||||
if (jump) {
|
||||
// I'd like to use setcontext here (and get rid of the
|
||||
// sigprocmask call), but it doesn't work on my Linux x86_64
|
||||
// system, and I can't tell from the documentation if it's even
|
||||
// supposed to work.
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, signal);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, 0);
|
||||
|
||||
vmJump(ip, frame, stack, thread, 0, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
crash();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace posix
|
||||
|
||||
NO_RETURN void crash()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
SignalRegistrar::SignalRegistrar()
|
||||
{
|
||||
data = new (malloc(sizeof(Data))) Data();
|
||||
}
|
||||
|
||||
SignalRegistrar::~SignalRegistrar()
|
||||
{
|
||||
data->~Data();
|
||||
free(data);
|
||||
}
|
||||
|
||||
bool SignalRegistrar::Data::registerHandler(Handler* handler, int index)
|
||||
{
|
||||
if (handler) {
|
||||
handlers[index] = handler;
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = posix::handleSignal;
|
||||
|
||||
return sigaction(posix::signals[index], &sa, oldHandlers + index) == 0;
|
||||
} else if (handlers[index]) {
|
||||
handlers[index] = 0;
|
||||
return sigaction(posix::signals[index], oldHandlers + index, 0) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SignalRegistrar::registerHandler(Signal signal, Handler* handler)
|
||||
{
|
||||
switch(signal) {
|
||||
case SegFault:
|
||||
if(!data->registerHandler(handler, posix::SegFaultSignalIndex)) {
|
||||
return false;
|
||||
}
|
||||
if (posix::AltSegFaultSignal != posix::InvalidSignal) {
|
||||
return data->registerHandler(handler, posix::AltSegFaultSignalIndex);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
case DivideByZero:
|
||||
return data->registerHandler(handler, posix::DivideByZeroSignalIndex);
|
||||
default:
|
||||
crash();
|
||||
}
|
||||
}
|
||||
|
||||
bool SignalRegistrar::unregisterHandler(Signal signal)
|
||||
{
|
||||
switch(signal) {
|
||||
case SegFault:
|
||||
if(!data->registerHandler(0, posix::SegFaultSignalIndex)) {
|
||||
return false;
|
||||
}
|
||||
if (posix::AltSegFaultSignal != posix::InvalidSignal) {
|
||||
return data->registerHandler(0, posix::AltSegFaultSignalIndex);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
case DivideByZero:
|
||||
return data->registerHandler(0, posix::DivideByZeroSignalIndex);
|
||||
default:
|
||||
crash();
|
||||
}
|
||||
}
|
||||
|
||||
void SignalRegistrar::setCrashDumpDirectory(const char*)
|
||||
{
|
||||
// Do nothing, not currently supported on posix
|
||||
}
|
||||
|
||||
} // namespace system
|
||||
} // namespace avian
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "sys/stat.h"
|
||||
#include "windows.h"
|
||||
#include "sys/timeb.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define S_ISREG(x) ((x) & _S_IFREG)
|
||||
@ -24,7 +23,8 @@
|
||||
#undef min
|
||||
|
||||
#include "avian/arch.h"
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
#include <avian/system/signal.h>
|
||||
#include <avian/util/runtime-array.h>
|
||||
|
||||
#if defined(WINAPI_FAMILY)
|
||||
@ -115,11 +115,6 @@ class MutexResource {
|
||||
HANDLE m;
|
||||
};
|
||||
|
||||
const unsigned SegFaultIndex = 0;
|
||||
const unsigned DivideByZeroIndex = 1;
|
||||
|
||||
const unsigned HandlerCount = 2;
|
||||
|
||||
class MySystem;
|
||||
MySystem* system;
|
||||
|
||||
@ -626,68 +621,15 @@ class MySystem: public System {
|
||||
System::Library* next_;
|
||||
};
|
||||
|
||||
MySystem(const char* crashDumpDirectory):
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
oldHandler(0),
|
||||
#endif
|
||||
crashDumpDirectory(crashDumpDirectory)
|
||||
MySystem()
|
||||
{
|
||||
expect(this, system == 0);
|
||||
system = this;
|
||||
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
|
||||
mutex = CreateMutex(0, false, 0);
|
||||
assert(this, mutex);
|
||||
}
|
||||
|
||||
bool findHandler() {
|
||||
for (unsigned i = 0; i < HandlerCount; ++i) {
|
||||
if (handlers[i]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int registerHandler(System::SignalHandler* handler, int index) {
|
||||
if (handler) {
|
||||
handlers[index] = handler;
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
if (oldHandler == 0) {
|
||||
# ifdef ARCH_x86_32
|
||||
oldHandler = SetUnhandledExceptionFilter(handleException);
|
||||
# elif defined ARCH_x86_64
|
||||
AddVectoredExceptionHandler(1, handleException);
|
||||
oldHandler = reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(1);
|
||||
# endif
|
||||
}
|
||||
#else
|
||||
#pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
} else if (handlers[index]) {
|
||||
handlers[index] = 0;
|
||||
|
||||
if (not findHandler()) {
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# ifdef ARCH_x86_32
|
||||
SetUnhandledExceptionFilter(oldHandler);
|
||||
oldHandler = 0;
|
||||
# elif defined ARCH_x86_64
|
||||
// do nothing, handlers are never "unregistered" anyway
|
||||
# endif
|
||||
#else
|
||||
#pragma message("TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* tryAllocate(unsigned sizeInBytes) {
|
||||
return malloc(sizeInBytes);
|
||||
}
|
||||
@ -746,14 +688,6 @@ class MySystem: public System {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status handleSegFault(SignalHandler* handler) {
|
||||
return registerHandler(handler, SegFaultIndex);
|
||||
}
|
||||
|
||||
virtual Status handleDivideByZero(SignalHandler* handler) {
|
||||
return registerHandler(handler, DivideByZeroIndex);
|
||||
}
|
||||
|
||||
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
|
||||
ThreadVisitor* visitor)
|
||||
{
|
||||
@ -1008,9 +942,7 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
virtual void abort() {
|
||||
// trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
|
||||
// generate a debug dump for
|
||||
*static_cast<volatile int*>(0) = 0;
|
||||
avian::system::crash();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
@ -1020,139 +952,16 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
HANDLE mutex;
|
||||
SignalHandler* handlers[HandlerCount];
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
|
||||
#endif
|
||||
const char* crashDumpDirectory;
|
||||
};
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
#pragma pack(push,4)
|
||||
struct MINIDUMP_EXCEPTION_INFORMATION {
|
||||
DWORD thread;
|
||||
LPEXCEPTION_POINTERS exception;
|
||||
BOOL exceptionInCurrentAddressSpace;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct MINIDUMP_USER_STREAM_INFORMATION;
|
||||
struct MINIDUMP_CALLBACK_INFORMATION;
|
||||
|
||||
enum MINIDUMP_TYPE {
|
||||
MiniDumpNormal = 0,
|
||||
MiniDumpWithFullMemory = 2
|
||||
};
|
||||
|
||||
typedef BOOL (*MiniDumpWriteDumpType)
|
||||
(HANDLE processHandle,
|
||||
DWORD processId,
|
||||
HANDLE file,
|
||||
MINIDUMP_TYPE type,
|
||||
const MINIDUMP_EXCEPTION_INFORMATION* exception,
|
||||
const MINIDUMP_USER_STREAM_INFORMATION* userStream,
|
||||
const MINIDUMP_CALLBACK_INFORMATION* callback);
|
||||
|
||||
void
|
||||
dump(LPEXCEPTION_POINTERS e, const char* directory)
|
||||
{
|
||||
HINSTANCE dbghelp = LoadLibrary("dbghelp.dll");
|
||||
|
||||
if (dbghelp) {
|
||||
MiniDumpWriteDumpType MiniDumpWriteDump = reinterpret_cast
|
||||
<MiniDumpWriteDumpType>(GetProcAddress(dbghelp, "MiniDumpWriteDump"));
|
||||
|
||||
if (MiniDumpWriteDump) {
|
||||
char name[MAX_PATH];
|
||||
_timeb tb;
|
||||
FTIME(&tb);
|
||||
vm::snprintf(name, MAX_PATH, "%s\\crash-%" LLD ".mdmp", directory,
|
||||
(static_cast<int64_t>(tb.time) * 1000)
|
||||
+ static_cast<int64_t>(tb.millitm));
|
||||
|
||||
HANDLE file = CreateFile
|
||||
(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
MINIDUMP_EXCEPTION_INFORMATION exception
|
||||
= { GetCurrentThreadId(), e, true };
|
||||
|
||||
MiniDumpWriteDump
|
||||
(GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
file,
|
||||
MiniDumpWithFullMemory,
|
||||
&exception,
|
||||
0,
|
||||
0);
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary(dbghelp);
|
||||
}
|
||||
}
|
||||
|
||||
LONG CALLBACK
|
||||
handleException(LPEXCEPTION_POINTERS e)
|
||||
{
|
||||
System::SignalHandler* handler = 0;
|
||||
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
||||
handler = system->handlers[SegFaultIndex];
|
||||
} else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
|
||||
{
|
||||
handler = system->handlers[DivideByZeroIndex];
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
#ifdef ARCH_x86_32
|
||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
|
||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
|
||||
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
|
||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
|
||||
#elif defined ARCH_x86_64
|
||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Rip);
|
||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Rbp);
|
||||
void* stack = reinterpret_cast<void*>(e->ContextRecord->Rsp);
|
||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
|
||||
#endif
|
||||
|
||||
bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
|
||||
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
|
||||
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
|
||||
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
|
||||
#elif defined ARCH_x86_64
|
||||
e->ContextRecord->Rip = reinterpret_cast<DWORD64>(ip);
|
||||
e->ContextRecord->Rbp = reinterpret_cast<DWORD64>(base);
|
||||
e->ContextRecord->Rsp = reinterpret_cast<DWORD64>(stack);
|
||||
e->ContextRecord->Rbx = reinterpret_cast<DWORD64>(thread);
|
||||
#endif
|
||||
|
||||
if (jump) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
} else if (system->crashDumpDirectory) {
|
||||
dump(e, system->crashDumpDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
AVIAN_EXPORT System*
|
||||
makeSystem(const char* crashDumpDirectory)
|
||||
makeSystem()
|
||||
{
|
||||
return new (malloc(sizeof(MySystem))) MySystem(crashDumpDirectory);
|
||||
return new (malloc(sizeof(MySystem))) MySystem();
|
||||
}
|
||||
|
||||
} // namespace vm
|
292
src/system/windows/signal.cpp
Normal file
292
src/system/windows/signal.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "windows.h"
|
||||
#include "sys/timeb.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FTIME _ftime_s
|
||||
#else
|
||||
#define FTIME _ftime
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_FAMILY
|
||||
|
||||
#ifndef WINAPI_PARTITION_DESKTOP
|
||||
#define WINAPI_PARTITION_DESKTOP 1
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_FAMILY_PARTITION
|
||||
#define WINAPI_FAMILY_PARTITION(x) (x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <avian/system/signal.h>
|
||||
#include <avian/common.h>
|
||||
|
||||
namespace avian {
|
||||
namespace system {
|
||||
|
||||
namespace windows {
|
||||
|
||||
const unsigned HandlerCount = 2;
|
||||
|
||||
} // namespace windows
|
||||
|
||||
struct SignalRegistrar::Data {
|
||||
Handler* handlers[windows::HandlerCount];
|
||||
const char* crashDumpDirectory;
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
|
||||
#endif
|
||||
|
||||
Data() : crashDumpDirectory(0),
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
oldHandler(0)
|
||||
#endif
|
||||
{
|
||||
if (instance) {
|
||||
crash();
|
||||
}
|
||||
instance = this;
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
}
|
||||
|
||||
~Data()
|
||||
{
|
||||
instance = 0;
|
||||
}
|
||||
|
||||
bool registerHandler(Handler* handler, int index);
|
||||
|
||||
bool findHandler() {
|
||||
for (unsigned i = 0; i < windows::HandlerCount; ++i) {
|
||||
if (handlers[i]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static SignalRegistrar::Data* instance;
|
||||
};
|
||||
|
||||
SignalRegistrar::Data* SignalRegistrar::Data::instance = 0;
|
||||
|
||||
namespace windows {
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct MINIDUMP_EXCEPTION_INFORMATION {
|
||||
DWORD thread;
|
||||
LPEXCEPTION_POINTERS exception;
|
||||
BOOL exceptionInCurrentAddressSpace;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct MINIDUMP_USER_STREAM_INFORMATION;
|
||||
struct MINIDUMP_CALLBACK_INFORMATION;
|
||||
|
||||
enum MINIDUMP_TYPE {
|
||||
MiniDumpNormal = 0,
|
||||
MiniDumpWithFullMemory = 2
|
||||
};
|
||||
|
||||
typedef BOOL (*MiniDumpWriteDumpType)(HANDLE processHandle,
|
||||
DWORD processId,
|
||||
HANDLE file,
|
||||
MINIDUMP_TYPE type,
|
||||
const MINIDUMP_EXCEPTION_INFORMATION
|
||||
* exception,
|
||||
const MINIDUMP_USER_STREAM_INFORMATION
|
||||
* userStream,
|
||||
const MINIDUMP_CALLBACK_INFORMATION
|
||||
* callback);
|
||||
|
||||
#endif
|
||||
|
||||
void dump(LPEXCEPTION_POINTERS e, const char* directory)
|
||||
{
|
||||
HINSTANCE dbghelp = LoadLibrary("dbghelp.dll");
|
||||
|
||||
if (dbghelp) {
|
||||
MiniDumpWriteDumpType MiniDumpWriteDump = reinterpret_cast
|
||||
<MiniDumpWriteDumpType>(GetProcAddress(dbghelp, "MiniDumpWriteDump"));
|
||||
|
||||
if (MiniDumpWriteDump) {
|
||||
char name[MAX_PATH];
|
||||
_timeb tb;
|
||||
FTIME(&tb);
|
||||
vm::snprintf(name,
|
||||
MAX_PATH,
|
||||
"%s\\crash-%" LLD ".mdmp",
|
||||
directory,
|
||||
(static_cast<int64_t>(tb.time) * 1000) + static_cast
|
||||
<int64_t>(tb.millitm));
|
||||
|
||||
HANDLE file
|
||||
= CreateFile(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
MINIDUMP_EXCEPTION_INFORMATION exception
|
||||
= {GetCurrentThreadId(), e, true};
|
||||
|
||||
MiniDumpWriteDump(GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
file,
|
||||
MiniDumpWithFullMemory,
|
||||
&exception,
|
||||
0,
|
||||
0);
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary(dbghelp);
|
||||
}
|
||||
}
|
||||
|
||||
LONG CALLBACK handleException(LPEXCEPTION_POINTERS e)
|
||||
{
|
||||
SignalRegistrar::Handler* handler = 0;
|
||||
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
||||
handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::SegFault];
|
||||
} else if (e->ExceptionRecord->ExceptionCode
|
||||
== EXCEPTION_INT_DIVIDE_BY_ZERO) {
|
||||
handler = SignalRegistrar::Data::instance->handlers[SignalRegistrar::DivideByZero];
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
#ifdef ARCH_x86_32
|
||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
|
||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
|
||||
void* stack = reinterpret_cast<void*>(e->ContextRecord->Esp);
|
||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Ebx);
|
||||
#elif defined ARCH_x86_64
|
||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Rip);
|
||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Rbp);
|
||||
void* stack = reinterpret_cast<void*>(e->ContextRecord->Rsp);
|
||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
|
||||
#endif
|
||||
|
||||
bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
|
||||
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
|
||||
e->ContextRecord->Esp = reinterpret_cast<DWORD>(stack);
|
||||
e->ContextRecord->Ebx = reinterpret_cast<DWORD>(thread);
|
||||
#elif defined ARCH_x86_64
|
||||
e->ContextRecord->Rip = reinterpret_cast<DWORD64>(ip);
|
||||
e->ContextRecord->Rbp = reinterpret_cast<DWORD64>(base);
|
||||
e->ContextRecord->Rsp = reinterpret_cast<DWORD64>(stack);
|
||||
e->ContextRecord->Rbx = reinterpret_cast<DWORD64>(thread);
|
||||
#endif
|
||||
|
||||
if (jump) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
} else if (SignalRegistrar::Data::instance->crashDumpDirectory) {
|
||||
dump(e, SignalRegistrar::Data::instance->crashDumpDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
|
||||
SignalRegistrar::SignalRegistrar()
|
||||
{
|
||||
data = new (malloc(sizeof(Data))) Data();
|
||||
}
|
||||
|
||||
SignalRegistrar::~SignalRegistrar()
|
||||
{
|
||||
data->~Data();
|
||||
free(data);
|
||||
}
|
||||
|
||||
bool SignalRegistrar::Data::registerHandler(Handler* handler, int index)
|
||||
{
|
||||
if(index != SegFault && index != DivideByZero) {
|
||||
crash();
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
handlers[index] = handler;
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
if (oldHandler == 0) {
|
||||
#ifdef ARCH_x86_32
|
||||
oldHandler = SetUnhandledExceptionFilter(windows::handleException);
|
||||
#elif defined ARCH_x86_64
|
||||
AddVectoredExceptionHandler(1, windows::handleException);
|
||||
oldHandler = reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(1);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#pragma message( \
|
||||
"TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
|
||||
#endif
|
||||
|
||||
return true;
|
||||
} else if (handlers[index]) {
|
||||
handlers[index] = 0;
|
||||
|
||||
if (not findHandler()) {
|
||||
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#ifdef ARCH_x86_32
|
||||
SetUnhandledExceptionFilter(oldHandler);
|
||||
oldHandler = 0;
|
||||
#elif defined ARCH_x86_64
|
||||
// do nothing, handlers are never "unregistered" anyway
|
||||
#endif
|
||||
#else
|
||||
#pragma message( \
|
||||
"TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx")
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NO_RETURN void crash()
|
||||
{
|
||||
// trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and
|
||||
// generate a debug dump for
|
||||
*static_cast<volatile int*>(0) = 0;
|
||||
|
||||
// Some (all?) compilers don't realize that we can't possibly continue past
|
||||
// the above statement.
|
||||
abort();
|
||||
}
|
||||
|
||||
bool SignalRegistrar::registerHandler(Signal signal, Handler* handler)
|
||||
{
|
||||
return data->registerHandler(handler, signal);
|
||||
}
|
||||
|
||||
bool SignalRegistrar::unregisterHandler(Signal signal)
|
||||
{
|
||||
return data->registerHandler(0, signal);
|
||||
}
|
||||
|
||||
void SignalRegistrar::setCrashDumpDirectory(const char* crashDumpDirectory)
|
||||
{
|
||||
data->crashDumpDirectory = crashDumpDirectory;
|
||||
}
|
||||
|
||||
} // namespace system
|
||||
} // namespace avian
|
@ -8,16 +8,16 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/system/system.h>
|
||||
|
||||
#include <avian/util/arg-parser.h>
|
||||
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/targets.h>
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/targets.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/heap/heap.h>
|
||||
|
||||
// since we aren't linking against libstdc++, we must implement this
|
||||
// ourselves:
|
||||
@ -34,7 +34,7 @@ public:
|
||||
Architecture* arch;
|
||||
|
||||
BasicEnv():
|
||||
s(makeSystem(0)),
|
||||
s(makeSystem()),
|
||||
heap(makeHeap(s, 32 * 1024)),
|
||||
arch(makeArchitectureNative(s, true))
|
||||
{
|
||||
|
@ -8,14 +8,14 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/heap/heap.h>
|
||||
#include "avian/heapwalk.h"
|
||||
#include "avian/common.h"
|
||||
#include "avian/machine.h"
|
||||
#include "avian/util.h"
|
||||
#include <avian/util/stream.h>
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/promise.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/promise.h>
|
||||
#include "avian/target.h"
|
||||
#include <avian/tools/object-writer/tools.h>
|
||||
#include <avian/util/runtime-array.h>
|
||||
@ -1899,11 +1899,11 @@ main(int ac, const char** av)
|
||||
Arguments args(ac, av);
|
||||
// args.dump();
|
||||
|
||||
System* s = makeSystem(0);
|
||||
System* s = makeSystem();
|
||||
Heap* h = makeHeap(s, HeapCapacity * 2);
|
||||
Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX);
|
||||
Finder* f = makeFinder(s, h, args.classpath, 0);
|
||||
Processor* p = makeProcessor(s, h, false);
|
||||
Processor* p = makeProcessor(s, h, 0, false);
|
||||
|
||||
// todo: currently, the compiler cannot compile code with jumps or
|
||||
// calls spanning more than the maximum size of an immediate value
|
||||
|
@ -1941,7 +1941,7 @@ main(int ac, char** av)
|
||||
local::usageAndExit(av[0]);
|
||||
}
|
||||
|
||||
System* system = makeSystem(0);
|
||||
System* system = makeSystem();
|
||||
|
||||
class MyAllocator: public Allocator {
|
||||
public:
|
||||
|
@ -11,14 +11,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "avian/common.h"
|
||||
#include <avian/vm/heap/heap.h>
|
||||
#include <avian/vm/system/system.h>
|
||||
#include <avian/heap/heap.h>
|
||||
#include <avian/system/system.h>
|
||||
#include "avian/target.h"
|
||||
|
||||
#include <avian/vm/codegen/assembler.h>
|
||||
#include <avian/vm/codegen/architecture.h>
|
||||
#include <avian/vm/codegen/targets.h>
|
||||
#include <avian/vm/codegen/lir.h>
|
||||
#include <avian/codegen/assembler.h>
|
||||
#include <avian/codegen/architecture.h>
|
||||
#include <avian/codegen/targets.h>
|
||||
#include <avian/codegen/lir.h>
|
||||
|
||||
#include "test-harness.h"
|
||||
|
||||
@ -33,7 +33,7 @@ public:
|
||||
Architecture* arch;
|
||||
|
||||
BasicEnv():
|
||||
s(makeSystem(0)),
|
||||
s(makeSystem()),
|
||||
heap(makeHeap(s, 32 * 1024)),
|
||||
arch(makeArchitectureNative(s, true))
|
||||
{
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avian/vm/codegen/registers.h>
|
||||
#include <avian/codegen/registers.h>
|
||||
|
||||
#include "test-harness.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user