mirror of https://github.com/geohot/qira
added vtimeline
This commit is contained in:
parent
ffdb831739
commit
5bdf38293d
10
go.sh
10
go.sh
|
@ -16,10 +16,12 @@ fi
|
|||
|
||||
cd scripts
|
||||
#echo "hello" | ./run_qemu.sh $BIN
|
||||
echo "4t_l34st_it_was_1mperat1v3..." | ./run_qemu.sh $BIN
|
||||
python db_commit_asm.py $BIN $SRC
|
||||
#echo "4t_l34st_it_was_1mperat1v3..." | ./run_qemu.sh $BIN
|
||||
echo "i wish i were a valid key bob" | ./run_qemu.sh $BIN
|
||||
#python db_commit_asm.py $BIN $SRC
|
||||
python db_commit_log.py
|
||||
python db_commit_blocks.py
|
||||
python memory_server.py
|
||||
python mem_json_extract.py
|
||||
#python db_commit_blocks.py
|
||||
#python memory_server.py
|
||||
#python build_multigraph.py
|
||||
|
||||
|
|
|
@ -42,7 +42,10 @@ Template.change.is_mem = function() {
|
|||
Template.change.events({
|
||||
'click .daddress': function() {
|
||||
p("new daddr is "+hex(this.address));
|
||||
Session.set('daddr', this.address);
|
||||
var addr = this.address;
|
||||
// update_dview should be called here
|
||||
Session.set('daddr', addr);
|
||||
Session.set('dview', (addr-0x20)-(addr-0x20)%0x10);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ window.onmousewheel = function(e) {
|
|||
}
|
||||
} else if (e.target.id == "hexdump" || $(e.target).parents("#hexdump").length > 0) {
|
||||
if (e.wheelDelta < 0) {
|
||||
Session.set('daddr', Session.get('daddr')+0x10);
|
||||
Session.set('dview', Session.get('dview')+0x10);
|
||||
} else if (e.wheelDelta > 0) {
|
||||
Session.set('daddr', Session.get('daddr')-0x10);
|
||||
Session.set('dview', Session.get('dview')-0x10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -31,7 +31,7 @@ Deps.autorun(function() {
|
|||
json['clnum'] = Session.get('clnum');
|
||||
json['iaddr'] = Session.get('iaddr');
|
||||
json['daddr'] = Session.get('daddr');
|
||||
json['collapsed'] = Session.get('collapsed');
|
||||
json['dview'] = Session.get('dview');
|
||||
var hash = JSON.stringify(json);
|
||||
//p("updating hash to "+hash);
|
||||
window.location.hash = hash;
|
||||
|
@ -55,15 +55,6 @@ window.onload = check_hash;
|
|||
// TODO: fix this to not snapback
|
||||
//window.onhashchange = check_hash;
|
||||
|
||||
Deps.autorun(function() {
|
||||
var cl_selector = $('#cl_selector');
|
||||
var clnum = Session.get("clnum");
|
||||
var max_clnum = Session.get("max_clnum");
|
||||
if (cl_selector.length > 0) {
|
||||
cl_selector[0].value = clnum;
|
||||
cl_selector.slider('refresh');
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.subscribe('max_clnum', {onReady: function() {
|
||||
post = Change.findOne({}, {sort: {clnum: -1}});
|
||||
|
@ -71,12 +62,22 @@ Meteor.subscribe('max_clnum', {onReady: function() {
|
|||
Session.setDefault("clnum", post.clnum);
|
||||
Session.set("max_clnum", post.clnum);
|
||||
|
||||
var cl_selector = $('#cl_selector');
|
||||
/*var cl_selector = $('#cl_selector');
|
||||
cl_selector[0].max = post.clnum;
|
||||
cl_selector.on("change", function(e) {
|
||||
var val = parseInt($('#cl_selector')[0].value);
|
||||
Session.set('clnum', val);
|
||||
});
|
||||
cl_selector.slider('refresh');
|
||||
cl_selector.slider('refresh');*/
|
||||
}});
|
||||
|
||||
/*Deps.autorun(function() {
|
||||
var cl_selector = $('#cl_selector');
|
||||
var clnum = Session.get("clnum");
|
||||
var max_clnum = Session.get("max_clnum");
|
||||
if (cl_selector.length > 0) {
|
||||
cl_selector[0].value = clnum;
|
||||
cl_selector.slider('refresh');
|
||||
}
|
||||
});*/
|
||||
|
||||
|
|
|
@ -4,25 +4,69 @@ stream.on('memory', function(msg) {
|
|||
// render the hex editor
|
||||
var addr = msg['address'];
|
||||
html = "<table><tr>";
|
||||
str = "";
|
||||
for (var i = 0; i < msg['len']; i++) {
|
||||
if ((i&0xF) == 0) html += "</tr><tr><td>"+hex(addr+i)+":</td>";
|
||||
if ((i&0x3) == 0) html += "<td></td>";
|
||||
if (msg['dat'][addr+i] === undefined) {
|
||||
var me = " ";
|
||||
var me = "__";
|
||||
str += " ";
|
||||
} else {
|
||||
var me = msg['dat'][addr+i].toString(16);
|
||||
var ii = msg['dat'][addr+i];
|
||||
if (ii >= 0x21 && ii <= 0x7e) str += String.fromCharCode(ii);
|
||||
else str += " ";
|
||||
|
||||
var me = ii.toString(16);
|
||||
if (me.length == 1) me = "0" + me;
|
||||
}
|
||||
if (addr+i == Session.get('daddr')) {
|
||||
html += '<td class="highlight">'+me+"</td>";
|
||||
html += '<td class="data highlight" daddr='+(addr+i)+'>'+me+"</td>";
|
||||
} else {
|
||||
html += "<td>"+me+"</td>";
|
||||
html += '<td class="data" daddr='+(addr+i)+">"+me+"</td>";
|
||||
}
|
||||
if ((i&0xF) == 0xF) { html += "<td>" + str + "</td>"; str = ""; }
|
||||
}
|
||||
/*for (var i = 0; i < msg['len']; i+=4) {
|
||||
if ((i&0xF) == 0) html += "</tr><tr><td>"+hex(addr+i)+":</td>";
|
||||
|
||||
var exclass = "";
|
||||
if (msg['dat'][addr+i] === undefined) {
|
||||
var me = " ";
|
||||
} else {
|
||||
var v = 0;
|
||||
for (var j = 3; j >= 0; j--) {
|
||||
if (addr+i+j == Session.get('daddr')) {
|
||||
exclass = "highlight";
|
||||
}
|
||||
v *= 0x100;
|
||||
var t = msg['dat'][addr+i+j];
|
||||
if (t !== undefined) v += t;
|
||||
}
|
||||
var me = v.toString(16);
|
||||
while (me.length != 8) me = "0" + me;
|
||||
}
|
||||
html += '<td class="data '+exclass+'" daddr='+(addr+i)+">"+me+"</td>";
|
||||
}*/
|
||||
html += "</tr></table>";
|
||||
$("#hexdump")[0].innerHTML = html;
|
||||
});
|
||||
|
||||
function update_dview(addr) {
|
||||
Session.set('daddr', addr);
|
||||
Session.set('dview', (addr-0x20)-(addr-0x20)%0x10);
|
||||
}
|
||||
|
||||
Template.memviewer.events({
|
||||
'dblclick .data': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'click .data': function(e) {
|
||||
var daddr = parseInt(e.target.getAttribute('daddr'));
|
||||
Session.set('daddr', daddr);
|
||||
},
|
||||
});
|
||||
|
||||
stream.on('registers', function(msg) {
|
||||
$('#regviewer')[0].innerHTML = "";
|
||||
UI.insert(UI.renderWithData(Template.regviewer, {regs: msg}), $('#regviewer')[0]);
|
||||
|
@ -34,16 +78,16 @@ Template.regviewer.hexvalue = function() {
|
|||
|
||||
Template.regviewer.events({
|
||||
'click .daddress': function() {
|
||||
Session.set('daddr', this.value);
|
||||
update_dview(this.value);
|
||||
},
|
||||
});
|
||||
|
||||
// keep these updated
|
||||
Deps.autorun(function() {
|
||||
var daddr = Session.get('daddr');
|
||||
var dview = Session.get('dview');
|
||||
var clnum = Session.get('clnum');
|
||||
stream.emit('getmemory',
|
||||
{"clnum":clnum, "address":(daddr-0x20)-(daddr-0x20)%0x10, "len":0x100});
|
||||
stream.emit('getmemory', {"clnum":clnum, "address":dview, "len":0x100});
|
||||
});
|
||||
|
||||
Deps.autorun(function() {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
Meteor.startup(function() {
|
||||
Deps.autorun(function() {
|
||||
var max = Session.get("max_clnum");
|
||||
if (max === undefined) return;
|
||||
var working_height = $("#vtimeline").height();
|
||||
var scale = Math.ceil(max/working_height);
|
||||
Session.set("cview", [0, max, scale]);
|
||||
});
|
||||
$("#vtimeline").click(function(e) {
|
||||
if (e.target !== $("#vtimeline")[0]) return;
|
||||
var cview = Session.get("cview");
|
||||
Session.set("clnum", e.offsetY * cview[2]);
|
||||
});
|
||||
});
|
||||
|
||||
function draw_flag(type, clnum) {
|
||||
var cview = Session.get("cview");
|
||||
if (cview == undefined) return;
|
||||
if (cview[0] > clnum || cview[1] < clnum) return;
|
||||
var already = $("#flag"+clnum);
|
||||
if (already.length > 0) {
|
||||
already.addClass("flag"+type);
|
||||
}
|
||||
var flag = $('<div id="flag'+clnum+'" class="flag flag'+type+'">'+clnum+'</div>');
|
||||
flag[0].style.marginTop = (clnum/cview[2]) + "px";
|
||||
flag.click(function() { Session.set("clnum", clnum); });
|
||||
$('#vtimeline').append(flag);
|
||||
}
|
||||
|
||||
function remove_flags(type) {
|
||||
$(".flag"+type).remove();
|
||||
}
|
||||
|
||||
Deps.autorun(function() {
|
||||
var clnum = Session.get("clnum");
|
||||
remove_flags("change");
|
||||
draw_flag("change", clnum);
|
||||
});
|
||||
|
||||
Deps.autorun(function() {
|
||||
var clnum = Session.get("clnum");
|
||||
var iaddr = Session.get('iaddr');
|
||||
remove_flags("iaddr");
|
||||
Change.find({address: iaddr, type: "I"}).forEach(function(x) {
|
||||
if (x.clnum == clnum) return;
|
||||
draw_flag("iaddr", x.clnum);
|
||||
});
|
||||
});
|
||||
|
||||
Deps.autorun(function() {
|
||||
var clnum = Session.get("clnum");
|
||||
var daddr = Session.get('daddr');
|
||||
remove_flags("daddrr");
|
||||
remove_flags("daddrw");
|
||||
//Change.find({address: daddr, $or: [{type: "L"}, {type: "S"}] }).forEach(function(x) {
|
||||
Change.find({address: daddr}).forEach(function(x) {
|
||||
if (x.clnum == clnum) return;
|
||||
if (x.type == "L") draw_flag("daddrr", x.clnum);
|
||||
if (x.type == "S") draw_flag("daddrw", x.clnum);
|
||||
});
|
||||
});
|
||||
|
51
web/qira.css
51
web/qira.css
|
@ -23,6 +23,40 @@
|
|||
font-size: 8px !important;
|
||||
}
|
||||
|
||||
#vtimeline {
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
.flag {
|
||||
width: 100px;
|
||||
height: 1px;
|
||||
position: fixed;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.flagchange {
|
||||
background-color: blue !important;
|
||||
color: blue !important;
|
||||
}
|
||||
|
||||
.flagiaddr {
|
||||
background-color: red;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.flagdaddrr {
|
||||
background-color: #888800;
|
||||
color: #888800;
|
||||
}
|
||||
|
||||
.flagdaddrw {
|
||||
background-color: yellow;
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
#timeline {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
|
@ -52,29 +86,31 @@
|
|||
}
|
||||
|
||||
#onlypanel {
|
||||
background-color: #FFAAAA;
|
||||
background-color: #AAAAAA;
|
||||
border: 1px solid black;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
left: 100px;
|
||||
}
|
||||
|
||||
#clviewer {
|
||||
height: 320px;
|
||||
border: 1px solid gray;
|
||||
background-color: #9999FF;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
#regviewer {
|
||||
height: 80px;
|
||||
border: 1px solid gray;
|
||||
background-color: #FFCCFF;
|
||||
background-color: #DDDDDD;
|
||||
border: 1px solid black;
|
||||
width: 500px;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
#hexeditor {
|
||||
border: 1px solid gray;
|
||||
background-color: #FFFF55;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
#cl_selector {
|
||||
|
@ -100,8 +136,8 @@
|
|||
}
|
||||
|
||||
.change {
|
||||
color: yellow;
|
||||
width: 35px;
|
||||
color: #888800;
|
||||
width: 50px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
@ -132,4 +168,3 @@ body {
|
|||
font-family: monospace;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
<head>
|
||||
<title>qira</title>
|
||||
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">
|
||||
<!--<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="timeline">
|
||||
<!--<div id="timeline">
|
||||
<div id="cl_selector_box">
|
||||
<input type="range" id="cl_selector" value="1" min="1" max="1">
|
||||
</div>
|
||||
</div>-->
|
||||
<div id="vtimeline">
|
||||
</div>
|
||||
<!--
|
||||
<div id="cfg">
|
||||
{{> cfg}}
|
||||
</div>
|
||||
<div id="rightpanel">-->
|
||||
<div id="onlypanel">
|
||||
<div id="clviewer">
|
||||
{{> changelist}}
|
||||
</div>
|
||||
<div id="regviewer">
|
||||
<!--regviewer-->
|
||||
<!--{{> regviewer}}-->
|
||||
</div>
|
||||
<div id="hexeditor">
|
||||
<div id="hexdump"></div>
|
||||
{{> memviewer}}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -36,25 +31,8 @@
|
|||
{{/each}}
|
||||
</template>
|
||||
|
||||
<template name="cfg">
|
||||
{{#each blocks}}
|
||||
<!--block {{clstart}}-{{clend}} from {{hexstart}}-{{hexend}}-->
|
||||
<div class="block" style="margin-left: {{ddepth}}px">
|
||||
<!--{{loopcnt}}-->
|
||||
{{#each instructions}}
|
||||
<div class="instruction">
|
||||
<div class="change {{ischange}}">{{clnum}}</div>
|
||||
{{#with program_instruction}}
|
||||
<span class="name">{{name}}</span>
|
||||
<span class="address {{isiaddr}}">{{hexaddress}}</span>
|
||||
{{instruction}}
|
||||
<span class="comment">{{comment}}</span>
|
||||
{{/with}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<div class="collapse">{{fxncollapse}}</div>
|
||||
</div><br/>
|
||||
{{/each}}
|
||||
<template name="memviewer">
|
||||
<div id="hexdump"></div>
|
||||
</template>
|
||||
|
||||
<!-- related to the changelist viewer -->
|
||||
|
|
|
@ -10,20 +10,20 @@ Meteor.publish('max_clnum', function() {
|
|||
|
||||
Meteor.publish('dat_clnum', function(clnum){
|
||||
// can only return as many as in the changelist
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:20});
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:30});
|
||||
});
|
||||
|
||||
|
||||
Meteor.publish('dat_iaddr', function(iaddr){
|
||||
// fetch the static info about the range
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1}, limit:10})
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1}, limit:30})
|
||||
});
|
||||
|
||||
Meteor.publish('dat_daddr', function(daddr){
|
||||
// fetch the dynamic info about the instruction range
|
||||
//return Change.find({address : {$gt: daddr-0x100, $lt: daddr+0x300}});
|
||||
if (daddr >= 0x1000) {
|
||||
return Change.find({address:daddr}, {sort: {clnum: 1}, limit:10});
|
||||
return Change.find({address:daddr, $or: [{type: "L"}, {type: "S"}]}, {sort: {clnum: 1}, limit:50});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ function map_getbelow(map, a) {
|
|||
if (best == undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
console.log("search for "+a+" found "+map[best][0]);
|
||||
//console.log("search for "+a+" found "+map[best][0]);
|
||||
return map[best][1];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue