Function listing and selection.
This commit is contained in:
parent
a631ada0f7
commit
4ecdfed46f
|
@ -156,21 +156,36 @@ body {
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
overflow: scroll;
|
overflow-x: auto;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.debugger-fnlist-list > table > tbody > tr > td {
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.2em;
|
||||||
|
font-family: monospace;
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
.debugger-fnlist-footer {
|
.debugger-fnlist-footer {
|
||||||
order: 3;
|
order: 3;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.debugger-fnview {
|
.debugger-fnview-outer {
|
||||||
order: 2;
|
order: 2;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
display: flex;
|
position: relative;
|
||||||
flex-flow: column nowrap;
|
|
||||||
border-left: 2px solid #ddd;
|
border-left: 2px solid #ddd;
|
||||||
border-right: 2px solid #ddd;
|
border-right: 2px solid #ddd;
|
||||||
}
|
}
|
||||||
|
.debugger-fnview {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
}
|
||||||
.debugger-fnview-header {
|
.debugger-fnview-header {
|
||||||
order: 1;
|
order: 1;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
|
@ -1,75 +1,35 @@
|
||||||
<div class="debugger-main" ng-controller="CodeTabController">
|
<div class="debugger-main" ng-controller="CodeTabController">
|
||||||
<div class="debugger-header">
|
<div class="debugger-header">
|
||||||
debug header/toolbar/etc
|
debug header/toolbar/etc
|
||||||
<div ui-view></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-body">
|
<div class="debugger-body">
|
||||||
<div class="debugger-fnlist">
|
<div class="debugger-fnlist">
|
||||||
<div class="debugger-fnlist-header">
|
<div class="debugger-fnlist-header">
|
||||||
<div class="btn-group btn-group-xs full-width">
|
<div class="btn-group btn-group-xs full-width">
|
||||||
<button type="button" class="btn btn-default dropdown-toggle full-width" data-toggle="dropdown">
|
<button type="button" class="btn btn-default dropdown-toggle full-width" data-toggle="dropdown">
|
||||||
module_name.xex <span class="caret"></span>
|
{{selectedModule.name}} <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li><a href="#">module 1</a></li>
|
<li ng-repeat="module in moduleList"><a href="" ng-click="selectModule(module)">{{module.name}}</a></li>
|
||||||
<li><a href="#">module 2</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnlist-body">
|
<div class="debugger-fnlist-body">
|
||||||
<div class="debugger-fnlist-list">
|
<div class="debugger-fnlist-list">
|
||||||
fn<br/>fn<br/>fn
|
<table class="table table-hover">
|
||||||
|
<tr ng-repeat="fn in functionList | filter:functionFilter | orderBy:'address'">
|
||||||
|
<td><a ui-sref="session.code.function({module: selectedModule.name, function: (fn.address | hex32)})">{{fn.name}}</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnlist-footer">
|
<div class="debugger-fnlist-footer">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-addon">@</span>
|
<input type="text" class="form-control" placeholder="Filter" ng-model="functionFilter" ui-escape="functionFilter = ''">
|
||||||
<input type="text" class="form-control" placeholder="Filter">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnview">
|
<div class="debugger-fnview-outer" ui-view></div>
|
||||||
<div class="debugger-fnview-header">
|
|
||||||
<div class="debugger-fnview-header-left">
|
|
||||||
<span class="debugger-fnview-header-name">function name</span>
|
|
||||||
<span class="debugger-fnview-header-address">(0x80000000-0x80000000)</span>
|
|
||||||
</div>
|
|
||||||
<div class="debugger-fnview-header-right">
|
|
||||||
<div class="btn-toolbar" role="toolbar">
|
|
||||||
<div class="btn-group btn-group-sm">
|
|
||||||
<button type="button" class="btn btn-default" ng-model="radioModel" btn-radio="'PPC'">PPC</button>
|
|
||||||
<button type="button" class="btn btn-default" ng-model="radioModel" btn-radio="'HIR'">HIR</button>
|
|
||||||
<button type="button" class="btn btn-default" ng-model="radioModel" btn-radio="'LIR'">LIR</button>
|
|
||||||
</div>
|
|
||||||
<div class="btn-group btn-group-sm">
|
|
||||||
<button type="button" class="btn btn-default">1</button>
|
|
||||||
<button type="button" class="btn btn-default">2</button>
|
|
||||||
<div class="btn-group btn-group-sm">
|
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
|
||||||
Dropdown
|
|
||||||
<span class="caret"></span>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a href="#">Dropdown link</a></li>
|
|
||||||
<li><a href="#">Dropdown link</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="debugger-fnview-body">
|
|
||||||
<div class="debugger-fnview-codeview">
|
|
||||||
<textarea class="debugger-fnview-textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="debugger-fnview-graphview">
|
|
||||||
graph!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="debugger-fnview-footer">
|
|
||||||
footer
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="debugger-tools">
|
<div class="debugger-tools">
|
||||||
<div class="debugger-tools-threads">
|
<div class="debugger-tools-threads">
|
||||||
<div class="btn-group btn-group-xs full-width">
|
<div class="btn-group btn-group-xs full-width">
|
||||||
|
|
|
@ -17,16 +17,42 @@ var module = angular.module('xe.ui.code', [
|
||||||
|
|
||||||
module.controller('CodeTabController', function(
|
module.controller('CodeTabController', function(
|
||||||
$rootScope, $scope, app, log) {
|
$rootScope, $scope, app, log) {
|
||||||
|
$scope.moduleList = [];
|
||||||
|
$scope.selectedModule = null;
|
||||||
|
$scope.functionList = [];
|
||||||
|
|
||||||
$rootScope.$on('refresh', function() {
|
$rootScope.$on('refresh', function() {
|
||||||
var dataSource = app.session.dataSource;
|
var dataSource = app.session.dataSource;
|
||||||
|
|
||||||
dataSource.getModuleList().then(function(list) {
|
dataSource.getModuleList().then(function(list) {
|
||||||
console.log(list);
|
$scope.moduleList = list;
|
||||||
|
if (!$scope.selectedModule) {
|
||||||
|
if (list.length) {
|
||||||
|
$scope.selectModule(list[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$scope.selectModule($scope.selectedModule);
|
||||||
|
}
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
log('Unable to fetch module list');
|
log.error('Unable to fetch module list');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('refresh');
|
console.log('refresh');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.selectModule = function(module) {
|
||||||
|
var moduleChange = module != $scope.selectedModule;
|
||||||
|
$scope.selectedModule = module;
|
||||||
|
|
||||||
|
if (moduleChange) {
|
||||||
|
$scope.functionList = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataSource = app.session.dataSource;
|
||||||
|
dataSource.getFunctionList(module.name).then(function(list) {
|
||||||
|
$scope.functionList = list;
|
||||||
|
}, function(e) {
|
||||||
|
log.error('Unable to fetch function list');
|
||||||
|
});
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,2 +1,43 @@
|
||||||
TODO: function
|
<div class="debugger-fnview" ng-controller="FunctionViewController">
|
||||||
|
<div class="debugger-fnview-header">
|
||||||
|
<div class="debugger-fnview-header-left">
|
||||||
|
<span class="debugger-fnview-header-name" ng-bind="fn.name"></span>
|
||||||
|
<span class="debugger-fnview-header-address">(0x{{fn.startAddress | hex32}}-0x{{fn.endAddress | hex32}})</span>
|
||||||
|
</div>
|
||||||
|
<div class="debugger-fnview-header-right">
|
||||||
|
<div class="btn-toolbar" role="toolbar">
|
||||||
|
<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="'hir'">HIR</button>
|
||||||
|
<button type="button" class="btn btn-default" ng-model="codeType" btn-radio="'lir'">LIR</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group btn-group-sm">
|
||||||
|
<button type="button" class="btn btn-default">1</button>
|
||||||
|
<button type="button" class="btn btn-default">2</button>
|
||||||
|
<div class="btn-group btn-group-sm">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
|
Dropdown
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#">Dropdown link</a></li>
|
||||||
|
<li><a href="#">Dropdown link</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="debugger-fnview-body">
|
||||||
<div ui-view></div>
|
<div ui-view></div>
|
||||||
|
<div class="debugger-fnview-codeview">
|
||||||
|
<textarea class="debugger-fnview-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="debugger-fnview-graphview">
|
||||||
|
graph!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="debugger-fnview-footer">
|
||||||
|
footer
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var module = angular.module('xe.ui.code.functionView', [
|
||||||
|
'xe.log',
|
||||||
|
'xe.session'
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
module.controller('FunctionViewController', function(
|
||||||
|
$rootScope, $scope, app, log) {
|
||||||
|
$scope.codeType = 'ppc';
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
var dataSource = app.session.dataSource;
|
||||||
|
|
||||||
|
dataSource.getFunction($scope.functionAddress).then(function(fn) {
|
||||||
|
$scope.fn = fn;
|
||||||
|
}, function(e) {
|
||||||
|
log.error('Unable to fetch function');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$rootScope.$on('refresh', refresh);
|
||||||
|
$scope.$watch('functionAddress', refresh);
|
||||||
|
});
|
|
@ -26,12 +26,14 @@
|
||||||
<script src="src/app.js"></script>
|
<script src="src/app.js"></script>
|
||||||
<script src="src/datasources.js"></script>
|
<script src="src/datasources.js"></script>
|
||||||
<script src="src/directives.js"></script>
|
<script src="src/directives.js"></script>
|
||||||
|
<script src="src/filters.js"></script>
|
||||||
<script src="src/log.js"></script>
|
<script src="src/log.js"></script>
|
||||||
<script src="src/router.js"></script>
|
<script src="src/router.js"></script>
|
||||||
<script src="src/session.js"></script>
|
<script src="src/session.js"></script>
|
||||||
<script src="assets/ui/navbar.js"></script>
|
<script src="assets/ui/navbar.js"></script>
|
||||||
<script src="assets/ui/console/console.js"></script>
|
<script src="assets/ui/console/console.js"></script>
|
||||||
<script src="assets/ui/code/code-tab.js"></script>
|
<script src="assets/ui/code/code-tab.js"></script>
|
||||||
|
<script src="assets/ui/code/function-view.js"></script>
|
||||||
|
|
||||||
<script src="debugger.js"></script>
|
<script src="debugger.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -14,10 +14,12 @@ var module = angular.module('app', [
|
||||||
'ui.router',
|
'ui.router',
|
||||||
'xe.datasources',
|
'xe.datasources',
|
||||||
'xe.directives',
|
'xe.directives',
|
||||||
|
'xe.filters',
|
||||||
'xe.log',
|
'xe.log',
|
||||||
'xe.router',
|
'xe.router',
|
||||||
'xe.session',
|
'xe.session',
|
||||||
'xe.ui.code',
|
'xe.ui.code',
|
||||||
|
'xe.ui.code.functionView',
|
||||||
'xe.ui.console',
|
'xe.ui.console',
|
||||||
'xe.ui.navbar'
|
'xe.ui.navbar'
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -63,17 +63,17 @@ module.service('DataSource', function($q) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource.prototype.getModule = function(moduleId) {
|
DataSource.prototype.getModule = function(moduleName) {
|
||||||
return this.issue({
|
return this.issue({
|
||||||
command: 'cpu.get_module',
|
command: 'cpu.get_module',
|
||||||
moduleId: moduleId
|
module: moduleName
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource.prototype.getFunctionList = function(moduleId) {
|
DataSource.prototype.getFunctionList = function(moduleName) {
|
||||||
return this.issue({
|
return this.issue({
|
||||||
command: 'cpu.get_function_list',
|
command: 'cpu.get_function_list',
|
||||||
moduleId: moduleId
|
module: moduleName
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,17 @@ module.directive('uiEnter', function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.directive('uiEscape', function() {
|
||||||
|
return function($scope, element, attrs) {
|
||||||
|
element.bind("keydown keypress", function(e) {
|
||||||
|
if(e.which === 27) {
|
||||||
|
$scope.$apply(function(){
|
||||||
|
$scope.$eval(attrs.uiEscape);
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var module = angular.module('xe.filters', []);
|
||||||
|
|
||||||
|
|
||||||
|
module.filter("hex32", function() {
|
||||||
|
return function(number) {
|
||||||
|
if (number !== null && number !== undefined) {
|
||||||
|
var str = "" + number.toString(16).toUpperCase();
|
||||||
|
while (str.length < 8) str = "0" + str;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -26,7 +26,7 @@ module.config(function($stateProvider, $urlRouterProvider) {
|
||||||
templateUrl: 'assets/ui/session.html',
|
templateUrl: 'assets/ui/session.html',
|
||||||
resolve: {
|
resolve: {
|
||||||
app: 'app',
|
app: 'app',
|
||||||
session: function($stateParams, $urlRouter, $state, $q, $timeout,
|
session: function($stateParams, $state, $q,
|
||||||
Session, app) {
|
Session, app) {
|
||||||
// If we are given a session we assume the user is trying to connect to
|
// If we are given a session we assume the user is trying to connect to
|
||||||
// it. Attempt that now. If we fail we redirect to home, otherwise we
|
// it. Attempt that now. If we fail we redirect to home, otherwise we
|
||||||
|
@ -100,7 +100,11 @@ module.config(function($stateProvider, $urlRouterProvider) {
|
||||||
$stateProvider.state('session.code.function', {
|
$stateProvider.state('session.code.function', {
|
||||||
url: '/:module/:function',
|
url: '/:module/:function',
|
||||||
templateUrl: 'assets/ui/code/function-view.html',
|
templateUrl: 'assets/ui/code/function-view.html',
|
||||||
controller: function($stateParams) {
|
controller: function($scope, $stateParams) {
|
||||||
|
$scope.moduleName = $stateParams.module;
|
||||||
|
$scope.functionAddress = parseInt($stateParams.function, 16);
|
||||||
|
$scope.$emit('xxx');
|
||||||
|
$scope.$broadcast('yyy');
|
||||||
},
|
},
|
||||||
onEnter: function() {},
|
onEnter: function() {},
|
||||||
onExit: function() {}
|
onExit: function() {}
|
||||||
|
|
|
@ -152,3 +152,15 @@ SymbolInfo::Status Module::DefineFunction(FunctionInfo* symbol_info) {
|
||||||
SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
|
SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
|
||||||
return DefineSymbol((SymbolInfo*)symbol_info);
|
return DefineSymbol((SymbolInfo*)symbol_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::ForEachFunction(std::function<void (FunctionInfo*)> callback) {
|
||||||
|
LockMutex(lock_);
|
||||||
|
for (SymbolMap::iterator it = map_.begin();
|
||||||
|
it != map_.end(); ++it) {
|
||||||
|
if (it->second->type() == SymbolInfo::TYPE_FUNCTION) {
|
||||||
|
FunctionInfo* info = (FunctionInfo*)it->second;
|
||||||
|
callback(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockMutex(lock_);
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef ALLOY_RUNTIME_MODULE_H_
|
#ifndef ALLOY_RUNTIME_MODULE_H_
|
||||||
#define ALLOY_RUNTIME_MODULE_H_
|
#define ALLOY_RUNTIME_MODULE_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <alloy/core.h>
|
#include <alloy/core.h>
|
||||||
#include <alloy/memory.h>
|
#include <alloy/memory.h>
|
||||||
#include <alloy/runtime/symbol_info.h>
|
#include <alloy/runtime/symbol_info.h>
|
||||||
|
@ -41,6 +43,8 @@ public:
|
||||||
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
||||||
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
|
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
|
||||||
|
|
||||||
|
void ForEachFunction(std::function<void (FunctionInfo*)> callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SymbolInfo::Status DeclareSymbol(
|
SymbolInfo::Status DeclareSymbol(
|
||||||
SymbolInfo::Type type, uint64_t address, SymbolInfo** out_symbol_info);
|
SymbolInfo::Type type, uint64_t address, SymbolInfo** out_symbol_info);
|
||||||
|
|
|
@ -116,6 +116,29 @@ int Runtime::AddModule(Module* module) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Module* Runtime::GetModule(const char* name) {
|
||||||
|
Module* result = NULL;
|
||||||
|
LockMutex(modules_lock_);
|
||||||
|
for (ModuleList::iterator it = modules_.begin();
|
||||||
|
it != modules_.end(); ++it) {
|
||||||
|
Module* module = *it;
|
||||||
|
if (xestrcmpa(module->name(), name) == 0) {
|
||||||
|
result = module;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockMutex(modules_lock_);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Runtime::ModuleList Runtime::GetModules() {
|
||||||
|
ModuleList clone;
|
||||||
|
LockMutex(modules_lock_);
|
||||||
|
clone = modules_;
|
||||||
|
UnlockMutex(modules_lock_);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
int Runtime::ResolveFunction(uint64_t address, Function** out_function) {
|
int Runtime::ResolveFunction(uint64_t address, Function** out_function) {
|
||||||
*out_function = NULL;
|
*out_function = NULL;
|
||||||
Entry* entry;
|
Entry* entry;
|
||||||
|
|
|
@ -26,6 +26,9 @@ namespace runtime {
|
||||||
|
|
||||||
|
|
||||||
class Runtime {
|
class Runtime {
|
||||||
|
public:
|
||||||
|
typedef std::vector<Module*> ModuleList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Runtime(Memory* memory);
|
Runtime(Memory* memory);
|
||||||
virtual ~Runtime();
|
virtual ~Runtime();
|
||||||
|
@ -40,6 +43,8 @@ public:
|
||||||
int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0);
|
int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0);
|
||||||
|
|
||||||
int AddModule(Module* module);
|
int AddModule(Module* module);
|
||||||
|
Module* GetModule(const char* name);
|
||||||
|
ModuleList GetModules();
|
||||||
|
|
||||||
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
||||||
int ResolveFunction(uint64_t address, Function** out_function);
|
int ResolveFunction(uint64_t address, Function** out_function);
|
||||||
|
@ -60,7 +65,6 @@ protected:
|
||||||
|
|
||||||
EntryTable entry_table_;
|
EntryTable entry_table_;
|
||||||
Mutex* modules_lock_;
|
Mutex* modules_lock_;
|
||||||
typedef std::vector<Module*> ModuleList;
|
|
||||||
ModuleList modules_;
|
ModuleList modules_;
|
||||||
|
|
||||||
RegisterAccessCallbacks* access_callbacks_;
|
RegisterAccessCallbacks* access_callbacks_;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <xenia/emulator.h>
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
#include <xenia/cpu/xenon_memory.h>
|
||||||
#include <xenia/cpu/xenon_runtime.h>
|
#include <xenia/cpu/xenon_runtime.h>
|
||||||
|
#include <xenia/cpu/xex_module.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
|
@ -169,5 +170,90 @@ uint64_t Processor::ExecuteInterrupt(
|
||||||
json_t* Processor::OnDebugRequest(
|
json_t* Processor::OnDebugRequest(
|
||||||
const char* command, json_t* request, bool& succeeded) {
|
const char* command, json_t* request, bool& succeeded) {
|
||||||
succeeded = true;
|
succeeded = true;
|
||||||
return json_null();
|
if (xestrcmpa(command, "get_module_list") == 0) {
|
||||||
|
json_t* list = json_array();
|
||||||
|
Runtime::ModuleList modules = runtime_->GetModules();
|
||||||
|
for (Runtime::ModuleList::iterator it = modules.begin();
|
||||||
|
it != modules.end(); ++it) {
|
||||||
|
XexModule* module = (XexModule*)(*it);
|
||||||
|
json_t* module_json = json_object();
|
||||||
|
json_t* module_name_json = json_string(module->name());
|
||||||
|
json_object_set_new(module_json, "name", module_name_json);
|
||||||
|
json_array_append_new(list, module_json);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
/*} else if (xestrcmpa(command, "get_module") == 0) {
|
||||||
|
return json_null();*/
|
||||||
|
} else if (xestrcmpa(command, "get_function_list") == 0) {
|
||||||
|
json_t* module_name_json = json_object_get(request, "module");
|
||||||
|
if (!module_name_json || !json_is_string(module_name_json)) {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Module name not specified");
|
||||||
|
}
|
||||||
|
const char* module_name = json_string_value(module_name_json);
|
||||||
|
XexModule* module = (XexModule*)runtime_->GetModule(module_name);
|
||||||
|
if (!module) {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Module not found");
|
||||||
|
}
|
||||||
|
json_t* list = json_array();
|
||||||
|
module->ForEachFunction([&](FunctionInfo* info) {
|
||||||
|
json_t* fn_json = json_object();
|
||||||
|
// TODO(benvanik): get name
|
||||||
|
char name_buffer[32];
|
||||||
|
xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X",
|
||||||
|
info->address());
|
||||||
|
json_t* name_json = json_string(name_buffer);
|
||||||
|
json_object_set_new(fn_json, "name", name_json);
|
||||||
|
json_t* address_json = json_integer(info->address());
|
||||||
|
json_object_set_new(fn_json, "address", address_json);
|
||||||
|
json_t* link_status_json = json_integer(info->status());
|
||||||
|
json_object_set_new(fn_json, "linkStatus", link_status_json);
|
||||||
|
json_array_append_new(list, fn_json);
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
} else if (xestrcmpa(command, "get_function") == 0) {
|
||||||
|
json_t* address_json = json_object_get(request, "address");
|
||||||
|
if (!address_json || !json_is_number(address_json)) {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Function address not specified");
|
||||||
|
}
|
||||||
|
uint64_t address = (uint64_t)json_number_value(address_json);
|
||||||
|
|
||||||
|
FunctionInfo* info;
|
||||||
|
if (runtime_->LookupFunctionInfo(address, &info)) {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Function not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demand a new function with all debug info retained.
|
||||||
|
// If we ever wanted absolute x64 addresses/etc we could
|
||||||
|
// use the x64 from the function in the symbol table.
|
||||||
|
Function* fn;
|
||||||
|
if (runtime_->frontend()->DefineFunction(info, &fn)) {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Unable to resolve function");
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t* fn_json = json_object();
|
||||||
|
// TODO(benvanik): get name
|
||||||
|
char name_buffer[32];
|
||||||
|
xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X",
|
||||||
|
info->address());
|
||||||
|
json_t* name_json = json_string(name_buffer);
|
||||||
|
json_object_set_new(fn_json, "name", name_json);
|
||||||
|
json_t* start_address_json = json_integer(info->address());
|
||||||
|
json_object_set_new(fn_json, "startAddress", start_address_json);
|
||||||
|
json_t* end_address_json = json_integer(info->end_address());
|
||||||
|
json_object_set_new(fn_json, "endAddress", end_address_json);
|
||||||
|
json_t* link_status_json = json_integer(info->status());
|
||||||
|
json_object_set_new(fn_json, "linkStatus", link_status_json);
|
||||||
|
|
||||||
|
delete fn;
|
||||||
|
|
||||||
|
return fn_json;
|
||||||
|
} else {
|
||||||
|
succeeded = false;
|
||||||
|
return json_string("Unknown command");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue