Experimenting with xdb API, starting on compare tool.
This commit is contained in:
parent
3de39aaf10
commit
1a39f5bd06
|
@ -249,7 +249,6 @@ int Translate_SOURCE_OFFSET(TranslationContext& ctx, Instr* i) {
|
|||
|
||||
// TODO(benvanik): dispatch of register forms.
|
||||
uint32_t IntCode_TRACE_SOURCE(IntCodeState& ics, const IntCode* i) {
|
||||
// TODO(benvanik): append to active trace writer.
|
||||
uint64_t trace_base = ics.thread_state->memory()->trace_base();
|
||||
if (trace_base) {
|
||||
auto ev = xdb::protocol::InstrEvent::Append(trace_base);
|
||||
|
@ -323,7 +322,7 @@ uint32_t IntCode_TRAP(IntCodeState& ics, const IntCode* i) {
|
|||
switch (i->flags) {
|
||||
case 20:
|
||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||
break;
|
||||
return IA_NEXT;
|
||||
case 22:
|
||||
// Always trap?
|
||||
break;
|
||||
|
|
|
@ -20,6 +20,9 @@ namespace alloy {
|
|||
|
||||
// TODO(benvanik): go lockfree, and don't hold the lock while emitting.
|
||||
|
||||
template <typename T>
|
||||
class Delegate;
|
||||
|
||||
template <typename T>
|
||||
class Delegate {
|
||||
public:
|
||||
|
@ -30,16 +33,6 @@ class Delegate {
|
|||
listeners_.push_back(listener);
|
||||
}
|
||||
|
||||
void RemoveListener(Listener const& listener) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
for (auto it = listeners_.begin(); it != listeners_.end(); ++it) {
|
||||
if (it == listener) {
|
||||
listeners_.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveAllListeners() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
listeners_.clear();
|
||||
|
@ -57,6 +50,33 @@ class Delegate {
|
|||
std::vector<Listener> listeners_;
|
||||
};
|
||||
|
||||
template <>
|
||||
class Delegate<void> {
|
||||
public:
|
||||
typedef std::function<void()> Listener;
|
||||
|
||||
void AddListener(Listener const& listener) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
listeners_.push_back(listener);
|
||||
}
|
||||
|
||||
void RemoveAllListeners() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
listeners_.clear();
|
||||
}
|
||||
|
||||
void operator()() {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
for (auto& listener : listeners_) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex lock_;
|
||||
std::vector<Listener> listeners_;
|
||||
};
|
||||
|
||||
} // namespace alloy
|
||||
|
||||
#endif // ALLOY_DELEGATE_H_
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xdb/cursor.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
//
|
||||
|
||||
} // namespace xdb
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XDB_CURSOR_H_
|
||||
#define XDB_CURSOR_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <alloy/delegate.h>
|
||||
#include <xdb/module.h>
|
||||
#include <xdb/protocol.h>
|
||||
#include <xdb/thread.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
virtual ~Cursor() = default;
|
||||
|
||||
virtual bool can_step() const = 0;
|
||||
|
||||
// TODO(benvanik): breakpoints/events
|
||||
|
||||
alloy::Delegate<void> end_of_stream;
|
||||
|
||||
std::vector<Module*> modules();
|
||||
std::vector<Thread*> threads();
|
||||
|
||||
alloy::Delegate<Module*> module_loaded;
|
||||
alloy::Delegate<Module*> module_unloaded;
|
||||
alloy::Delegate<Thread*> thread_created;
|
||||
alloy::Delegate<Thread*> thread_exited;
|
||||
|
||||
// TODO(benvanik): memory access
|
||||
|
||||
virtual void Continue(Thread* thread = nullptr) = 0;
|
||||
virtual void ContinueTo(uint32_t address, Thread* thread = nullptr) = 0;
|
||||
virtual void ContinueToNextCall(Thread* thread = nullptr) = 0;
|
||||
virtual void ContinueToReturn(Thread* thread = nullptr) = 0;
|
||||
virtual void ContinueUntil(
|
||||
const std::function<bool(protocol::EventType, uint8_t*)> predicate,
|
||||
Thread* thread = nullptr) = 0;
|
||||
virtual void Break() = 0;
|
||||
|
||||
protected:
|
||||
Cursor() = default;
|
||||
};
|
||||
|
||||
} // namespace xdb
|
||||
|
||||
#endif // XDB_CURSOR_H_
|
|
@ -27,4 +27,16 @@ bool DebugTarget::InitializeFileSystem(const std::wstring& path) {
|
|||
return true;
|
||||
}
|
||||
|
||||
Module* DebugTarget::GetModule(uint16_t module_id) {
|
||||
std::lock_guard<std::mutex> lock(object_lock_);
|
||||
auto it = module_map_.find(module_id);
|
||||
return it != module_map_.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
Thread* DebugTarget::GetThread(uint16_t thread_id) {
|
||||
std::lock_guard<std::mutex> lock(object_lock_);
|
||||
auto it = thread_map_.find(thread_id);
|
||||
return it != thread_map_.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
} // namespace xdb
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
#ifndef XDB_DEBUG_TARGET_H_
|
||||
#define XDB_DEBUG_TARGET_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <xdb/cursor.h>
|
||||
#include <xenia/kernel/fs/filesystem.h>
|
||||
|
||||
namespace xdb {
|
||||
|
@ -20,12 +26,23 @@ class DebugTarget {
|
|||
|
||||
xe::kernel::fs::FileSystem* file_system() const { return file_system_.get(); }
|
||||
|
||||
virtual std::unique_ptr<Cursor> CreateCursor() = 0;
|
||||
|
||||
Module* GetModule(uint16_t module_id);
|
||||
Thread* GetThread(uint16_t thread_id);
|
||||
|
||||
protected:
|
||||
DebugTarget() = default;
|
||||
|
||||
bool InitializeFileSystem(const std::wstring& path);
|
||||
|
||||
std::unique_ptr<xe::kernel::fs::FileSystem> file_system_;
|
||||
|
||||
std::mutex object_lock_;
|
||||
std::vector<std::unique_ptr<Module>> modules_;
|
||||
std::vector<std::unique_ptr<Thread>> threads_;
|
||||
std::unordered_map<uint16_t, Module*> module_map_;
|
||||
std::unordered_map<uint16_t, Thread*> thread_map_;
|
||||
};
|
||||
|
||||
} // namespace xdb
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xdb/module.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
//
|
||||
|
||||
} // namespace xdb
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XDB_MODULE_H_
|
||||
#define XDB_MODULE_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
class Module {
|
||||
public:
|
||||
uint16_t module_id;
|
||||
// info
|
||||
};
|
||||
|
||||
} // namespace xdb
|
||||
|
||||
#endif // XDB_MODULE_H_
|
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xdb/postmortem_cursor.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
|
||||
#include <xdb/postmortem_debug_target.h>
|
||||
#include <xdb/protocol.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
using xdb::protocol::EventType;
|
||||
|
||||
struct Command {
|
||||
enum class Type {
|
||||
EXIT,
|
||||
CONTINUE,
|
||||
};
|
||||
Type type;
|
||||
|
||||
protected:
|
||||
Command(Type type) : type(type) {}
|
||||
};
|
||||
|
||||
struct ExitCommand : public Command {
|
||||
ExitCommand() : Command(Type::EXIT) {}
|
||||
};
|
||||
|
||||
struct ContinueCommand : public Command {
|
||||
ContinueCommand() : Command(Type::CONTINUE), thread(nullptr) {}
|
||||
Thread* thread;
|
||||
};
|
||||
|
||||
class PostmortemCursor::Executor {
|
||||
public:
|
||||
Executor(PostmortemCursor* cursor) : cursor_(cursor), running_(true) {
|
||||
trace_ptr_ = cursor->target_->trace_base();
|
||||
|
||||
// Must be last, as it'll spin up here.
|
||||
thread_ = std::thread(std::bind(&Executor::ExecutionThread, this));
|
||||
}
|
||||
~Executor() {
|
||||
running_ = false;
|
||||
IssueCommand(std::make_unique<ExitCommand>());
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
bool eof() const { return eof_; }
|
||||
|
||||
void IssueCommand(std::unique_ptr<Command> command) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(queue_lock_);
|
||||
queue_.push(std::move(command));
|
||||
pending_commands_ = true;
|
||||
}
|
||||
queue_cond_.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
void ExecutionThread() {
|
||||
while (running_) {
|
||||
auto command = AwaitCommand();
|
||||
if (!running_ || !command || command->type == Command::Type::EXIT) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (command->type) {
|
||||
case Command::Type::CONTINUE: {
|
||||
auto cmd = static_cast<ContinueCommand*>(command.get());
|
||||
cmd->thread;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
Process(pending_commands_);
|
||||
}
|
||||
}
|
||||
|
||||
void Process(std::atomic<bool>& exit_signal) {
|
||||
if (eof_) {
|
||||
return;
|
||||
}
|
||||
while (!exit_signal) {
|
||||
auto event_type = poly::load<EventType>(trace_ptr_);
|
||||
switch (event_type) {
|
||||
case EventType::END_OF_STREAM: {
|
||||
eof_= true;
|
||||
cursor_->end_of_stream();
|
||||
return;
|
||||
}
|
||||
case EventType::MODULE_LOAD: {
|
||||
auto ev = protocol::ModuleLoadEvent::Get(trace_ptr_);
|
||||
break;
|
||||
}
|
||||
case EventType::MODULE_UNLOAD: {
|
||||
auto ev = protocol::ModuleLoadEvent::Get(trace_ptr_);
|
||||
break;
|
||||
}
|
||||
case EventType::THREAD_CREATE: {
|
||||
auto ev = protocol::ThreadCreateEvent::Get(trace_ptr_);
|
||||
break;
|
||||
}
|
||||
case EventType::THREAD_INFO: {
|
||||
auto ev = protocol::ThreadInfoEvent::Get(trace_ptr_);
|
||||
break;
|
||||
}
|
||||
case EventType::THREAD_EXIT: {
|
||||
auto ev = protocol::ThreadExitEvent::Get(trace_ptr_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
trace_ptr_ += protocol::kEventSizes[static_cast<uint8_t>(event_type)];
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Command> AwaitCommand() {
|
||||
std::unique_lock<std::mutex> lock(queue_lock_);
|
||||
while (queue_.empty()) {
|
||||
queue_cond_.wait(lock);
|
||||
}
|
||||
auto command = std::move(queue_.front());
|
||||
queue_.pop();
|
||||
pending_commands_ = !queue_.empty();
|
||||
return command;
|
||||
}
|
||||
|
||||
PostmortemCursor* cursor_;
|
||||
std::atomic<bool> running_;
|
||||
const uint8_t* trace_ptr_;
|
||||
std::atomic<bool> eof_;
|
||||
std::thread thread_;
|
||||
|
||||
std::queue<std::unique_ptr<Command>> queue_;
|
||||
std::mutex queue_lock_;
|
||||
std::condition_variable queue_cond_;
|
||||
std::atomic<bool> pending_commands_;
|
||||
};
|
||||
|
||||
PostmortemCursor::PostmortemCursor(PostmortemDebugTarget* target)
|
||||
: target_(target) {
|
||||
executor_.reset(new Executor(this));
|
||||
}
|
||||
|
||||
PostmortemCursor::~PostmortemCursor() { executor_.reset(); }
|
||||
|
||||
bool PostmortemCursor::can_step() const {
|
||||
// TODO(benvanik): check trace flags.
|
||||
return true;
|
||||
}
|
||||
|
||||
void PostmortemCursor::Continue(Thread* thread) {
|
||||
auto cmd = std::make_unique<ContinueCommand>();
|
||||
cmd->thread = thread;
|
||||
executor_->IssueCommand(std::move(cmd));
|
||||
}
|
||||
|
||||
void PostmortemCursor::ContinueTo(uint32_t address, Thread* thread) {}
|
||||
|
||||
void PostmortemCursor::ContinueToNextCall(Thread* thread) {}
|
||||
|
||||
void PostmortemCursor::ContinueToReturn(Thread* thread) {}
|
||||
|
||||
void PostmortemCursor::ContinueUntil(
|
||||
const std::function<bool(protocol::EventType, uint8_t*)> predicate,
|
||||
Thread* thread) {}
|
||||
|
||||
void PostmortemCursor::Break() {}
|
||||
|
||||
} // namespace xdb
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XDB_POSTMORTEM_CURSOR_H_
|
||||
#define XDB_POSTMORTEM_CURSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <xdb/cursor.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
class PostmortemDebugTarget;
|
||||
|
||||
class PostmortemCursor : public Cursor {
|
||||
public:
|
||||
PostmortemCursor(PostmortemDebugTarget* target);
|
||||
~PostmortemCursor() override;
|
||||
|
||||
bool can_step() const override;
|
||||
|
||||
void Continue(Thread* thread = nullptr) override;
|
||||
void ContinueTo(uint32_t address, Thread* thread = nullptr) override;
|
||||
void ContinueToNextCall(Thread* thread = nullptr) override;
|
||||
void ContinueToReturn(Thread* thread = nullptr) override;
|
||||
void ContinueUntil(
|
||||
const std::function<bool(protocol::EventType, uint8_t*)> predicate,
|
||||
Thread* thread = nullptr) override;
|
||||
void Break() override;
|
||||
|
||||
private:
|
||||
class Executor;
|
||||
|
||||
PostmortemDebugTarget* target_;
|
||||
std::unique_ptr<Executor> executor_;
|
||||
};
|
||||
|
||||
} // namespace xdb
|
||||
|
||||
#endif // XDB_POSTMORTEM_CURSOR_H_
|
|
@ -10,37 +10,13 @@
|
|||
#include <xdb/postmortem_debug_target.h>
|
||||
|
||||
#include <poly/poly.h>
|
||||
#include <xdb/postmortem_cursor.h>
|
||||
#include <xenia/logging.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
using xdb::protocol::EventType;
|
||||
|
||||
// Matches the EventType ordering to allow for quick event size checks.
|
||||
const size_t event_sizes[] = {
|
||||
0,
|
||||
sizeof(protocol::ProcessStartEvent),
|
||||
sizeof(protocol::ProcessExitEvent),
|
||||
sizeof(protocol::ModuleLoadEvent),
|
||||
sizeof(protocol::ModuleUnloadEvent),
|
||||
sizeof(protocol::ThreadCreateEvent),
|
||||
sizeof(protocol::ThreadInfoEvent),
|
||||
sizeof(protocol::ThreadExitEvent),
|
||||
sizeof(protocol::FunctionCompiledEvent),
|
||||
sizeof(protocol::OutputStringEvent),
|
||||
sizeof(protocol::KernelCallEvent),
|
||||
sizeof(protocol::KernelCallReturnEvent),
|
||||
sizeof(protocol::UserCallEvent),
|
||||
sizeof(protocol::UserCallReturnEvent),
|
||||
sizeof(protocol::InstrEvent),
|
||||
sizeof(protocol::InstrEventR8),
|
||||
sizeof(protocol::InstrEventR8R8),
|
||||
sizeof(protocol::InstrEventR8R16),
|
||||
sizeof(protocol::InstrEventR16),
|
||||
sizeof(protocol::InstrEventR16R8),
|
||||
sizeof(protocol::InstrEventR16R16),
|
||||
};
|
||||
|
||||
PostmortemDebugTarget::PostmortemDebugTarget()
|
||||
: file_(nullptr),
|
||||
file_mapping_(nullptr),
|
||||
|
@ -66,8 +42,8 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path,
|
|||
return false;
|
||||
}
|
||||
|
||||
file_mapping_ = CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0,
|
||||
L"Local\\xenia_xdb_trace");
|
||||
file_mapping_ =
|
||||
CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
if (!file_mapping_) {
|
||||
XELOGE("Could not create trace file mapping");
|
||||
return false;
|
||||
|
@ -95,7 +71,7 @@ bool PostmortemDebugTarget::LoadTrace(const std::wstring& path,
|
|||
if (process_start_event_) {
|
||||
break;
|
||||
}
|
||||
ptr += event_sizes[static_cast<uint8_t>(event_type)];
|
||||
ptr += protocol::kEventSizes[static_cast<uint8_t>(event_type)];
|
||||
}
|
||||
|
||||
bool initialized_filesystem = false;
|
||||
|
@ -129,7 +105,8 @@ bool PostmortemDebugTarget::Prepare(std::atomic<bool>& cancelled) {
|
|||
EventType::END_OF_STREAM) {
|
||||
switch (event_type) {
|
||||
case EventType::PROCESS_START: {
|
||||
process_start_event_ = protocol::ProcessStartEvent::Get(ptr);
|
||||
assert_true(process_start_event_ ==
|
||||
protocol::ProcessStartEvent::Get(ptr));
|
||||
break;
|
||||
}
|
||||
case EventType::PROCESS_EXIT: {
|
||||
|
@ -209,10 +186,17 @@ bool PostmortemDebugTarget::Prepare(std::atomic<bool>& cancelled) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
ptr += event_sizes[static_cast<uint8_t>(event_type)];
|
||||
ptr += protocol::kEventSizes[static_cast<uint8_t>(event_type)];
|
||||
};
|
||||
|
||||
trace_length_ = ptr - trace_base_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Cursor> PostmortemDebugTarget::CreateCursor() {
|
||||
auto cursor = std::make_unique<PostmortemCursor>(this);
|
||||
return std::unique_ptr<Cursor>(cursor.release());
|
||||
}
|
||||
|
||||
} // namespace xdb
|
||||
|
|
|
@ -25,16 +25,22 @@ class PostmortemDebugTarget : public DebugTarget {
|
|||
PostmortemDebugTarget();
|
||||
~PostmortemDebugTarget() override;
|
||||
|
||||
const uint8_t* trace_base() const { return trace_base_ + 8; }
|
||||
size_t trace_length() const { return trace_length_; }
|
||||
|
||||
bool LoadTrace(const std::wstring& path,
|
||||
const std::wstring& content_path = L"");
|
||||
|
||||
bool Prepare();
|
||||
bool Prepare(std::atomic<bool>& cancelled);
|
||||
|
||||
std::unique_ptr<Cursor> CreateCursor() override;
|
||||
|
||||
private:
|
||||
HANDLE file_;
|
||||
HANDLE file_mapping_;
|
||||
const uint8_t* trace_base_;
|
||||
size_t trace_length_;
|
||||
|
||||
const protocol::ProcessStartEvent* process_start_event_;
|
||||
const protocol::ProcessExitEvent* process_exit_event_;
|
||||
|
|
|
@ -77,14 +77,9 @@ struct ProcessExitEvent : public Event<ProcessExitEvent> {
|
|||
EventType type;
|
||||
};
|
||||
|
||||
struct ModuleInfo {
|
||||
uint32_t module_id;
|
||||
};
|
||||
|
||||
struct ModuleLoadEvent : public Event<ModuleLoadEvent> {
|
||||
EventType type;
|
||||
uint32_t module_id;
|
||||
ModuleInfo module_info;
|
||||
};
|
||||
|
||||
struct ModuleUnloadEvent : public Event<ModuleUnloadEvent> {
|
||||
|
@ -227,6 +222,31 @@ struct InstrEventR16R16 : public Event<InstrEventR16R16> {
|
|||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Matches the EventType ordering to allow for quick event size checks.
|
||||
const size_t kEventSizes[] = {
|
||||
0,
|
||||
sizeof(protocol::ProcessStartEvent),
|
||||
sizeof(protocol::ProcessExitEvent),
|
||||
sizeof(protocol::ModuleLoadEvent),
|
||||
sizeof(protocol::ModuleUnloadEvent),
|
||||
sizeof(protocol::ThreadCreateEvent),
|
||||
sizeof(protocol::ThreadInfoEvent),
|
||||
sizeof(protocol::ThreadExitEvent),
|
||||
sizeof(protocol::FunctionCompiledEvent),
|
||||
sizeof(protocol::OutputStringEvent),
|
||||
sizeof(protocol::KernelCallEvent),
|
||||
sizeof(protocol::KernelCallReturnEvent),
|
||||
sizeof(protocol::UserCallEvent),
|
||||
sizeof(protocol::UserCallReturnEvent),
|
||||
sizeof(protocol::InstrEvent),
|
||||
sizeof(protocol::InstrEventR8),
|
||||
sizeof(protocol::InstrEventR8R8),
|
||||
sizeof(protocol::InstrEventR8R16),
|
||||
sizeof(protocol::InstrEventR16),
|
||||
sizeof(protocol::InstrEventR16R8),
|
||||
sizeof(protocol::InstrEventR16R16),
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace xdb
|
||||
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'cursor.cc',
|
||||
'cursor.h',
|
||||
'debug_target.cc',
|
||||
'debug_target.h',
|
||||
'module.cc',
|
||||
'module.h',
|
||||
'postmortem_cursor.cc',
|
||||
'postmortem_cursor.h',
|
||||
'postmortem_debug_target.cc',
|
||||
'postmortem_debug_target.h',
|
||||
'protocol.h',
|
||||
'thread.cc',
|
||||
'thread.h',
|
||||
'xdb.cc',
|
||||
'xdb.h',
|
||||
],
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xdb/thread.h>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
//
|
||||
|
||||
} // namespace xdb
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XDB_THREAD_H_
|
||||
#define XDB_THREAD_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xdb {
|
||||
|
||||
class Thread {
|
||||
public:
|
||||
uint16_t thread_id;
|
||||
// name
|
||||
// etc
|
||||
};
|
||||
|
||||
} // namespace xdb
|
||||
|
||||
#endif // XDB_THREAD_H_
|
|
@ -13,7 +13,32 @@ namespace xdb {
|
|||
namespace ui {
|
||||
|
||||
MainFrame::MainFrame(std::unique_ptr<DebugTarget> debug_target)
|
||||
: MainFrameBase(nullptr), debug_target_(std::move(debug_target)) {}
|
||||
: MainFrameBase(nullptr), debug_target_(std::move(debug_target)) {
|
||||
cursor_ = std::move(debug_target_->CreateCursor());
|
||||
cursor_->end_of_stream.AddListener([]() {
|
||||
XELOGI("eos");
|
||||
});
|
||||
cursor_->module_loaded.AddListener([](Module* module) {
|
||||
//
|
||||
XELOGI("mod load");
|
||||
});
|
||||
cursor_->module_unloaded.AddListener([](Module* module) {
|
||||
//
|
||||
XELOGI("mod unload");
|
||||
});
|
||||
cursor_->thread_created.AddListener([](Thread* thread) {
|
||||
//
|
||||
XELOGI("thread create");
|
||||
});
|
||||
cursor_->thread_exited.AddListener([](Thread* thread) {
|
||||
//
|
||||
XELOGI("thread exit");
|
||||
});
|
||||
cursor_->Continue();
|
||||
}
|
||||
|
||||
void MainFrame::OnIdle(wxIdleEvent& event) {
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xdb
|
||||
|
|
|
@ -23,10 +23,11 @@ class MainFrame : public MainFrameBase {
|
|||
MainFrame(std::unique_ptr<DebugTarget> debug_target);
|
||||
|
||||
protected:
|
||||
//
|
||||
void OnIdle(wxIdleEvent& event) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<DebugTarget> debug_target_;
|
||||
std::unique_ptr<DebugTarget> debug_target_;
|
||||
std::unique_ptr<Cursor> cursor_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnHibernate"></event>
|
||||
<event name="OnIconize"></event>
|
||||
<event name="OnIdle"></event>
|
||||
<event name="OnIdle">OnIdle</event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
|
@ -536,7 +536,7 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="Dialog" expanded="1">
|
||||
<object class="Dialog" expanded="0">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style"></property>
|
||||
<property name="bg"></property>
|
||||
|
@ -598,16 +598,16 @@
|
|||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<object class="wxBoxSizer" expanded="0">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">root_panel_outer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">10</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<object class="wxPanel" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
|
@ -681,7 +681,7 @@
|
|||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="wxFlexGridSizer" expanded="1">
|
||||
<object class="wxFlexGridSizer" expanded="0">
|
||||
<property name="cols">1</property>
|
||||
<property name="flexible_direction">wxVERTICAL</property>
|
||||
<property name="growablecols">0</property>
|
||||
|
@ -693,11 +693,11 @@
|
|||
<property name="permission">none</property>
|
||||
<property name="rows">0</property>
|
||||
<property name="vgap">0</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<object class="wxStaticText" expanded="0">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
|
@ -776,11 +776,11 @@
|
|||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxFlexGridSizer" expanded="1">
|
||||
<object class="wxFlexGridSizer" expanded="0">
|
||||
<property name="cols">2</property>
|
||||
<property name="flexible_direction">wxBOTH</property>
|
||||
<property name="growablecols">1</property>
|
||||
|
@ -1138,11 +1138,11 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">0</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="1">
|
||||
<object class="wxStdDialogButtonSizer" expanded="0">
|
||||
<property name="Apply">0</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
|
|
|
@ -40,10 +40,16 @@ MainFrameBase::MainFrameBase( wxWindow* parent, wxWindowID id, const wxString& t
|
|||
|
||||
m_mgr.Update();
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) );
|
||||
}
|
||||
|
||||
MainFrameBase::~MainFrameBase()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( MainFrameBase::OnIdle ) );
|
||||
|
||||
m_mgr.UnInit();
|
||||
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ namespace xdb
|
|||
wxAuiNotebook* notebook_;
|
||||
wxPanel* m_panel3;
|
||||
wxPanel* m_panel4;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
'includes': [
|
||||
'alloy-sandbox/alloy-sandbox.gypi',
|
||||
'xenia-compare/xenia-compare.gypi',
|
||||
'xenia-debug/xenia-debug.gypi',
|
||||
'xenia-run/xenia-run.gypi',
|
||||
#'xenia-test/xenia-test.gypi',
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <poly/poly.h>
|
||||
#include <xdb/postmortem_debug_target.h>
|
||||
#include <xdb/xdb.h>
|
||||
|
||||
DEFINE_string(trace_file_left, "", "Trace file to compare (original).");
|
||||
DEFINE_string(trace_file_right, "", "Trace file to compare (new).");
|
||||
|
||||
namespace xc {
|
||||
|
||||
using xdb::PostmortemDebugTarget;
|
||||
|
||||
int main(int argc, xechar_t** argv) {
|
||||
// Create platform abstraction layer.
|
||||
xe_pal_options_t pal_options;
|
||||
xe_zero_struct(&pal_options, sizeof(pal_options));
|
||||
if (xe_pal_init(pal_options)) {
|
||||
XEFATAL("Failed to initialize PAL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto left_target = std::make_unique<PostmortemDebugTarget>();
|
||||
if (!left_target->LoadTrace(poly::to_wstring(FLAGS_trace_file_left))) {
|
||||
XEFATAL("Unable to load left trace file: %s",
|
||||
FLAGS_trace_file_left.c_str());
|
||||
}
|
||||
auto right_target = std::make_unique<PostmortemDebugTarget>();
|
||||
if (!right_target->LoadTrace(poly::to_wstring(FLAGS_trace_file_right))) {
|
||||
XEFATAL("Unable to load right trace file: %s",
|
||||
FLAGS_trace_file_right.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace xc
|
||||
|
||||
// TODO(benvanik): move main thunk into poly
|
||||
// ehhh
|
||||
XE_MAIN_WINDOW_THUNK(xc::main, L"xenia-compare", "xenia-compare");
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright 2014 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'xenia-compare',
|
||||
'type': 'executable',
|
||||
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
'SubSystem': '2'
|
||||
}
|
||||
},
|
||||
|
||||
'dependencies': [
|
||||
'xdb',
|
||||
'xenia',
|
||||
],
|
||||
|
||||
'include_dirs': [
|
||||
'.',
|
||||
],
|
||||
|
||||
'sources': [
|
||||
'xenia-compare.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
Loading…
Reference in New Issue