Mostly complete tracing. Probably a lot of bugs.
This commit is contained in:
@@ -12,18 +12,14 @@
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
|
||||
DECLARE_bool(trace_function_generation);
|
||||
DECLARE_bool(trace_kernel_calls);
|
||||
DECLARE_bool(trace_user_calls);
|
||||
DECLARE_bool(trace_instructions);
|
||||
DECLARE_bool(trace_registers);
|
||||
DECLARE_bool(trace_branches);
|
||||
DECLARE_bool(trace_user_calls);
|
||||
DECLARE_bool(trace_kernel_calls);
|
||||
DECLARE_uint64(trace_thread_mask);
|
||||
|
||||
DECLARE_string(load_module_map);
|
||||
|
||||
DECLARE_string(dump_path);
|
||||
DECLARE_bool(dump_module_map);
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PRIVATE_H_
|
||||
|
||||
@@ -9,32 +9,22 @@
|
||||
|
||||
#include <xenia/cpu/cpu-private.h>
|
||||
|
||||
|
||||
// Tracing:
|
||||
DEFINE_bool(trace_instructions, false,
|
||||
"Trace all instructions.");
|
||||
DEFINE_bool(trace_registers, false,
|
||||
"Trace register values when tracing instructions.");
|
||||
DEFINE_bool(trace_branches, false,
|
||||
"Trace all branches.");
|
||||
DEFINE_bool(trace_user_calls, false,
|
||||
"Trace all user function calls.");
|
||||
DEFINE_bool(trace_kernel_calls, false,
|
||||
"Trace all kernel function calls.");
|
||||
DEFINE_uint64(trace_thread_mask, -1,
|
||||
"Trace threads with IDs in the mask, or -1 for all.");
|
||||
|
||||
|
||||
// Debugging:
|
||||
DEFINE_string(load_module_map, "",
|
||||
DEFINE_bool(trace_function_generation, false,
|
||||
"Trace function generation/JITing.");
|
||||
DEFINE_bool(trace_kernel_calls, false, "Trace all kernel function calls.");
|
||||
DEFINE_bool(trace_user_calls, false, "Trace all user function calls.");
|
||||
DEFINE_bool(trace_instructions, false, "Trace all instructions.");
|
||||
DEFINE_bool(trace_registers, false,
|
||||
"Trace register values when tracing instructions.");
|
||||
DEFINE_string(
|
||||
load_module_map, "",
|
||||
"Loads a .map for symbol names and to diff with the generated symbol "
|
||||
"database.");
|
||||
|
||||
|
||||
// Dumping:
|
||||
DEFINE_string(dump_path, "build/",
|
||||
"Directory that dump files are placed into.");
|
||||
"Directory that dump files are placed into.");
|
||||
DEFINE_bool(dump_module_bitcode, true,
|
||||
"Writes the module bitcode both before and after optimizations.");
|
||||
DEFINE_bool(dump_module_map, true,
|
||||
"Dumps the module symbol database.");
|
||||
"Writes the module bitcode both before and after optimizations.");
|
||||
DEFINE_bool(dump_module_map, true, "Dumps the module symbol database.");
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/cpu/cpu-private.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/cpu/xenon_runtime.h>
|
||||
#include <xenia/cpu/xex_module.h>
|
||||
@@ -70,7 +71,26 @@ Processor::~Processor() {
|
||||
int Processor::Setup() {
|
||||
assert_null(runtime_);
|
||||
|
||||
runtime_ = new XenonRuntime(memory_, export_resolver_);
|
||||
uint32_t debug_info_flags = DEBUG_INFO_DEFAULT;
|
||||
uint32_t trace_flags = 0;
|
||||
if (FLAGS_trace_function_generation) {
|
||||
trace_flags |= TRACE_FUNCTION_GENERATION;
|
||||
}
|
||||
if (FLAGS_trace_kernel_calls) {
|
||||
trace_flags |= TRACE_EXTERN_CALLS;
|
||||
}
|
||||
if (FLAGS_trace_user_calls) {
|
||||
trace_flags |= TRACE_USER_CALLS;
|
||||
}
|
||||
if (FLAGS_trace_instructions) {
|
||||
trace_flags |= TRACE_SOURCE;
|
||||
}
|
||||
if (FLAGS_trace_registers) {
|
||||
trace_flags |= TRACE_SOURCE_VALUES;
|
||||
}
|
||||
|
||||
runtime_ = new XenonRuntime(memory_, export_resolver_, debug_info_flags,
|
||||
trace_flags);
|
||||
if (!runtime_) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,11 @@ using namespace alloy::runtime;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
|
||||
|
||||
XenonRuntime::XenonRuntime(
|
||||
alloy::Memory* memory, ExportResolver* export_resolver) :
|
||||
Runtime(memory),
|
||||
export_resolver_(export_resolver) {
|
||||
}
|
||||
XenonRuntime::XenonRuntime(alloy::Memory* memory,
|
||||
ExportResolver* export_resolver,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags)
|
||||
: Runtime(memory, debug_info_flags, trace_flags),
|
||||
export_resolver_(export_resolver) {}
|
||||
|
||||
XenonRuntime::~XenonRuntime() = default;
|
||||
|
||||
|
||||
@@ -17,29 +17,26 @@
|
||||
|
||||
XEDECLARECLASS1(xe, ExportResolver);
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
class XenonThreadState;
|
||||
|
||||
|
||||
class XenonRuntime : public alloy::runtime::Runtime {
|
||||
public:
|
||||
XenonRuntime(Memory* memory, ExportResolver* export_resolver);
|
||||
public:
|
||||
XenonRuntime(Memory* memory, ExportResolver* export_resolver,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags);
|
||||
virtual ~XenonRuntime();
|
||||
|
||||
ExportResolver* export_resolver() const { return export_resolver_; }
|
||||
|
||||
virtual int Initialize(std::unique_ptr<alloy::backend::Backend> backend = 0);
|
||||
|
||||
private:
|
||||
private:
|
||||
ExportResolver* export_resolver_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_XENON_RUNTIME_H_
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <xenia/cpu/xenon_thread_state.h>
|
||||
|
||||
#include <xdb/protocol.h>
|
||||
#include <xenia/cpu/xenon_runtime.h>
|
||||
|
||||
using namespace alloy;
|
||||
@@ -36,6 +37,7 @@ XenonThreadState::XenonThreadState(XenonRuntime* runtime, uint32_t thread_id,
|
||||
context_->membase = memory_->membase();
|
||||
context_->runtime = runtime;
|
||||
context_->thread_state = this;
|
||||
context_->thread_id = thread_id_;
|
||||
|
||||
// Set initial registers.
|
||||
context_->r[1] = stack_address_ + stack_size;
|
||||
@@ -56,3 +58,28 @@ XenonThreadState::~XenonThreadState() {
|
||||
xe_free_aligned(context_);
|
||||
memory_->HeapFree(stack_address_, stack_size_);
|
||||
}
|
||||
|
||||
void XenonThreadState::WriteRegisters(xdb::protocol::Registers* registers) {
|
||||
registers->lr = context_->lr;
|
||||
registers->ctr = context_->ctr;
|
||||
registers->xer = 0xFEFEFEFE;
|
||||
registers->cr[0] = context_->cr0.value;
|
||||
registers->cr[1] = context_->cr1.value;
|
||||
registers->cr[2] = context_->cr2.value;
|
||||
registers->cr[3] = context_->cr3.value;
|
||||
registers->cr[4] = context_->cr4.value;
|
||||
registers->cr[5] = context_->cr5.value;
|
||||
registers->cr[6] = context_->cr6.value;
|
||||
registers->cr[7] = context_->cr7.value;
|
||||
registers->fpscr = context_->fpscr.value;
|
||||
registers->vscr = context_->vscr_sat;
|
||||
static_assert(sizeof(registers->gpr) == sizeof(context_->r),
|
||||
"structs must match");
|
||||
static_assert(sizeof(registers->fpr) == sizeof(context_->f),
|
||||
"structs must match");
|
||||
static_assert(sizeof(registers->vr) == sizeof(context_->v),
|
||||
"structs must match");
|
||||
memcpy(registers->gpr, context_->r, sizeof(context_->r));
|
||||
memcpy(registers->fpr, context_->f, sizeof(context_->f));
|
||||
memcpy(registers->vr, context_->v, sizeof(context_->v));
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
namespace xdb {
|
||||
namespace protocol {
|
||||
struct Registers;
|
||||
} // namespace protocol
|
||||
} // namespace xdb
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
@@ -34,6 +39,8 @@ public:
|
||||
uint64_t thread_state_address() const { return thread_state_address_; }
|
||||
PPCContext* context() const { return context_; }
|
||||
|
||||
void WriteRegisters(xdb::protocol::Registers* registers);
|
||||
|
||||
private:
|
||||
uint64_t stack_address_;
|
||||
size_t stack_size_;
|
||||
|
||||
79
src/xenia/debug_agent.cc
Normal file
79
src/xenia/debug_agent.cc
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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 <xenia/debug_agent.h>
|
||||
|
||||
#include <codecvt>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
DEFINE_string(trace_file, "", "Trace to the given file.");
|
||||
DEFINE_uint64(trace_capacity, 0x40000000, "Trace file capacity to allocate.");
|
||||
|
||||
namespace xe {
|
||||
|
||||
DebugAgent::DebugAgent(Emulator* emulator)
|
||||
: emulator_(emulator),
|
||||
file_(nullptr),
|
||||
file_mapping_(nullptr),
|
||||
trace_base_(0) {}
|
||||
|
||||
DebugAgent::~DebugAgent() {
|
||||
if (trace_base_) {
|
||||
UnmapViewOfFile(trace_base_);
|
||||
}
|
||||
|
||||
CloseHandle(file_mapping_);
|
||||
CloseHandle(file_);
|
||||
}
|
||||
|
||||
int DebugAgent::Initialize() {
|
||||
if (!FLAGS_trace_file.empty()) {
|
||||
if (SetupTracing(FLAGS_trace_file, FLAGS_trace_capacity)) {
|
||||
XELOGE("Failed to setup tracing - out of disk space?");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DebugAgent::SetupTracing(const std::string& trace_file, uint64_t capacity) {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cvt;
|
||||
auto file_path = cvt.from_bytes(trace_file);
|
||||
file_ = CreateFile(file_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY,
|
||||
nullptr);
|
||||
if (!file_) {
|
||||
XELOGE("Could not open trace file for writing");
|
||||
return 1;
|
||||
}
|
||||
|
||||
file_mapping_ = CreateFileMapping(
|
||||
file_, nullptr, PAGE_READWRITE, static_cast<uint32_t>(capacity >> 32),
|
||||
static_cast<uint32_t>(capacity), L"Local\\xenia_xdb_trace");
|
||||
if (!file_mapping_) {
|
||||
XELOGE("Could not create trace file mapping - out of disk space?");
|
||||
return 1;
|
||||
}
|
||||
|
||||
trace_base_ = MapViewOfFile(file_mapping_, FILE_MAP_WRITE, 0, 0, 0);
|
||||
if (!trace_base_) {
|
||||
XELOGE("Could not map view of trace file - out of disk space?");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Store initial trace base.
|
||||
poly::store<uint64_t>(trace_base_, trace_base() + 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
44
src/xenia/debug_agent.h
Normal file
44
src/xenia/debug_agent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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 XENIA_DEBUG_AGENT_H_
|
||||
#define XENIA_DEBUG_AGENT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <xenia/core.h>
|
||||
|
||||
namespace xe {
|
||||
|
||||
class Emulator;
|
||||
|
||||
class DebugAgent {
|
||||
public:
|
||||
DebugAgent(Emulator* emulator);
|
||||
~DebugAgent();
|
||||
|
||||
uint64_t trace_base() const {
|
||||
return reinterpret_cast<uint64_t>(trace_base_);
|
||||
}
|
||||
|
||||
int Initialize();
|
||||
|
||||
private:
|
||||
int SetupTracing(const std::string& trace_file, uint64_t capacity);
|
||||
|
||||
Emulator* emulator_;
|
||||
|
||||
HANDLE file_;
|
||||
HANDLE file_mapping_;
|
||||
void* trace_base_;
|
||||
};
|
||||
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_DEBUG_AGENT_H_
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <xenia/emulator.h>
|
||||
|
||||
#include <xdb/protocol.h>
|
||||
#include <xenia/apu/apu.h>
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
@@ -44,10 +45,17 @@ Emulator::Emulator(const xechar_t* command_line) :
|
||||
Emulator::~Emulator() {
|
||||
// Note that we delete things in the reverse order they were initialized.
|
||||
|
||||
auto ev = xdb::protocol::ProcessExitEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::PROCESS_EXIT;
|
||||
}
|
||||
|
||||
if (main_window_) {
|
||||
main_window_->Close();
|
||||
}
|
||||
|
||||
debug_agent_.reset();
|
||||
|
||||
delete xam_;
|
||||
delete xboxkrnl_;
|
||||
delete kernel_state_;
|
||||
@@ -70,11 +78,16 @@ Emulator::~Emulator() {
|
||||
X_STATUS Emulator::Setup() {
|
||||
X_STATUS result = X_STATUS_UNSUCCESSFUL;
|
||||
|
||||
debug_agent_.reset(new DebugAgent(this));
|
||||
result = debug_agent_->Initialize();
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Create memory system first, as it is required for other systems.
|
||||
memory_ = new XenonMemory();
|
||||
XEEXPECTNOTNULL(memory_);
|
||||
result = memory_->Initialize();
|
||||
XEEXPECTZERO(result);
|
||||
memory_->set_trace_base(debug_agent_->trace_base());
|
||||
|
||||
// Shared export resolver used to attach and query for HLE exports.
|
||||
export_resolver_ = new ExportResolver();
|
||||
@@ -144,6 +157,11 @@ X_STATUS Emulator::LaunchXexFile(const xechar_t* path) {
|
||||
// and then get that symlinked to game:\, so
|
||||
// -> game:\foo.xex
|
||||
|
||||
auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::PROCESS_START;
|
||||
}
|
||||
|
||||
int result_code = 0;
|
||||
|
||||
// Get just the filename (foo.xex).
|
||||
@@ -193,6 +211,11 @@ X_STATUS Emulator::LaunchXexFile(const xechar_t* path) {
|
||||
X_STATUS Emulator::LaunchDiscImage(const xechar_t* path) {
|
||||
int result_code = 0;
|
||||
|
||||
auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::PROCESS_START;
|
||||
}
|
||||
|
||||
// Register the disc image in the virtual filesystem.
|
||||
result_code = file_system_->RegisterDiscImageDevice(
|
||||
"\\Device\\Cdrom0", path);
|
||||
@@ -216,6 +239,11 @@ X_STATUS Emulator::LaunchDiscImage(const xechar_t* path) {
|
||||
X_STATUS Emulator::LaunchSTFSTitle(const xechar_t* path) {
|
||||
int result_code = 0;
|
||||
|
||||
auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::PROCESS_START;
|
||||
}
|
||||
|
||||
// TODO(benvanik): figure out paths.
|
||||
|
||||
// Register the disc image in the virtual filesystem.
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/debug_agent.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
|
||||
@@ -19,7 +20,6 @@
|
||||
XEDECLARECLASS1(xe, ExportResolver);
|
||||
XEDECLARECLASS2(xe, apu, AudioSystem);
|
||||
XEDECLARECLASS2(xe, cpu, Processor);
|
||||
XEDECLARECLASS2(xe, debug, DebugServer);
|
||||
XEDECLARECLASS2(xe, gpu, GraphicsSystem);
|
||||
XEDECLARECLASS2(xe, hid, InputSystem);
|
||||
XEDECLARECLASS2(xe, kernel, KernelState);
|
||||
@@ -31,7 +31,6 @@ XEDECLARECLASS2(xe, ui, Window);
|
||||
|
||||
namespace xe {
|
||||
|
||||
|
||||
class Emulator {
|
||||
public:
|
||||
Emulator(const xechar_t* command_line);
|
||||
@@ -44,7 +43,7 @@ public:
|
||||
|
||||
cpu::XenonMemory* memory() const { return memory_; }
|
||||
|
||||
debug::DebugServer* debug_server() const { return debug_server_; }
|
||||
DebugAgent* debug_agent() const { return debug_agent_.get(); }
|
||||
|
||||
cpu::Processor* processor() const { return processor_; }
|
||||
apu::AudioSystem* audio_system() const { return audio_system_; }
|
||||
@@ -71,7 +70,7 @@ private:
|
||||
|
||||
cpu::XenonMemory* memory_;
|
||||
|
||||
debug::DebugServer* debug_server_;
|
||||
std::unique_ptr<DebugAgent> debug_agent_;
|
||||
|
||||
cpu::Processor* processor_;
|
||||
apu::AudioSystem* audio_system_;
|
||||
|
||||
@@ -73,6 +73,10 @@ KernelState* KernelState::shared() {
|
||||
return shared_kernel_state_;
|
||||
}
|
||||
|
||||
void KernelState::RegisterModule(XModule* module) {}
|
||||
|
||||
void KernelState::UnregisterModule(XModule* module) {}
|
||||
|
||||
XModule* KernelState::GetModule(const char* name) {
|
||||
if (!name) {
|
||||
// NULL name = self.
|
||||
|
||||
@@ -56,6 +56,8 @@ public:
|
||||
|
||||
ObjectTable* object_table() const { return object_table_; }
|
||||
|
||||
void RegisterModule(XModule* module);
|
||||
void UnregisterModule(XModule* module);
|
||||
XModule* GetModule(const char* name);
|
||||
XUserModule* GetExecutableModule();
|
||||
void SetExecutableModule(XUserModule* module);
|
||||
|
||||
@@ -24,6 +24,8 @@ XKernelModule::XKernelModule(KernelState* kernel_state, const char* path) :
|
||||
emulator_ = kernel_state->emulator();
|
||||
memory_ = emulator_->memory();
|
||||
export_resolver_ = kernel_state->emulator()->export_resolver();
|
||||
|
||||
OnLoad();
|
||||
}
|
||||
|
||||
XKernelModule::~XKernelModule() {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <xenia/kernel/objects/xmodule.h>
|
||||
|
||||
#include <xdb/protocol.h>
|
||||
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
@@ -32,6 +34,23 @@ XModule::XModule(KernelState* kernel_state, const char* path) :
|
||||
}
|
||||
|
||||
XModule::~XModule() {
|
||||
auto ev = xdb::protocol::ModuleUnloadEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::MODULE_UNLOAD;
|
||||
ev->module_id = handle();
|
||||
}
|
||||
|
||||
kernel_state_->UnregisterModule(this);
|
||||
}
|
||||
|
||||
void XModule::OnLoad() {
|
||||
auto ev = xdb::protocol::ModuleLoadEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::MODULE_LOAD;
|
||||
ev->module_id = handle();
|
||||
}
|
||||
|
||||
kernel_state_->RegisterModule(this);
|
||||
}
|
||||
|
||||
X_STATUS XModule::GetSection(
|
||||
|
||||
@@ -33,6 +33,8 @@ public:
|
||||
uint32_t* out_section_data, uint32_t* out_section_size);
|
||||
|
||||
protected:
|
||||
void OnLoad();
|
||||
|
||||
char name_[256];
|
||||
char path_[poly::max_path];
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <poly/math.h>
|
||||
|
||||
#include <xdb/protocol.h>
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/kernel/native_list.h>
|
||||
#include <xenia/kernel/xboxkrnl_threading.h>
|
||||
@@ -70,6 +71,12 @@ XThread::XThread(KernelState* kernel_state,
|
||||
}
|
||||
|
||||
XThread::~XThread() {
|
||||
auto ev = xdb::protocol::ThreadExitEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::THREAD_EXIT;
|
||||
ev->thread_id = handle();
|
||||
}
|
||||
|
||||
// Unregister first to prevent lookups while deleting.
|
||||
kernel_state_->UnregisterThread(this);
|
||||
|
||||
@@ -254,6 +261,13 @@ X_STATUS XThread::Create() {
|
||||
SetAffinity(proc_mask);
|
||||
}
|
||||
|
||||
auto ev = xdb::protocol::ThreadCreateEvent::Append(memory()->trace_base());
|
||||
if (ev) {
|
||||
ev->type = xdb::protocol::EventType::THREAD_CREATE;
|
||||
ev->thread_id = handle();
|
||||
thread_state_->WriteRegisters(&ev->registers);
|
||||
}
|
||||
|
||||
module->Release();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
OnLoad();
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
'common.h',
|
||||
'config.h',
|
||||
'core.h',
|
||||
'debug_agent.cc',
|
||||
'debug_agent.h',
|
||||
'emulator.cc',
|
||||
'emulator.h',
|
||||
'export_resolver.cc',
|
||||
|
||||
Reference in New Issue
Block a user