Displaying (unformatted) function code.

This commit is contained in:
Ben Vanik
2013-12-22 09:25:44 -08:00
parent 4ecdfed46f
commit c92142ca02
20 changed files with 242 additions and 44 deletions

View File

@@ -18,6 +18,7 @@ namespace hir {
class FunctionBuilder;
}
namespace runtime {
class DebugInfo;
class Function;
class FunctionInfo;
class Runtime;
@@ -41,7 +42,7 @@ public:
virtual int Assemble(
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
runtime::Function** out_function) = 0;
runtime::DebugInfo* debug_info, runtime::Function** out_function) = 0;
protected:
Backend* backend_;

View File

@@ -53,8 +53,9 @@ void IVMAssembler::Reset() {
int IVMAssembler::Assemble(
FunctionInfo* symbol_info, FunctionBuilder* builder,
Function** out_function) {
DebugInfo* debug_info, Function** out_function) {
IVMFunction* fn = new IVMFunction(symbol_info);
fn->set_debug_info(debug_info);
TranslationContext ctx;
ctx.access_callbacks = backend_->runtime()->access_callbacks();

View File

@@ -31,7 +31,7 @@ public:
virtual int Assemble(
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
runtime::Function** out_function);
runtime::DebugInfo* debug_info, runtime::Function** out_function);
private:
Arena intcode_arena_;

View File

@@ -13,6 +13,7 @@
#include <alloy/frontend/tracing.h>
#include <alloy/frontend/ppc/ppc_frontend.h>
#include <alloy/frontend/ppc/ppc_function_builder.h>
#include <alloy/frontend/ppc/ppc_instr.h>
#include <alloy/frontend/ppc/ppc_scanner.h>
#include <alloy/runtime/runtime.h>
@@ -34,6 +35,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
compiler_->AddPass(new passes::ContextPromotionPass());
compiler_->AddPass(new passes::SimplificationPass());
// TODO(benvanik): run repeatedly?
compiler_->AddPass(new passes::ConstantPropagationPass());
//compiler_->AddPass(new passes::TypePropagationPass());
//compiler_->AddPass(new passes::ByteSwapEliminationPass());
@@ -55,9 +57,6 @@ PPCTranslator::~PPCTranslator() {
int PPCTranslator::Translate(
FunctionInfo* symbol_info,
Function** out_function) {
char* pre_ir = NULL;
char* post_ir = NULL;
// Scan the function to find its extents. We only need to do this if we
// haven't already been provided with them from some other source.
if (!symbol_info->has_end_address()) {
@@ -70,13 +69,24 @@ int PPCTranslator::Translate(
}
}
// NOTE: we only want to do this when required, as it's expensive to build.
DebugInfo* debug_info = new DebugInfo();
// Stash source.
if (debug_info) {
DumpSource(symbol_info, &string_buffer_);
debug_info->set_source_disasm(string_buffer_.ToString());
string_buffer_.Reset();
}
// Emit function.
int result = builder_->Emit(symbol_info);
XEEXPECTZERO(result);
if (true) {
// Stash raw HIR.
if (debug_info) {
builder_->Dump(&string_buffer_);
pre_ir = string_buffer_.ToString();
debug_info->set_raw_hir_disasm(string_buffer_.ToString());
string_buffer_.Reset();
}
@@ -84,24 +94,64 @@ int PPCTranslator::Translate(
result = compiler_->Compile(builder_);
XEEXPECTZERO(result);
if (true) {
// Stash optimized HIR.
if (debug_info) {
builder_->Dump(&string_buffer_);
post_ir = string_buffer_.ToString();
debug_info->set_hir_disasm(string_buffer_.ToString());
string_buffer_.Reset();
}
// Assemble to backend machine code.
result = assembler_->Assemble(symbol_info, builder_, out_function);
result = assembler_->Assemble(symbol_info, builder_, debug_info, out_function);
XEEXPECTZERO(result);
result = 0;
XECLEANUP:
if (pre_ir) xe_free(pre_ir);
if (post_ir) xe_free(post_ir);
if (result) {
delete debug_info;
}
builder_->Reset();
compiler_->Reset();
assembler_->Reset();
string_buffer_.Reset();
return result;
};
void PPCTranslator::DumpSource(
runtime::FunctionInfo* symbol_info, StringBuffer* string_buffer) {
Memory* memory = frontend_->memory();
const uint8_t* p = memory->membase();
// TODO(benvanik): get/make up symbol name.
string_buffer->Append("%s fn %.8X-%.8X %s\n",
symbol_info->module()->name(),
symbol_info->address(), symbol_info->end_address(),
"(symbol name)");
uint64_t start_address = symbol_info->address();
uint64_t end_address = symbol_info->end_address();
InstrData i;
for (uint64_t address = start_address, offset = 0; address <= end_address;
address += 4, offset++) {
i.address = address;
i.code = XEGETUINT32BE(p + address);
// TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code);
// TODO(benvanik): labels and such
if (!i.type) {
string_buffer->Append("%.8X %.8X ???", address, i.code);
} else if (i.type->disassemble) {
ppc::InstrDisasm d;
i.type->disassemble(i, d);
std::string disasm;
d.Dump(disasm);
string_buffer->Append("%.8X %.8X %s", address, i.code, disasm.c_str());
} else {
string_buffer->Append("%.8X %.8X %s ???", address, i.code, i.type->name);
}
string_buffer->Append("\n");
}
}

View File

@@ -33,6 +33,10 @@ public:
int Translate(runtime::FunctionInfo* symbol_info,
runtime::Function** out_function);
private:
void DumpSource(runtime::FunctionInfo* symbol_info,
StringBuffer* string_buffer);
private:
PPCFrontend* frontend_;
PPCScanner* scanner_;

View File

@@ -0,0 +1,32 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/runtime/debug_info.h>
using namespace alloy;
using namespace alloy::runtime;
DebugInfo::DebugInfo() :
source_disasm_(0),
raw_hir_disasm_(0),
hir_disasm_(0),
raw_lir_disasm_(0),
lir_disasm_(0),
machine_code_disasm_(0) {
}
DebugInfo::~DebugInfo() {
xe_free(source_disasm_);
xe_free(raw_hir_disasm_);
xe_free(hir_disasm_);
xe_free(raw_lir_disasm_);
xe_free(lir_disasm_);
xe_free(machine_code_disasm_);
}

View File

@@ -0,0 +1,57 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef ALLOY_RUNTIME_DEBUG_INFO_H_
#define ALLOY_RUNTIME_DEBUG_INFO_H_
#include <alloy/core.h>
namespace alloy {
namespace runtime {
class DebugInfo {
public:
DebugInfo();
~DebugInfo();
const char* source_disasm() const { return source_disasm_; }
void set_source_disasm(char* value) { source_disasm_ = value; }
const char* raw_hir_disasm() const { return raw_hir_disasm_; }
void set_raw_hir_disasm(char* value) { raw_hir_disasm_ = value; }
const char* hir_disasm() const { return hir_disasm_; }
void set_hir_disasm(char* value) { hir_disasm_ = value; }
const char* raw_lir_disasm() const { return raw_lir_disasm_; }
void set_raw_lir_disasm(char* value) { raw_lir_disasm_ = value; }
const char* lir_disasm() const { return lir_disasm_; }
void set_lir_disasm(char* value) { lir_disasm_ = value; }
const char* machine_code_disasm() const { return machine_code_disasm_; }
void set_machine_code_disasm(char* value) { machine_code_disasm_ = value; }
// map functions: source addr -> hir index (raw?)
// hir index (raw?) to lir index (raw?)
// lir index (raw?) to machine code offset
// source -> machine code offset
private:
char* source_disasm_;
char* raw_hir_disasm_;
char* hir_disasm_;
char* raw_lir_disasm_;
char* lir_disasm_;
char* machine_code_disasm_;
};
} // namespace runtime
} // namespace alloy
#endif // ALLOY_RUNTIME_DEBUG_INFO_H_

View File

@@ -17,7 +17,7 @@ using namespace alloy::runtime;
Function::Function(Type type, uint64_t address) :
type_(type), address_(address) {
type_(type), address_(address), debug_info_(0) {
}
Function::~Function() {

View File

@@ -11,6 +11,7 @@
#define ALLOY_RUNTIME_FUNCTION_H_
#include <alloy/core.h>
#include <alloy/runtime/debug_info.h>
namespace alloy {
@@ -34,6 +35,9 @@ public:
Type type() const { return type_; }
uint64_t address() const { return address_; }
DebugInfo* debug_info() const { return debug_info_; }
void set_debug_info(DebugInfo* debug_info) { debug_info_ = debug_info; }
int Call(ThreadState* thread_state, uint64_t return_address);
protected:
@@ -42,6 +46,7 @@ protected:
protected:
Type type_;
uint64_t address_;
DebugInfo* debug_info_;
};

View File

@@ -1,6 +1,8 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'debug_info.cc',
'debug_info.h',
'entry_table.cc',
'entry_table.h',
'function.cc',

View File

@@ -234,6 +234,11 @@ json_t* Processor::OnDebugRequest(
succeeded = false;
return json_string("Unable to resolve function");
}
DebugInfo* debug_info = fn->debug_info();
if (!debug_info) {
succeeded = false;
return json_string("No debug info present for function");
}
json_t* fn_json = json_object();
// TODO(benvanik): get name
@@ -249,6 +254,22 @@ json_t* Processor::OnDebugRequest(
json_t* link_status_json = json_integer(info->status());
json_object_set_new(fn_json, "linkStatus", link_status_json);
json_t* disasm_json = json_object();
json_t* disasm_str_json;
disasm_str_json = json_string(debug_info->source_disasm());
json_object_set_new(disasm_json, "source", disasm_str_json);
disasm_str_json = json_string(debug_info->raw_hir_disasm());
json_object_set_new(disasm_json, "rawHir", disasm_str_json);
disasm_str_json = json_string(debug_info->hir_disasm());
json_object_set_new(disasm_json, "hir", disasm_str_json);
disasm_str_json = json_string(debug_info->raw_lir_disasm());
json_object_set_new(disasm_json, "rawLir", disasm_str_json);
disasm_str_json = json_string(debug_info->lir_disasm());
json_object_set_new(disasm_json, "lir", disasm_str_json);
disasm_str_json = json_string(debug_info->machine_code_disasm());
json_object_set_new(disasm_json, "machineCode", disasm_str_json);
json_object_set_new(fn_json, "disasm", disasm_json);
delete fn;
return fn_json;