You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

323 lines
7.5 KiB

//debugData => contain all debug states.
//statesList => ListView
var currentSelectedState = null;
var currentDisplayedState = null;
var debugData = null;
var codeMap = null;
var locations = [];
var locationMap = {};
var breakpoints = {};
function init(data)
{
jumpOutBackAction.enabled(false);
jumpIntoBackAction.enabled(false);
jumpIntoForwardAction.enabled(false);
jumpOutForwardAction.enabled(false);
jumpOverBackAction.enabled(false);
jumpOverForwardAction.enabled(false);
if (data === null) {
statesList.model.clear();
statesSlider.maximumValue = 0;
statesSlider.value = 0;
currentSelectedState = null;
currentDisplayedState = null;
debugData = null;
locations = [];
locationMap = {};
return;
}
debugData = data;
currentSelectedState = 0;
currentDisplayedState = 0;
setupInstructions(currentSelectedState);
setupCallData(currentSelectedState);
initLocations();
initSlider();
selectState(currentSelectedState);
}
function updateMode()
{
initSlider();
}
function initLocations()
{
locations = [];
if (debugData.states.length === 0)
return;
var nullLocation = { start: -1, end: -1, documentId: "", state: 0 };
var prevLocation = nullLocation;
for (var i = 0; i < debugData.states.length - 1; i++) {
var code = debugData.states[i].code;
var location = code.documentId ? code.locations[codeStr(i)] : nullLocation;
if (location.start !== prevLocation.start || location.end !== prevLocation.end || code.documentId !== prevLocation.documentId)
{
prevLocation = { start: location.start, end: location.end, documentId: code.documentId, state: i };
locations.push(prevLocation);
}
locationMap[i] = locations.length - 1;
}
locations.push({ start: -1, end: -1, documentId: code.documentId, state: i });
locationMap[debugData.states.length - 1] = locations.length - 1;
}
function setBreakpoints(bp)
{
breakpoints = bp;
}
function srcMode()
{
return !assemblyMode && locations.length;
}
function initSlider()
{
if (!debugData)
statesSlider.maximumValue = 0;
else if (srcMode()) {
statesSlider.maximumValue = locations.length - 1;
} else {
statesSlider.maximumValue = debugData.states.length - 1;
}
statesSlider.value = 0;
}
function setupInstructions(stateIndex)
{
var instructions = debugData.states[stateIndex].code.instructions;
codeMap = {};
statesList.model.clear();
for (var i = 0; i < instructions.length; i++) {
statesList.model.append(instructions[i]);
codeMap[instructions[i].processIndex] = i;
}
callDataDump.listModel = debugData.states[stateIndex].callData.items;
}
function setupCallData(stateIndex)
{
callDataDump.listModel = debugData.states[stateIndex].callData.items;
}
function moveSelection(incr)
{
if (srcMode()) {
var locationIndex = locationMap[currentSelectedState];
if (locationIndex + incr >= 0 && locationIndex + incr < locations.length)
selectState(locations[locationIndex + incr].state);
} else {
if (currentSelectedState + incr >= 0 && currentSelectedState + incr < debugData.states.length)
selectState(currentSelectedState + incr);
}
}
function display(stateIndex)
{
if (stateIndex < 0)
stateIndex = 0;
if (stateIndex >= debugData.states.length)
stateIndex = debugData.states.length - 1;
if (debugData.states[stateIndex].codeIndex !== debugData.states[currentDisplayedState].codeIndex)
setupInstructions(stateIndex);
if (debugData.states[stateIndex].dataIndex !== debugData.states[currentDisplayedState].dataIndex)
setupCallData(stateIndex);
var codeLine = codeStr(stateIndex);
var state = debugData.states[stateIndex];
highlightSelection(codeLine);
completeCtxInformation(state);
currentDisplayedState = stateIndex;
var docId = debugData.states[stateIndex].code.documentId;
if (docId)
debugExecuteLocation(docId, locations[locationMap[stateIndex]]);
}
function displayFrame(frameIndex)
{
var state = debugData.states[currentSelectedState];
if (frameIndex === 0)
display(currentSelectedState);
else
display(state.levels[frameIndex - 1]);
}
function select(index)
{
if (srcMode())
selectState(locations[index].state);
else
selectState(index);
}
function selectState(stateIndex)
{
display(stateIndex);
currentSelectedState = stateIndex;
var state = debugData.states[stateIndex];
jumpIntoForwardAction.enabled(stateIndex < debugData.states.length - 1)
jumpIntoBackAction.enabled(stateIndex > 0);
jumpOverForwardAction.enabled(stateIndex < debugData.states.length - 1);
jumpOverBackAction.enabled(stateIndex > 0);
jumpOutBackAction.enabled(state.levels.length > 1);
jumpOutForwardAction.enabled(state.levels.length > 1);
runForwardAction.enabled(stateIndex < debugData.states.length - 1)
runBackAction.enabled(stateIndex > 0);
var callStackData = [];
for (var l = 0; l < state.levels.length; l++) {
var address = debugData.states[state.levels[l] + 1].code.address;
callStackData.push(address);
}
callStackData.push(debugData.states[0].code.address);
callStack.listModel = callStackData;
if (srcMode())
statesSlider.value = locationMap[stateIndex];
else
statesSlider.value = stateIndex;
}
function codeStr(stateIndex)
{
var state = debugData.states[stateIndex];
return codeMap[state.curPC];
}
function highlightSelection(index)
{
statesList.positionViewAtRow(index, ListView.Center);
statesList.selection.clear();
statesList.selection.select(index);
}
function completeCtxInformation(state)
{
currentStep.update(state.step);
mem.update(state.newMemSize.value() + " " + qsTr("words"));
stepCost.update(state.gasCost.value());
gasSpent.update(debugData.states[0].gas.subtract(state.gas).value());
stack.listModel = state.debugStack;
storage.listModel = state.debugStorage;
memoryDump.listModel = state.debugMemory;
}
function isCallInstruction(index)
{
var state = debugData.states[index];
return state.instruction === "CALL" || state.instruction === "CREATE";
}
function isReturnInstruction(index)
{
var state = debugData.states[index];
return state.instruction === "RETURN"
}
function locationsIntersect(l1, l2)
{
return l1.start <= l2.end && l1.end >= l2.start;
}
function breakpointHit(i)
{
var bpLocations = breakpoints[debugData.states[i].code.documentId];
if (bpLocations) {
var location = locations[locationMap[i]];
if (location.start >= 0 && location.end >= location.start)
for (var b = 0; b < bpLocations.length; b++)
if (locationsIntersect(location, bpLocations[b]))
return true;
}
return false;
}
function stepIntoBack()
{
moveSelection(-1);
}
function stepOverBack()
{
if (currentSelectedState > 0 && isReturnInstruction(currentSelectedState - 1))
stepOutBack();
else
moveSelection(-1);
}
function stepOverForward()
{
if (isCallInstruction(currentSelectedState))
stepOutForward();
else
moveSelection(1);
}
function stepIntoForward()
{
moveSelection(1);
}
function runBack()
{
var i = currentSelectedState - 1;
while (i > 0 && !breakpointHit(i)) {
--i;
}
selectState(i);
}
function runForward()
{
var i = currentSelectedState + 1;
while (i < debugData.states.length - 1 && !breakpointHit(i)) {
++i;
}
selectState(i);
}
function stepOutBack()
{
var i = currentSelectedState - 1;
var depth = 0;
while (--i >= 0) {
if (breakpointHit(i))
break;
if (isCallInstruction(i))
if (depth == 0)
break;
else depth--;
else if (isReturnInstruction(i))
depth++;
}
selectState(i);
}
function stepOutForward()
{
var i = currentSelectedState;
var depth = 0;
while (++i < debugData.states.length) {
if (breakpointHit(i))
break;
if (isReturnInstruction(i))
if (depth == 0)
break;
else
depth--;
else if (isCallInstruction(i))
depth++;
}
selectState(i + 1);
}
function jumpTo(value)
{
select(value);
}