--trace_functions and --trace_function_coverage

This commit is contained in:
Ben Vanik
2015-05-05 22:44:36 -07:00
parent ade5388728
commit 94c62b91d0
24 changed files with 365 additions and 82 deletions

View File

@@ -9,11 +9,16 @@
#include "xenia/debug/debugger.h"
#include <gflags/gflags.h>
#include <mutex>
#include "xenia/base/string.h"
#include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h"
DEFINE_string(debug_session_path, "", "Debug output path.");
namespace xe {
namespace debug {
@@ -28,6 +33,34 @@ Debugger::Debugger(cpu::Processor* processor) : processor_(processor) {}
Debugger::~Debugger() = default;
bool Debugger::StartSession() {
std::wstring session_path = xe::to_wstring(FLAGS_debug_session_path);
std::wstring trace_functions_path =
xe::join_paths(session_path, L"trace.functions");
trace_functions_ = ChunkedMappedMemoryWriter::Open(trace_functions_path,
32 * 1024 * 1024, true);
return true;
}
void Debugger::StopSession() {
FlushSession();
trace_functions_.reset();
}
void Debugger::FlushSession() {
if (trace_functions_) {
trace_functions_->Flush();
}
}
uint8_t* Debugger::AllocateTraceFunctionData(size_t size) {
if (!trace_functions_) {
return nullptr;
}
return trace_functions_->Allocate(size);
}
int Debugger::SuspendAllThreads(uint32_t timeout_ms) {
std::lock_guard<std::mutex> guard(threads_lock_);

View File

@@ -11,11 +11,13 @@
#define XENIA_DEBUG_DEBUGGER_H_
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include "xenia/base/delegate.h"
#include "xenia/base/mapped_memory.h"
#include "xenia/cpu/thread_state.h"
#include "xenia/debug/breakpoint.h"
@@ -65,6 +67,12 @@ class Debugger {
cpu::Processor* processor() const { return processor_; }
bool StartSession();
void StopSession();
void FlushSession();
uint8_t* AllocateTraceFunctionData(size_t size);
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX);
int ResumeThread(uint32_t thread_id);
int ResumeAllThreads(bool force = false);
@@ -92,6 +100,8 @@ class Debugger {
private:
cpu::Processor* processor_;
std::unique_ptr<ChunkedMappedMemoryWriter> trace_functions_;
std::mutex threads_lock_;
std::unordered_map<uint32_t, cpu::ThreadState*> threads_;

View File

@@ -5,5 +5,6 @@
'debug_server.h',
'debugger.cc',
'debugger.h',
'trace_data.h',
],
}

View File

@@ -0,0 +1,92 @@
/**
******************************************************************************
* 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_DEBUG_TRACE_DATA_H_
#define XENIA_DEBUG_TRACE_DATA_H_
#include <cstdint>
#include "xenia/base/memory.h"
namespace xe {
namespace debug {
class FunctionTraceData {
public:
static const int kFunctionCallerHistoryCount = 4;
struct Header {
// Format is used by tooling, changes must be made across all targets.
// + 0 4b (data size)
// + 4 4b start_address
// + 8 4b end_address
// +12 4b type (user, external, etc)
// +16 8b function_thread_use // bitmask of thread id
// +24 8b function_call_count
// +32 4b+ function_caller_history[4]
// +48 8b+ instruction_execute_count[instruction count]
uint32_t data_size;
uint32_t start_address;
uint32_t end_address;
uint32_t type;
uint64_t function_thread_use;
uint64_t function_call_count;
uint32_t function_caller_history[kFunctionCallerHistoryCount];
// uint64_t instruction_execute_count[];
};
FunctionTraceData() : header_(nullptr) {}
void Reset(uint8_t* trace_data, size_t trace_data_size,
uint32_t start_address, uint32_t end_address) {
header_ = reinterpret_cast<Header*>(trace_data);
header_->data_size = uint32_t(trace_data_size);
header_->start_address = start_address;
header_->end_address = end_address;
header_->type = 0;
header_->function_thread_use = 0;
header_->function_call_count = 0;
for (int i = 0; i < kFunctionCallerHistoryCount; ++i) {
header_->function_caller_history[i] = 0;
}
// Clear any remaining.
std::memset(trace_data + sizeof(Header), 0,
trace_data_size - sizeof(Header));
}
bool is_valid() const { return header_ != nullptr; }
uint32_t start_address() const { return header_->start_address; }
uint32_t end_address() const { return header_->end_address; }
uint32_t instruction_count() const {
return (header_->end_address - header_->start_address) / 4 + 1;
}
Header* header() const { return header_; }
uint8_t* instruction_execute_counts() const {
return reinterpret_cast<uint8_t*>(header_) + sizeof(Header);
}
static size_t SizeOfHeader() { return sizeof(Header); }
static size_t SizeOfInstructionCounts(uint32_t start_address,
uint32_t end_address) {
uint32_t instruction_count = (end_address - start_address) / 4 + 1;
return instruction_count * 8;
}
private:
Header* header_;
};
} // namespace debug
} // namespace xe
#endif // XENIA_DEBUG_TRACE_DATA_H_