86 lines
2.5 KiB
C++
86 lines
2.5 KiB
C++
/**
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2015 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef XENIA_BASE_EXCEPTION_HANDLER_H_
|
|
#define XENIA_BASE_EXCEPTION_HANDLER_H_
|
|
|
|
#include <functional>
|
|
#include <vector>
|
|
|
|
#include "xenia/base/assert.h"
|
|
#include "xenia/base/x64_context.h"
|
|
|
|
namespace xe {
|
|
|
|
class Exception {
|
|
public:
|
|
enum class Code {
|
|
kInvalidException = 0,
|
|
kAccessViolation,
|
|
kIllegalInstruction,
|
|
};
|
|
|
|
void InitializeAccessViolation(X64Context* thread_context,
|
|
uint64_t fault_address) {
|
|
code_ = Code::kAccessViolation;
|
|
thread_context_ = thread_context;
|
|
fault_address_ = fault_address;
|
|
}
|
|
void InitializeIllegalInstruction(X64Context* thread_context) {
|
|
code_ = Code::kIllegalInstruction;
|
|
thread_context_ = thread_context;
|
|
}
|
|
|
|
Code code() const { return code_; }
|
|
|
|
// Returns the platform-specific thread context info.
|
|
X64Context* thread_context() const { return thread_context_; }
|
|
|
|
#if XE_ARCH_AMD64
|
|
// Returns the program counter where the exception occurred.
|
|
// RIP on x64.
|
|
uint64_t pc() const { return thread_context_->rip; }
|
|
// Sets the program counter where execution will resume.
|
|
void set_resume_pc(uint64_t pc) { thread_context_->rip = pc; }
|
|
#else
|
|
// Returns the program counter where the exception occurred.
|
|
// RIP on x64.
|
|
uint64_t pc() const {
|
|
assert_always();
|
|
return 0;
|
|
}
|
|
// Sets the program counter where execution will resume.
|
|
void set_resume_pc(uint64_t pc) { assert_always(); }
|
|
#endif
|
|
|
|
// In case of AV, address that was read from/written to.
|
|
uint64_t fault_address() const { return fault_address_; }
|
|
|
|
private:
|
|
Code code_ = Code::kInvalidException;
|
|
X64Context* thread_context_ = nullptr;
|
|
uint64_t fault_address_ = 0;
|
|
};
|
|
|
|
class ExceptionHandler {
|
|
public:
|
|
typedef bool (*Handler)(Exception* ex, void* data);
|
|
|
|
// Installs an exception handler.
|
|
// Handlers are called in the order they are installed.
|
|
static void Install(Handler fn, void* data);
|
|
|
|
// Uninstalls a previously-installed exception handler.
|
|
static void Uninstall(Handler fn, void* data);
|
|
};
|
|
|
|
} // namespace xe
|
|
|
|
#endif // XENIA_BASE_EXCEPTION_HANDLER_H_
|