Threads displayed.
This commit is contained in:
parent
d368e0cb74
commit
a1da55a006
|
@ -10,6 +10,9 @@
|
||||||
.full-width {
|
.full-width {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.left-align {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -194,6 +197,7 @@ body {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-left: 2px solid #ddd;
|
border-left: 2px solid #ddd;
|
||||||
border-right: 2px solid #ddd;
|
border-right: 2px solid #ddd;
|
||||||
|
min-width: 720px;
|
||||||
}
|
}
|
||||||
.debugger-fnview {
|
.debugger-fnview {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -215,6 +219,7 @@ body {
|
||||||
order: 1;
|
order: 1;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.debugger-fnview-header-name {
|
.debugger-fnview-header-name {
|
||||||
font-size: 21px;
|
font-size: 21px;
|
||||||
|
@ -227,6 +232,7 @@ body {
|
||||||
order: 2;
|
order: 2;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
.debugger-fnview-body {
|
.debugger-fnview-body {
|
||||||
order: 2;
|
order: 2;
|
||||||
|
@ -300,20 +306,37 @@ body {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
min-width: 200px;
|
width: 40%;
|
||||||
}
|
}
|
||||||
.debugger-tools-threads {
|
.debugger-tools-threads {
|
||||||
order: 1;
|
order: 1;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
.debugger-tools-threads {
|
||||||
|
order: 1;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
}
|
||||||
|
.debugger-tools-threads-header-left {
|
||||||
|
order: 1;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
.debugger-tools-threads-header-right {
|
||||||
|
order: 2;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
.debugger-tools-callstack {
|
.debugger-tools-callstack {
|
||||||
order: 2;
|
order: 2;
|
||||||
flex: 1 1 auto;
|
flex: 0 0 auto;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-top: 1px solid #ddd;
|
border-top: 1px solid #ddd;
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 100px;
|
||||||
}
|
}
|
||||||
.debugger-tools-registers {
|
.debugger-tools-registers {
|
||||||
order: 3;
|
order: 3;
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<div class="debugger-main" ng-controller="CodeTabController">
|
<div class="debugger-main" ng-controller="CodeTabController">
|
||||||
<div class="debugger-header">
|
<div class="debugger-header">
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
<button type="button" class="btn btn-success" ng-click="app.session.continueExecution()" ng-disabled="!app.session.dataSource || !app.session.paused">
|
<button type="button" class="btn btn-success" ng-click="app.session.continueExecution()" ng-disabled="!app.session.paused">
|
||||||
<span class="glyphicon glyphicon-play"></span>
|
<span class="glyphicon glyphicon-play"></span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-danger" ng-click="app.session.breakExecution()" ng-disabled="!app.session.dataSource || app.session.paused">
|
<button type="button" class="btn btn-danger" ng-click="app.session.breakExecution()" ng-disabled="app.session.paused">
|
||||||
<span class="glyphicon glyphicon-pause"></span>
|
<span class="glyphicon glyphicon-pause"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
<button type="button" class="btn btn-default" ng-click="showLocation()" ng-disabled="!app.session.dataSource || !app.session.paused">
|
<button type="button" class="btn btn-default" ng-click="showLocation()" ng-disabled="!app.session.paused">
|
||||||
<span class="glyphicon glyphicon glyphicon-arrow-right"></span>
|
<span class="glyphicon glyphicon glyphicon-arrow-right"></span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-default" ng-click="app.session.stepNext()" ng-disabled="!app.session.dataSource || !app.session.paused">
|
<button type="button" class="btn btn-default" ng-click="app.session.stepNext()" ng-disabled="!app.session.paused">
|
||||||
<span class="glyphicon glyphicon-step-forward"></span>
|
<span class="glyphicon glyphicon-step-forward"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<div class="debugger-fnlist">
|
<div class="debugger-fnlist">
|
||||||
<div class="debugger-fnlist-header">
|
<div class="debugger-fnlist-header">
|
||||||
<div class="debugger-fnlist-header-left btn-group btn-group-xs full-width">
|
<div class="debugger-fnlist-header-left 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 left-align full-width" data-toggle="dropdown">
|
||||||
{{selectedModule.name}} <span class="caret"></span>
|
{{selectedModule.name}} <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnlist-header-right btn-group btn-group-xs">
|
<div class="debugger-fnlist-header-right btn-group btn-group-xs">
|
||||||
<button type="button" class="btn btn-default" ng-click="showModuleInfo(selectedModule)">
|
<button type="button" class="btn btn-default" ng-click="showModuleInfo()">
|
||||||
Info
|
Info
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,15 +52,21 @@
|
||||||
<div class="debugger-fnview-outer" ui-view></div>
|
<div class="debugger-fnview-outer" ui-view></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="debugger-tools-threads-header-left 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 left-align dropdown-toggle full-width" data-toggle="dropdown">
|
||||||
thread 0 <span class="caret"></span>
|
Thread {{app.session.activeThread.id}}: {{app.session.activeThread.name}} <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li><a href="#">thread 1</a></li>
|
<li ng-repeat="thread in app.session.state.threadList | orderBy:'id'">
|
||||||
<li><a href="#">thread 2</a></li>
|
<a href="" ng-click="app.session.activeThread = thread;">Thread {{thread.id}}: {{thread.name}}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="debugger-tools-threads-header-right btn-group btn-group-xs">
|
||||||
|
<button type="button" class="btn btn-default" ng-click="showThreadInfo()">
|
||||||
|
Info
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-tools-callstack">
|
<div class="debugger-tools-callstack">
|
||||||
callstack
|
callstack
|
||||||
|
|
|
@ -23,24 +23,19 @@ module.controller('CodeTabController', function(
|
||||||
$scope.functionList = [];
|
$scope.functionList = [];
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (!app.session || !app.session.dataSource) {
|
if (!app.session) {
|
||||||
$scope.moduleList = [];
|
$scope.moduleList = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var dataSource = app.session.dataSource;
|
|
||||||
|
|
||||||
dataSource.getModuleList().then(function(list) {
|
$scope.moduleList = app.session.state.getModuleList();
|
||||||
$scope.moduleList = list;
|
if (!$scope.selectedModule) {
|
||||||
if (!$scope.selectedModule) {
|
if ($scope.moduleList.length) {
|
||||||
if (list.length) {
|
$scope.selectModule($scope.moduleList[0]);
|
||||||
$scope.selectModule(list[0]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$scope.selectModule($scope.selectedModule);
|
|
||||||
}
|
}
|
||||||
}, function(e) {
|
} else {
|
||||||
log.error('Unable to fetch module list');
|
$scope.selectModule($scope.selectedModule);
|
||||||
});
|
}
|
||||||
|
|
||||||
console.log('refresh');
|
console.log('refresh');
|
||||||
};
|
};
|
||||||
|
@ -54,15 +49,10 @@ module.controller('CodeTabController', function(
|
||||||
$scope.functionList = [];
|
$scope.functionList = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataSource = app.session.dataSource;
|
$scope.functionList = app.session.state.getFunctionList(module.name);
|
||||||
dataSource.getFunctionList(module.name).then(function(list) {
|
|
||||||
$scope.functionList = list;
|
|
||||||
}, function(e) {
|
|
||||||
log.error('Unable to fetch function list');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.showModuleInfo = function(module) {
|
$scope.showModuleInfo = function() {
|
||||||
var modalInstance = $modal.open({
|
var modalInstance = $modal.open({
|
||||||
templateUrl: 'assets/ui/code/module-info.html',
|
templateUrl: 'assets/ui/code/module-info.html',
|
||||||
controller: 'ModuleInfoController',
|
controller: 'ModuleInfoController',
|
||||||
|
@ -72,13 +62,23 @@ module.controller('CodeTabController', function(
|
||||||
return $scope.selectedModule.name;
|
return $scope.selectedModule.name;
|
||||||
},
|
},
|
||||||
moduleInfo: function() {
|
moduleInfo: function() {
|
||||||
return app.session.dataSource.getModule(
|
return app.session.state.getModule(
|
||||||
$scope.selectedModule.name);
|
$scope.selectedModule.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
modalInstance.result.then(function() {
|
};
|
||||||
}, function () {
|
|
||||||
|
$scope.showThreadInfo = function() {
|
||||||
|
var modalInstance = $modal.open({
|
||||||
|
templateUrl: 'assets/ui/code/thread-info.html',
|
||||||
|
controller: 'ThreadInfoController',
|
||||||
|
windowClass: 'debugger-module-info',
|
||||||
|
resolve: {
|
||||||
|
thread: function() {
|
||||||
|
return app.session.activeThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="debugger-fnview" ng-controller="FunctionViewController">
|
<div class="debugger-fnview" ng-controller="FunctionViewController">
|
||||||
<div class="debugger-fnview-header">
|
<div class="debugger-fnview-header">
|
||||||
<div class="debugger-fnview-header-left">
|
<div class="debugger-fnview-header-left">
|
||||||
<span class="debugger-fnview-header-name" ng-bind="fn.name"></span>
|
<span class="debugger-fnview-header-name" ng-bind="fn.name"></span><br/>
|
||||||
<span class="debugger-fnview-header-address">(0x{{fn.startAddress | hex32}}-0x{{fn.endAddress | hex32}})</span>
|
<span class="debugger-fnview-header-address">(0x{{fn.startAddress | hex32}}-0x{{fn.endAddress | hex32}})</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="debugger-fnview-header-right">
|
<div class="debugger-fnview-header-right">
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
<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>
|
<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>
|
||||||
<button type="button" class="btn btn-default">2</button>
|
<button type="button" class="btn btn-default">2</button>
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,17 +21,15 @@ module.controller('FunctionViewController', function(
|
||||||
$scope.highlightInfo = null;
|
$scope.highlightInfo = null;
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (!app.session || !app.session.dataSource) {
|
if (!app.session) {
|
||||||
$scope.fn = null;
|
$scope.fn = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var dataSource = app.session.dataSource;
|
app.session.state.fetchFunction($scope.functionAddress).then(function(fn) {
|
||||||
|
|
||||||
dataSource.getFunction($scope.functionAddress).then(function(fn) {
|
|
||||||
$scope.fn = fn;
|
$scope.fn = fn;
|
||||||
updateCode();
|
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);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" ng-click="close()">×</button>
|
||||||
|
<h4 class="modal-title">Thread {{ thread.id }}: {{ thread.name }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<table class="table debugger-module-info-outer-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Thread</td>
|
||||||
|
<td>
|
||||||
|
<table class="table table-hover table-condensed debugger-module-info-inner-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Stack Address</td>
|
||||||
|
<td><a xe-memref="{{ thread.stackAddress | hex32 }}" ng-click="$close()">{{ thread.stackAddress | hex32 }}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Stack Size</td>
|
||||||
|
<td>{{ thread.stackSize }}b</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>State Address</td>
|
||||||
|
<td><a xe-memref="{{ thread.threadStateAddress | hex32 }}" ng-click="$close()">{{ thread.threadStateAddress | hex32 }}</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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.threadInfo', [
|
||||||
|
'ui.bootstrap',
|
||||||
|
'xe.log',
|
||||||
|
'xe.session'
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
module.controller('ThreadInfoController', function(
|
||||||
|
$rootScope, $scope, $modal, log, thread) {
|
||||||
|
$scope.thread = thread;
|
||||||
|
|
||||||
|
$scope.headerSort = {
|
||||||
|
column: 'key',
|
||||||
|
reverse: false
|
||||||
|
};
|
||||||
|
$scope.sectionSort = {
|
||||||
|
column: 'startAddress',
|
||||||
|
reverse: false
|
||||||
|
};
|
||||||
|
$scope.staticLibrarySort = {
|
||||||
|
column: 'name',
|
||||||
|
reverse: false
|
||||||
|
};
|
||||||
|
$scope.importSort = {
|
||||||
|
column: 'ordinal',
|
||||||
|
reverse: false
|
||||||
|
};
|
||||||
|
$scope.changeSort = function(sort, column) {
|
||||||
|
if (sort.column == column) {
|
||||||
|
sort.reverse = !sort.reverse;
|
||||||
|
} else {
|
||||||
|
sort.column = column;
|
||||||
|
sort.reverse = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.close = function() {
|
||||||
|
$scope.$close(null);
|
||||||
|
};
|
||||||
|
});
|
|
@ -35,6 +35,7 @@
|
||||||
<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="assets/ui/code/function-view.js"></script>
|
||||||
<script src="assets/ui/code/module-info.js"></script>
|
<script src="assets/ui/code/module-info.js"></script>
|
||||||
|
<script src="assets/ui/code/thread-info.js"></script>
|
||||||
|
|
||||||
<script src="debugger.js"></script>
|
<script src="debugger.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -21,6 +21,7 @@ var module = angular.module('app', [
|
||||||
'xe.ui.code',
|
'xe.ui.code',
|
||||||
'xe.ui.code.functionView',
|
'xe.ui.code.functionView',
|
||||||
'xe.ui.code.moduleInfo',
|
'xe.ui.code.moduleInfo',
|
||||||
|
'xe.ui.code.threadInfo',
|
||||||
'xe.ui.console',
|
'xe.ui.console',
|
||||||
'xe.ui.navbar'
|
'xe.ui.navbar'
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -61,12 +61,6 @@ module.service('DataSource', function($q) {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
this.online = false;
|
this.online = false;
|
||||||
this.status = 'disconnected';
|
this.status = 'disconnected';
|
||||||
|
|
||||||
this.cache_ = {
|
|
||||||
modules: {},
|
|
||||||
moduleFunctionLists: {},
|
|
||||||
functions: {}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
inherits(DataSource, EventEmitter);
|
inherits(DataSource, EventEmitter);
|
||||||
DataSource.prototype.open = function() {};
|
DataSource.prototype.open = function() {};
|
||||||
|
@ -86,69 +80,35 @@ module.service('DataSource', function($q) {
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource.prototype.getModule = function(moduleName) {
|
DataSource.prototype.getModule = function(moduleName) {
|
||||||
var d = $q.defer();
|
return this.issue({
|
||||||
var cached = this.cache_.modules[moduleName];
|
|
||||||
if (cached) {
|
|
||||||
d.resolve(cached);
|
|
||||||
return d.promise;
|
|
||||||
}
|
|
||||||
this.issue({
|
|
||||||
command: 'cpu.get_module',
|
command: 'cpu.get_module',
|
||||||
module: moduleName
|
module: moduleName
|
||||||
}).then((function(result) {
|
});
|
||||||
this.cache_.modules[moduleName] = result;
|
|
||||||
d.resolve(result);
|
|
||||||
}).bind(this), (function(e) {
|
|
||||||
d.reject(e);
|
|
||||||
}).bind(this));
|
|
||||||
return d.promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource.prototype.getFunctionList = function(moduleName) {
|
DataSource.prototype.getFunctionList = function(moduleName, opt_since) {
|
||||||
var d = $q.defer();
|
return this.issue({
|
||||||
var cached = this.cache_.moduleFunctionLists[moduleName];
|
|
||||||
this.issue({
|
|
||||||
command: 'cpu.get_function_list',
|
command: 'cpu.get_function_list',
|
||||||
module: moduleName,
|
module: moduleName,
|
||||||
since: cached ? cached.version : 0
|
since: opt_since || 0
|
||||||
}).then((function(result) {
|
});
|
||||||
if (cached) {
|
|
||||||
cached.version = result.version;
|
|
||||||
for (var n = 0; n < result.list.length; n++) {
|
|
||||||
cached.list.push(result.list[n]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cached = this.cache_.moduleFunctionLists[moduleName] = {
|
|
||||||
version: result.version,
|
|
||||||
list: result.list
|
|
||||||
};
|
|
||||||
}
|
|
||||||
d.resolve(cached.list);
|
|
||||||
}).bind(this), (function(e) {
|
|
||||||
d.reject(e);
|
|
||||||
}).bind(this));
|
|
||||||
return d.promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataSource.prototype.getFunction = function(address) {
|
DataSource.prototype.getFunction = function(address) {
|
||||||
var d = $q.defer();
|
return this.issue({
|
||||||
var cached = this.cache_.functions[address];
|
|
||||||
if (cached) {
|
|
||||||
d.resolve(cached);
|
|
||||||
return d.promise;
|
|
||||||
}
|
|
||||||
this.issue({
|
|
||||||
command: 'cpu.get_function',
|
command: 'cpu.get_function',
|
||||||
address: address
|
address: address
|
||||||
}).then((function(result) {
|
});
|
||||||
this.cache_.functions[address] = result;
|
|
||||||
d.resolve(result);
|
|
||||||
}).bind(this), (function(e) {
|
|
||||||
d.reject(e);
|
|
||||||
}).bind(this));
|
|
||||||
return d.promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DataSource.prototype.getThreadStates = function() {
|
||||||
|
return this.issue({
|
||||||
|
command: 'cpu.get_thread_states'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// set registers/etc?
|
||||||
|
|
||||||
DataSource.prototype.addBreakpoint = function(breakpoint) {
|
DataSource.prototype.addBreakpoint = function(breakpoint) {
|
||||||
return this.addBreakpoints([breakpoint]);
|
return this.addBreakpoints([breakpoint]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,154 @@ var module = angular.module('xe.session', []);
|
||||||
module.service('Session', function(
|
module.service('Session', function(
|
||||||
$rootScope, $q, $http, $state, log,
|
$rootScope, $q, $http, $state, log,
|
||||||
Breakpoint, FileDataSource, RemoteDataSource) {
|
Breakpoint, FileDataSource, RemoteDataSource) {
|
||||||
|
var State = function(session) {
|
||||||
|
this.session = session;
|
||||||
|
this.clear();
|
||||||
|
};
|
||||||
|
State.prototype.clear = function() {
|
||||||
|
this.cache_ = {
|
||||||
|
moduleList: [],
|
||||||
|
modules: {},
|
||||||
|
moduleFunctionLists: {},
|
||||||
|
functions: {},
|
||||||
|
threadStates: {},
|
||||||
|
threadList: []
|
||||||
|
};
|
||||||
|
};
|
||||||
|
State.prototype.sync = function() {
|
||||||
|
var cache = this.cache_;
|
||||||
|
var dataSource = this.session.dataSource;
|
||||||
|
if (!dataSource) {
|
||||||
|
var d = $q.defer();
|
||||||
|
d.resolve();
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
var ps = [];
|
||||||
|
|
||||||
|
// Update all modules/functions.
|
||||||
|
var modulesUpdated = $q.defer();
|
||||||
|
ps.push(modulesUpdated.promise);
|
||||||
|
dataSource.getModuleList().then((function(list) {
|
||||||
|
cache.moduleList = list;
|
||||||
|
|
||||||
|
// Update module information.
|
||||||
|
var moduleFetches = [];
|
||||||
|
list.forEach(function(module) {
|
||||||
|
if (cache.modules[module.name]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var moduleFetch = $q.defer();
|
||||||
|
moduleFetches.push(moduleFetch.promise);
|
||||||
|
dataSource.getModule(module.name).
|
||||||
|
then(function(moduleInfo) {
|
||||||
|
cache.modules[module.name] = moduleInfo;
|
||||||
|
moduleFetch.resolve();
|
||||||
|
}, function(e) {
|
||||||
|
moduleFetch.reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update function lists for each module.
|
||||||
|
list.forEach(function(module) {
|
||||||
|
var cached = cache.moduleFunctionLists[module.name];
|
||||||
|
var functionListFetch = $q.defer();
|
||||||
|
moduleFetches.push(functionListFetch);
|
||||||
|
dataSource.getFunctionList(module.name, cached ? cached.version : 0).
|
||||||
|
then(function(result) {
|
||||||
|
if (cached) {
|
||||||
|
cached.version = result.version;
|
||||||
|
for (var n = 0; n < result.list.length; n++) {
|
||||||
|
cached.list.push(result.list[n]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cached = cache.moduleFunctionLists[module.name] = {
|
||||||
|
version: result.version,
|
||||||
|
list: result.list
|
||||||
|
};
|
||||||
|
}
|
||||||
|
functionListFetch.resolve();
|
||||||
|
}, function(e) {
|
||||||
|
functionListFetch.reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$q.all(moduleFetches).then(function() {
|
||||||
|
modulesUpdated.resolve();
|
||||||
|
}, function(e) {
|
||||||
|
modulesUpdated.reject();
|
||||||
|
});
|
||||||
|
}).bind(this), function(e) {
|
||||||
|
modulesUpdated.reject(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update threads/thread states.
|
||||||
|
var threadsUpdated = $q.defer();
|
||||||
|
ps.push(threadsUpdated.promise);
|
||||||
|
dataSource.getThreadStates().then((function(states) {
|
||||||
|
cache.threadStates = states;
|
||||||
|
cache.threadList = [];
|
||||||
|
for (var threadId in states) {
|
||||||
|
cache.threadList.push(states[threadId]);
|
||||||
|
}
|
||||||
|
threadsUpdated.resolve();
|
||||||
|
}).bind(this), function(e) {
|
||||||
|
threadsUpdated.reject(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
var d = $q.defer();
|
||||||
|
$q.all(ps).then((function() {
|
||||||
|
d.resolve();
|
||||||
|
}).bind(this), (function(e) {
|
||||||
|
d.reject(e);
|
||||||
|
}).bind(this));
|
||||||
|
return d.promise;
|
||||||
|
};
|
||||||
|
State.prototype.getModuleList = function() {
|
||||||
|
return this.cache_.moduleList;
|
||||||
|
};
|
||||||
|
State.prototype.getModule = function(moduleName) {
|
||||||
|
return this.cache_.modules[moduleName] || null;
|
||||||
|
};
|
||||||
|
State.prototype.getFunctionList = function(moduleName) {
|
||||||
|
var cached = this.cache_.moduleFunctionLists[moduleName];
|
||||||
|
return cached ? cached.list : [];
|
||||||
|
};
|
||||||
|
State.prototype.getFunction = function(address) {
|
||||||
|
return this.cache_.functions[address] || null;
|
||||||
|
};
|
||||||
|
State.prototype.fetchFunction = function(address) {
|
||||||
|
var cache = this.cache_;
|
||||||
|
var d = $q.defer();
|
||||||
|
var cached = cache.functions[address];
|
||||||
|
if (cached) {
|
||||||
|
d.resolve(cached);
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
var dataSource = this.session.dataSource;
|
||||||
|
if (!dataSource) {
|
||||||
|
d.reject(new Error('Not online.'));
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
dataSource.getFunction(address).then(function(result) {
|
||||||
|
cache.functions[address] = result;
|
||||||
|
d.resolve(result);
|
||||||
|
}, function(e) {
|
||||||
|
d.reject(e);
|
||||||
|
});
|
||||||
|
return d.promise;
|
||||||
|
}
|
||||||
|
Object.defineProperty(State.prototype, 'threadList', {
|
||||||
|
get: function() {
|
||||||
|
return this.cache_.threadList || [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
State.prototype.getThreadStates = function() {
|
||||||
|
return this.cache_.threadStates || {};
|
||||||
|
};
|
||||||
|
State.prototype.getThreadState = function(threadId) {
|
||||||
|
return this.cache_.threadStates[threadId] || null;
|
||||||
|
};
|
||||||
|
|
||||||
var Session = function(id, opt_dataSource) {
|
var Session = function(id, opt_dataSource) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
|
@ -22,6 +170,9 @@ module.service('Session', function(
|
||||||
this.breakpointsById = {};
|
this.breakpointsById = {};
|
||||||
|
|
||||||
this.dataSource = opt_dataSource || null;
|
this.dataSource = opt_dataSource || null;
|
||||||
|
this.state = new State(this);
|
||||||
|
|
||||||
|
this.activeThread = null;
|
||||||
|
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
|
|
||||||
|
@ -144,6 +295,8 @@ module.service('Session', function(
|
||||||
d.resolve();
|
d.resolve();
|
||||||
return d.promise;
|
return d.promise;
|
||||||
}
|
}
|
||||||
|
this.state.clear();
|
||||||
|
this.activeThread = null;
|
||||||
|
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.dataSource.on('online', function() {
|
this.dataSource.on('online', function() {
|
||||||
|
@ -165,28 +318,31 @@ module.service('Session', function(
|
||||||
}
|
}
|
||||||
ps.push(this.dataSource.addBreakpoints(breakpointList));
|
ps.push(this.dataSource.addBreakpoints(breakpointList));
|
||||||
|
|
||||||
// Fetch main module info.
|
// Perform a full sync.
|
||||||
// We need this for entry point info/etc.
|
var syncDeferred = $q.defer();
|
||||||
var moduleInfoDeferred = $q.defer();
|
ps.push(syncDeferred.promise);
|
||||||
this.dataSource.getModuleList().then(function(moduleList) {
|
this.state.sync().then((function() {
|
||||||
|
// Put a breakpoint at the entry point.
|
||||||
|
// TODO(benvanik): make an option?
|
||||||
|
var moduleList = this.state.getModuleList();
|
||||||
if (!moduleList.length) {
|
if (!moduleList.length) {
|
||||||
// Uh.
|
log.error('No modules found!');
|
||||||
log.error('No modules loaded on startup!');
|
syncDeferred.reject(new Error('No modules found.'));
|
||||||
moduleInfoDeferred.reject(new Error('No modules found'));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
moduleList.forEach(function(module) {
|
var moduleInfo = this.state.getModule(moduleList[0].name);
|
||||||
dataSource.getModule(module.name).then(function(moduleInfo) {
|
if (!moduleInfo) {
|
||||||
// Put a breakpoint at the entry point.
|
log.error('Main module not found!');
|
||||||
var entryPoint = moduleInfo.exeEntryPoint;
|
syncDeferred.reject(new Error('Main module not found.'));
|
||||||
self.addTempBreakpoint(entryPoint, entryPoint);
|
return;
|
||||||
moduleInfoDeferred.resolve();
|
}
|
||||||
});
|
var entryPoint = moduleInfo.exeEntryPoint;
|
||||||
});
|
self.addTempBreakpoint(entryPoint, entryPoint);
|
||||||
}, function(e) {
|
|
||||||
moduleInfoDeferred.reject(e);
|
syncDeferred.resolve();
|
||||||
});
|
}).bind(this), (function(e) {
|
||||||
ps.push(moduleInfoDeferred.promise);
|
syncDeferred.reject(e);
|
||||||
|
}).bind(this));
|
||||||
|
|
||||||
$q.all(ps).then((function() {
|
$q.all(ps).then((function() {
|
||||||
this.dataSource.makeReady().then(function() {
|
this.dataSource.makeReady().then(function() {
|
||||||
|
@ -258,16 +414,25 @@ module.service('Session', function(
|
||||||
// Now paused!
|
// Now paused!
|
||||||
this.paused = true;
|
this.paused = true;
|
||||||
|
|
||||||
$rootScope.$emit('refresh');
|
this.state.sync().then((function() {
|
||||||
|
// Switch active thread.
|
||||||
|
var thread = this.state.getThreadState(threadId);
|
||||||
|
this.activeThread = thread;
|
||||||
|
|
||||||
if (breakpointId) {
|
if (!breakpointId) {
|
||||||
var breakpoint = this.breakpointsById[breakpointId];
|
// Just a general pause.
|
||||||
var thread = null; // TODO
|
log.info('Execution paused.');
|
||||||
if (!breakpoint) {
|
|
||||||
log.error('Breakpoint hit but not found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var breakpoint = this.breakpointsById[breakpointId];
|
||||||
|
if (!breakpoint) {
|
||||||
|
log.error('Breakpoint hit but not found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(benvanik): stash current breakpoint/thread/etc.
|
||||||
|
|
||||||
log.info('Breakpoint hit at 0x' +
|
log.info('Breakpoint hit at 0x' +
|
||||||
breakpoint.address.toString(16).toUpperCase() + '.');
|
breakpoint.address.toString(16).toUpperCase() + '.');
|
||||||
|
|
||||||
|
@ -279,10 +444,9 @@ module.service('Session', function(
|
||||||
notify: true,
|
notify: true,
|
||||||
reloadOnSearch: false
|
reloadOnSearch: false
|
||||||
});
|
});
|
||||||
} else {
|
}).bind(this), (function(e) {
|
||||||
// Just a general pause.
|
log.error('Unable to synchronize state,');
|
||||||
log.info('Execution paused.');
|
}).bind(this));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Session.prototype.continueExecution = function() {
|
Session.prototype.continueExecution = function() {
|
||||||
|
|
|
@ -76,6 +76,15 @@ int Debugger::ResumeAllThreads(bool force) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Debugger::ForEachThread(std::function<void(ThreadState*)> callback) {
|
||||||
|
LockMutex(threads_lock_);
|
||||||
|
for (auto it = threads_.begin(); it != threads_.end(); ++it) {
|
||||||
|
ThreadState* thread_state = it->second;
|
||||||
|
callback(thread_state);
|
||||||
|
}
|
||||||
|
UnlockMutex(threads_lock_);
|
||||||
|
}
|
||||||
|
|
||||||
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
||||||
// Add to breakpoints map.
|
// Add to breakpoints map.
|
||||||
LockMutex(breakpoints_lock_);
|
LockMutex(breakpoints_lock_);
|
||||||
|
|
|
@ -86,6 +86,8 @@ public:
|
||||||
int ResumeThread(uint32_t thread_id);
|
int ResumeThread(uint32_t thread_id);
|
||||||
int ResumeAllThreads(bool force = false);
|
int ResumeAllThreads(bool force = false);
|
||||||
|
|
||||||
|
void ForEachThread(std::function<void (ThreadState*)> callback);
|
||||||
|
|
||||||
int AddBreakpoint(Breakpoint* breakpoint);
|
int AddBreakpoint(Breakpoint* breakpoint);
|
||||||
int RemoveBreakpoint(Breakpoint* breakpoint);
|
int RemoveBreakpoint(Breakpoint* breakpoint);
|
||||||
void FindBreakpoints(
|
void FindBreakpoints(
|
||||||
|
|
|
@ -22,7 +22,7 @@ __declspec(thread) ThreadState* thread_state_ = NULL;
|
||||||
|
|
||||||
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id) :
|
ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id) :
|
||||||
runtime_(runtime), memory_(runtime->memory()),
|
runtime_(runtime), memory_(runtime->memory()),
|
||||||
thread_id_(thread_id),
|
thread_id_(thread_id), name_(0),
|
||||||
backend_data_(0), raw_context_(0) {
|
backend_data_(0), raw_context_(0) {
|
||||||
if (thread_id_ == UINT_MAX) {
|
if (thread_id_ == UINT_MAX) {
|
||||||
// System thread. Assign the system thread ID with a high bit
|
// System thread. Assign the system thread ID with a high bit
|
||||||
|
@ -40,6 +40,19 @@ ThreadState::~ThreadState() {
|
||||||
if (thread_state_ == this) {
|
if (thread_state_ == this) {
|
||||||
thread_state_ = NULL;
|
thread_state_ = NULL;
|
||||||
}
|
}
|
||||||
|
if (name_) {
|
||||||
|
xe_free(name_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadState::set_name(const char* value) {
|
||||||
|
if (value == name_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (name_) {
|
||||||
|
xe_free(name_);
|
||||||
|
}
|
||||||
|
name_ = xestrdupa(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadState::Bind(ThreadState* thread_state) {
|
void ThreadState::Bind(ThreadState* thread_state) {
|
||||||
|
|
|
@ -29,6 +29,8 @@ public:
|
||||||
Runtime* runtime() const { return runtime_; }
|
Runtime* runtime() const { return runtime_; }
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
uint32_t thread_id() const { return thread_id_; }
|
uint32_t thread_id() const { return thread_id_; }
|
||||||
|
const char* name() const { return name_; }
|
||||||
|
void set_name(const char* value);
|
||||||
void* backend_data() const { return backend_data_; }
|
void* backend_data() const { return backend_data_; }
|
||||||
void* raw_context() const { return raw_context_; }
|
void* raw_context() const { return raw_context_; }
|
||||||
|
|
||||||
|
@ -45,6 +47,7 @@ protected:
|
||||||
Runtime* runtime_;
|
Runtime* runtime_;
|
||||||
Memory* memory_;
|
Memory* memory_;
|
||||||
uint32_t thread_id_;
|
uint32_t thread_id_;
|
||||||
|
char* name_;
|
||||||
void* backend_data_;
|
void* backend_data_;
|
||||||
void* raw_context_;
|
void* raw_context_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
const char* GetString() const;
|
const char* GetString() const;
|
||||||
char* ToString();
|
char* ToString();
|
||||||
|
char* EncodeBase64();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* buffer_;
|
char* buffer_;
|
||||||
|
|
|
@ -330,6 +330,17 @@ json_t* Processor::OnDebugRequest(
|
||||||
}
|
}
|
||||||
uint64_t address = (uint64_t)json_number_value(address_json);
|
uint64_t address = (uint64_t)json_number_value(address_json);
|
||||||
return DumpFunction(address, succeeded);
|
return DumpFunction(address, succeeded);
|
||||||
|
} else if (xestrcmpa(command, "get_thread_states") == 0) {
|
||||||
|
json_t* result = json_object();
|
||||||
|
runtime_->debugger()->ForEachThread([&](ThreadState* thread_state) {
|
||||||
|
json_t* state_json = DumpThreadState((XenonThreadState*)thread_state);
|
||||||
|
char threadIdString[32];
|
||||||
|
xesnprintfa(
|
||||||
|
threadIdString, XECOUNT(threadIdString),
|
||||||
|
"%d", thread_state->thread_id());
|
||||||
|
json_object_set_new(result, threadIdString, state_json);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
} else if (xestrcmpa(command, "add_breakpoints") == 0) {
|
} else if (xestrcmpa(command, "add_breakpoints") == 0) {
|
||||||
// breakpoints: [{}]
|
// breakpoints: [{}]
|
||||||
json_t* breakpoints_json = json_object_get(request, "breakpoints");
|
json_t* breakpoints_json = json_object_get(request, "breakpoints");
|
||||||
|
@ -699,6 +710,61 @@ json_t* Processor::DumpFunction(uint64_t address, bool& succeeded) {
|
||||||
return fn_json;
|
return fn_json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json_t* Processor::DumpThreadState(XenonThreadState* thread_state) {
|
||||||
|
json_t* result = json_object();
|
||||||
|
|
||||||
|
json_object_set_integer_new(result, "id", thread_state->thread_id());
|
||||||
|
json_object_set_string_new(result, "name", thread_state->name());
|
||||||
|
json_object_set_integer_new(
|
||||||
|
result, "stackAddress", thread_state->stack_address());
|
||||||
|
json_object_set_integer_new(
|
||||||
|
result, "stackSize", thread_state->stack_size());
|
||||||
|
json_object_set_integer_new(
|
||||||
|
result, "threadStateAddress", thread_state->thread_state_address());
|
||||||
|
|
||||||
|
json_t* context_json = json_object();
|
||||||
|
auto context = thread_state->context();
|
||||||
|
|
||||||
|
json_object_set_new(
|
||||||
|
context_json, "lr", json_integer(context->lr));
|
||||||
|
json_object_set_new(
|
||||||
|
context_json, "ctr", json_integer(context->ctr));
|
||||||
|
|
||||||
|
// xer
|
||||||
|
// cr*
|
||||||
|
// fpscr
|
||||||
|
|
||||||
|
json_t* r_json = json_array();
|
||||||
|
for (size_t n = 0; n < 32; n++) {
|
||||||
|
json_array_append_new(r_json, json_integer(context->r[n]));
|
||||||
|
}
|
||||||
|
json_object_set_new(context_json, "r", r_json);
|
||||||
|
|
||||||
|
json_t* f_json = json_array();
|
||||||
|
for (size_t n = 0; n < 32; n++) {
|
||||||
|
json_array_append_new(f_json, json_real(context->f[n]));
|
||||||
|
}
|
||||||
|
json_object_set_new(context_json, "f", f_json);
|
||||||
|
|
||||||
|
json_t* v_json = json_array();
|
||||||
|
for (size_t n = 0; n < 128; n++) {
|
||||||
|
auto& v = context->v[n];
|
||||||
|
json_t* vec4_json = json_array();
|
||||||
|
json_array_append_new(vec4_json, json_integer(v.ix));
|
||||||
|
json_array_append_new(vec4_json, json_integer(v.iy));
|
||||||
|
json_array_append_new(vec4_json, json_integer(v.iz));
|
||||||
|
json_array_append_new(vec4_json, json_integer(v.iw));
|
||||||
|
json_array_append_new(v_json, vec4_json);
|
||||||
|
}
|
||||||
|
json_object_set_new(context_json, "v", v_json);
|
||||||
|
|
||||||
|
json_object_set_new(result, "context", context_json);
|
||||||
|
|
||||||
|
// TODO(benvanik): callstack
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Processor::DebugClientState::DebugClientState(XenonRuntime* runtime) :
|
Processor::DebugClientState::DebugClientState(XenonRuntime* runtime) :
|
||||||
runtime_(runtime) {
|
runtime_(runtime) {
|
||||||
breakpoints_lock_ = xe_mutex_alloc(10000);
|
breakpoints_lock_ = xe_mutex_alloc(10000);
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
private:
|
private:
|
||||||
json_t* DumpModule(XexModule* module, bool& succeeded);
|
json_t* DumpModule(XexModule* module, bool& succeeded);
|
||||||
json_t* DumpFunction(uint64_t address, bool& succeeded);
|
json_t* DumpFunction(uint64_t address, bool& succeeded);
|
||||||
|
json_t* DumpThreadState(XenonThreadState* thread_state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Emulator* emulator_;
|
Emulator* emulator_;
|
||||||
|
|
|
@ -29,6 +29,9 @@ public:
|
||||||
size_t stack_size, uint64_t thread_state_address);
|
size_t stack_size, uint64_t thread_state_address);
|
||||||
virtual ~XenonThreadState();
|
virtual ~XenonThreadState();
|
||||||
|
|
||||||
|
uint64_t stack_address() const { return stack_address_; }
|
||||||
|
size_t stack_size() const { return stack_size_; }
|
||||||
|
uint64_t thread_state_address() const { return thread_state_address_; }
|
||||||
PPCContext* context() const { return context_; }
|
PPCContext* context() const { return context_; }
|
||||||
|
|
||||||
virtual volatile int* suspend_flag_address() const;
|
virtual volatile int* suspend_flag_address() const;
|
||||||
|
@ -37,11 +40,9 @@ public:
|
||||||
virtual void EnterSuspend();
|
virtual void EnterSuspend();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t stack_size_;
|
|
||||||
uint64_t thread_state_address;
|
|
||||||
|
|
||||||
uint32_t thread_id_;
|
uint32_t thread_id_;
|
||||||
uint64_t stack_address_;
|
uint64_t stack_address_;
|
||||||
|
size_t stack_size_;
|
||||||
uint64_t thread_state_address_;
|
uint64_t thread_state_address_;
|
||||||
|
|
||||||
// NOTE: must be 64b aligned for SSE ops.
|
// NOTE: must be 64b aligned for SSE ops.
|
||||||
|
|
Loading…
Reference in New Issue