Exception handler abstraction class
This commit is contained in:
parent
edef57065b
commit
8e716a3a7e
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
class ExceptionHandler {
|
||||||
|
public:
|
||||||
|
struct Info {
|
||||||
|
enum {
|
||||||
|
kInvalidException = 0,
|
||||||
|
kAccessViolation,
|
||||||
|
} code = kInvalidException;
|
||||||
|
|
||||||
|
uint64_t pc = 0; // Program counter address. RIP on x64.
|
||||||
|
uint64_t fault_address =
|
||||||
|
0; // In case of AV, address that was read from/written to.
|
||||||
|
|
||||||
|
void* thread_context = nullptr; // Platform-specific thread context info.
|
||||||
|
};
|
||||||
|
typedef std::function<bool(Info* ex_info)> Handler;
|
||||||
|
|
||||||
|
// Static initialization. Only call this once!
|
||||||
|
static bool Initialize();
|
||||||
|
|
||||||
|
// Install an exception handler. Returns an ID which you can save to remove
|
||||||
|
// this later. This will install the exception handler in the last place
|
||||||
|
// on Windows.
|
||||||
|
static uint32_t Install(Handler fn);
|
||||||
|
static bool Remove(uint32_t id);
|
||||||
|
|
||||||
|
static const std::vector<Handler>& handlers() { return handlers_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector<Handler> handlers_;
|
||||||
|
};
|
||||||
|
}; // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_BASE_EXCEPTION_HANDLER_H_
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/base/exception_handler.h"
|
||||||
|
|
||||||
|
#include "xenia/base/platform_win.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
std::vector<ExceptionHandler::Handler> ExceptionHandler::handlers_;
|
||||||
|
|
||||||
|
LONG CALLBACK ExceptionHandlerCallback(PEXCEPTION_POINTERS ex_info) {
|
||||||
|
// Visual Studio SetThreadName
|
||||||
|
if (ex_info->ExceptionRecord->ExceptionCode == 0x406D1388) {
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto code = ex_info->ExceptionRecord->ExceptionCode;
|
||||||
|
ExceptionHandler::Info info;
|
||||||
|
info.pc = ex_info->ContextRecord->Rip;
|
||||||
|
info.thread_context = ex_info->ContextRecord;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case STATUS_ACCESS_VIOLATION:
|
||||||
|
info.code = ExceptionHandler::Info::kAccessViolation;
|
||||||
|
info.fault_address = ex_info->ExceptionRecord->ExceptionInformation[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only call a handler if we support this type of exception.
|
||||||
|
if (info.code != ExceptionHandler::Info::kInvalidException) {
|
||||||
|
for (auto handler : ExceptionHandler::handlers()) {
|
||||||
|
if (handler(&info)) {
|
||||||
|
// Exception handled.
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExceptionHandler::Initialize() {
|
||||||
|
AddVectoredExceptionHandler(0, ExceptionHandlerCallback);
|
||||||
|
|
||||||
|
// TODO: Do we need a continue handler if a debugger is attached?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExceptionHandler::Install(std::function<bool(Info* ex_info)> fn) {
|
||||||
|
handlers_.push_back(fn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue