Displaying (unformatted) function code.
This commit is contained in:
parent
4ecdfed46f
commit
c92142ca02
|
@ -21,7 +21,11 @@ module.controller('CodeTabController', function(
|
||||||
$scope.selectedModule = null;
|
$scope.selectedModule = null;
|
||||||
$scope.functionList = [];
|
$scope.functionList = [];
|
||||||
|
|
||||||
$rootScope.$on('refresh', function() {
|
function refresh() {
|
||||||
|
if (!app.session || !app.session.dataSource) {
|
||||||
|
$scope.moduleList = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
var dataSource = app.session.dataSource;
|
var dataSource = app.session.dataSource;
|
||||||
|
|
||||||
dataSource.getModuleList().then(function(list) {
|
dataSource.getModuleList().then(function(list) {
|
||||||
|
@ -38,7 +42,8 @@ module.controller('CodeTabController', function(
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('refresh');
|
console.log('refresh');
|
||||||
});
|
};
|
||||||
|
$rootScope.$on('refresh', refresh);
|
||||||
|
|
||||||
$scope.selectModule = function(module) {
|
$scope.selectModule = function(module) {
|
||||||
var moduleChange = module != $scope.selectedModule;
|
var moduleChange = module != $scope.selectedModule;
|
||||||
|
@ -55,4 +60,8 @@ module.controller('CodeTabController', function(
|
||||||
log.error('Unable to fetch function list');
|
log.error('Unable to fetch function list');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (app.session.dataSource) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,9 +7,12 @@
|
||||||
<div class="debugger-fnview-header-right">
|
<div class="debugger-fnview-header-right">
|
||||||
<div class="btn-toolbar" role="toolbar">
|
<div class="btn-toolbar" role="toolbar">
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'ppc'">PPC</button>
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'source'">PPC</button>
|
||||||
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'rawHir'">HIR (raw)</button>
|
||||||
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'hir'">HIR</button>
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'hir'">HIR</button>
|
||||||
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'rawLir'">LIR (raw)</button>
|
||||||
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'lir'">LIR</button>
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'lir'">LIR</button>
|
||||||
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'machineCode'">MC</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
<button type="button" class="btn btn-default">1</button>
|
<button type="button" class="btn btn-default">1</button>
|
||||||
|
@ -29,7 +32,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnview-body">
|
<div class="debugger-fnview-body">
|
||||||
<div ui-view></div>
|
|
||||||
<div class="debugger-fnview-codeview">
|
<div class="debugger-fnview-codeview">
|
||||||
<textarea class="debugger-fnview-textarea"></textarea>
|
<textarea class="debugger-fnview-textarea"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,17 +17,47 @@ var module = angular.module('xe.ui.code.functionView', [
|
||||||
|
|
||||||
module.controller('FunctionViewController', function(
|
module.controller('FunctionViewController', function(
|
||||||
$rootScope, $scope, app, log) {
|
$rootScope, $scope, app, log) {
|
||||||
$scope.codeType = 'ppc';
|
$scope.codeType = 'source';
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
|
if (!app.session || !app.session.dataSource) {
|
||||||
|
$scope.fn = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
var dataSource = app.session.dataSource;
|
var dataSource = app.session.dataSource;
|
||||||
|
|
||||||
dataSource.getFunction($scope.functionAddress).then(function(fn) {
|
dataSource.getFunction($scope.functionAddress).then(function(fn) {
|
||||||
$scope.fn = fn;
|
$scope.fn = fn;
|
||||||
|
updateCode();
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
log.error('Unable to fetch function');
|
log.error('Unable to fetch function');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$rootScope.$on('refresh', refresh);
|
$rootScope.$on('refresh', refresh);
|
||||||
$scope.$watch('functionAddress', refresh);
|
$scope.$watch('functionAddress', refresh);
|
||||||
|
|
||||||
|
var textArea = document.querySelector('.debugger-fnview-textarea');
|
||||||
|
$scope.codeMirror = CodeMirror.fromTextArea(textArea, {
|
||||||
|
mode: 'javascript',
|
||||||
|
theme: 'default',
|
||||||
|
indentUnit: 2,
|
||||||
|
tabSize: 2,
|
||||||
|
lineNumbers: true,
|
||||||
|
firstLineNumber: 0,
|
||||||
|
lineNumberFormatter: function(line) {
|
||||||
|
return String(line);
|
||||||
|
},
|
||||||
|
gutters: [],
|
||||||
|
readOnly: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateCode() {
|
||||||
|
var codeType = $scope.codeType;
|
||||||
|
var value = '';
|
||||||
|
if ($scope.fn) {
|
||||||
|
value = $scope.fn.disasm[codeType];
|
||||||
|
}
|
||||||
|
$scope.codeMirror.setValue(value || '');
|
||||||
|
};
|
||||||
|
$scope.$watch('codeType', updateCode);
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
<button type="button" class="btn btn-default" ng-click="connect()" ng-disabled="app.loading">
|
<button type="button" class="btn btn-default" ng-click="connect()" ng-disabled="app.loading">
|
||||||
<span class="glyphicon glyphicon-link"></span> Connect
|
<span class="glyphicon glyphicon-link"></span> Connect
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="open()" ng-disabled="app.loading">
|
<!--<button type="button" class="btn btn-default" ng-click="open()" ng-disabled="app.loading">
|
||||||
<span class="glyphicon glyphicon-file"></span> Open
|
<span class="glyphicon glyphicon-file"></span> Open
|
||||||
</button>
|
</button>-->
|
||||||
<button type="button" class="btn btn-default" ng-click="refresh()" ng-disabled="app.loading">
|
<button type="button" class="btn btn-default" ng-click="refresh()" ng-disabled="app.loading">
|
||||||
<span class="glyphicon glyphicon-refresh"></span> Refresh
|
<span class="glyphicon glyphicon-refresh"></span> Refresh
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -6,22 +6,3 @@
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
var myTextArea = document.querySelector('.debugger-fnview-textarea');
|
|
||||||
var myCodeMirror = CodeMirror.fromTextArea(myTextArea, {
|
|
||||||
mode: 'javascript',
|
|
||||||
theme: 'default',
|
|
||||||
indentUnit: 2,
|
|
||||||
tabSize: 2,
|
|
||||||
|
|
||||||
lineNumbers: true,
|
|
||||||
firstLineNumber: 0,
|
|
||||||
lineNumberFormatter: function(line) {
|
|
||||||
return String('0x00000000' + line);
|
|
||||||
},
|
|
||||||
gutters: [],
|
|
||||||
|
|
||||||
//readOnly: true,
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.7.0.js"></script>
|
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.7.0.js"></script>
|
||||||
<script src="//angular-ui.github.io/ui-router/build/angular-ui-router.js"></script>
|
<script src="//angular-ui.github.io/ui-router/build/angular-ui-router.js"></script>
|
||||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
|
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
|
||||||
<!--<link rel="stylesheet" href="//codemirror.net/lib/codemirror.css">-->
|
<link rel="stylesheet" href="//codemirror.net/lib/codemirror.css">
|
||||||
<link rel="stylesheet" href="assets/styles/app.css">
|
<link rel="stylesheet" href="assets/styles/app.css">
|
||||||
<style>
|
<style>
|
||||||
</style>
|
</style>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<div class="app-console navbar-default" ng-include="'assets/ui/console/console.html'"></div>
|
<div class="app-console navbar-default" ng-include="'assets/ui/console/console.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--<script src="http://codemirror.net/lib/codemirror.js"></script>-->
|
<script src="http://codemirror.net/lib/codemirror.js"></script>
|
||||||
|
|
||||||
<script src="src/base.js"></script>
|
<script src="src/base.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ module.service('app', function(
|
||||||
this.close();
|
this.close();
|
||||||
|
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
$rootScope.$emit('refresh');
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.close = function() {
|
App.prototype.close = function() {
|
||||||
|
|
|
@ -87,7 +87,7 @@ module.service('DataSource', function($q) {
|
||||||
return DataSource;
|
return DataSource;
|
||||||
});
|
});
|
||||||
|
|
||||||
module.service('RemoteDataSource', function($q, DataSource) {
|
module.service('RemoteDataSource', function($q, log, DataSource) {
|
||||||
var RemoteDataSource = function(url) {
|
var RemoteDataSource = function(url) {
|
||||||
DataSource.call(this, url);
|
DataSource.call(this, url);
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
@ -121,6 +121,7 @@ module.service('RemoteDataSource', function($q, DataSource) {
|
||||||
d.reject(e.code + ' ' + e.reason);
|
d.reject(e.code + ' ' + e.reason);
|
||||||
} else {
|
} else {
|
||||||
this.status = 'disconnected';
|
this.status = 'disconnected';
|
||||||
|
log.info('Disconnected');
|
||||||
}
|
}
|
||||||
}).bind(this);
|
}).bind(this);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ var module = angular.module('xe.session', []);
|
||||||
|
|
||||||
|
|
||||||
module.service('Session', function(
|
module.service('Session', function(
|
||||||
$q, $http, log, FileDataSource, RemoteDataSource) {
|
$rootScope, $q, $http, log, FileDataSource, RemoteDataSource) {
|
||||||
var Session = function(id, opt_dataSource) {
|
var Session = function(id, opt_dataSource) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ module.service('Session', function(
|
||||||
if (this.dataSource) {
|
if (this.dataSource) {
|
||||||
this.dataSource.dispose();
|
this.dataSource.dispose();
|
||||||
this.dataSource = null;
|
this.dataSource = null;
|
||||||
|
$rootScope.$emit('refresh');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace hir {
|
||||||
class FunctionBuilder;
|
class FunctionBuilder;
|
||||||
}
|
}
|
||||||
namespace runtime {
|
namespace runtime {
|
||||||
|
class DebugInfo;
|
||||||
class Function;
|
class Function;
|
||||||
class FunctionInfo;
|
class FunctionInfo;
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
@ -41,7 +42,7 @@ public:
|
||||||
|
|
||||||
virtual int Assemble(
|
virtual int Assemble(
|
||||||
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
|
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
|
||||||
runtime::Function** out_function) = 0;
|
runtime::DebugInfo* debug_info, runtime::Function** out_function) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Backend* backend_;
|
Backend* backend_;
|
||||||
|
|
|
@ -53,8 +53,9 @@ void IVMAssembler::Reset() {
|
||||||
|
|
||||||
int IVMAssembler::Assemble(
|
int IVMAssembler::Assemble(
|
||||||
FunctionInfo* symbol_info, FunctionBuilder* builder,
|
FunctionInfo* symbol_info, FunctionBuilder* builder,
|
||||||
Function** out_function) {
|
DebugInfo* debug_info, Function** out_function) {
|
||||||
IVMFunction* fn = new IVMFunction(symbol_info);
|
IVMFunction* fn = new IVMFunction(symbol_info);
|
||||||
|
fn->set_debug_info(debug_info);
|
||||||
|
|
||||||
TranslationContext ctx;
|
TranslationContext ctx;
|
||||||
ctx.access_callbacks = backend_->runtime()->access_callbacks();
|
ctx.access_callbacks = backend_->runtime()->access_callbacks();
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
|
|
||||||
virtual int Assemble(
|
virtual int Assemble(
|
||||||
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
|
runtime::FunctionInfo* symbol_info, hir::FunctionBuilder* builder,
|
||||||
runtime::Function** out_function);
|
runtime::DebugInfo* debug_info, runtime::Function** out_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Arena intcode_arena_;
|
Arena intcode_arena_;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <alloy/frontend/tracing.h>
|
#include <alloy/frontend/tracing.h>
|
||||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||||
#include <alloy/frontend/ppc/ppc_function_builder.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/frontend/ppc/ppc_scanner.h>
|
||||||
#include <alloy/runtime/runtime.h>
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
|
||||||
|
|
||||||
compiler_->AddPass(new passes::ContextPromotionPass());
|
compiler_->AddPass(new passes::ContextPromotionPass());
|
||||||
compiler_->AddPass(new passes::SimplificationPass());
|
compiler_->AddPass(new passes::SimplificationPass());
|
||||||
|
// TODO(benvanik): run repeatedly?
|
||||||
compiler_->AddPass(new passes::ConstantPropagationPass());
|
compiler_->AddPass(new passes::ConstantPropagationPass());
|
||||||
//compiler_->AddPass(new passes::TypePropagationPass());
|
//compiler_->AddPass(new passes::TypePropagationPass());
|
||||||
//compiler_->AddPass(new passes::ByteSwapEliminationPass());
|
//compiler_->AddPass(new passes::ByteSwapEliminationPass());
|
||||||
|
@ -55,9 +57,6 @@ PPCTranslator::~PPCTranslator() {
|
||||||
int PPCTranslator::Translate(
|
int PPCTranslator::Translate(
|
||||||
FunctionInfo* symbol_info,
|
FunctionInfo* symbol_info,
|
||||||
Function** out_function) {
|
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
|
// 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.
|
// haven't already been provided with them from some other source.
|
||||||
if (!symbol_info->has_end_address()) {
|
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.
|
// Emit function.
|
||||||
int result = builder_->Emit(symbol_info);
|
int result = builder_->Emit(symbol_info);
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
if (true) {
|
// Stash raw HIR.
|
||||||
|
if (debug_info) {
|
||||||
builder_->Dump(&string_buffer_);
|
builder_->Dump(&string_buffer_);
|
||||||
pre_ir = string_buffer_.ToString();
|
debug_info->set_raw_hir_disasm(string_buffer_.ToString());
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,24 +94,64 @@ int PPCTranslator::Translate(
|
||||||
result = compiler_->Compile(builder_);
|
result = compiler_->Compile(builder_);
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
if (true) {
|
// Stash optimized HIR.
|
||||||
|
if (debug_info) {
|
||||||
builder_->Dump(&string_buffer_);
|
builder_->Dump(&string_buffer_);
|
||||||
post_ir = string_buffer_.ToString();
|
debug_info->set_hir_disasm(string_buffer_.ToString());
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble to backend machine code.
|
// 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);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
XECLEANUP:
|
XECLEANUP:
|
||||||
if (pre_ir) xe_free(pre_ir);
|
if (result) {
|
||||||
if (post_ir) xe_free(post_ir);
|
delete debug_info;
|
||||||
|
}
|
||||||
builder_->Reset();
|
builder_->Reset();
|
||||||
compiler_->Reset();
|
compiler_->Reset();
|
||||||
assembler_->Reset();
|
assembler_->Reset();
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
return result;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,10 @@ public:
|
||||||
int Translate(runtime::FunctionInfo* symbol_info,
|
int Translate(runtime::FunctionInfo* symbol_info,
|
||||||
runtime::Function** out_function);
|
runtime::Function** out_function);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DumpSource(runtime::FunctionInfo* symbol_info,
|
||||||
|
StringBuffer* string_buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
PPCScanner* scanner_;
|
PPCScanner* scanner_;
|
||||||
|
|
|
@ -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_);
|
||||||
|
}
|
|
@ -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_
|
|
@ -17,7 +17,7 @@ using namespace alloy::runtime;
|
||||||
|
|
||||||
|
|
||||||
Function::Function(Type type, uint64_t address) :
|
Function::Function(Type type, uint64_t address) :
|
||||||
type_(type), address_(address) {
|
type_(type), address_(address), debug_info_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Function::~Function() {
|
Function::~Function() {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define ALLOY_RUNTIME_FUNCTION_H_
|
#define ALLOY_RUNTIME_FUNCTION_H_
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
|
#include <alloy/runtime/debug_info.h>
|
||||||
|
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
@ -34,6 +35,9 @@ public:
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
uint64_t address() const { return address_; }
|
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);
|
int Call(ThreadState* thread_state, uint64_t return_address);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -42,6 +46,7 @@ protected:
|
||||||
protected:
|
protected:
|
||||||
Type type_;
|
Type type_;
|
||||||
uint64_t address_;
|
uint64_t address_;
|
||||||
|
DebugInfo* debug_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'debug_info.cc',
|
||||||
|
'debug_info.h',
|
||||||
'entry_table.cc',
|
'entry_table.cc',
|
||||||
'entry_table.h',
|
'entry_table.h',
|
||||||
'function.cc',
|
'function.cc',
|
||||||
|
|
|
@ -234,6 +234,11 @@ json_t* Processor::OnDebugRequest(
|
||||||
succeeded = false;
|
succeeded = false;
|
||||||
return json_string("Unable to resolve function");
|
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();
|
json_t* fn_json = json_object();
|
||||||
// TODO(benvanik): get name
|
// TODO(benvanik): get name
|
||||||
|
@ -249,6 +254,22 @@ json_t* Processor::OnDebugRequest(
|
||||||
json_t* link_status_json = json_integer(info->status());
|
json_t* link_status_json = json_integer(info->status());
|
||||||
json_object_set_new(fn_json, "linkStatus", link_status_json);
|
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;
|
delete fn;
|
||||||
|
|
||||||
return fn_json;
|
return fn_json;
|
||||||
|
|
Loading…
Reference in New Issue