Prettier ppc disasm.
This commit is contained in:
parent
de6dc92663
commit
d861ef8aab
|
@ -231,6 +231,28 @@ body {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
.debugger-fnview-gutter-icon {
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
.debugger-fnview-gutter-icon-el {
|
||||||
|
}
|
||||||
|
.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-graphview {
|
.debugger-fnview-graphview {
|
||||||
order: 2;
|
order: 2;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
|
@ -42,22 +42,116 @@ module.controller('FunctionViewController', function(
|
||||||
theme: 'default',
|
theme: 'default',
|
||||||
indentUnit: 2,
|
indentUnit: 2,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
lineNumbers: true,
|
lineNumbers: false,
|
||||||
firstLineNumber: 0,
|
gutters: [
|
||||||
lineNumberFormatter: function(line) {
|
'debugger-fnview-gutter-icon',
|
||||||
return String(line);
|
'debugger-fnview-gutter-addr',
|
||||||
},
|
'debugger-fnview-gutter-code'
|
||||||
gutters: [],
|
],
|
||||||
readOnly: true
|
readOnly: true
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateCode() {
|
function hex32(number) {
|
||||||
var codeType = $scope.codeType;
|
var str = "" + number.toString(16).toUpperCase();
|
||||||
var value = '';
|
while (str.length < 8) str = "0" + str;
|
||||||
if ($scope.fn) {
|
return str;
|
||||||
value = $scope.fn.disasm[codeType];
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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':
|
||||||
|
updateSourceCode(fn);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var value = fn ? fn.disasm[codeType] : null;
|
||||||
|
cm.setValue(value || '');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
$scope.codeMirror.setValue(value || '');
|
|
||||||
};
|
};
|
||||||
$scope.$watch('codeType', updateCode);
|
$scope.$watch('codeType', updateCode);
|
||||||
|
|
||||||
|
$scope.codeMirror.on('gutterClick', function(
|
||||||
|
instance, line, gutterClass, e) {
|
||||||
|
if (e.which == 1) {
|
||||||
|
if (gutterClass == 'debugger-fnview-gutter-icon') {
|
||||||
|
console.log('click', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// $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();
|
||||||
|
// });
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
<a class="navbar-brand" href="http://xenia.jp/" target="_blank">Xenia</a>
|
<a class="navbar-brand" href="http://xenia.jp/" target="_blank">Xenia</a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav navbar-nav" ng-show="app.session">
|
<ul class="nav navbar-nav" ng-show="app.session">
|
||||||
<li ui-sref-active="active"><a ui-sref="session.code">Code</a></li>
|
<li ng-class="{ active: $state.includes('session.code') }"><a ui-sref="session.code">Code</a></li>
|
||||||
<li ui-sref-active="active"><a ui-sref="session.memory">Memory</a></li>
|
<li ng-class="{ active: $state.includes('session.memory') }"><a ui-sref="session.memory">Memory</a></li>
|
||||||
<li ui-sref-active="active"><a ui-sref="session.kernel">Kernel</a></li>
|
<li ng-class="{ active: $state.includes('session.kernel') }"><a ui-sref="session.kernel">Kernel</a></li>
|
||||||
<li ui-sref-active="active"><a ui-sref="session.gpu">GPU</a></li>
|
<li ng-class="{ active: $state.includes('session.gpu') }"><a ui-sref="session.gpu">GPU</a></li>
|
||||||
<li ui-sref-active="active"><a ui-sref="session.apu">APU</a></li>
|
<li ng-class="{ active: $state.includes('session.apu') }"><a ui-sref="session.apu">APU</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="navbar-text navbar-right"></p>
|
<p class="navbar-text navbar-right"></p>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
|
|
@ -105,7 +105,10 @@ module.service('app', function(
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.run(function($rootScope, app, log) {
|
module.run(function($rootScope, $state, $stateParams, app, log) {
|
||||||
|
$rootScope.$state = $state;
|
||||||
|
$rootScope.$stateParams = $stateParams;
|
||||||
|
|
||||||
$rootScope.app = app;
|
$rootScope.app = app;
|
||||||
$rootScope.log = log;
|
$rootScope.log = log;
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_scanner.h>
|
#include <alloy/frontend/ppc/ppc_scanner.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <alloy/frontend/tracing.h>
|
#include <alloy/frontend/tracing.h>
|
||||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||||
#include <alloy/frontend/ppc/ppc_instr.h>
|
#include <alloy/frontend/ppc/ppc_instr.h>
|
||||||
|
@ -278,3 +280,81 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
|
||||||
XELOGSDB("Finished analyzing %.8X", start_address);
|
XELOGSDB("Finished analyzing %.8X", start_address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
|
||||||
|
Memory* memory = frontend_->memory();
|
||||||
|
const uint8_t* p = memory->membase();
|
||||||
|
|
||||||
|
std::map<uint64_t, BlockInfo> block_map;
|
||||||
|
|
||||||
|
uint64_t start_address = symbol_info->address();
|
||||||
|
uint64_t end_address = symbol_info->end_address();
|
||||||
|
bool in_block = false;
|
||||||
|
uint64_t block_start = 0;
|
||||||
|
InstrData i;
|
||||||
|
for (uint64_t address = start_address;
|
||||||
|
address <= end_address; address += 4) {
|
||||||
|
i.address = address;
|
||||||
|
i.code = XEGETUINT32BE(p + address);
|
||||||
|
if (!i.code) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(benvanik): find a way to avoid using the opcode tables.
|
||||||
|
// This lookup is *expensive* and should be avoided when scanning.
|
||||||
|
i.type = GetInstrType(i.code);
|
||||||
|
|
||||||
|
if (!in_block) {
|
||||||
|
in_block = true;
|
||||||
|
block_start = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ends_block = false;
|
||||||
|
if (!i.type) {
|
||||||
|
// Invalid instruction.
|
||||||
|
} else if (i.code == 0x4E800020) {
|
||||||
|
// blr -- unconditional branch to LR.
|
||||||
|
ends_block = true;
|
||||||
|
} else if (i.code == 0x4E800420) {
|
||||||
|
// bctr -- unconditional branch to CTR.
|
||||||
|
ends_block = true;
|
||||||
|
} else if (i.type->opcode == 0x48000000) {
|
||||||
|
// b/ba/bl/bla
|
||||||
|
uint32_t target =
|
||||||
|
(uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
|
||||||
|
ends_block = true;
|
||||||
|
} else if (i.type->opcode == 0x40000000) {
|
||||||
|
// bc/bca/bcl/bcla
|
||||||
|
uint32_t target =
|
||||||
|
(uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address);
|
||||||
|
ends_block = true;
|
||||||
|
} else if (i.type->opcode == 0x4C000020) {
|
||||||
|
// bclr/bclrl
|
||||||
|
ends_block = true;
|
||||||
|
} else if (i.type->opcode == 0x4C000420) {
|
||||||
|
// bcctr/bcctrl
|
||||||
|
ends_block = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ends_block) {
|
||||||
|
in_block = false;
|
||||||
|
block_map[block_start] = {
|
||||||
|
block_start,
|
||||||
|
address,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_block) {
|
||||||
|
block_map[block_start] = {
|
||||||
|
block_start,
|
||||||
|
end_address,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BlockInfo> blocks;
|
||||||
|
for (auto it = block_map.begin(); it != block_map.end(); ++it) {
|
||||||
|
blocks.push_back(it->second);
|
||||||
|
}
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ namespace ppc {
|
||||||
|
|
||||||
class PPCFrontend;
|
class PPCFrontend;
|
||||||
|
|
||||||
|
typedef struct BlockInfo_t {
|
||||||
|
uint64_t start_address;
|
||||||
|
uint64_t end_address;
|
||||||
|
} BlockInfo;
|
||||||
|
|
||||||
|
|
||||||
class PPCScanner {
|
class PPCScanner {
|
||||||
public:
|
public:
|
||||||
|
@ -28,6 +33,8 @@ public:
|
||||||
|
|
||||||
int FindExtents(runtime::FunctionInfo* symbol_info);
|
int FindExtents(runtime::FunctionInfo* symbol_info);
|
||||||
|
|
||||||
|
std::vector<BlockInfo> FindBlocks(runtime::FunctionInfo* symbol_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsRestGprLr(uint64_t address);
|
bool IsRestGprLr(uint64_t address);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,10 @@ int PPCTranslator::Translate(
|
||||||
DumpSource(symbol_info, &string_buffer_);
|
DumpSource(symbol_info, &string_buffer_);
|
||||||
debug_info->set_source_disasm(string_buffer_.ToString());
|
debug_info->set_source_disasm(string_buffer_.ToString());
|
||||||
string_buffer_.Reset();
|
string_buffer_.Reset();
|
||||||
|
|
||||||
|
DumpSourceJson(symbol_info, &string_buffer_);
|
||||||
|
debug_info->set_source_json(string_buffer_.ToString());
|
||||||
|
string_buffer_.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit function.
|
// Emit function.
|
||||||
|
@ -134,9 +138,12 @@ void PPCTranslator::DumpSource(
|
||||||
symbol_info->address(), symbol_info->end_address(),
|
symbol_info->address(), symbol_info->end_address(),
|
||||||
"(symbol name)");
|
"(symbol name)");
|
||||||
|
|
||||||
|
auto blocks = scanner_->FindBlocks(symbol_info);
|
||||||
|
|
||||||
uint64_t start_address = symbol_info->address();
|
uint64_t start_address = symbol_info->address();
|
||||||
uint64_t end_address = symbol_info->end_address();
|
uint64_t end_address = symbol_info->end_address();
|
||||||
InstrData i;
|
InstrData i;
|
||||||
|
auto block_it = blocks.begin();
|
||||||
for (uint64_t address = start_address, offset = 0; address <= end_address;
|
for (uint64_t address = start_address, offset = 0; address <= end_address;
|
||||||
address += 4, offset++) {
|
address += 4, offset++) {
|
||||||
i.address = address;
|
i.address = address;
|
||||||
|
@ -144,7 +151,13 @@ void PPCTranslator::DumpSource(
|
||||||
// TODO(benvanik): find a way to avoid using the opcode tables.
|
// TODO(benvanik): find a way to avoid using the opcode tables.
|
||||||
i.type = GetInstrType(i.code);
|
i.type = GetInstrType(i.code);
|
||||||
|
|
||||||
// TODO(benvanik): labels and such
|
// Check labels.
|
||||||
|
if (block_it != blocks.end() &&
|
||||||
|
block_it->start_address == address) {
|
||||||
|
string_buffer->Append(
|
||||||
|
"%.8X loc_%.8X:\n", address, address);
|
||||||
|
++block_it;
|
||||||
|
}
|
||||||
|
|
||||||
if (!i.type) {
|
if (!i.type) {
|
||||||
string_buffer->Append("%.8X %.8X ???", address, i.code);
|
string_buffer->Append("%.8X %.8X ???", address, i.code);
|
||||||
|
@ -160,3 +173,68 @@ void PPCTranslator::DumpSource(
|
||||||
string_buffer->Append("\n");
|
string_buffer->Append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PPCTranslator::DumpSourceJson(
|
||||||
|
runtime::FunctionInfo* symbol_info, StringBuffer* string_buffer) {
|
||||||
|
Memory* memory = frontend_->memory();
|
||||||
|
const uint8_t* p = memory->membase();
|
||||||
|
|
||||||
|
string_buffer->Append("{\n");
|
||||||
|
|
||||||
|
auto blocks = scanner_->FindBlocks(symbol_info);
|
||||||
|
string_buffer->Append("\"blocks\": [\n");
|
||||||
|
for (auto it = blocks.begin(); it != blocks.end(); ++it) {
|
||||||
|
string_buffer->Append("{ \"start\": %u, \"end\": %u }%c",
|
||||||
|
it->start_address, it->end_address,
|
||||||
|
(it + 1 != blocks.end()) ? ',' : ' ');
|
||||||
|
}
|
||||||
|
string_buffer->Append("],\n");
|
||||||
|
|
||||||
|
string_buffer->Append("\"lines\": [\n");
|
||||||
|
uint64_t start_address = symbol_info->address();
|
||||||
|
uint64_t end_address = symbol_info->end_address();
|
||||||
|
InstrData i;
|
||||||
|
auto block_it = blocks.begin();
|
||||||
|
for (uint64_t address = start_address, offset = 0; address <= end_address;
|
||||||
|
address += 4, offset++) {
|
||||||
|
i.address = address;
|
||||||
|
i.code = XEGETUINT32BE(p + address);
|
||||||
|
// TODO(benvanik): find a way to avoid using the opcode tables.
|
||||||
|
i.type = GetInstrType(i.code);
|
||||||
|
|
||||||
|
// Check labels.
|
||||||
|
if (block_it != blocks.end() &&
|
||||||
|
block_it->start_address == address) {
|
||||||
|
if (address != start_address) {
|
||||||
|
// Whitespace to pad blocks.
|
||||||
|
string_buffer->Append(
|
||||||
|
"[\"c\", %u, 0, \"\", \"\"],\n",
|
||||||
|
address);
|
||||||
|
}
|
||||||
|
string_buffer->Append(
|
||||||
|
"[\"l\", %u, 0, \"loc_%.8X:\", \"\"],\n",
|
||||||
|
address, address);
|
||||||
|
++block_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* disasm_str = "";
|
||||||
|
const char* comment_str = "";
|
||||||
|
std::string disasm;
|
||||||
|
if (!i.type) {
|
||||||
|
disasm_str = "?";
|
||||||
|
} else if (i.type->disassemble) {
|
||||||
|
ppc::InstrDisasm d;
|
||||||
|
i.type->disassemble(i, d);
|
||||||
|
d.Dump(disasm);
|
||||||
|
disasm_str = disasm.c_str();
|
||||||
|
} else {
|
||||||
|
disasm_str = i.type->name;
|
||||||
|
}
|
||||||
|
string_buffer->Append("[\"i\", %u, %u, \" %s\", \"%s\"]%c\n",
|
||||||
|
address, i.code, disasm_str, comment_str,
|
||||||
|
(address + 4 <= end_address) ? ',' : ' ');
|
||||||
|
}
|
||||||
|
string_buffer->Append("]\n");
|
||||||
|
|
||||||
|
string_buffer->Append("}\n");
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void DumpSource(runtime::FunctionInfo* symbol_info,
|
void DumpSource(runtime::FunctionInfo* symbol_info,
|
||||||
StringBuffer* string_buffer);
|
StringBuffer* string_buffer);
|
||||||
|
void DumpSourceJson(runtime::FunctionInfo* symbol_info,
|
||||||
|
StringBuffer* string_buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPCFrontend* frontend_;
|
PPCFrontend* frontend_;
|
||||||
|
|
|
@ -14,7 +14,7 @@ using namespace alloy::runtime;
|
||||||
|
|
||||||
|
|
||||||
DebugInfo::DebugInfo() :
|
DebugInfo::DebugInfo() :
|
||||||
source_disasm_(0),
|
source_disasm_(0), source_json_(0),
|
||||||
raw_hir_disasm_(0),
|
raw_hir_disasm_(0),
|
||||||
hir_disasm_(0),
|
hir_disasm_(0),
|
||||||
raw_lir_disasm_(0),
|
raw_lir_disasm_(0),
|
||||||
|
@ -24,6 +24,7 @@ DebugInfo::DebugInfo() :
|
||||||
|
|
||||||
DebugInfo::~DebugInfo() {
|
DebugInfo::~DebugInfo() {
|
||||||
xe_free(source_disasm_);
|
xe_free(source_disasm_);
|
||||||
|
xe_free(source_json_);
|
||||||
xe_free(raw_hir_disasm_);
|
xe_free(raw_hir_disasm_);
|
||||||
xe_free(hir_disasm_);
|
xe_free(hir_disasm_);
|
||||||
xe_free(raw_lir_disasm_);
|
xe_free(raw_lir_disasm_);
|
||||||
|
|
|
@ -24,6 +24,8 @@ public:
|
||||||
|
|
||||||
const char* source_disasm() const { return source_disasm_; }
|
const char* source_disasm() const { return source_disasm_; }
|
||||||
void set_source_disasm(char* value) { source_disasm_ = value; }
|
void set_source_disasm(char* value) { source_disasm_ = value; }
|
||||||
|
const char* source_json() const { return source_json_; }
|
||||||
|
void set_source_json(char* value) { source_json_ = value; }
|
||||||
const char* raw_hir_disasm() const { return raw_hir_disasm_; }
|
const char* raw_hir_disasm() const { return raw_hir_disasm_; }
|
||||||
void set_raw_hir_disasm(char* value) { raw_hir_disasm_ = value; }
|
void set_raw_hir_disasm(char* value) { raw_hir_disasm_ = value; }
|
||||||
const char* hir_disasm() const { return hir_disasm_; }
|
const char* hir_disasm() const { return hir_disasm_; }
|
||||||
|
@ -42,6 +44,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* source_disasm_;
|
char* source_disasm_;
|
||||||
|
char* source_json_;
|
||||||
char* raw_hir_disasm_;
|
char* raw_hir_disasm_;
|
||||||
char* hir_disasm_;
|
char* hir_disasm_;
|
||||||
char* raw_lir_disasm_;
|
char* raw_lir_disasm_;
|
||||||
|
|
|
@ -256,7 +256,7 @@ json_t* Processor::OnDebugRequest(
|
||||||
|
|
||||||
json_t* disasm_json = json_object();
|
json_t* disasm_json = json_object();
|
||||||
json_t* disasm_str_json;
|
json_t* disasm_str_json;
|
||||||
disasm_str_json = json_string(debug_info->source_disasm());
|
disasm_str_json = json_loads(debug_info->source_json(), 0, NULL);
|
||||||
json_object_set_new(disasm_json, "source", disasm_str_json);
|
json_object_set_new(disasm_json, "source", disasm_str_json);
|
||||||
disasm_str_json = json_string(debug_info->raw_hir_disasm());
|
disasm_str_json = json_string(debug_info->raw_hir_disasm());
|
||||||
json_object_set_new(disasm_json, "rawHir", disasm_str_json);
|
json_object_set_new(disasm_json, "rawHir", disasm_str_json);
|
||||||
|
|
Loading…
Reference in New Issue