diff --git a/.gitmodules b/.gitmodules index cfeadeb7d..2a1898d63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,12 +13,6 @@ [submodule "third_party/beaengine"] path = third_party/beaengine url = https://github.com/benvanik/beaengine.git -[submodule "third_party/wslay"] - path = third_party/wslay - url = https://github.com/benvanik/wslay.git -[submodule "third_party/jansson"] - path = third_party/jansson - url = https://github.com/akheron/jansson.git [submodule "third_party/xbyak"] path = third_party/xbyak url = https://github.com/herumi/xbyak.git diff --git a/debugger/assets/styles/app.css b/debugger/assets/styles/app.css deleted file mode 100644 index a66515e68..000000000 --- a/debugger/assets/styles/app.css +++ /dev/null @@ -1,468 +0,0 @@ -/** - ****************************************************************************** - * 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. * - ****************************************************************************** - */ - -.full-width { - width: 100%; -} -.left-align { - text-align: left; -} - -body { - margin: 0; -} - -.app-main { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - overflow: hidden; - min-width: 900px; - min-height: 350px; - display: flex; - flex-flow: column nowrap; -} -.app-header { - order: 1; - flex: 0 0 auto; - align-self: auto; -} -.app-header .navbar { - border-radius: 0; - min-height: 0; - margin-bottom: 0; -} - -.app-body { - order: 2; - flex: 1 1 auto; - align-self: auto; - position: relative; - left: 0; - top: 0; - right: 0; - bottom: 0; -} -.disconnected .app-body { - opacity: 0.25; - pointer-events: none; -} -.tab-pane { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; -} - -.app-console { - order: 3; - flex: 0 0 auto; - align-self: auto; - border-top-width: 2px; - border-top-style: solid; -} -.console { - display: flex; - flex-flow: column nowrap; - padding: 5px; -} -.console-part-log { - order: 1; - flex: 1 1 auto; - align-self: auto; -} -.console-log-outer { - position: relative; - left: 0; - top: 0; - right: 0; - bottom: 0; - border: 1px solid #ddd; - overflow-y: scroll; - height: 100px; -} -.console-part-input { - order: 2; - flex: 0 0 auto; - align-self: auto; - display: flex; - flex-flow: row nowrap; - padding-top: 5px; -} -.console-input-left { - order: 1; - flex: 0 0 auto; - min-width: 0; -} -.console-input-middle { - order: 2; - flex: 1 1 auto; -} -.console-input-right { - order: 3; - flex: 0 0 auto; - padding-left: 10px; -} - -.debugger-main { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - display: flex; - flex-flow: column nowrap; -} -.debugger-header { - order: 1; - flex: 0 0 auto; - align-self: auto; - border-bottom: 1px solid #ddd; - padding: 5px; -} -.debugger-body { - order: 2; - flex: 1 1 auto; - align-self: auto; - display: flex; - flex-flow: row nowrap; -} -.debugger-fnlist { - order: 1; - flex: 0 0 auto; - display: flex; - flex-flow: column nowrap; - min-width: 270px; -} -.debugger-fnlist-header { - order: 1; - flex: 0 0 auto; - padding: 5px; - display: flex; - flex-flow: row nowrap; -} -.debugger-fnlist-header-left { - order: 1; - flex: 1 1 auto; - padding-right: 5px; -} -.debugger-fnlist-header-right { - order: 2; - flex: 0 0 auto; -} -.debugger-fnlist-body { - order: 2; - flex: 1 1 auto; - padding: 5px; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - position: relative; -} -.debugger-fnlist-list { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - padding: 5px; - 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 { - order: 3; - flex: 0 0 auto; - padding: 5px; -} -.debugger-fnlist-footer .input-group { - width: 100%; -} -.debugger-fnview-outer { - order: 2; - flex: 1 1 auto; - position: relative; - border-left: 2px solid #ddd; - border-right: 2px solid #ddd; - min-width: 720px; -} -.debugger-fnview { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - display: flex; - flex-flow: column nowrap; -} -.debugger-fnview-header { - order: 1; - flex: 0 0 auto; - padding: 5px; - display: flex; - flex-flow: row nowrap; -} -.debugger-fnview-header-left { - order: 1; - flex: 1 1 auto; - padding: 5px; - line-height: 1; -} -.debugger-fnview-header-name { - font-size: 21px; - font-family: monospace; -} -.debugger-fnview-header-address { - font-family: monospace; -} -.debugger-fnview-header-right { - order: 2; - flex: 0 0 auto; - padding: 5px; - margin-top: 3px; -} -.debugger-fnview-body { - order: 2; - flex: 1 1 auto; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - display: flex; - flex-flow: row nowrap; -} -.debugger-fnview-codeview { - order: 1; - flex: 1 1 auto; - position: relative; -} -.debugger-fnview-codeview .CodeMirror { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - height: 100%; -} -.debugger-fnview-gutter-icon { - width: 30px; -} -.debugger-fnview-gutter-icon-el { - padding-left: 7px; - position: relative; - top: -6px; - display: inline-block; - -webkit-font-smoothing: antialiased; - font-style: normal; - font-weight: normal; - line-height: 1; - font-size: 28px; -} -.debugger-fnview-gutter-addr { - width: 70px; -} -.debugger-fnview-gutter-addr-el { -} -.debugger-fnview-gutter-addr-el-inactive { - color: #999; -} -.debugger-fnview-gutter-code { - width: 76px; - background-color: #fff; - border-left: 1px solid #ddd; -} -.debugger-fnview-gutter-code-el { - padding-left: 6px; - color: #aaa; -} -.debugger-fnview-line-highlight-bg { - background-color: red; -} -.debugger-fnview-graphview { - order: 2; - flex: 0 0 auto; - position: relative; - border-left: 1px solid #ddd; - min-width: 100px; -} -.debugger-fnview-footer { - order: 3; - flex: 0 0 auto; - padding: 5px; -} -.debugger-tools { - order: 3; - flex: 0 0 auto; - display: flex; - flex-flow: column nowrap; - width: 40%; -} -.debugger-tools-threads { - order: 1; - flex: 0 0 auto; - 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 { - order: 2; - flex: 0 0 auto; - padding: 5px; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - position: relative; - height: 100px; -} -.debugger-tools-registers { - order: 3; - flex: 1 1 auto; - padding: 5px; - overflow-y: auto; -} -.debugger-tools-registers-container { - display: flex; - flex-direction: column; - flex-wrap: wrap; - justify-content: flex-start; - align-content: flex-start; - align-items: flex-start; - margin-bottom: 5px; -} -.debugger-tools-registers-entry { - flex: 0 0 auto; - font-family: monospace; - padding-right: 5px; - width: 160px; -} -.debugger-tools-registers-entry .name { - font-weight: bold; - width: 26px; - display: inline-block; - text-align: right; -} -.debugger-tools-registers-entry .value { -} -.debugger-tools-registers-container.special { - height: 46px; -} -.debugger-tools-registers-container.gpr { - height: 332px; -} -.special .debugger-tools-registers-entry, -.gpr .debugger-tools-registers-entry { - width: 300px; -} -.debugger-tools-registers-entry .hex-value { - border-style: none; - padding: 0; - width: 130px; - text-align: right; -} -.debugger-tools-registers-entry .int-value { - display: inline-block; - border-style: none; - padding: 0; - width: 92px; - text-align: right; -} -.debugger-tools-registers-container.fpr { - height: 172px; -} -.fpr .debugger-tools-registers-entry { - width: 170px; -} -.fpr .debugger-tools-registers-entry .value { - white-space: pre; -} -.vec .debugger-tools-registers-entry { - width: 160px; -} -.vec .debugger-tools-registers-entry .name { - width: 35px; -} - -.debugger-module-info { - display: block; - pointer-events: none; -} -.debugger-module-info .modal-dialog { - width: 60vw; -} -.debugger-module-info.fade .modal-dialog { - -webkit-transition: none; - -webkit-transform: translate(0,0); -} -.debugger-module-info div { - pointer-events: auto; -} -.debugger-module-info .modal-body { - max-width: 60vw; - max-height: 80vh; - overflow-y: auto; -} -.debugger-module-info-outer-table { -} -.debugger-module-info-outer-table tbody tr td:nth-child(1) { - width: 110px; -} -.debugger-module-info-inner-table { - width: 300px; -} -.debugger-module-info-inner-table td:nth-child(1) { - text-align: right; -} -.debugger-module-info-headers { - width: 400px; -} -.debugger-module-info-sections { - width: 400px; -} -.debugger-module-info-static-libraries { - width: 400px; -} -.debugger-module-info-imports { - width: 900px; -} -.debugger-module-info-imports td:nth-child(1) { - width: 40px; -} -.debugger-module-info-imports td:nth-child(2) { - width: 64px; -} -.debugger-module-info-imports td:nth-child(3) { - width: 60px; -} -.debugger-module-info-imports td:nth-child(4) { - width: 100%; -} -.debugger-module-info-imports td:nth-child(5) { - width: 80px; -} -.debugger-module-info-imports td:nth-child(6) { - width: 80px; -} diff --git a/debugger/assets/ui/apu/apu-tab.html b/debugger/assets/ui/apu/apu-tab.html deleted file mode 100644 index f57223d9b..000000000 --- a/debugger/assets/ui/apu/apu-tab.html +++ /dev/null @@ -1 +0,0 @@ -TODO: APU diff --git a/debugger/assets/ui/code/code-tab.html b/debugger/assets/ui/code/code-tab.html deleted file mode 100644 index b81d68ef3..000000000 --- a/debugger/assets/ui/code/code-tab.html +++ /dev/null @@ -1,135 +0,0 @@ -
-
-
- - -
-
- - -
-
-
-
-
-
- - -
-
- -
-
-
-
- - - - -
{{fn.name}}
-
-
- -
-
-
-
-
- - -
-
- -
-
-
- callstack -
-
-
-
- pc - -
-
- lr - -
-
- ctr - - -
-
-
-
- r{{$index}} - - -
-
-
-
- f{{$index}} - {{v|exp8}} -
-
-
-
- v{{$index}} - {{v}} -
-
-
-
-
-
diff --git a/debugger/assets/ui/code/code-tab.js b/debugger/assets/ui/code/code-tab.js deleted file mode 100644 index 07530a919..000000000 --- a/debugger/assets/ui/code/code-tab.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - ****************************************************************************** - * 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', [ - 'ui.bootstrap', - 'xe.log', - 'xe.session' -]); - - -module.controller('CodeTabController', function( - $rootScope, $scope, $modal, app, log) { - $scope.app = app; - $scope.moduleList = []; - $scope.selectedModule = null; - $scope.functionList = []; - - function refresh() { - if (!app.session) { - $scope.moduleList = []; - return; - } - - $scope.moduleList = app.session.state.getModuleList(); - if (!$scope.selectedModule) { - if ($scope.moduleList.length) { - $scope.selectModule($scope.moduleList[0]); - } - } else { - $scope.selectModule($scope.selectedModule); - } - - console.log('refresh'); - }; - $rootScope.$on('refresh', refresh); - - $scope.selectModule = function(module) { - var moduleChange = module != $scope.selectedModule; - $scope.selectedModule = module; - - if (moduleChange) { - $scope.functionList = []; - } - - $scope.functionList = app.session.state.getFunctionList(module.name); - }; - - $scope.showModuleInfo = function() { - var modalInstance = $modal.open({ - templateUrl: 'assets/ui/code/module-info.html', - controller: 'ModuleInfoController', - windowClass: 'debugger-module-info', - resolve: { - moduleName: function() { - return $scope.selectedModule.name; - }, - moduleInfo: function() { - return app.session.state.getModule( - $scope.selectedModule.name); - } - } - }); - }; - - $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; - } - } - }); - }; - - $scope.showLocation = function() { - // - }; - - if (app.session.dataSource) { - refresh(); - } -}); diff --git a/debugger/assets/ui/code/function-view.html b/debugger/assets/ui/code/function-view.html deleted file mode 100644 index 7a530e296..000000000 --- a/debugger/assets/ui/code/function-view.html +++ /dev/null @@ -1,47 +0,0 @@ -
-
-
-
- (0x{{fn.startAddress | hex32}}-0x{{fn.endAddress | hex32}}) -
-
- -
-
-
-
- -
-
- graph! -
-
- -
diff --git a/debugger/assets/ui/code/function-view.js b/debugger/assets/ui/code/function-view.js deleted file mode 100644 index 6f42127b3..000000000 --- a/debugger/assets/ui/code/function-view.js +++ /dev/null @@ -1,268 +0,0 @@ -/** - ****************************************************************************** - * 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, $location, app, log, Breakpoint) { - $scope.codeType = 'source'; - $scope.highlightInfo = null; - - function refresh() { - if (!app.session) { - $scope.fn = null; - return; - } - app.session.state.fetchFunction($scope.functionAddress).then(function(fn) { - $scope.fn = fn; - updateCode(); - }, function(e) { - log.error('Unable to fetch function.'); - }); - }; - $rootScope.$on('refresh', refresh); - $scope.$watch('functionAddress', refresh); - - function updateHighlight(address) { - if (!$scope.sourceLines || $scope.codeType != 'source') { - return; - } - if ($scope.highlightInfo) { - if ($scope.highlightInfo.address == address) { - return; - } - var oldLine = $scope.highlightInfo.line; - if ($scope.highlightInfo.widget) { - $scope.highlightInfo.widget.clear(); - } - $scope.highlightInfo = null; - updateLine(oldLine); - } - // TODO(benvanik): a better mapping. - var line = -1; - for (var n = 0; n < $scope.sourceLines.length; n++) { - var sourceLine = $scope.sourceLines[n]; - if (sourceLine[0] == 'i' && - sourceLine[1] == address) { - line = n; - break; - } - } - if (line != -1) { - $scope.highlightInfo = { - address: address, - line: line, - widget: null - }; - updateLine(line); - } - }; - $scope.$watch(function() { - return $location.search(); - }, function(search) { - updateHighlight(parseInt(search.a, 16)); - }); - - var textArea = document.querySelector('.debugger-fnview-textarea'); - $scope.codeMirror = CodeMirror.fromTextArea(textArea, { - mode: 'javascript', - theme: 'default', - indentUnit: 2, - tabSize: 2, - lineNumbers: false, - gutters: [ - 'debugger-fnview-gutter-icon', - 'debugger-fnview-gutter-addr', - 'debugger-fnview-gutter-code' - ], - readOnly: true - }); - - function hex32(number) { - var str = "" + number.toString(16).toUpperCase(); - while (str.length < 8) str = "0" + str; - return str; - }; - - function updateSourceCode(fn) { - var cm = $scope.codeMirror; - if (!fn) { - $scope.sourceLines = []; - cm.setValue(''); - return; - } - - var doc = cm.getDoc(); - - var lines = fn.disasm.source.lines; - $scope.sourceLines = lines; - - var textContent = []; - for (var n = 0; n < lines.length; n++) { - var line = lines[n]; - textContent.push(line[3]); - } - cm.setValue(textContent.join('\n')); - - for (var n = 0; n < lines.length; n++) { - var line = lines[n]; - - var el = document.createElement('div'); - el.classList.add('debugger-fnview-gutter-addr-el'); - el.innerText = hex32(line[1]); - cm.setGutterMarker(n, 'debugger-fnview-gutter-addr', el); - if (line[0] != 'i') { - el.classList.add('debugger-fnview-gutter-addr-el-inactive'); - } - - if (line[0] == 'i') { - el = document.createElement('div'); - el.classList.add('debugger-fnview-gutter-code-el'); - el.innerText = hex32(line[2]); - cm.setGutterMarker(n, 'debugger-fnview-gutter-code', el); - - updateLine(n); - } - } - }; - function updateCode() { - var cm = $scope.codeMirror; - var fn = $scope.fn || null; - var codeType = $scope.codeType; - - var gutters; - switch (codeType) { - case 'source': - gutters = [ - 'debugger-fnview-gutter-icon', - 'debugger-fnview-gutter-addr', - 'debugger-fnview-gutter-code' - ]; - break; - default: - gutters = [ - 'debugger-fnview-gutter-icon', - 'debugger-fnview-gutter-addr' - ]; - break; - } - cm.setOption('gutters', gutters); - - cm.clearGutter('debugger-fnview-gutter-icon'); - cm.clearGutter('debugger-fnview-gutter-addr'); - cm.clearGutter('debugger-fnview-gutter-code'); - - // Set last to make all option changes stick. - switch (codeType) { - case 'source': - cm.operation(function() { - updateSourceCode(fn); - }); - break; - default: - var value = fn ? fn.disasm[codeType] : null; - cm.setValue(value || ''); - break; - } - }; - $scope.$watch('codeType', updateCode); - - function updateLine(line) { - var sourceLine = $scope.sourceLines[line]; - var cm = $scope.codeMirror; - if (sourceLine[0] != 'i') { - return; - } - var address = sourceLine[1]; - var breakpoint = app.session.breakpoints[address]; - var el; - if (breakpoint && breakpoint.type == 'code') { - el = document.createElement('span'); - el.classList.add('debugger-fnview-gutter-icon-el'); - if (breakpoint.enabled) { - el.innerHTML = '●'; - } else { - el.innerHTML = '◌'; - } - } else { - el = null; - } - cm.setGutterMarker(line, 'debugger-fnview-gutter-icon', el); - - var highlightInfo = $scope.highlightInfo; - if (highlightInfo && highlightInfo.line == line) { - /* - if (!highlightInfo.widget) { - el = document.createElement('div'); - el.style.width = '100%'; - el.style.height = '20px'; - el.style.backgroundColor = 'red'; - el.innerHTML = 'hi!'; - highlightInfo.widget = cm.addLineWidget(line, el, { - coverGutter: false - }); - cm.scrollIntoView(line, 50); - } - */ - cm.addLineClass(line, 'background', 'debugger-fnview-line-highlight-bg'); - } else { - cm.removeLineClass(line, 'background'); - } - }; - - function toggleBreakpoint(line, sourceLine, shiftKey) { - var address = sourceLine[1]; - var breakpoint = app.session.breakpoints[address]; - if (breakpoint) { - // Existing breakpoint - toggle or remove. - if (shiftKey || !breakpoint.enabled) { - app.session.toggleBreakpoint(breakpoint, !breakpoint.enabled); - } else { - app.session.removeBreakpoint(breakpoint); - } - } else { - // New breakpoint needed. - breakpoint = app.session.addCodeBreakpoint( - $scope.functionAddress, address); - } - - updateLine(line); - }; - - $scope.codeMirror.on('gutterClick', function( - instance, line, gutterClass, e) { - if (e.which == 1) { - if (gutterClass == 'debugger-fnview-gutter-icon' || - gutterClass == 'debugger-fnview-gutter-addr') { - var sourceLine = $scope.sourceLines[line]; - if (!sourceLine || sourceLine[0] != 'i') { - return; - } - e.preventDefault(); - toggleBreakpoint(line, sourceLine, e.shiftKey); - } - } - }); -// $scope.codeMirror.on('gutterContextMenu', function( -// instance, line, gutterClass, e) { -// console.log('context menu'); -// e.preventDefault(); -// }); -// $scope.codeMirror.on('contextmenu', function( -// instance, e) { -// console.log('context menu main'); -// e.preventDefault(); -// }); -}); diff --git a/debugger/assets/ui/code/module-info.html b/debugger/assets/ui/code/module-info.html deleted file mode 100644 index 018b604d9..000000000 --- a/debugger/assets/ui/code/module-info.html +++ /dev/null @@ -1,218 +0,0 @@ - diff --git a/debugger/assets/ui/code/module-info.js b/debugger/assets/ui/code/module-info.js deleted file mode 100644 index 8078d955e..000000000 --- a/debugger/assets/ui/code/module-info.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - ****************************************************************************** - * 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.moduleInfo', [ - 'ui.bootstrap', - 'xe.log', - 'xe.session' -]); - - -module.controller('ModuleInfoController', function( - $rootScope, $scope, $modal, log, moduleName, moduleInfo) { - $scope.moduleName = moduleName; - $scope.moduleInfo = moduleInfo; - - $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); - }; -}); diff --git a/debugger/assets/ui/code/thread-info.html b/debugger/assets/ui/code/thread-info.html deleted file mode 100644 index 9d1c925af..000000000 --- a/debugger/assets/ui/code/thread-info.html +++ /dev/null @@ -1,35 +0,0 @@ - diff --git a/debugger/assets/ui/code/thread-info.js b/debugger/assets/ui/code/thread-info.js deleted file mode 100644 index bd48acfb6..000000000 --- a/debugger/assets/ui/code/thread-info.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - ****************************************************************************** - * 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); - }; -}); diff --git a/debugger/assets/ui/console/console.html b/debugger/assets/ui/console/console.html deleted file mode 100644 index 2f674513b..000000000 --- a/debugger/assets/ui/console/console.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-
-
    -
  • {{line}}
  • -
-
-
-
-
-
-
-
- @ - -
-
-
-
- - - -
-
-
-
diff --git a/debugger/assets/ui/console/console.js b/debugger/assets/ui/console/console.js deleted file mode 100644 index 6a07556b2..000000000 --- a/debugger/assets/ui/console/console.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - ****************************************************************************** - * 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.console', [ - 'xe.log' -]); - - -module.controller('ConsoleController', function($scope, log) { - $scope.log = log; - - $scope.commandText = ''; - - $scope.issueCommand = function() { - var command = $scope.commandText; - $scope.commandText = ''; - if (!command) { - return; - } - - log.appendLine('@' + command); - - // TODO(benvanik): execute. - console.log(command); - }; -}); diff --git a/debugger/assets/ui/gpu/gpu-tab.html b/debugger/assets/ui/gpu/gpu-tab.html deleted file mode 100644 index cf32ac752..000000000 --- a/debugger/assets/ui/gpu/gpu-tab.html +++ /dev/null @@ -1 +0,0 @@ -TODO: GPU diff --git a/debugger/assets/ui/kernel/kernel-tab.html b/debugger/assets/ui/kernel/kernel-tab.html deleted file mode 100644 index 92d33f5ee..000000000 --- a/debugger/assets/ui/kernel/kernel-tab.html +++ /dev/null @@ -1 +0,0 @@ -TODO: kernel diff --git a/debugger/assets/ui/memory/memory-tab.html b/debugger/assets/ui/memory/memory-tab.html deleted file mode 100644 index f15b42831..000000000 --- a/debugger/assets/ui/memory/memory-tab.html +++ /dev/null @@ -1 +0,0 @@ -TODO: memory diff --git a/debugger/assets/ui/navbar.html b/debugger/assets/ui/navbar.html deleted file mode 100644 index c2a64c9ec..000000000 --- a/debugger/assets/ui/navbar.html +++ /dev/null @@ -1,40 +0,0 @@ - diff --git a/debugger/assets/ui/navbar.js b/debugger/assets/ui/navbar.js deleted file mode 100644 index 4ae3bcde2..000000000 --- a/debugger/assets/ui/navbar.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - ****************************************************************************** - * 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.navbar', []); - - -module.controller('NavbarController', function( - $rootScope, $scope, $state, app, log) { - - $scope.refresh = function() { - $rootScope.$emit('refresh'); - }; - - $scope.connect = function() { - // TODO(benvanik): show a fancy dialog or something. - var oldSession = app.session; - app.connect().then(function(session) { - if (!oldSession || oldSession.id != session.id) { - $state.go('session', { - 'sessionId': session.id - }, { - notify: true - }); - } - }, function(e) { - $state.go('/', { - }, { - notify: true - }); - }); - }; - - $scope.open = function() { - var inputEl = document.createElement('input'); - inputEl.type = 'file'; - inputEl.accept = '.xe-trace,application/x-extension-xe-trace'; - inputEl.onchange = function(e) { - $scope.$apply(function() { - if (inputEl.files.length) { - //app.open(inputEl.files[0]); - log.info('Not implemented yet'); - } - }); - }; - inputEl.click(); - }; - -}); diff --git a/debugger/assets/ui/session.html b/debugger/assets/ui/session.html deleted file mode 100644 index 31800c0de..000000000 --- a/debugger/assets/ui/session.html +++ /dev/null @@ -1 +0,0 @@ -
diff --git a/debugger/debugger.js b/debugger/debugger.js deleted file mode 100644 index e8f39d267..000000000 --- a/debugger/debugger.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - ****************************************************************************** - * 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. * - ****************************************************************************** - */ diff --git a/debugger/index.html b/debugger/index.html deleted file mode 100644 index 92e653ee4..000000000 --- a/debugger/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - Xenia Debugger - - - - - - - - - - -
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - diff --git a/debugger/src/app.js b/debugger/src/app.js deleted file mode 100644 index 9cd2f4d45..000000000 --- a/debugger/src/app.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - ****************************************************************************** - * 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('app', [ - 'ui.bootstrap', - 'ui.router', - 'xe.datasources', - 'xe.directives', - 'xe.filters', - 'xe.log', - 'xe.router', - 'xe.session', - 'xe.ui.code', - 'xe.ui.code.functionView', - 'xe.ui.code.moduleInfo', - 'xe.ui.code.threadInfo', - 'xe.ui.console', - 'xe.ui.navbar' -]); - - -module.controller('AppController', function($scope, app) { - this.app = app; -}); - - -module.service('app', function( - $rootScope, $q, $state, log, Session) { - var App = function() { - this.loading = false; - this.session = null; - }; - - App.prototype.setSession = function(session) { - this.close(); - - this.session = session; - $rootScope.$emit('refresh'); - }; - - App.prototype.close = function() { - this.loading = false; - if (this.session) { - this.session.dispose(); - this.session = null; - } - }; - - App.prototype.open = function(sessionId) { - var d = $q.defer(); - - // Ignore if already open. - if (this.session && this.session.id == sessionId) { - d.resolve(this.session); - return d.promise; - } - - // Close existing. - this.close(); - - this.loading = true; - - log.info('Opening session ' + sessionId); - - // Open session. - var session = new Session(sessionId); - this.loading = false; - this.setSession(session); - d.resolve(session); - - return d.promise; - }; - - App.prototype.connect = function(opt_host) { - this.close(); - - var d = $q.defer(); - this.loading = true; - - Session.query(opt_host).then((function(infos) { - var info = infos[0]; - var id = info.titleId; - if (id == '00000000') { - id = info.name; - } - var session = new Session(id); - var p = session.connect(opt_host); - p.then((function(session) { - this.loading = false; - this.setSession(session); - d.resolve(session); - }).bind(this), (function(e) { - this.loading = false; - d.reject(e); - }).bind(this), function(update) { - d.notify(update); - }); - }).bind(this), (function(e) { - this.loading = false; - log.info('No sessions found at ' + Session.getHost(opt_host)); - d.reject(e); - }).bind(this)); - - return d.promise; - }; - - return new App(); -}); - - -module.run(function($rootScope, $state, $stateParams, app, log) { - $rootScope.$state = $state; - $rootScope.$stateParams = $stateParams; - - $rootScope.app = app; - $rootScope.log = log; -}); diff --git a/debugger/src/base.js b/debugger/src/base.js deleted file mode 100644 index 172e9ae64..000000000 --- a/debugger/src/base.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - ****************************************************************************** - * 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'; - - -function inherits(childCtor, parentCtor) { - function tempCtor() {}; - tempCtor.prototype = parentCtor.prototype; - childCtor.superClass_ = parentCtor.prototype; - childCtor.prototype = new tempCtor(); - childCtor.prototype.constructor = childCtor; -}; - -var EventEmitter = function() { - this.events_ = {}; -}; -EventEmitter.prototype.dispose = function() { - this.events_ = {}; -}; -EventEmitter.prototype.on = function(name, listener, opt_scope) { - var listeners = this.events_[name]; - if (!listeners) { - listeners = this.events_[name] = []; - } - listeners.push({ - callback: listener, - scope: opt_scope || null - }); -}; -EventEmitter.prototype.off = function(name, listener, opt_scope) { - var listeners = this.events_[name]; - if (!listeners) { - return; - } - for (var n = 0; n < listeners.length; n++) { - if (listeners[n].callback == listener) { - listeners.splice(n, 1); - if (!listeners.length) { - delete this.events_[name]; - } - return; - } - } -} -EventEmitter.prototype.emit = function(name, args) { - var listeners = this.events_[name]; - if (!listeners) { - return; - } - for (var n = 0; n < listeners.length; n++) { - var listener = listeners[n]; - listener.callback.apply(listener.scope, args); - } -}; diff --git a/debugger/src/datasources.js b/debugger/src/datasources.js deleted file mode 100644 index 62e3e66bc..000000000 --- a/debugger/src/datasources.js +++ /dev/null @@ -1,317 +0,0 @@ -/** - ****************************************************************************** - * 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.datasources', []); - - -module.service('Breakpoint', function() { - // http://stackoverflow.com/a/2117523/377392 - var uuidFormat = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; - function uuid4() { - return uuidFormat.replace(/[xy]/g, function(c) { - var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8); - return v.toString(16); - }); - }; - - var Breakpoint = function(opt_id) { - this.id = opt_id || uuid4(); - this.type = Breakpoint.Type.TEMP; - this.fnAddress = 0; - this.address = 0; - this.enabled = true; - }; - Breakpoint.Type = { - TEMP: 'temp', - CODE: 'code' - }; - Breakpoint.fromJSON = function(json) { - var breakpoint = new Breakpoint(json.id); - breakpoint.type = json.type; - breakpoint.fnAddress = json.fnAddress; - breakpoint.address = json.address; - breakpoint.enabled = json.enabled; - return breakpoint; - }; - Breakpoint.prototype.toJSON = function() { - return { - 'id': this.id, - 'type': this.type, - 'fnAddress': this.fnAddress, - 'address': this.address, - 'enabled': this.enabled - }; - }; - return Breakpoint; -}); - - -module.service('DataSource', function($q) { - var DataSource = function(source, delegate) { - EventEmitter.call(this); - this.source = source; - this.delegate = delegate; - this.online = false; - this.status = 'disconnected'; - }; - inherits(DataSource, EventEmitter); - DataSource.prototype.open = function() {}; - DataSource.prototype.dispose = function() {}; - DataSource.prototype.issue = function(command) {}; - - DataSource.prototype.makeReady = function() { - return this.issue({ - command: 'debug.make_ready' - }); - }; - - DataSource.prototype.getModuleList = function() { - return this.issue({ - command: 'cpu.get_module_list' - }); - }; - - DataSource.prototype.getModule = function(moduleName) { - return this.issue({ - command: 'cpu.get_module', - module: moduleName - }); - }; - - DataSource.prototype.getFunctionList = function(moduleName, opt_since) { - return this.issue({ - command: 'cpu.get_function_list', - module: moduleName, - since: opt_since || 0 - }); - }; - - DataSource.prototype.getFunction = function(address) { - return this.issue({ - command: 'cpu.get_function', - address: address - }); - }; - - DataSource.prototype.getThreadStates = function() { - return this.issue({ - command: 'cpu.get_thread_states' - }); - }; - - // set registers/etc? - - DataSource.prototype.addBreakpoint = function(breakpoint) { - return this.addBreakpoints([breakpoint]); - }; - - DataSource.prototype.addBreakpoints = function(breakpoints) { - if (!breakpoints.length) { - var d = $q.defer(); - d.resolve(); - return d.promise; - } - return this.issue({ - command: 'cpu.add_breakpoints', - breakpoints: breakpoints.map(function(breakpoint) { - return breakpoint.toJSON(); - }) - }); - }; - - DataSource.prototype.removeBreakpoint = function(breakpointId) { - return this.removeBreakpoints([breakpointId]); - }; - - DataSource.prototype.removeBreakpoints = function(breakpointIds) { - return this.issue({ - command: 'cpu.remove_breakpoints', - breakpointIds: breakpointIds - }); - }; - - DataSource.prototype.removeAllBreakpoints = function() { - return this.issue({ - command: 'cpu.remove_all_breakpoints' - }); - }; - - DataSource.prototype.continueExecution = function() { - return this.issue({ - command: 'cpu.continue' - }); - }; - - DataSource.prototype.breakExecution = function() { - return this.issue({ - command: 'cpu.break' - }); - }; - - DataSource.prototype.stepNext = function(threadId) { - return this.issue({ - command: 'cpu.step', - threadId: threadId - }); - }; - - return DataSource; -}); - -module.service('RemoteDataSource', function( - $rootScope, $q, log, DataSource) { - var RemoteDataSource = function(url, delegate) { - DataSource.call(this, url, delegate); - this.url = url; - this.socket = null; - this.nextRequestId_ = 1; - this.pendingRequests_ = {}; - }; - inherits(RemoteDataSource, DataSource); - - RemoteDataSource.prototype.open = function() { - var url = this.url; - - this.online = false; - this.status = 'connecting'; - - var d = $q.defer(); - - this.socket = new WebSocket(url, []); - this.socket.onopen = (function() { - $rootScope.$apply((function() { - // TODO(benvanik): handshake - - this.online = true; - this.status = 'connected'; - this.emit('online'); - d.resolve(); - }).bind(this)); - }).bind(this); - - this.socket.onclose = (function(e) { - $rootScope.$apply((function() { - this.online = false; - if (this.status == 'connecting') { - this.status = 'disconnected'; - d.reject(e.code + ' ' + e.reason); - } else { - this.status = 'disconnected'; - log.info('Disconnected'); - this.emit('offline'); - } - }).bind(this)); - }).bind(this); - - this.socket.onerror = (function(e) { - // ? - }).bind(this); - - this.socket.onmessage = (function(e) { - $rootScope.$apply((function() { - this.socketMessage(e); - }).bind(this)); - }).bind(this); - - return d.promise; - }; - - RemoteDataSource.prototype.socketMessage = function(e) { - console.log('message', e.data); - var json = JSON.parse(e.data); - if (json.requestId) { - // Response to a previous request. - var request = this.pendingRequests_[json.requestId]; - if (request) { - delete this.pendingRequests_[json.requestId]; - if (json.status) { - request.deferred.resolve(json.result); - } else { - request.deferred.reject(json.result); - } - } - } else { - // Notification. - switch (json.type) { - case 'breakpoint': - this.delegate.onBreakpointHit( - json.breakpointId, json.threadId); - break; - default: - log.error('Unknown notification type: ' + json.type); - break; - } - } - }; - - RemoteDataSource.prototype.dispose = function() { - this.pendingRequests_ = {}; - this.online = false; - this.status = 'disconnected'; - if (this.socket) { - this.socket.close(); - this.socket = null; - } - DataSource.prototype.dispose.call(this); - }; - - RemoteDataSource.prototype.issue = function(command) { - var d = $q.defer(); - command.requestId = this.nextRequestId_++; - this.socket.send(JSON.stringify(command)); - command.deferred = d; - this.pendingRequests_[command.requestId] = command; - return d.promise; - }; - - return RemoteDataSource; -}); - - -module.service('FileDataSource', function($q, DataSource) { - var FileDataSource = function(file, delegate) { - DataSource.call(this, file.name, delegate); - this.file = file; - }; - inherits(FileDataSource, DataSource); - - FileDataSource.prototype.open = function() { - this.status = 'connecting'; - - var d = $q.defer(); - - var self = this; - window.setTimeout(function() { - $scope.$apply((function() { - // TODO(benvanik): scan/load trace - - this.online = true; - this.status = 'connected'; - d.resolve(); - }).bind(self)); - }); - - return d.promise; - }; - - FileDataSource.prototype.dispose = function() { - this.online = false; - if (this.file) { - if (this.file.close) { - this.file.close(); - } - this.file = null; - } - DataSource.prototype.dispose.call(this); - }; - - return FileDataSource; -}); diff --git a/debugger/src/directives.js b/debugger/src/directives.js deleted file mode 100644 index 30925723e..000000000 --- a/debugger/src/directives.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - ****************************************************************************** - * 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.directives', [ - 'ui.router' -]); - - -module.directive('uiEnter', function() { - return function($scope, element, attrs) { - element.bind('keydown keypress', function(e) { - if(e.which === 13) { - $scope.$apply(function(){ - $scope.$eval(attrs.uiEnter); - }); - e.preventDefault(); - } - }); - }; -}); - -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(); - } - }); - }; -}); - -module.directive('uiScrollDownOn', function() { - return { - priority: 1, - link: function($scope, element, attrs) { - $scope.$watch(attrs.uiScrollDownOn, function() { - element[0].scrollTop = element[0].scrollHeight; - }); - } - }; -}); - -module.directive('xeCoderef', function($state) { - return { - priority: 1, - link: function($scope, element, attrs) { - var target = attrs.xeCoderef; - var stateName = 'session.code.function'; - var stateParams = { - function: target, - a: null - }; - element.attr('href', $state.href(stateName, stateParams)); - element.bind('click', function(e) { - e.preventDefault(); - $state.go(stateName, stateParams); - }); - } - }; -}); - -module.directive('xeMemref', function($state) { - return { - priority: 1, - link: function($scope, element, attrs) { - var target = attrs.xeMemref; - var stateName = 'session.memory'; - var stateParams = { - a: target - }; - element.attr('href', $state.href(stateName, stateParams)); - element.bind('click', function(e) { - e.preventDefault(); - $state.go(stateName, stateParams); - }); - } - }; -}); diff --git a/debugger/src/filters.js b/debugger/src/filters.js deleted file mode 100644 index d76fb4637..000000000 --- a/debugger/src/filters.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - ****************************************************************************** - * 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('hex16', function() { - return function(number) { - if (number !== null && number !== undefined) { - var str = '' + number.toString(16).toUpperCase(); - while (str.length < 4) str = '0' + str; - return str; - } - }; -}); - -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; - } - }; -}); - -module.filter('exp8', function() { - return function(number) { - if (number !== null && number !== undefined) { - var str = number.toExponential(8); - if (number >= 0) { - str = ' ' + str; - } - return str; - } - } -}); diff --git a/debugger/src/log.js b/debugger/src/log.js deleted file mode 100644 index 5768e849c..000000000 --- a/debugger/src/log.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - ****************************************************************************** - * 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.log', []); - - -module.service('log', function($rootScope) { - var Log = function() { - this.lines = []; - - this.progressActive = false; - this.progress = 0; - }; - - Log.prototype.appendLine = function(line) { - this.lines.push(line); - }; - - Log.prototype.info = function(line) { - this.appendLine('I ' + line); - }; - - Log.prototype.error = function(line) { - this.appendLine('E ' + line); - }; - - Log.prototype.setProgress = function(value) { - this.progressActive = true; - this.progress = value; - }; - - Log.prototype.clearProgress = function() { - this.progressActive = false; - }; - - return new Log(); -}); diff --git a/debugger/src/router.js b/debugger/src/router.js deleted file mode 100644 index b1953e300..000000000 --- a/debugger/src/router.js +++ /dev/null @@ -1,146 +0,0 @@ -/** - ****************************************************************************** - * 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.router', [ - 'ui.router', -]); - - -module.config(function($stateProvider, $urlRouterProvider) { - $urlRouterProvider.otherwise('/'); - - $stateProvider.state('/', { - template: 'empty' - }); - - $stateProvider.state('session', { - url: '/:sessionId', - templateUrl: 'assets/ui/session.html', - resolve: { - app: 'app', - session: function($stateParams, $state, $q, - Session, app) { - // 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 - // check whether it's the same game down below. - var d = $q.defer(); - if ($stateParams.sessionId) { - if (!app.session || - app.session.id != $stateParams.sessionId) { - Session.query().then(function(infos) { - var id = (infos[0].titleId == '00000000') ? - infos[0].name : infos[0].titleId; - if (!app.session || app.session.id == id) { - // Same session, continue. - var p = app.connect(); - p.then(function(session) { - d.resolve(session); - }, function(e) { - $state.go('session', { - 'sessionId': session.id - }, { - notify: true - }); - d.reject(e); - }) - } else { - // Different session. Create without connection. - var p = app.open(id); - p.then(function(session) { - d.resolve(session); - }, function(e) { - d.reject(e); - }); - } - }, function(e) { - var p = app.open($stateParams.sessionId); - p.then(function(session) { - d.resolve(session); - }, function(e) { - d.reject(e); - }); - }); - } else { - var p = app.open($stateParams.sessionId); - p.then(function(session) { - d.resolve(session); - }, function(e) { - d.reject(e); - }); - } - } else { - d.resolve(null); - } - return d.promise; - } - }, - controller: function($scope, $stateParams, $q, app, session) { - }, - onEnter: function() { - }, - onExit: function() {} - }); - - $stateProvider.state('session.code', { - url: '/code', - templateUrl: 'assets/ui/code/code-tab.html', - controller: function($stateParams) { - }, - onEnter: function() {}, - onExit: function() {} - }); - $stateProvider.state('session.code.function', { - url: '/:function?a', - templateUrl: 'assets/ui/code/function-view.html', - controller: function($scope, $stateParams) { - $scope.functionAddress = parseInt($stateParams.function, 16); - $scope.highlightAddress = parseInt($stateParams.a, 16); - }, - onEnter: function() {}, - onExit: function() {} - }); - - $stateProvider.state('session.memory', { - url: '/memory?a', - templateUrl: 'assets/ui/memory/memory-tab.html', - controller: function($stateParams) { - }, - onEnter: function() {}, - onExit: function() {} - }); - - $stateProvider.state('session.kernel', { - url: '/kernel', - templateUrl: 'assets/ui/kernel/kernel-tab.html', - controller: function($stateParams) { - }, - onEnter: function() {}, - onExit: function() {} - }); - - $stateProvider.state('session.gpu', { - url: '/gpu', - templateUrl: 'assets/ui/gpu/gpu-tab.html', - controller: function($stateParams) { - }, - onEnter: function() {}, - onExit: function() {} - }); - - $stateProvider.state('session.apu', { - url: '/apu', - templateUrl: 'assets/ui/apu/apu-tab.html', - controller: function($stateParams) { - }, - onEnter: function() {}, - onExit: function() {} - }); -}); diff --git a/debugger/src/session.js b/debugger/src/session.js deleted file mode 100644 index 7676035ef..000000000 --- a/debugger/src/session.js +++ /dev/null @@ -1,489 +0,0 @@ -/** - ****************************************************************************** - * 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.session', []); - - -module.service('Session', function( - $rootScope, $q, $http, $state, log, - 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) { - this.id = id; - - this.breakpoints = {}; - this.breakpointsById = {}; - - this.dataSource = opt_dataSource || null; - this.state = new State(this); - - this.activeThread = null; - - this.paused = false; - - this.loadState(); - }; - - Session.prototype.dispose = function() { - this.saveState(); - this.disconnect(); - }; - - Session.prototype.loadState = function() { - var raw = window.localStorage[this.id]; - if (!raw) { - return; - } - var json = JSON.parse(raw); - if (!json) { - return; - } - - var breakpointList = json.breakpoints; - this.breakpoints = {}; - for (var n = 0; n < breakpointList.length; n++) { - var breakpointJson = breakpointList[n]; - var breakpoint = Breakpoint.fromJSON(breakpointJson); - this.breakpoints[breakpointJson.address] = breakpoint; - this.breakpointsById[breakpoint.id] = breakpoint; - } - }; - - Session.prototype.saveState = function() { - var json = { - id: this.id, - breakpoints: [] - }; - for (var key in this.breakpointsById) { - var breakpoint = this.breakpointsById[key]; - if (breakpoint.type != Breakpoint.TEMP) { - json.breakpoints.push(breakpoint.toJSON()); - } - } - window.localStorage[this.id] = JSON.stringify(json); - }; - - Session.DEFAULT_HOST = '127.0.0.1:6200'; - - Session.getHost = function(opt_host) { - return opt_host || Session.DEFAULT_HOST; - }; - - Session.query = function(opt_host) { - var url = 'http://' + Session.getHost(opt_host); - var p = $http({ - method: 'GET', - url: url + '/sessions', - cache: false, - timeout: 500, - responseType: 'json' - }); - var d = $q.defer(); - p.then(function(response) { - if (!response.data || !response.data.length) { - d.reject(new Error('No session data')); - return; - } - d.resolve(response.data); - }, function(e) { - d.reject(e); - }); - return d.promise; - }; - - Session.prototype.connect = function(opt_host) { - this.disconnect(); - - var url = 'ws://' + Session.getHost(opt_host); - - log.info('Connecting to ' + url + '...'); - log.setProgress(0); - - var d = $q.defer(); - - var dataSource = new RemoteDataSource(url, this); - var p = dataSource.open(); - p.then((function() { - log.info('Connected!'); - log.clearProgress(); - this.setDataSource(dataSource).then((function() { - d.resolve(this); - }).bind(this), (function(e) { - d.reject(e); - }).bind(this)); - }).bind(this), (function(e) { - log.error('Unable to connect: ' + e); - log.clearProgress(); - d.reject(e); - }).bind(this), function(update) { - log.setProgress(update.progress); - d.notify(update); - }); - - return d.promise; - }; - - Session.prototype.disconnect = function() { - this.setDataSource(null); - }; - - Session.prototype.setDataSource = function(dataSource) { - var self = this; - - var d = $q.defer(); - if (this.dataSource) { - this.dataSource.dispose(); - this.dataSource = null; - } - $rootScope.$emit('refresh'); - if (!dataSource) { - d.resolve(); - return d.promise; - } - this.state.clear(); - this.activeThread = null; - - this.dataSource = dataSource; - this.dataSource.on('online', function() { - // - }, this); - this.dataSource.on('offline', function() { - this.setDataSource(null); - }, this); - - var ps = []; - - // Add breakpoints. - var breakpointList = []; - for (var key in this.breakpoints) { - var breakpoint = this.breakpoints[key]; - if (breakpoint.enabled) { - breakpointList.push(breakpoint); - } - } - ps.push(this.dataSource.addBreakpoints(breakpointList)); - - // Perform a full sync. - var syncDeferred = $q.defer(); - ps.push(syncDeferred.promise); - 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) { - log.error('No modules found!'); - syncDeferred.reject(new Error('No modules found.')); - return; - } - var moduleInfo = this.state.getModule(moduleList[0].name); - if (!moduleInfo) { - log.error('Main module not found!'); - syncDeferred.reject(new Error('Main module not found.')); - return; - } - var entryPoint = moduleInfo.exeEntryPoint; - self.addTempBreakpoint(entryPoint, entryPoint); - - syncDeferred.resolve(); - }).bind(this), (function(e) { - syncDeferred.reject(e); - }).bind(this)); - - $q.all(ps).then((function() { - this.dataSource.makeReady().then(function() { - d.resolve(); - }, function(e) { - log.error('Error making target ready: ' + e); - d.reject(e); - }); - }).bind(this), (function(e) { - log.error('Errors preparing target: ' + e); - this.disconnect(); - d.reject(e); - }).bind(this)); - - return d.promise; - }; - - Session.prototype.addBreakpoint = function(breakpoint) { - this.breakpoints[breakpoint.address] = breakpoint; - this.breakpointsById[breakpoint.id] = breakpoint; - if (this.dataSource) { - this.dataSource.addBreakpoint(breakpoint); - } - this.saveState(); - return breakpoint; - }; - - Session.prototype.addTempBreakpoint = function(fnAddress, address) { - var breakpoint = new Breakpoint(); - breakpoint.type = Breakpoint.Type.TEMP; - breakpoint.fnAddress = fnAddress; - breakpoint.address = address; - breakpoint.enabled = true; - return this.addBreakpoint(breakpoint); - }; - - Session.prototype.addCodeBreakpoint = function(fnAddress, address) { - var breakpoint = new Breakpoint(); - breakpoint.type = Breakpoint.Type.CODE; - breakpoint.fnAddress = fnAddress; - breakpoint.address = address; - breakpoint.enabled = true; - return this.addBreakpoint(breakpoint); - }; - - Session.prototype.removeBreakpoint = function(breakpoint) { - delete this.breakpoints[breakpoint.address]; - delete this.breakpointsById[breakpoint.id]; - if (this.dataSource) { - this.dataSource.removeBreakpoint(breakpoint.id); - } - this.saveState(); - }; - - Session.prototype.toggleBreakpoint = function(breakpoint, enabled) { - var oldEnabled = enabled; - breakpoint.enabled = enabled; - if (this.dataSource) { - if (breakpoint.enabled) { - this.dataSource.addBreakpoint(breakpoint); - } else { - this.dataSource.removeBreakpoint(breakpoint.id); - } - } - this.saveState(); - }; - - Session.prototype.onBreakpointHit = function(breakpointId, threadId) { - // Now paused! - this.paused = true; - - this.state.sync().then((function() { - // Switch active thread. - var thread = this.state.getThreadState(threadId); - this.activeThread = thread; - - if (!breakpointId) { - // Just a general pause. - log.info('Execution paused.'); - 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' + - breakpoint.address.toString(16).toUpperCase() + '.'); - - $state.go('session.code.function', { - sessionId: this.id, - function: breakpoint.fnAddress.toString(16).toUpperCase(), - a: breakpoint.address.toString(16).toUpperCase() - }, { - notify: true, - reloadOnSearch: false - }); - }).bind(this), (function(e) { - log.error('Unable to synchronize state,'); - }).bind(this)); - }; - - Session.prototype.continueExecution = function() { - if (!this.dataSource) { - return; - } - this.paused = false; - this.dataSource.continueExecution().then(function() { - log.info('Execution resumed.'); - }, function(e) { - log.error('Unable to continue: ' + e); - }); - }; - - Session.prototype.breakExecution = function() { - if (!this.dataSource) { - return; - } - this.paused = true; - this.dataSource.breakExecution().then(function() { - log.info('Execution paused.'); - $rootScope.$emit('refresh'); - }, function(e) { - log.error('Unable to break: ' + e); - }); - }; - - Session.prototype.stepNext = function(threadId) { - if (!this.dataSource) { - return; - } - this.paused = false; - this.dataSource.stepNext(threadId).then(function() { - }, function(e) { - log.error('Unable to step: ' + e); - }); - }; - - return Session; -}); diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 969907d96..7aa67ccdf 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -9,9 +9,6 @@ #include -#include - -#include #include #include #include @@ -56,28 +53,11 @@ Processor::Processor(Emulator* emulator) : emulator_(emulator), export_resolver_(emulator->export_resolver()), runtime_(0), memory_(emulator->memory()), interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL), - interrupt_thread_block_(0), - DebugTarget(emulator->debug_server()) { + interrupt_thread_block_(0) { InitializeIfNeeded(); - - debug_client_states_lock_ = xe_mutex_alloc(); - - emulator_->debug_server()->AddTarget("cpu", this); } Processor::~Processor() { - emulator_->debug_server()->RemoveTarget("cpu"); - - xe_mutex_lock(debug_client_states_lock_); - for (auto it = debug_client_states_.begin(); - it != debug_client_states_.end(); ++it) { - DebugClientState* client_state = it->second; - delete client_state; - } - debug_client_states_.clear(); - xe_mutex_unlock(debug_client_states_lock_); - xe_mutex_free(debug_client_states_lock_); - if (interrupt_thread_block_) { memory_->HeapFree(interrupt_thread_block_, 2048); delete interrupt_thread_state_; @@ -105,31 +85,6 @@ int Processor::Setup() { return result; } - // Setup debugger events. - auto debugger = runtime_->debugger(); - auto debug_server = emulator_->debug_server(); - debugger->breakpoint_hit.AddListener( - [debug_server](BreakpointHitEvent& e) { - const char* breakpoint_id = e.breakpoint()->id(); - if (!breakpoint_id) { - // This is not a breakpoint we know about. Ignore. - return; - } - - json_t* event_json = json_object(); - json_t* type_json = json_string("breakpoint"); - json_object_set_new(event_json, "type", type_json); - - json_t* thread_id_json = json_integer(e.thread_state()->thread_id()); - json_object_set_new(event_json, "threadId", thread_id_json); - json_t* breakpoint_id_json = json_string(breakpoint_id); - json_object_set_new(event_json, "breakpointId", breakpoint_id_json); - - debug_server->BroadcastEvent(event_json); - - json_decref(event_json); - }); - interrupt_thread_lock_ = xe_mutex_alloc(10000); interrupt_thread_state_ = new XenonThreadState( runtime_, 0, 16 * 1024, 0); @@ -199,640 +154,3 @@ uint64_t Processor::ExecuteInterrupt( xe_mutex_unlock(interrupt_thread_lock_); return result; } - -void Processor::OnDebugClientConnected(uint32_t client_id) { - DebugClientState* client_state = new DebugClientState(runtime_); - xe_mutex_lock(debug_client_states_lock_); - debug_client_states_[client_id] = client_state; - xe_mutex_unlock(debug_client_states_lock_); -} - -void Processor::OnDebugClientDisconnected(uint32_t client_id) { - DebugClientState* client_state = debug_client_states_[client_id]; - xe_mutex_lock(debug_client_states_lock_); - debug_client_states_.erase(client_id); - xe_mutex_unlock(debug_client_states_lock_); - delete client_state; - - // Whenever we support multiple clients we will need to respect pause - // settings. For now, resume until running. - runtime_->debugger()->ResumeAllThreads(true); -} - -json_t* json_object_set_string_new( - json_t* object, const char* key, const char* value) { - json_t* value_json = json_string(value); - json_object_set_new(object, key, value_json); - return value_json; -} - -json_t* json_object_set_string_format_new( - json_t* object, const char* key, const char* format, ...) { - char buffer[1024]; - va_list args; - va_start(args, format); - xevsnprintfa(buffer, XECOUNT(buffer), format, args); - va_end(args); - json_t* value_json = json_string(buffer); - json_object_set_new(object, key, value_json); - return value_json; -} - -json_t* json_object_set_integer_new( - json_t* object, const char* key, json_int_t value) { - json_t* value_json = json_integer(value); - json_object_set_new(object, key, value_json); - return value_json; -} - -json_t* Processor::OnDebugRequest( - uint32_t client_id, const char* command, json_t* request, - bool& succeeded) { - xe_mutex_lock(debug_client_states_lock_); - DebugClientState* client_state = debug_client_states_[client_id]; - xe_mutex_unlock(debug_client_states_lock_); - XEASSERTNOTNULL(client_state); - - succeeded = true; - if (xestrcmpa(command, "get_module_list") == 0) { - json_t* list = json_array(); - Runtime::ModuleList modules = runtime_->GetModules(); - for (auto it = modules.begin(); it != modules.end(); ++it) { - XexModule* module = (XexModule*)(*it); - json_t* module_json = json_object(); - json_object_set_string_new(module_json, "name", module->name()); - json_array_append_new(list, module_json); - } - return list; - } else if (xestrcmpa(command, "get_module") == 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"); - } - return DumpModule(module, succeeded); - } 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* since_json = json_object_get(request, "since"); - if (since_json && !json_is_number(since_json)) { - succeeded = false; - return json_string("Version since is an invalid type"); - } - size_t since = since_json ? - (size_t)json_number_value(since_json) : 0; - json_t* list = json_array(); - size_t version = 0; - module->ForEachFunction(since, version, [&](FunctionInfo* info) { - json_t* fn_json = json_object(); - const char* name = info->name(); - char name_buffer[32]; - if (!name) { - xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", - info->address()); - name = name_buffer; - } - json_object_set_string_new(fn_json, "name", name); - json_object_set_integer_new(fn_json, "address", info->address()); - json_object_set_integer_new(fn_json, "linkStatus", info->status()); - json_array_append_new(list, fn_json); - }); - json_t* result = json_object(); - json_object_set_integer_new(result, "version", version); - json_object_set_new(result, "list", list); - return result; - } 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); - 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) { - // breakpoints: [{}] - json_t* breakpoints_json = json_object_get(request, "breakpoints"); - if (!breakpoints_json || !json_is_array(breakpoints_json)) { - succeeded = false; - return json_string("Breakpoints not specified"); - } - if (!json_array_size(breakpoints_json)) { - // No-op; - return json_null(); - } - for (size_t n = 0; n < json_array_size(breakpoints_json); n++) { - json_t* breakpoint_json = json_array_get(breakpoints_json, n); - if (!breakpoint_json || !json_is_object(breakpoint_json)) { - succeeded = false; - return json_string("Invalid breakpoint type"); - } - - json_t* breakpoint_id_json = json_object_get(breakpoint_json, "id"); - json_t* type_json = json_object_get(breakpoint_json, "type"); - json_t* address_json = json_object_get(breakpoint_json, "address"); - if (!breakpoint_id_json || !json_is_string(breakpoint_id_json) || - !type_json || !json_is_string(type_json) || - !address_json || !json_is_number(address_json)) { - succeeded = false; - return json_string("Invalid breakpoint members"); - } - const char* breakpoint_id = json_string_value(breakpoint_id_json); - const char* type_str = json_string_value(type_json); - uint64_t address = (uint64_t)json_number_value(address_json); - Breakpoint::Type type; - if (xestrcmpa(type_str, "temp") == 0) { - type = Breakpoint::TEMP_TYPE; - } else if (xestrcmpa(type_str, "code") == 0) { - type = Breakpoint::CODE_TYPE; - } else { - succeeded = false; - return json_string("Unknown breakpoint type"); - } - - Breakpoint* breakpoint = new Breakpoint( - type, address); - breakpoint->set_id(breakpoint_id); - if (client_state->AddBreakpoint(breakpoint_id, breakpoint)) { - succeeded = false; - return json_string("Error adding breakpoint"); - } - } - return json_null(); - } else if (xestrcmpa(command, "remove_breakpoints") == 0) { - // breakpointIds: ['id'] - json_t* breakpoint_ids_json = json_object_get(request, "breakpointIds"); - if (!breakpoint_ids_json || !json_is_array(breakpoint_ids_json)) { - succeeded = false; - return json_string("Breakpoint IDs not specified"); - } - if (!json_array_size(breakpoint_ids_json)) { - // No-op; - return json_null(); - } - for (size_t n = 0; n < json_array_size(breakpoint_ids_json); n++) { - json_t* breakpoint_id_json = json_array_get(breakpoint_ids_json, n); - if (!breakpoint_id_json || !json_is_string(breakpoint_id_json)) { - succeeded = false; - return json_string("Invalid breakpoint ID type"); - } - const char* breakpoint_id = json_string_value(breakpoint_id_json); - if (client_state->RemoveBreakpoint(breakpoint_id)) { - succeeded = false; - return json_string("Unable to remove breakpoints"); - } - } - return json_null(); - } else if (xestrcmpa(command, "remove_all_breakpoints") == 0) { - if (client_state->RemoveAllBreakpoints()) { - succeeded = false; - return json_string("Unable to remove breakpoints"); - } - return json_null(); - } else if (xestrcmpa(command, "continue") == 0) { - if (runtime_->debugger()->ResumeAllThreads()) { - succeeded = false; - return json_string("Unable to resume threads"); - } - return json_null(); - } else if (xestrcmpa(command, "break") == 0) { - if (runtime_->debugger()->SuspendAllThreads()) { - succeeded = false; - return json_string("Unable to suspend threads"); - } - return json_null(); - } else if (xestrcmpa(command, "step") == 0) { - // threadId - return json_null(); - } else { - succeeded = false; - return json_string("Unknown command"); - } -} - -json_t* Processor::DumpModule(XexModule* module, bool& succeeded) { - auto xex = module->xex(); - auto header = xe_xex2_get_header(xex); - - auto export_resolver = runtime_->export_resolver(); - - json_t* module_json = json_object(); - - json_object_set_integer_new( - module_json, "moduleFlags", header->module_flags); - json_object_set_integer_new( - module_json, "systemFlags", header->system_flags); - json_object_set_integer_new( - module_json, "exeAddress", header->exe_address); - json_object_set_integer_new( - module_json, "exeEntryPoint", header->exe_entry_point); - json_object_set_integer_new( - module_json, "exeStackSize", header->exe_stack_size); - json_object_set_integer_new( - module_json, "exeHeapSize", header->exe_heap_size); - - json_t* exec_info_json = json_object(); - json_object_set_integer_new( - exec_info_json, "mediaId", header->execution_info.media_id); - json_object_set_string_format_new( - exec_info_json, "version", "%d.%d.%d.%d", - header->execution_info.version.major, - header->execution_info.version.minor, - header->execution_info.version.build, - header->execution_info.version.qfe); - json_object_set_string_format_new( - exec_info_json, "baseVersion", "%d.%d.%d.%d", - header->execution_info.base_version.major, - header->execution_info.base_version.minor, - header->execution_info.base_version.build, - header->execution_info.base_version.qfe); - json_object_set_integer_new( - exec_info_json, "titleId", header->execution_info.title_id); - json_object_set_integer_new( - exec_info_json, "platform", header->execution_info.platform); - json_object_set_integer_new( - exec_info_json, "executableTable", header->execution_info.executable_table); - json_object_set_integer_new( - exec_info_json, "discNumber", header->execution_info.disc_number); - json_object_set_integer_new( - exec_info_json, "discCount", header->execution_info.disc_count); - json_object_set_integer_new( - exec_info_json, "savegameId", header->execution_info.savegame_id); - json_object_set_new(module_json, "executionInfo", exec_info_json); - - json_t* loader_info_json = json_object(); - json_object_set_integer_new( - loader_info_json, "imageFlags", header->loader_info.image_flags); - json_object_set_integer_new( - loader_info_json, "gameRegions", header->loader_info.game_regions); - json_object_set_integer_new( - loader_info_json, "mediaFlags", header->loader_info.media_flags); - json_object_set_new(module_json, "loaderInfo", loader_info_json); - - json_t* tls_info_json = json_object(); - json_object_set_integer_new( - tls_info_json, "slotCount", header->tls_info.slot_count); - json_object_set_integer_new( - tls_info_json, "dataSize", header->tls_info.data_size); - json_object_set_integer_new( - tls_info_json, "rawDataAddress", header->tls_info.raw_data_address); - json_object_set_integer_new( - tls_info_json, "rawDataSize", header->tls_info.raw_data_size); - json_object_set_new(module_json, "tlsInfo", tls_info_json); - - json_t* headers_json = json_array(); - for (size_t n = 0; n < header->header_count; n++) { - auto opt_header = &header->headers[n]; - json_t* header_entry_json = json_object(); - json_object_set_integer_new( - header_entry_json, "key", opt_header->key); - json_object_set_integer_new( - header_entry_json, "length", opt_header->length); - json_object_set_integer_new( - header_entry_json, "value", opt_header->value); - json_array_append_new(headers_json, header_entry_json); - } - json_object_set_new(module_json, "headers", headers_json); - - json_t* resource_infos_json = json_array(); - for (size_t n = 0; n < header->resource_info_count; n++) { - auto& res = header->resource_infos[n]; - json_t* resource_info_json = json_object(); - json_object_set_string_new( - resource_info_json, "name", res.name); - json_object_set_integer_new( - resource_info_json, "address", res.address); - json_object_set_integer_new( - resource_info_json, "size", res.size); - json_array_append_new(resource_infos_json, resource_info_json); - } - json_object_set_new(module_json, "resourceInfos", resource_infos_json); - - json_t* sections_json = json_array(); - for (size_t n = 0, i = 0; n < header->section_count; n++) { - const xe_xex2_section_t* section = &header->sections[n]; - const char* type = "unknown"; - switch (section->info.type) { - case XEX_SECTION_CODE: - type = "code"; - break; - case XEX_SECTION_DATA: - type = "rwdata"; - break; - case XEX_SECTION_READONLY_DATA: - type = "rodata"; - break; - } - const size_t start_address = - header->exe_address + (i * xe_xex2_section_length); - const size_t end_address = - start_address + (section->info.page_count * xe_xex2_section_length); - json_t* section_entry_json = json_object(); - json_object_set_string_new( - section_entry_json, "type", type); - json_object_set_integer_new( - section_entry_json, "pageCount", section->info.page_count); - json_object_set_integer_new( - section_entry_json, "startAddress", start_address); - json_object_set_integer_new( - section_entry_json, "endAddress", end_address); - json_object_set_integer_new( - section_entry_json, "totalLength", - section->info.page_count * xe_xex2_section_length); - json_array_append_new(sections_json, section_entry_json); - i += section->info.page_count; - } - json_object_set_new(module_json, "sections", sections_json); - - json_t* static_libraries_json = json_array(); - for (size_t n = 0; n < header->static_library_count; n++) { - const xe_xex2_static_library_t *library = &header->static_libraries[n]; - json_t* static_library_entry_json = json_object(); - json_object_set_string_new( - static_library_entry_json, "name", library->name); - json_object_set_string_format_new( - static_library_entry_json, "version", "%d.%d.%d.%d", - library->major, library->minor, library->build, library->qfe); - json_array_append_new(static_libraries_json, static_library_entry_json); - } - json_object_set_new(module_json, "staticLibraries", static_libraries_json); - - json_t* library_imports_json = json_array(); - for (size_t n = 0; n < header->import_library_count; n++) { - const xe_xex2_import_library_t* library = &header->import_libraries[n]; - xe_xex2_import_info_t* import_infos; - size_t import_info_count; - if (xe_xex2_get_import_infos( - xex, library, &import_infos, &import_info_count)) { - continue; - } - - json_t* import_library_json = json_object(); - json_object_set_string_new( - import_library_json, "name", library->name); - json_object_set_string_format_new( - import_library_json, "version", "%d.%d.%d.%d", - library->version.major, library->version.minor, - library->version.build, library->version.qfe); - json_object_set_string_format_new( - import_library_json, "minVersion", "%d.%d.%d.%d", - library->min_version.major, library->min_version.minor, - library->min_version.build, library->min_version.qfe); - - json_t* imports_json = json_array(); - for (size_t m = 0; m < import_info_count; m++) { - auto info = &import_infos[m]; - auto kernel_export = export_resolver->GetExportByOrdinal( - library->name, info->ordinal); - json_t* import_json = json_object(); - if (kernel_export) { - json_object_set_string_new( - import_json, "name", kernel_export->name); - json_object_set_new( - import_json, "implemented", - kernel_export->is_implemented ? json_true() : json_false()); - } else { - json_object_set_new(import_json, "name", json_null()); - json_object_set_new(import_json, "implemented", json_false()); - } - json_object_set_integer_new( - import_json, "ordinal", info->ordinal); - json_object_set_integer_new( - import_json, "valueAddress", info->value_address); - if (kernel_export && kernel_export->type == KernelExport::Variable) { - json_object_set_string_new( - import_json, "type", "variable"); - } else if (kernel_export) { - json_object_set_string_new( - import_json, "type", "function"); - json_object_set_integer_new( - import_json, "thunkAddress", info->thunk_address); - } else { - json_object_set_string_new( - import_json, "type", "unknown"); - } - json_array_append_new(imports_json, import_json); - } - json_object_set_new(import_library_json, "imports", imports_json); - - json_array_append_new(library_imports_json, import_library_json); - } - json_object_set_new(module_json, "libraryImports", library_imports_json); - - // TODO(benvanik): exports? - - return module_json; -} - -json_t* Processor::DumpFunction(uint64_t address, bool& succeeded) { - 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, DEBUG_INFO_ALL_DISASM, &fn)) { - succeeded = false; - return json_string("Unable to resolve function"); - } - DebugInfo* debug_info = fn->debug_info(); - if (!debug_info) { - succeeded = false; - return json_string("No debug info present for function"); - } - - json_t* fn_json = json_object(); - const char* name = info->name(); - char name_buffer[32]; - if (!name) { - xesnprintfa(name_buffer, XECOUNT(name_buffer), "sub_%.8X", - info->address()); - name = name_buffer; - } - json_t* name_json = json_string(name); - 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); - - json_t* disasm_json = json_object(); - json_t* disasm_str_json; - disasm_str_json = json_loads(debug_info->source_disasm(), 0, NULL); - 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->machine_code_disasm()); - json_object_set_new(disasm_json, "machineCode", disasm_str_json); - json_object_set_new(fn_json, "disasm", disasm_json); - - delete fn; - - succeeded = true; - 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()); - - char value[32]; - - json_t* context_json = json_object(); - auto context = thread_state->context(); - - json_object_set_new( - context_json, "pc", json_integer(0)); - json_object_set_new( - context_json, "lr", json_integer(context->lr)); - - json_object_set_new( - context_json, "ctr", json_integer(context->ctr)); - xesnprintfa(value, XECOUNT(value), "%.16llX", context->ctr); - json_object_set_new( - context_json, "ctrh", json_string(value)); - xesnprintfa(value, XECOUNT(value), "%lld", context->ctr); - json_object_set_new( - context_json, "ctrs", json_string(value)); - - // 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* rh_json = json_array(); - for (size_t n = 0; n < 32; n++) { - xesnprintfa(value, XECOUNT(value), "%.16llX", context->r[n]); - json_array_append_new(rh_json, json_string(value)); - } - json_object_set_new(context_json, "rh", rh_json); - json_t* rs_json = json_array(); - for (size_t n = 0; n < 32; n++) { - xesnprintfa(value, XECOUNT(value), "%lld", context->r[n]); - json_array_append_new(rs_json, json_string(value)); - } - json_object_set_new(context_json, "rs", rs_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* fh_json = json_array(); - for (size_t n = 0; n < 32; n++) { - union { - double f; - uint64_t i; - } fi = { context->f[n] }; - xesnprintfa(value, XECOUNT(value), "%.16llX", fi.i); - json_array_append_new(fh_json, json_string(value)); - } - json_object_set_new(context_json, "fh", fh_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) : - runtime_(runtime) { - breakpoints_lock_ = xe_mutex_alloc(10000); -} - -Processor::DebugClientState::~DebugClientState() { - RemoveAllBreakpoints(); - xe_mutex_free(breakpoints_lock_); -} - -int Processor::DebugClientState::AddBreakpoint( - const char* breakpoint_id, Breakpoint* breakpoint) { - xe_mutex_lock(breakpoints_lock_); - breakpoints_[breakpoint_id] = breakpoint; - int result = runtime_->debugger()->AddBreakpoint(breakpoint); - xe_mutex_unlock(breakpoints_lock_); - return result; -} - -int Processor::DebugClientState::RemoveBreakpoint(const char* breakpoint_id) { - xe_mutex_lock(breakpoints_lock_); - Breakpoint* breakpoint = breakpoints_[breakpoint_id]; - if (breakpoint) { - breakpoints_.erase(breakpoint_id); - runtime_->debugger()->RemoveBreakpoint(breakpoint); - delete breakpoint; - } - xe_mutex_unlock(breakpoints_lock_); - return 0; -} - -int Processor::DebugClientState::RemoveAllBreakpoints() { - xe_mutex_lock(breakpoints_lock_); - for (auto it = breakpoints_.begin(); it != breakpoints_.end(); ++it) { - Breakpoint* breakpoint = it->second; - runtime_->debugger()->RemoveBreakpoint(breakpoint); - delete breakpoint; - } - breakpoints_.clear(); - xe_mutex_unlock(breakpoints_lock_); - return 0; -} diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 3ad8217db..f13587ef5 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -11,7 +11,6 @@ #define XENIA_CPU_PROCESSOR_H_ #include -#include #include @@ -28,7 +27,7 @@ namespace xe { namespace cpu { -class Processor : public debug::DebugTarget { +class Processor { public: Processor(Emulator* emulator); ~Processor(); @@ -48,17 +47,6 @@ public: uint64_t ExecuteInterrupt( uint32_t cpu, uint64_t address, uint64_t args[], size_t arg_count); - virtual void OnDebugClientConnected(uint32_t client_id); - virtual void OnDebugClientDisconnected(uint32_t client_id); - virtual json_t* OnDebugRequest( - uint32_t client_id, const char* command, json_t* request, - bool& succeeded); - -private: - json_t* DumpModule(XexModule* module, bool& succeeded); - json_t* DumpFunction(uint64_t address, bool& succeeded); - json_t* DumpThreadState(XenonThreadState* thread_state); - private: Emulator* emulator_; ExportResolver* export_resolver_; @@ -69,27 +57,6 @@ private: xe_mutex_t* interrupt_thread_lock_; XenonThreadState* interrupt_thread_state_; uint64_t interrupt_thread_block_; - - class DebugClientState { - public: - DebugClientState(XenonRuntime* runtime); - ~DebugClientState(); - - int AddBreakpoint(const char* breakpoint_id, - alloy::runtime::Breakpoint* breakpoint); - int RemoveBreakpoint(const char* breakpoint_id); - int RemoveAllBreakpoints(); - - private: - XenonRuntime* runtime_; - - xe_mutex_t* breakpoints_lock_; - typedef std::unordered_map BreakpointMap; - BreakpointMap breakpoints_; - }; - xe_mutex_t* debug_client_states_lock_; - typedef std::unordered_map DebugClientStateMap; - DebugClientStateMap debug_client_states_; }; diff --git a/src/xenia/debug/debug_client.cc b/src/xenia/debug/debug_client.cc deleted file mode 100644 index 40d482664..000000000 --- a/src/xenia/debug/debug_client.cc +++ /dev/null @@ -1,39 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include - - -using namespace xe; -using namespace xe::debug; - - -uint32_t DebugClient::next_client_id_ = 1; - - -DebugClient::DebugClient(DebugServer* debug_server) : - debug_server_(debug_server), - readied_(false) { - client_id_ = next_client_id_++; - debug_server_->AddClient(this); -} - -DebugClient::~DebugClient() { - debug_server_->RemoveClient(this); -} - -void DebugClient::MakeReady() { - if (readied_) { - return; - } - debug_server_->ReadyClient(this); - readied_ = true; -} diff --git a/src/xenia/debug/debug_client.h b/src/xenia/debug/debug_client.h deleted file mode 100644 index ad263e129..000000000 --- a/src/xenia/debug/debug_client.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_DEBUG_CLIENT_H_ -#define XENIA_DEBUG_DEBUG_CLIENT_H_ - -#include -#include - - -XEDECLARECLASS2(xe, debug, DebugServer); - -struct json_t; - - -namespace xe { -namespace debug { - - -class DebugClient { -public: - DebugClient(DebugServer* debug_server); - virtual ~DebugClient(); - - uint32_t client_id() const { return client_id_; } - - virtual int Setup() = 0; - virtual void Close() = 0; - - virtual void SendEvent(json_t* event_json) = 0; - -protected: - void MakeReady(); - -protected: - static uint32_t next_client_id_; - - DebugServer* debug_server_; - uint32_t client_id_; - bool readied_; -}; - - -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_DEBUG_CLIENT_H_ diff --git a/src/xenia/debug/debug_server.cc b/src/xenia/debug/debug_server.cc deleted file mode 100644 index 3a5e6d87c..000000000 --- a/src/xenia/debug/debug_server.cc +++ /dev/null @@ -1,186 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include - -#include -#include -#include -#include -#include -#include - - -using namespace xe; -using namespace xe::debug; - - -DEFINE_bool(wait_for_debugger, false, - "Whether to wait for the debugger to attach before launching."); - - -DebugServer::DebugServer(Emulator* emulator) : - emulator_(emulator), lock_(0) { - lock_ = xe_mutex_alloc(10000); - - client_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); - - protocols_.push_back( - new protocols::gdb::GDBProtocol(this)); - protocols_.push_back( - new protocols::ws::WSProtocol(this)); -} - -DebugServer::~DebugServer() { - Shutdown(); - - CloseHandle(client_event_); - - xe_free(lock_); - lock_ = 0; -} - -bool DebugServer::has_clients() { - xe_mutex_lock(lock_); - bool has_clients = clients_.size() > 0; - xe_mutex_unlock(lock_); - return has_clients; -} - -int DebugServer::Startup() { - return 0; -} - -int DebugServer::BeforeEntry() { - // HACK(benvanik): say we are ok even if we have no listener. - if (!protocols_.size()) { - return 0; - } - - // Start listeners. - // This may launch threads and such. - for (std::vector::iterator it = protocols_.begin(); - it != protocols_.end(); ++it) { - Protocol* protocol = *it; - if (protocol->Setup()) { - return 1; - } - } - - // If desired, wait until the first client connects. - if (FLAGS_wait_for_debugger) { - XELOGI("Waiting for debugger..."); - if (WaitForClient()) { - return 1; - } - XELOGI("Debugger attached, continuing..."); - } - - return 0; -} - -void DebugServer::Shutdown() { - xe_mutex_lock(lock_); - - std::vector clients(clients_.begin(), clients_.end()); - clients_.clear(); - for (std::vector::iterator it = clients.begin(); - it != clients.end(); ++it) { - delete *it; - } - - std::vector protocols(protocols_.begin(), protocols_.end()); - protocols_.clear(); - for (std::vector::iterator it = protocols.begin(); - it != protocols.end(); ++it) { - delete *it; - } - - xe_mutex_unlock(lock_); -} - -void DebugServer::AddTarget(const char* name, DebugTarget* target) { - xe_mutex_lock(lock_); - targets_[name] = target; - xe_mutex_unlock(lock_); -} - -void DebugServer::RemoveTarget(const char* name) { - xe_mutex_lock(lock_); - targets_[name] = NULL; - xe_mutex_unlock(lock_); -} - -DebugTarget* DebugServer::GetTarget(const char* name) { - xe_mutex_lock(lock_); - DebugTarget* target = targets_[name]; - xe_mutex_unlock(lock_); - return target; -} - -void DebugServer::BroadcastEvent(json_t* event_json) { - // TODO(benvanik): avoid lock somehow? - xe_mutex_lock(lock_); - for (auto client : clients_) { - client->SendEvent(event_json); - } - xe_mutex_unlock(lock_); -} - -int DebugServer::WaitForClient() { - while (!has_clients()) { - WaitForSingleObject(client_event_, INFINITE); - } - return 0; -} - -void DebugServer::AddClient(DebugClient* debug_client) { - xe_mutex_lock(lock_); - - // Only one debugger at a time right now. Kill any old one. - while (clients_.size()) { - DebugClient* old_client = clients_.back(); - clients_.pop_back(); - old_client->Close(); - } - - clients_.push_back(debug_client); - - // Notify targets. - for (auto it = targets_.begin(); it != targets_.end(); ++it) { - it->second->OnDebugClientConnected(debug_client->client_id()); - } - - xe_mutex_unlock(lock_); -} - -void DebugServer::ReadyClient(DebugClient* debug_client) { - SetEvent(client_event_); -} - -void DebugServer::RemoveClient(DebugClient* debug_client) { - xe_mutex_lock(lock_); - - // Notify targets. - for (auto it = targets_.begin(); it != targets_.end(); ++it) { - it->second->OnDebugClientDisconnected(debug_client->client_id()); - } - - for (std::vector::iterator it = clients_.begin(); - it != clients_.end(); ++it) { - if (*it == debug_client) { - clients_.erase(it); - break; - } - } - - xe_mutex_unlock(lock_); -} diff --git a/src/xenia/debug/debug_server.h b/src/xenia/debug/debug_server.h deleted file mode 100644 index 3c140de0c..000000000 --- a/src/xenia/debug/debug_server.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_DEBUG_SERVER_H_ -#define XENIA_DEBUG_DEBUG_SERVER_H_ - -#include -#include - -#include - - -XEDECLARECLASS1(xe, Emulator); -XEDECLARECLASS2(xe, debug, DebugClient); -XEDECLARECLASS2(xe, debug, DebugTarget); -XEDECLARECLASS2(xe, debug, Protocol); - -struct json_t; - - -namespace xe { -namespace debug { - - -class DebugServer { -public: - DebugServer(Emulator* emulator); - virtual ~DebugServer(); - - Emulator* emulator() const { return emulator_; } - - bool has_clients(); - - int Startup(); - int BeforeEntry(); - void Shutdown(); - - void AddTarget(const char* name, DebugTarget* target); - void RemoveTarget(const char* name); - DebugTarget* GetTarget(const char* name); - - void BroadcastEvent(json_t* event_json); - - int WaitForClient(); - -private: - void AddClient(DebugClient* debug_client); - void ReadyClient(DebugClient* debug_client); - void RemoveClient(DebugClient* debug_client); - - friend class DebugClient; - -private: - Emulator* emulator_; - std::vector protocols_; - - xe_mutex_t* lock_; - typedef std::unordered_map TargetMap; - TargetMap targets_; - std::vector clients_; - HANDLE client_event_; -}; - - -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_DEBUG_SERVER_H_ diff --git a/src/xenia/debug/debug_target.h b/src/xenia/debug/debug_target.h deleted file mode 100644 index 7f202757f..000000000 --- a/src/xenia/debug/debug_target.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_DEBUG_TARGET_H_ -#define XENIA_DEBUG_DEBUG_TARGET_H_ - -#include -#include -#include - - -struct json_t; - - -namespace xe { -namespace debug { - - -class DebugTarget { -public: - DebugTarget(DebugServer* debug_server) : - debug_server_(debug_server) {} - virtual ~DebugTarget() {} - - DebugServer* debug_server() const { return debug_server_; } - - virtual void OnDebugClientConnected(uint32_t client_id) {} - virtual void OnDebugClientDisconnected(uint32_t client_id) {} - virtual json_t* OnDebugRequest( - uint32_t client_id, const char* command, json_t* request, - bool& succeeded) = 0; - -protected: - DebugServer* debug_server_; -}; - - -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_DEBUG_TARGET_H_ diff --git a/src/xenia/debug/protocol.cc b/src/xenia/debug/protocol.cc deleted file mode 100644 index 190e7b53a..000000000 --- a/src/xenia/debug/protocol.cc +++ /dev/null @@ -1,22 +0,0 @@ -/** - ****************************************************************************** - * 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 - - -using namespace xe; -using namespace xe::debug; - - -Protocol::Protocol(DebugServer* debug_server) : - debug_server_(debug_server) { -} - -Protocol::~Protocol() { -} diff --git a/src/xenia/debug/protocol.h b/src/xenia/debug/protocol.h deleted file mode 100644 index 5a0524317..000000000 --- a/src/xenia/debug/protocol.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOL_H_ -#define XENIA_DEBUG_PROTOCOL_H_ - -#include -#include - - -XEDECLARECLASS2(xe, debug, DebugServer); - - -namespace xe { -namespace debug { - - -class Protocol { -public: - Protocol(DebugServer* debug_server); - virtual ~Protocol(); - - virtual int Setup() = 0; - -protected: - DebugServer* debug_server_; -}; - - -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOL_H_ diff --git a/src/xenia/debug/protocols/gdb/gdb_client.cc b/src/xenia/debug/protocols/gdb/gdb_client.cc deleted file mode 100644 index 52cb1524a..000000000 --- a/src/xenia/debug/protocols/gdb/gdb_client.cc +++ /dev/null @@ -1,456 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include -#include - - -using namespace xe; -using namespace xe::debug; -using namespace xe::debug::protocols::gdb; - - -GDBClient::GDBClient(DebugServer* debug_server, socket_t socket_id) : - DebugClient(debug_server), - thread_(NULL), - socket_id_(socket_id), - current_reader_(0), send_queue_stalled_(false) { - mutex_ = xe_mutex_alloc(1000); - - loop_ = xe_socket_loop_create(socket_id); -} - -GDBClient::~GDBClient() { - xe_mutex_t* mutex = mutex_; - xe_mutex_lock(mutex); - - mutex_ = NULL; - - delete current_reader_; - for (auto it = message_reader_pool_.begin(); - it != message_reader_pool_.end(); ++it) { - delete *it; - } - for (auto it = message_writer_pool_.begin(); - it != message_writer_pool_.end(); ++it) { - delete *it; - } - for (auto it = send_queue_.begin(); it != send_queue_.end(); ++it) { - delete *it; - } - - xe_socket_close(socket_id_); - socket_id_ = 0; - - xe_socket_loop_destroy(loop_); - loop_ = NULL; - - xe_mutex_unlock(mutex); - xe_mutex_free(mutex); - - xe_thread_release(thread_); -} - -int GDBClient::Setup() { - // Prep the socket. - xe_socket_set_keepalive(socket_id_, true); - xe_socket_set_nodelay(socket_id_, true); - - thread_ = xe_thread_create("GDB Debugger Client", StartCallback, this); - return xe_thread_start(thread_); -} - -void GDBClient::Close() { - xe_socket_close(socket_id_); - socket_id_ = 0; -} - -void GDBClient::StartCallback(void* param) { - GDBClient* client = reinterpret_cast(param); - client->EventThread(); -} - -int GDBClient::PerformHandshake() { - return 0; -} - -void GDBClient::EventThread() { - // Enable non-blocking IO on the socket. - xe_socket_set_nonblock(socket_id_, true); - - // First run the HTTP handshake. - // This will fail if the connection is not for websockets. - if (PerformHandshake()) { - delete this; - return; - } - - MakeReady(); - - // Loop forever. - while (true) { - // Wait on the event. - if (xe_socket_loop_poll(loop_, true, send_queue_stalled_)) { - break; - } - - // Handle any self-generated events to queue messages. - xe_mutex_lock(mutex_); - for (auto it = pending_messages_.begin(); - it != pending_messages_.end(); it++) { - MessageWriter* message = *it; - send_queue_.push_back(message); - } - pending_messages_.clear(); - xe_mutex_unlock(mutex_); - - // Handle websocket messages. - if (xe_socket_loop_check_socket_recv(loop_) && CheckReceive()) { - // Error handling the event. - XELOGE("Error handling WebSocket data"); - break; - } - if (!send_queue_stalled_ || xe_socket_loop_check_socket_send(loop_)) { - if (PumpSendQueue()) { - // Error handling the event. - XELOGE("Error handling WebSocket data"); - break; - } - } - } -} - -int GDBClient::CheckReceive() { - uint8_t buffer[4096]; - while (true) { - int error_code = 0; - int64_t r = xe_socket_recv( - socket_id_, buffer, sizeof(buffer), 0, &error_code); - if (r == -1) { - if (error_code == EAGAIN || error_code == EWOULDBLOCK) { - return 0; - } else { - return 1; - } - } else if (r == 0) { - return 1; - } else { - // Append current reader until #. - int64_t pos = 0; - if (current_reader_) { - for (; pos < r; pos++) { - if (buffer[pos] == '#') { - pos++; - current_reader_->Append(buffer, pos); - MessageReader* message = current_reader_; - current_reader_ = NULL; - DispatchMessage(message); - break; - } - } - } - - // Loop reading all messages in the buffer. - for (; pos < r; pos++) { - if (buffer[pos] == '$') { - if (message_reader_pool_.size()) { - current_reader_ = message_reader_pool_.back(); - message_reader_pool_.pop_back(); - current_reader_->Reset(); - } else { - current_reader_ = new MessageReader(); - } - size_t start_pos = pos; - - // Scan until next #. - bool found_end = false; - for (; pos < r; pos++) { - if (buffer[pos] == '#') { - pos++; - current_reader_->Append(buffer + start_pos, pos - start_pos); - MessageReader* message = current_reader_; - current_reader_ = NULL; - DispatchMessage(message); - found_end = true; - break; - } - } - if (!found_end) { - // Ran out of bytes before message ended, keep around. - current_reader_->Append(buffer + start_pos, r - start_pos); - } - break; - } - } - } - } - - return 0; -} - -void GDBClient::DispatchMessage(MessageReader* message) { - // $[message]# - const char* str = message->GetString(); - str++; // skip $ - - printf("GDB: %s", str); - - bool handled = false; - switch (str[0]) { - case '!': - // Enable extended mode. - Send("OK"); - handled = true; - break; - case 'v': - // Verbose packets. - if (strstr(str, "vRun") == str) { - Send("S05"); - handled = true; - } else if (strstr(str, "vCont") == str) { - Send("S05"); - handled = true; - } - break; - case 'q': - // Query packets. - switch (str[1]) { - case 'C': - // Get current thread ID. - Send("QC01"); - handled = true; - break; - case 'R': - // Command. - Send("OK"); - handled = true; - break; - default: - if (strstr(str, "qfThreadInfo") == str) { - // Start of thread list request. - Send("m01"); - handled = true; - } else if (strstr(str, "qsThreadInfo") == str) { - // Continuation of thread list. - Send("l"); // l = last - handled = true; - } - break; - } - break; - -#if 0 - case 'H': - // Set current thread. - break; -#endif - - case 'g': - // Read all registers. - HandleReadRegisters(str + 1); - handled = true; - break; - case 'G': - // Write all registers. - HandleWriteRegisters(str + 1); - handled = true; - break; - case 'p': - // Read register. - HandleReadRegister(str + 1); - handled = true; - break; - case 'P': - // Write register. - HandleWriteRegister(str + 1); - handled = true; - break; - - case 'm': - // Read memory. - HandleReadMemory(str + 1); - handled = true; - case 'M': - // Write memory. - HandleWriteMemory(str + 1); - handled = true; - break; - - case 'Z': - // Insert breakpoint. - HandleAddBreakpoint(str + 1); - handled = true; - break; - case 'z': - // Remove breakpoint. - HandleRemoveBreakpoint(str + 1); - handled = true; - break; - - case '?': - // Query halt reason. - Send("S05"); - handled = true; - break; - case 'c': - // Continue. - // Deprecated: vCont should be used instead. - // NOTE: reply is sent on halt, not right now. - Send("S05"); - handled = true; - break; - case 's': - // Single step. - // NOTE: reply is sent on halt, not right now. - Send("S05"); - handled = true; - break; - } - - if (!handled) { - // Unknown packet type. We should ACK just to keep IDA happy. - XELOGW("Unknown GDB packet type: %c", str[0]); - Send(""); - } -} - -int GDBClient::PumpSendQueue() { - send_queue_stalled_ = false; - for (auto it = send_queue_.begin(); it != send_queue_.end(); it++) { - MessageWriter* message = *it; - int error_code = 0; - int64_t r; - const uint8_t* data = message->buffer() + message->offset(); - size_t bytes_remaining = message->length(); - while (bytes_remaining) { - r = xe_socket_send( - socket_id_, data, bytes_remaining, 0, &error_code); - if (r == -1) { - if (error_code == EAGAIN || error_code == EWOULDBLOCK) { - // Message did not finish sending. - send_queue_stalled_ = true; - return 0; - } else { - return 1; - } - } else { - bytes_remaining -= r; - data += r; - message->set_offset(message->offset() + r); - } - } - if (!bytes_remaining) { - xe_mutex_lock(mutex_); - message_writer_pool_.push_back(message); - xe_mutex_unlock(mutex_); - } - } - return 0; -} - -MessageWriter* GDBClient::BeginSend() { - MessageWriter* message = NULL; - xe_mutex_lock(mutex_); - if (message_writer_pool_.size()) { - message = message_writer_pool_.back(); - message_writer_pool_.pop_back(); - } - xe_mutex_unlock(mutex_); - if (message) { - message->Reset(); - } else { - message = new MessageWriter(); - } - return message; -} - -void GDBClient::EndSend(MessageWriter* message) { - message->Finalize(); - - xe_mutex_lock(mutex_); - pending_messages_.push_back(message); - bool needs_signal = pending_messages_.size() == 1; - xe_mutex_unlock(mutex_); - - if (needs_signal) { - // Notify the poll(). - xe_socket_loop_set_queued_write(loop_); - } -} - -void GDBClient::Send(const char* format, ...) { - auto message = BeginSend(); - va_list args; - va_start(args, format); - message->AppendVarargs(format, args); - va_end(args); - EndSend(message); -} - -void GDBClient::HandleReadRegisters(const char* str) { - auto message = BeginSend(); - for (int32_t n = 0; n < 32; n++) { - // gpr - message->Append("%08X", n); - } - for (int64_t n = 0; n < 32; n++) { - // fpr - message->Append("%016llX", n); - } - message->Append("%08X", 0x8202FB40); // pc - message->Append("%08X", 65); // msr - message->Append("%08X", 66); // cr - message->Append("%08X", 67); // lr - message->Append("%08X", 68); // ctr - message->Append("%08X", 69); // xer - message->Append("%08X", 70); // fpscr - EndSend(message); -} - -void GDBClient::HandleWriteRegisters(const char* str) { - Send("OK"); -} - -void GDBClient::HandleReadRegister(const char* str) { - // p...HH - // HH = hex digit indicating register # - auto message = BeginSend(); - message->Append("%.8X", 0x8202FB40); - EndSend(message); -} - -void GDBClient::HandleWriteRegister(const char* str) { - Send("OK"); -} - -void GDBClient::HandleReadMemory(const char* str) { - // m...ADDR,SIZE - uint32_t addr; - uint32_t size; - scanf("%X,%X", &addr, &size); - auto message = BeginSend(); - for (size_t n = 0; n < size; n++) { - message->Append("00"); - } - EndSend(message); -} - -void GDBClient::HandleWriteMemory(const char* str) { - Send("OK"); -} - -void GDBClient::HandleAddBreakpoint(const char* str) { - Send("OK"); -} - -void GDBClient::HandleRemoveBreakpoint(const char* str) { - Send("OK"); -} diff --git a/src/xenia/debug/protocols/gdb/gdb_client.h b/src/xenia/debug/protocols/gdb/gdb_client.h deleted file mode 100644 index 53570cb75..000000000 --- a/src/xenia/debug/protocols/gdb/gdb_client.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_GDB_GDB_CLIENT_H_ -#define XENIA_DEBUG_PROTOCOLS_GDB_GDB_CLIENT_H_ - -#include -#include - -#include - -#include - - -namespace xe { -namespace debug { -namespace protocols { -namespace gdb { - -class MessageReader; -class MessageWriter; - - -class GDBClient : public DebugClient { -public: - GDBClient(DebugServer* debug_server, socket_t socket_id); - virtual ~GDBClient(); - - socket_t socket_id() const { return socket_id_; } - - virtual int Setup(); - virtual void Close(); - - virtual void SendEvent(json_t* event_json) {} - -private: - static void StartCallback(void* param); - - int PerformHandshake(); - void EventThread(); - int CheckReceive(); - void DispatchMessage(MessageReader* message); - int PumpSendQueue(); - MessageWriter* BeginSend(); - void EndSend(MessageWriter* message); - void Send(const char* format, ...); - - void HandleReadRegisters(const char* str); - void HandleWriteRegisters(const char* str); - void HandleReadRegister(const char* str); - void HandleWriteRegister(const char* str); - void HandleReadMemory(const char* str); - void HandleWriteMemory(const char* str); - void HandleAddBreakpoint(const char* str); - void HandleRemoveBreakpoint(const char* str); - - xe_thread_ref thread_; - - socket_t socket_id_; - xe_socket_loop_t* loop_; - xe_mutex_t* mutex_; - std::vector message_reader_pool_; - std::vector message_writer_pool_; - std::vector pending_messages_; - - MessageReader* current_reader_; - std::vector send_queue_; - bool send_queue_stalled_; -}; - - -} // namespace gdb -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_GDB_GDB_CLIENT_H_ diff --git a/src/xenia/debug/protocols/gdb/gdb_protocol.cc b/src/xenia/debug/protocols/gdb/gdb_protocol.cc deleted file mode 100644 index dbf227cc7..000000000 --- a/src/xenia/debug/protocols/gdb/gdb_protocol.cc +++ /dev/null @@ -1,105 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include - -#include - - -DEFINE_int32(gdb_debug_port, 6201, - "Remote debugging port for GDB TCP connections."); - - -using namespace xe; -using namespace xe::debug; -using namespace xe::debug::protocols::gdb; - - -GDBProtocol::GDBProtocol(DebugServer* debug_server) : - port_(0), socket_id_(0), thread_(0), running_(false), - Protocol(debug_server) { - port_ = FLAGS_gdb_debug_port; -} - -GDBProtocol::~GDBProtocol() { - if (thread_) { - // Join thread. - running_ = false; - xe_thread_release(thread_); - thread_ = 0; - } - if (socket_id_) { - xe_socket_close(socket_id_); - } -} - -int GDBProtocol::Setup() { - if (port_ == 0 || port_ == -1) { - return 0; - } - - xe_socket_init(); - - socket_id_ = xe_socket_create_tcp(); - if (socket_id_ == XE_INVALID_SOCKET) { - return 1; - } - - xe_socket_set_keepalive(socket_id_, true); - xe_socket_set_reuseaddr(socket_id_, true); - xe_socket_set_nodelay(socket_id_, true); - - if (xe_socket_bind(socket_id_, port_)) { - XELOGE("Could not bind listen socket: %d", errno); - return 1; - } - - if (xe_socket_listen(socket_id_)) { - xe_socket_close(socket_id_); - return 1; - } - - thread_ = xe_thread_create("GDB Debugger Listener", StartCallback, this); - running_ = true; - return xe_thread_start(thread_); - - return 0; -} - -void GDBProtocol::StartCallback(void* param) { - GDBProtocol* protocol = reinterpret_cast(param); - protocol->AcceptThread(); -} - -void GDBProtocol::AcceptThread() { - while (running_) { - if (!socket_id_) { - break; - } - - // Accept the first connection we get. - xe_socket_connection_t client_info; - if (xe_socket_accept(socket_id_, &client_info)) { - XELOGE("WS debugger failed to accept connection"); - break; - } - - XELOGI("WS debugger connected from %s", client_info.addr); - - // Create the client object. - // Note that the client will delete itself when done. - GDBClient* client = new GDBClient(debug_server_, client_info.socket); - if (client->Setup()) { - // Client failed to setup - abort. - continue; - } - } -} diff --git a/src/xenia/debug/protocols/gdb/gdb_protocol.h b/src/xenia/debug/protocols/gdb/gdb_protocol.h deleted file mode 100644 index 8152ba21c..000000000 --- a/src/xenia/debug/protocols/gdb/gdb_protocol.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_GDB_GDB_PROTOCOL_H_ -#define XENIA_DEBUG_PROTOCOLS_GDB_GDB_PROTOCOL_H_ - -#include -#include - -#include - - -XEDECLARECLASS2(xe, debug, DebugServer); - - -namespace xe { -namespace debug { -namespace protocols { -namespace gdb { - - -class GDBProtocol : public Protocol { -public: - GDBProtocol(DebugServer* debug_server); - virtual ~GDBProtocol(); - - virtual int Setup(); - -private: - static void StartCallback(void* param); - void AcceptThread(); - -protected: - uint32_t port_; - - socket_t socket_id_; - - xe_thread_ref thread_; - bool running_; -}; - - -} // namespace gdb -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_GDB_GDB_PROTOCOL_H_ diff --git a/src/xenia/debug/protocols/gdb/message.cc b/src/xenia/debug/protocols/gdb/message.cc deleted file mode 100644 index 22fcbc05d..000000000 --- a/src/xenia/debug/protocols/gdb/message.cc +++ /dev/null @@ -1,90 +0,0 @@ -/** - ****************************************************************************** - * 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 - - -using namespace xe; -using namespace xe::debug; -using namespace xe::debug::protocols::gdb; - - -MessageReader::MessageReader() { - Reset(); -} - -MessageReader::~MessageReader() { -} - -void MessageReader::Reset() { - buffer_.Reset(); -} - -void MessageReader::Append(const uint8_t* buffer, size_t length) { - buffer_.AppendBytes(buffer, length); -} - -bool MessageReader::CheckComplete() { - // TODO(benvanik): verify checksum. - return true; -} - -const char* MessageReader::GetString() { - return buffer_.GetString(); -} - - -MessageWriter::MessageWriter() : - offset_(0) { - Reset(); -} - -MessageWriter::~MessageWriter() { -} - -const uint8_t* MessageWriter::buffer() const { - return (const uint8_t*)buffer_.GetString(); -} - -size_t MessageWriter::length() const { - return buffer_.length() + 1; -} - -void MessageWriter::Reset() { - buffer_.Reset(); - buffer_.Append("$"); - offset_ = 0; -} - -void MessageWriter::Append(const char* format, ...) { - va_list args; - va_start(args, format); - buffer_.AppendVarargs(format, args); - va_end(args); -} - -void MessageWriter::AppendVarargs(const char* format, va_list args) { - buffer_.AppendVarargs(format, args); -} - -void MessageWriter::Finalize() { - uint8_t checksum = 0; - const uint8_t* data = (const uint8_t*)buffer_.GetString(); - data++; // skip $ - while (true) { - uint8_t c = *data; - if (!c) { - break; - } - checksum += c; - data++; - } - - buffer_.Append("#%.2X", checksum); -} diff --git a/src/xenia/debug/protocols/gdb/message.h b/src/xenia/debug/protocols/gdb/message.h deleted file mode 100644 index fa6d21055..000000000 --- a/src/xenia/debug/protocols/gdb/message.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_GDB_MESSAGE_H_ -#define XENIA_DEBUG_PROTOCOLS_GDB_MESSAGE_H_ - -#include -#include - -#include - - -namespace xe { -namespace debug { -namespace protocols { -namespace gdb { - - -class MessageReader { -public: - MessageReader(); - ~MessageReader(); - - void Reset(); - void Append(const uint8_t* buffer, size_t length); - bool CheckComplete(); - - const char* GetString(); - -private: - alloy::StringBuffer buffer_; -}; - - -class MessageWriter { -public: - MessageWriter(); - ~MessageWriter(); - - const uint8_t* buffer() const; - size_t length() const; - size_t offset() const { return offset_; } - void set_offset(size_t value) { offset_ = value; } - - void Reset(); - - void Append(const char* format, ...); - void AppendVarargs(const char* format, va_list args); - - void Finalize(); - -private: - alloy::StringBuffer buffer_; - size_t offset_; -}; - - -} // namespace gdb -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_GDB_MESSAGE_H_ diff --git a/src/xenia/debug/protocols/gdb/sources.gypi b/src/xenia/debug/protocols/gdb/sources.gypi deleted file mode 100644 index 20e23c21b..000000000 --- a/src/xenia/debug/protocols/gdb/sources.gypi +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'gdb_client.cc', - 'gdb_client.h', - 'gdb_protocol.cc', - 'gdb_protocol.h', - 'message.cc', - 'message.h', - ], -} diff --git a/src/xenia/debug/protocols/sources.gypi b/src/xenia/debug/protocols/sources.gypi deleted file mode 100644 index aa87c61fd..000000000 --- a/src/xenia/debug/protocols/sources.gypi +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'includes': [ - 'gdb/sources.gypi', - 'ws/sources.gypi', - ], -} diff --git a/src/xenia/debug/protocols/ws/simple_sha1.cc b/src/xenia/debug/protocols/ws/simple_sha1.cc deleted file mode 100644 index 868f23a2c..000000000 --- a/src/xenia/debug/protocols/ws/simple_sha1.cc +++ /dev/null @@ -1,235 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#if XE_PLATFORM_WIN32 -#include -#else -#include -#endif // WIN32 - - -using namespace xe; -using namespace xe::debug::protocols::ws; - - -namespace { - - -// http://git.kernel.org/?p=git/git.git;a=blob;f=block-sha1/sha1.c - -/* - * SHA1 routine optimized to do word accesses rather than byte accesses, - * and to avoid unnecessary copies into the context array. - * - * This was initially based on the Mozilla SHA1 implementation, although - * none of the original Mozilla code remains. - */ - -typedef struct { - size_t size; - uint32_t H[5]; - uint32_t W[16]; -} SHA_CTX; - -#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) -#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) -#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) - -#define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) - -#define get_be32(p) ntohl(*(unsigned int *)(p)) -#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) - -#define W(x) (array[(x)&15]) - -#define SHA_SRC(t) get_be32((unsigned char *) block + (t)*4) -#define SHA_MIX(t) SHA_ROL(W((t)+13) ^ W((t)+8) ^ W((t)+2) ^ W(t), 1); - -#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ - unsigned int TEMP = input(t); setW(t, TEMP); \ - E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ - B = SHA_ROR(B, 2); } while (0) - -#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) -#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) -#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) -#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) -#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) - -static void SHA1_Block(SHA_CTX *ctx, const void *block) { - uint32_t A = ctx->H[0]; - uint32_t B = ctx->H[1]; - uint32_t C = ctx->H[2]; - uint32_t D = ctx->H[3]; - uint32_t E = ctx->H[4]; - - uint32_t array[16]; - - /* Round 1 - iterations 0-16 take their input from 'block' */ - T_0_15( 0, A, B, C, D, E); - T_0_15( 1, E, A, B, C, D); - T_0_15( 2, D, E, A, B, C); - T_0_15( 3, C, D, E, A, B); - T_0_15( 4, B, C, D, E, A); - T_0_15( 5, A, B, C, D, E); - T_0_15( 6, E, A, B, C, D); - T_0_15( 7, D, E, A, B, C); - T_0_15( 8, C, D, E, A, B); - T_0_15( 9, B, C, D, E, A); - T_0_15(10, A, B, C, D, E); - T_0_15(11, E, A, B, C, D); - T_0_15(12, D, E, A, B, C); - T_0_15(13, C, D, E, A, B); - T_0_15(14, B, C, D, E, A); - T_0_15(15, A, B, C, D, E); - - /* Round 1 - tail. Input from 512-bit mixing array */ - T_16_19(16, E, A, B, C, D); - T_16_19(17, D, E, A, B, C); - T_16_19(18, C, D, E, A, B); - T_16_19(19, B, C, D, E, A); - - /* Round 2 */ - T_20_39(20, A, B, C, D, E); - T_20_39(21, E, A, B, C, D); - T_20_39(22, D, E, A, B, C); - T_20_39(23, C, D, E, A, B); - T_20_39(24, B, C, D, E, A); - T_20_39(25, A, B, C, D, E); - T_20_39(26, E, A, B, C, D); - T_20_39(27, D, E, A, B, C); - T_20_39(28, C, D, E, A, B); - T_20_39(29, B, C, D, E, A); - T_20_39(30, A, B, C, D, E); - T_20_39(31, E, A, B, C, D); - T_20_39(32, D, E, A, B, C); - T_20_39(33, C, D, E, A, B); - T_20_39(34, B, C, D, E, A); - T_20_39(35, A, B, C, D, E); - T_20_39(36, E, A, B, C, D); - T_20_39(37, D, E, A, B, C); - T_20_39(38, C, D, E, A, B); - T_20_39(39, B, C, D, E, A); - - /* Round 3 */ - T_40_59(40, A, B, C, D, E); - T_40_59(41, E, A, B, C, D); - T_40_59(42, D, E, A, B, C); - T_40_59(43, C, D, E, A, B); - T_40_59(44, B, C, D, E, A); - T_40_59(45, A, B, C, D, E); - T_40_59(46, E, A, B, C, D); - T_40_59(47, D, E, A, B, C); - T_40_59(48, C, D, E, A, B); - T_40_59(49, B, C, D, E, A); - T_40_59(50, A, B, C, D, E); - T_40_59(51, E, A, B, C, D); - T_40_59(52, D, E, A, B, C); - T_40_59(53, C, D, E, A, B); - T_40_59(54, B, C, D, E, A); - T_40_59(55, A, B, C, D, E); - T_40_59(56, E, A, B, C, D); - T_40_59(57, D, E, A, B, C); - T_40_59(58, C, D, E, A, B); - T_40_59(59, B, C, D, E, A); - - /* Round 4 */ - T_60_79(60, A, B, C, D, E); - T_60_79(61, E, A, B, C, D); - T_60_79(62, D, E, A, B, C); - T_60_79(63, C, D, E, A, B); - T_60_79(64, B, C, D, E, A); - T_60_79(65, A, B, C, D, E); - T_60_79(66, E, A, B, C, D); - T_60_79(67, D, E, A, B, C); - T_60_79(68, C, D, E, A, B); - T_60_79(69, B, C, D, E, A); - T_60_79(70, A, B, C, D, E); - T_60_79(71, E, A, B, C, D); - T_60_79(72, D, E, A, B, C); - T_60_79(73, C, D, E, A, B); - T_60_79(74, B, C, D, E, A); - T_60_79(75, A, B, C, D, E); - T_60_79(76, E, A, B, C, D); - T_60_79(77, D, E, A, B, C); - T_60_79(78, C, D, E, A, B); - T_60_79(79, B, C, D, E, A); - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -void SHA1_Update(SHA_CTX *ctx, const void *data, unsigned long len) -{ - uint32_t lenW = ctx->size & 63; - ctx->size += len; - - if (lenW) { - uint32_t left = 64 - lenW; - if (len < left) { - left = len; - } - memcpy(lenW + (char *)ctx->W, data, left); - lenW = (lenW + left) & 63; - len -= left; - data = ((const char *)data + left); - if (lenW) { - return; - } - SHA1_Block(ctx, ctx->W); - } - while (len >= 64) { - SHA1_Block(ctx, data); - data = ((const char *)data + 64); - len -= 64; - } - if (len) { - memcpy(ctx->W, data, len); - } -} - -} - - -void xe::debug::protocols::ws::SHA1( - const uint8_t* data, size_t length, uint8_t out_hash[20]) { - static const uint8_t pad[64] = { 0x80 }; - - SHA_CTX ctx = { - 0, - { - 0x67452301, - 0xefcdab89, - 0x98badcfe, - 0x10325476, - 0xc3d2e1f0, - }, - { 0 } - }; - - SHA1_Update(&ctx, data, (unsigned long)length); - - uint32_t padlen[2] = { - htonl((uint32_t)(ctx.size >> 29)), - htonl((uint32_t)(ctx.size << 3)), - }; - - size_t i = ctx.size & 63; - SHA1_Update(&ctx, pad, 1 + (63 & (55 - i))); - SHA1_Update(&ctx, padlen, 8); - - for (size_t n = 0; n < 5; n++) { - put_be32(out_hash + n * 4, ctx.H[n]); - } -} diff --git a/src/xenia/debug/protocols/ws/simple_sha1.h b/src/xenia/debug/protocols/ws/simple_sha1.h deleted file mode 100644 index 25379799e..000000000 --- a/src/xenia/debug/protocols/ws/simple_sha1.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_WS_SIMPLE_SHA1_H_ -#define XENIA_DEBUG_PROTOCOLS_WS_SIMPLE_SHA1_H_ - -#include -#include - - -namespace xe { -namespace debug { -namespace protocols { -namespace ws { - - -// This is a (likely) slow SHA1 designed for use on small values such as -// Websocket security keys. If we need something more complex it'd be best -// to use a real library. -void SHA1(const uint8_t* data, size_t length, uint8_t out_hash[20]); - - -} // namespace ws -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_WS_SIMPLE_SHA1_H_ diff --git a/src/xenia/debug/protocols/ws/sources.gypi b/src/xenia/debug/protocols/ws/sources.gypi deleted file mode 100644 index f3313acf2..000000000 --- a/src/xenia/debug/protocols/ws/sources.gypi +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'simple_sha1.cc', - 'simple_sha1.h', - 'ws_client.cc', - 'ws_client.h', - 'ws_protocol.cc', - 'ws_protocol.h', - ], -} diff --git a/src/xenia/debug/protocols/ws/ws_client.cc b/src/xenia/debug/protocols/ws/ws_client.cc deleted file mode 100644 index 64f7fe7d3..000000000 --- a/src/xenia/debug/protocols/ws/ws_client.cc +++ /dev/null @@ -1,531 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#if XE_PLATFORM_WIN32 -// Required for wslay. -typedef SSIZE_T ssize_t; -#endif // WIN32 -#include - - -using namespace std; -using namespace xe; -using namespace xe::debug; -using namespace xe::debug::protocols::ws; -using namespace xe::kernel; - - -WSClient::WSClient(DebugServer* debug_server, socket_t socket_id) : - thread_(NULL), - socket_id_(socket_id), - DebugClient(debug_server) { - mutex_ = xe_mutex_alloc(1000); - - loop_ = xe_socket_loop_create(socket_id); -} - -WSClient::~WSClient() { - xe_mutex_t* mutex = mutex_; - xe_mutex_lock(mutex); - - mutex_ = NULL; - - xe_socket_close(socket_id_); - socket_id_ = 0; - - xe_socket_loop_destroy(loop_); - loop_ = NULL; - - xe_mutex_unlock(mutex); - xe_mutex_free(mutex); - - xe_thread_release(thread_); -} - -int WSClient::Setup() { - // Prep the socket. - xe_socket_set_keepalive(socket_id_, true); - xe_socket_set_nodelay(socket_id_, true); - - thread_ = xe_thread_create("WS Debugger Client", StartCallback, this); - return xe_thread_start(thread_); -} - -void WSClient::Close() { - xe_socket_close(socket_id_); - socket_id_ = 0; -} - -void WSClient::StartCallback(void* param) { - WSClient* client = reinterpret_cast(param); - client->EventThread(); -} - -namespace { - -int64_t WSClientSendCallback(wslay_event_context_ptr ctx, - const uint8_t* data, size_t len, int flags, - void* user_data) { - WSClient* client = reinterpret_cast(user_data); - - int error_code = 0; - int64_t r; - while ((r = xe_socket_send(client->socket_id(), data, len, 0, - &error_code)) == -1 && error_code == EINTR); - if (r == -1) { - if (error_code == EAGAIN || error_code == EWOULDBLOCK) { - wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); - } else { - wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); - } - } - return r; -} - -int64_t WSClientRecvCallback(wslay_event_context_ptr ctx, - uint8_t* data, size_t len, int flags, - void* user_data) { - WSClient* client = reinterpret_cast(user_data); - - int error_code = 0; - int64_t r; - while ((r = xe_socket_recv(client->socket_id(), data, len, 0, - &error_code)) == -1 && error_code == EINTR); - if (r == -1) { - if (error_code == EAGAIN || error_code == EWOULDBLOCK) { - wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); - } else { - wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); - } - } else if (r == 0) { - wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); - r = -1; - } - return r; -} - -void WSClientOnMsgCallback(wslay_event_context_ptr ctx, - const struct wslay_event_on_msg_recv_arg* arg, - void* user_data) { - if (wslay_is_ctrl_frame(arg->opcode)) { - // Ignore control frames. - return; - } - - WSClient* client = reinterpret_cast(user_data); - switch (arg->opcode) { - case WSLAY_TEXT_FRAME: - client->OnMessage(arg->msg, arg->msg_length); - break; - case WSLAY_BINARY_FRAME: - // Ignored. - break; - default: - // Unknown opcode - some frame stuff? - break; - } -} - -std::string EncodeBase64(const uint8_t* input, size_t length) { - static const char b64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - std::string result; - size_t remaining = length; - size_t n = 0; - while (remaining) { - result.push_back(b64[input[n] >> 2]); - result.push_back(b64[((input[n] & 0x03) << 4) | - ((input[n + 1] & 0xf0) >> 4)]); - remaining--; - if (remaining) { - result.push_back(b64[((input[n + 1] & 0x0f) << 2) | - ((input[n + 2] & 0xc0) >> 6)]); - remaining--; - } else { - result.push_back('='); - } - if (remaining) { - result.push_back(b64[input[n + 2] & 0x3f]); - remaining--; - } else { - result.push_back('='); - } - n += 3; - } - return result; -} - -} - -int WSClient::PerformHandshake() { - std::string headers; - uint8_t buffer[4096]; - int error_code = 0; - int64_t r; - while (true) { - while ((r = xe_socket_recv(socket_id_, buffer, sizeof(buffer), 0, - &error_code)) == -1 && error_code == EINTR); - if (r == -1) { - if (error_code == EWOULDBLOCK || error_code == EAGAIN) { - if (!headers.size()) { - // Nothing read yet - spin. - continue; - } - break; - } else { - XELOGE("HTTP header read failure"); - return 1; - } - } else if (r == 0) { - // EOF. - XELOGE("HTTP header EOF"); - return 2; - } else { - headers.append(buffer, buffer + r); - if (headers.size() > 8192) { - XELOGE("HTTP headers exceeded max buffer size"); - return 3; - } - } - } - - if (headers.find("\r\n\r\n") == std::string::npos) { - XELOGE("Incomplete HTTP headers: %s", headers.c_str()); - return 1; - } - - // If this is a get for the session list, just produce that and return. - // We could stub out better handling here, if we wanted. - if (headers.find("GET /sessions") != std::string::npos) { - Emulator* emulator = debug_server_->emulator(); - KernelState* kernel_state = emulator->xboxkrnl()->kernel_state(); - XUserModule* module = kernel_state->GetExecutableModule(); - const xe_xex2_header_t* header = module->xex_header(); - char title_id[9]; - xesnprintfa(title_id, XECOUNT(title_id), "%.8X", - header->execution_info.title_id); - - ostringstream response_body; - if (module) { - response_body << "[{"; - response_body << - "\"name\": \"" << module->name() << "\","; - response_body << - "\"titleId\": \"" << title_id << "\""; - response_body << "}]"; - } else { - response_body << - "[]"; - } - size_t content_length = response_body.str().length(); - ostringstream response; - response << - "HTTP/1.0 200 OK\r\n" - "Content-Type: application/json\r\n" - "Connection: close\r\n" - "Access-Control-Allow-Origin: *\r\n" - "Content-Length: " << content_length << "\r\n" - "\r\n"; - response << response_body.str(); - error_code = WriteResponse(response.str()); - if (error_code) { - return error_code; - } - - // Eh, we just kill the connection here. - return 1; - } - - // Parse the headers to verify its a websocket request. - std::string::size_type keyhdstart; - if (headers.find("Upgrade: websocket\r\n") == std::string::npos || - headers.find("Connection: Upgrade\r\n") == std::string::npos || - (keyhdstart = headers.find("Sec-WebSocket-Key: ")) == - std::string::npos) { - XELOGW("HTTP connection does not contain websocket headers"); - return 2; - } - keyhdstart += 19; - std::string::size_type keyhdend = headers.find("\r\n", keyhdstart); - std::string client_key = headers.substr(keyhdstart, keyhdend - keyhdstart); - std::string accept_key = client_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - uint8_t accept_sha[20]; - SHA1((uint8_t*)accept_key.c_str(), accept_key.size(), accept_sha); - accept_key = EncodeBase64(accept_sha, sizeof(accept_sha)); - - // Write the response to upgrade the connection. - std::string response = - "HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: " + accept_key + "\r\n" - "\r\n"; - return WriteResponse(response); -} - -int WSClient::WriteResponse(std::string& response) { - int error_code = 0; - int64_t r; - size_t write_offset = 0; - size_t write_length = response.size(); - while (true) { - while ((r = xe_socket_send(socket_id_, - (uint8_t*)response.c_str() + write_offset, - write_length, 0, &error_code)) == -1 && - error_code == EINTR); - if (r == -1) { - if (error_code == EAGAIN || error_code == EWOULDBLOCK) { - break; - } else { - XELOGE("HTTP response write failure"); - return 4; - } - } else { - write_offset += r; - write_length -= r; - if (!write_length) { - break; - } - } - } - return 0; -} - -void WSClient::EventThread() { - // Enable non-blocking IO on the socket. - xe_socket_set_nonblock(socket_id_, true); - - // First run the HTTP handshake. - // This will fail if the connection is not for websockets. - if (PerformHandshake()) { - delete this; - return; - } - - // Prep callbacks. - struct wslay_event_callbacks callbacks = { - (wslay_event_recv_callback)WSClientRecvCallback, - (wslay_event_send_callback)WSClientSendCallback, - NULL, - NULL, - NULL, - NULL, - WSClientOnMsgCallback, - }; - - // Prep the websocket server context. - wslay_event_context_ptr ctx; - wslay_event_context_server_init(&ctx, &callbacks, this); - - // Loop forever. - while (wslay_event_want_read(ctx) || wslay_event_want_write(ctx)) { - // Wait on the event. - if (xe_socket_loop_poll(loop_, - !!wslay_event_want_read(ctx), - !!wslay_event_want_write(ctx))) { - break; - } - - // Handle any self-generated events to queue messages. - if (xe_socket_loop_check_queued_write(loop_)) { - xe_mutex_lock(mutex_); - for (std::vector::iterator it = - pending_messages_.begin(); it != pending_messages_.end(); it++) { - struct wslay_event_msg* msg = &*it; - wslay_event_queue_msg(ctx, msg); - } - pending_messages_.clear(); - xe_mutex_unlock(mutex_); - } - - // Handle websocket messages. - if ((xe_socket_loop_check_socket_recv(loop_) && wslay_event_recv(ctx)) || - (xe_socket_loop_check_socket_send(loop_) && wslay_event_send(ctx))) { - // Error handling the event. - XELOGE("Error handling WebSocket data"); - break; - } - } - - wslay_event_context_free(ctx); - delete this; -} - -void WSClient::SendEvent(json_t* event_json) { - char* str = json_dumps(event_json, 0); - Write(str); -} - -void WSClient::Write(char* value) { - const uint8_t* buffers[] = { - (uint8_t*)value, - }; - size_t lengths[] = { - sizeof(char) * xestrlena(value), - }; - Write(buffers, lengths, XECOUNT(buffers), false); -} - -void WSClient::Write(const uint8_t** buffers, size_t* lengths, size_t count, - bool binary) { - if (!count) { - return; - } - - size_t combined_length; - uint8_t* combined_buffer; - if (count == 1) { - // Single buffer, just copy. - combined_length = lengths[0]; - combined_buffer = (uint8_t*)xe_malloc(lengths[0]); - XEIGNORE(xe_copy_memory(combined_buffer, combined_length, - buffers[0], lengths[0])); - } else { - // Multiple buffers, merge. - combined_length = 0; - for (size_t n = 0; n < count; n++) { - combined_length += lengths[n]; - } - combined_buffer = (uint8_t*)xe_malloc(combined_length); - for (size_t n = 0, offset = 0; n < count; n++) { - XEIGNORE(xe_copy_memory( - combined_buffer + offset, combined_length - offset, - buffers[n], lengths[n])); - offset += lengths[n]; - } - } - - struct wslay_event_msg msg = { - binary ? WSLAY_BINARY_FRAME : WSLAY_TEXT_FRAME, - combined_buffer, - combined_length, - }; - - xe_mutex_lock(mutex_); - pending_messages_.push_back(msg); - bool needs_signal = pending_messages_.size() == 1; - xe_mutex_unlock(mutex_); - - if (needs_signal) { - // Notify the poll(). - xe_socket_loop_set_queued_write(loop_); - } -} - -void WSClient::OnMessage(const uint8_t* data, size_t length) { - const char* s = (const char*)data; - - json_error_t error; - json_t* request = json_loadb( - (const char*)data, length, JSON_DECODE_INT_AS_REAL, &error); - if (!request) { - // Failed to parse. - XELOGE("Failed to parse JSON request: %d:%d %s %s", - error.line, error.column, - error.source, error.text); - return; - } - if (!json_is_object(request)) { - XELOGE("Expected JSON object"); - json_decref(request); - return; - } - - json_t* request_id_json = json_object_get(request, "requestId"); - if (!request_id_json || !json_is_number(request_id_json)) { - XELOGE("Need requestId field"); - json_decref(request); - return; - } - json_t* command_json = json_object_get(request, "command"); - if (!command_json || !json_is_string(command_json)) { - XELOGE("Need command field"); - json_decref(request); - return; - } - - // Handle command. - bool succeeded = false; - const char* command = json_string_value(command_json); - json_t* result_json = HandleMessage(command, request, succeeded); - if (!result_json) { - result_json = json_null(); - } - - // Prepare response. - json_t* response = json_object(); - json_object_set(response, "requestId", request_id_json); - json_t* status_json = succeeded ? json_true() : json_false(); - json_object_set_new(response, "status", status_json); - json_object_set_new(response, "result", result_json); - - // Encode response to string and send back. - // String freed by Write. - char* response_string = json_dumps(response, JSON_INDENT(2)); - Write(response_string); - - json_decref(request); - json_decref(response); -} - -json_t* WSClient::HandleMessage(const char* command, json_t* request, - bool& succeeded) { - succeeded = false; - - // Get target. - char target_name[16] = { 0 }; - const char* dot = xestrchra(command, '.'); - if (!dot) { - return json_string("No debug target specified."); - } - if (dot - command > XECOUNT(target_name)) { - return NULL; - } - xestrncpya(target_name, XECOUNT(target_name), - command, dot - command); - const char* sub_command = command + (dot - command + 1); - - // Check debugger meta commands. - if (xestrcmpa(target_name, "debug") == 0) { - succeeded = true; - if (xestrcmpa(sub_command, "ping") == 0) { - return json_true(); - } else if (xestrcmpa(sub_command, "make_ready") == 0) { - MakeReady(); - return json_true(); - } else { - succeeded = false; - return json_string("Unknown command"); - } - } - - // Lookup target. - DebugTarget* target = debug_server_->GetTarget(target_name); - if (!target) { - return json_string("Unknown debug target prefix."); - } - - // Dispatch. - return target->OnDebugRequest( - client_id(), sub_command, request, succeeded); -} diff --git a/src/xenia/debug/protocols/ws/ws_client.h b/src/xenia/debug/protocols/ws/ws_client.h deleted file mode 100644 index 32d265032..000000000 --- a/src/xenia/debug/protocols/ws/ws_client.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_WS_WS_CLIENT_H_ -#define XENIA_DEBUG_PROTOCOLS_WS_WS_CLIENT_H_ - -#include -#include - -#include - -#include - - -struct wslay_event_msg; -struct json_t; - - -namespace xe { -namespace debug { -namespace protocols { -namespace ws { - - -class WSClient : public DebugClient { -public: - WSClient(DebugServer* debug_server, socket_t socket_id); - virtual ~WSClient(); - - socket_t socket_id() const { return socket_id_; } - - virtual int Setup(); - virtual void Close(); - - virtual void SendEvent(json_t* event_json); - - void Write(char* value); - void Write(const uint8_t** buffers, size_t* lengths, size_t count, - bool binary = true); - - void OnMessage(const uint8_t* data, size_t length); - json_t* HandleMessage(const char* command, json_t* request, bool& succeeded); - -private: - static void StartCallback(void* param); - - int PerformHandshake(); - int WriteResponse(std::string& response); - void EventThread(); - - xe_thread_ref thread_; - - socket_t socket_id_; - xe_socket_loop_t* loop_; - xe_mutex_t* mutex_; - std::vector pending_messages_; -}; - - -} // namespace ws -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_WS_WS_CLIENT_H_ diff --git a/src/xenia/debug/protocols/ws/ws_protocol.cc b/src/xenia/debug/protocols/ws/ws_protocol.cc deleted file mode 100644 index 668eb5c8c..000000000 --- a/src/xenia/debug/protocols/ws/ws_protocol.cc +++ /dev/null @@ -1,104 +0,0 @@ -/** - ****************************************************************************** - * 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 - -#include -#include - -#include - - -using namespace xe; -using namespace xe::debug; -using namespace xe::debug::protocols::ws; - - -DEFINE_int32(ws_debug_port, 6200, - "Remote debugging port for ws:// connections."); - - -WSProtocol::WSProtocol(DebugServer* debug_server) : - port_(0), socket_id_(0), thread_(0), running_(false), - Protocol(debug_server) { - port_ = FLAGS_ws_debug_port; -} - -WSProtocol::~WSProtocol() { - if (thread_) { - // Join thread. - running_ = false; - xe_thread_release(thread_); - thread_ = 0; - } - if (socket_id_) { - xe_socket_close(socket_id_); - } -} - -int WSProtocol::Setup() { - if (port_ == 0 || port_ == -1) { - return 0; - } - - xe_socket_init(); - - socket_id_ = xe_socket_create_tcp(); - if (socket_id_ == XE_INVALID_SOCKET) { - return 1; - } - - xe_socket_set_keepalive(socket_id_, true); - xe_socket_set_reuseaddr(socket_id_, true); - xe_socket_set_nodelay(socket_id_, true); - - if (xe_socket_bind(socket_id_, port_)) { - XELOGE("Could not bind listen socket: %d", errno); - return 1; - } - - if (xe_socket_listen(socket_id_)) { - xe_socket_close(socket_id_); - return 1; - } - - thread_ = xe_thread_create("WS Debugger Listener", StartCallback, this); - running_ = true; - return xe_thread_start(thread_); -} - -void WSProtocol::StartCallback(void* param) { - WSProtocol* protocol = reinterpret_cast(param); - protocol->AcceptThread(); -} - -void WSProtocol::AcceptThread() { - while (running_) { - if (!socket_id_) { - break; - } - - // Accept the first connection we get. - xe_socket_connection_t client_info; - if (xe_socket_accept(socket_id_, &client_info)) { - XELOGE("WS debugger failed to accept connection"); - break; - } - - XELOGI("WS debugger connected from %s", client_info.addr); - - // Create the client object. - // Note that the client will delete itself when done. - WSClient* client = new WSClient(debug_server_, client_info.socket); - if (client->Setup()) { - // Client failed to setup - abort. - continue; - } - } -} diff --git a/src/xenia/debug/protocols/ws/ws_protocol.h b/src/xenia/debug/protocols/ws/ws_protocol.h deleted file mode 100644 index b5cce87be..000000000 --- a/src/xenia/debug/protocols/ws/ws_protocol.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - ****************************************************************************** - * 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 XENIA_DEBUG_PROTOCOLS_WS_WS_PROTOCOL_H_ -#define XENIA_DEBUG_PROTOCOLS_WS_WS_PROTOCOL_H_ - -#include -#include - -#include - - -XEDECLARECLASS2(xe, debug, DebugServer); - - -namespace xe { -namespace debug { -namespace protocols { -namespace ws { - - -class WSProtocol : public Protocol { -public: - WSProtocol(DebugServer* debug_server); - virtual ~WSProtocol(); - - virtual int Setup(); - -private: - static void StartCallback(void* param); - void AcceptThread(); - -protected: - uint32_t port_; - - socket_t socket_id_; - - xe_thread_ref thread_; - bool running_; -}; - - -} // namespace ws -} // namespace protocols -} // namespace debug -} // namespace xe - - -#endif // XENIA_DEBUG_PROTOCOLS_WS_WS_PROTOCOL_H_ diff --git a/src/xenia/debug/sources.gypi b/src/xenia/debug/sources.gypi deleted file mode 100644 index af6968004..000000000 --- a/src/xenia/debug/sources.gypi +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'debug_client.cc', - 'debug_client.h', - 'debug_server.cc', - 'debug_server.h', - 'debug_target.h', - 'protocol.cc', - 'protocol.h', - ], - - 'includes': [ - 'protocols/sources.gypi', - ], -} diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index bb7f302ae..deb33c9c3 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -25,7 +24,6 @@ using namespace xe; using namespace xe::apu; using namespace xe::cpu; -using namespace xe::debug; using namespace xe::gpu; using namespace xe::hid; using namespace xe::kernel; @@ -36,7 +34,6 @@ using namespace xe::ui; Emulator::Emulator(const xechar_t* command_line) : main_window_(0), memory_(0), - debug_server_(0), processor_(0), audio_system_(0), graphics_system_(0), input_system_(0), export_resolver_(0), file_system_(0), @@ -51,11 +48,6 @@ Emulator::~Emulator() { main_window_->Close(); } - // Disconnect all debug clients first. - if (debug_server_) { - debug_server_->Shutdown(); - } - delete xam_; delete xboxkrnl_; delete kernel_state_; @@ -72,8 +64,6 @@ Emulator::~Emulator() { delete processor_; - delete debug_server_; - delete export_resolver_; } @@ -90,10 +80,6 @@ X_STATUS Emulator::Setup() { export_resolver_ = new ExportResolver(); XEEXPECTNOTNULL(export_resolver_); - // Create the debugger. - debug_server_ = new DebugServer(this); - XEEXPECTNOTNULL(debug_server_); - // Initialize the CPU. processor_ = new Processor(this); XEEXPECTNOTNULL(processor_); @@ -134,11 +120,6 @@ X_STATUS Emulator::Setup() { xam_ = new XamModule(this, kernel_state_); XEEXPECTNOTNULL(xam_); - // Prepare the debugger. - // This may pause waiting for connections. - result = debug_server_->Startup(); - XEEXPECTZERO(result); - return result; XECLEANUP: diff --git a/src/xenia/kernel/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl_module.cc index 12ecd85ae..ae0612ff0 100644 --- a/src/xenia/kernel/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl_module.cc @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -164,12 +163,6 @@ int XboxkrnlModule::LaunchModule(const char* path) { return 0; } - // Spin up the debugger and let it know we are starting. - if (emulator_->debug_server()->BeforeEntry()) { - XELOGE("Debugger failed to startup."); - return 2; - } - // Launch the module. // NOTE: this won't return until the module exits. result_code = module->Launch(0); diff --git a/src/xenia/sources.gypi b/src/xenia/sources.gypi index 0d20898e0..9de67ac78 100644 --- a/src/xenia/sources.gypi +++ b/src/xenia/sources.gypi @@ -31,7 +31,6 @@ 'apu/sources.gypi', 'core/sources.gypi', 'cpu/sources.gypi', - 'debug/sources.gypi', 'gpu/sources.gypi', 'hid/sources.gypi', 'kernel/sources.gypi', diff --git a/src/xenia/xenia.h b/src/xenia/xenia.h index 9b18233d9..ebb04559d 100644 --- a/src/xenia/xenia.h +++ b/src/xenia/xenia.h @@ -17,7 +17,6 @@ #include #include -#include #include #include diff --git a/third_party/jansson b/third_party/jansson deleted file mode 160000 index 4e8c4bfbd..000000000 --- a/third_party/jansson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4e8c4bfbd209e50cc7b13993bbd56adb9282c465 diff --git a/third_party/jansson.gypi b/third_party/jansson.gypi deleted file mode 100644 index 17559564d..000000000 --- a/third_party/jansson.gypi +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'targets': [ - { - 'target_name': 'jansson', - 'type': '<(library)', - - 'direct_dependent_settings': { - 'include_dirs': [ - 'jansson/win32/', - 'jansson/src/', - ], - - 'defines': [ - ], - }, - - 'msvs_disabled_warnings': [4267], - - 'defines': [ - ], - - 'conditions': [ - ['OS != "win"', { - 'defines': [ - ], - }], - ['OS == "win"', { - 'defines': [ - ], - }], - ], - - 'include_dirs': [ - 'jansson/win32/', - 'jansson/src/', - ], - - 'sources': [ - 'jansson/win32/jansson_config.h', - 'jansson/src/dump.c', - 'jansson/src/error.c', - 'jansson/src/hashtable.c', - 'jansson/src/hashtable.h', - 'jansson/src/jansson.h', - 'jansson/src/jansson_private.h', - 'jansson/src/load.c', - 'jansson/src/memory.c', - 'jansson/src/pack_unpack.c', - 'jansson/src/strbuffer.c', - 'jansson/src/strbuffer.h', - 'jansson/src/strconv.c', - 'jansson/src/utf.c', - 'jansson/src/utf.h', - 'jansson/src/value.c', - ], - } - ] -} diff --git a/third_party/wslay b/third_party/wslay deleted file mode 160000 index b3571f1ed..000000000 --- a/third_party/wslay +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b3571f1ed27093e910ab8675d0c8333e5a2818ea diff --git a/third_party/wslay.gypi b/third_party/wslay.gypi deleted file mode 100644 index de99a01f1..000000000 --- a/third_party/wslay.gypi +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'targets': [ - { - 'target_name': 'wslay', - 'type': '<(library)', - - 'direct_dependent_settings': { - 'include_dirs': [ - 'wslay/lib/includes/', - ], - - 'defines': [ - 'WSLAY_VERSION=1', - ], - - # libraries: ws2_32 on windows - }, - - 'defines': [ - 'WSLAY_VERSION="1"', - ], - - 'conditions': [ - ['OS != "win"', { - 'defines': [ - 'HAVE_ARPA_INET_H=1', - 'HAVE_NETINET_IN_H=1', - ], - }], - ['OS == "win"', { - 'defines': [ - 'HAVE_WINSOCK2_H=1', - 'ssize_t=long long', - ], - }], - ], - - 'include_dirs': [ - 'wslay/lib/', - 'wslay/lib/includes/', - ], - - 'sources': [ - 'wslay/lib/includes/wslay/wslay.h', - 'wslay/lib/wslay_event.c', - 'wslay/lib/wslay_event.h', - 'wslay/lib/wslay_frame.c', - 'wslay/lib/wslay_frame.h', - 'wslay/lib/wslay_net.c', - 'wslay/lib/wslay_net.h', - 'wslay/lib/wslay_queue.c', - 'wslay/lib/wslay_queue.h', - 'wslay/lib/wslay_stack.c', - 'wslay/lib/wslay_stack.h', - ], - } - ] -} diff --git a/xenia.gyp b/xenia.gyp index 8933eb750..28dfca299 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -4,10 +4,8 @@ 'tools/tools.gypi', 'third_party/beaengine.gypi', 'third_party/gflags.gypi', - 'third_party/jansson.gypi', 'third_party/llvm.gypi', 'third_party/sparsehash.gypi', - 'third_party/wslay.gypi', ], 'default_configuration': 'release', @@ -285,14 +283,10 @@ 'dependencies': [ 'gflags', - 'jansson', - 'wslay', 'alloy', ], 'export_dependent_settings': [ 'gflags', - 'jansson', - 'wslay', 'alloy', ],