Better webui, fix segfault in ag, add agj for json graphs

More work on the webui
New 'agj' command to get function graphs in json
Fix segfault in 'ag' command
'agv' now launches the internal http server
Initial refactoring for RAnalHint integration into RCore
Add basic mime-type support in the http server
Enhace the graph view style
This commit is contained in:
pancake 2013-01-24 03:48:24 +01:00
parent 150c43d33c
commit 1c93e8a727
33 changed files with 425 additions and 211 deletions

View File

@ -14,6 +14,7 @@ Broken stuff to fixe before release
0.9.4
=====
* foldable stuff .. was in r1..redo?
* cmp rip+xx -> not resolved wtf
* search for CALL instructions in text segment.
- analyze the destination address of each call destination

View File

@ -46,6 +46,7 @@ R_API void r_core_anal_hint_list (RAnal *a, int mode) {
static char *r_core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
int is_html = r_cons_singleton ()->is_html;
int is_json = opts & R_CORE_ANAL_JSON;
char cmd[1024], file[1024], *cmdstr = NULL, *filestr = NULL, *str = NULL;
int i, j, line = 0, oline = 0, idx = 0;
ut64 at;
@ -67,7 +68,13 @@ static char *r_core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
cmdstr[idx] = 0;
// TODO: optimize all this strcat stuff
strcat (cmdstr, filestr);
strcat (cmdstr, "\\l");
if (is_json)
strcat (cmdstr, "\\n");
else
if (is_html)
strcat (cmdstr, "<br />");
else
strcat (cmdstr, "\\l");
idx += strlen (filestr);
free (filestr);
}
@ -75,6 +82,7 @@ static char *r_core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
oline = line;
}
} else if (opts & R_CORE_ANAL_GRAPHBODY) {
r_cons_flush ();
snprintf (cmd, sizeof (cmd), "pD %"PFMT64d" @ 0x%08"PFMT64x"", bb->size, bb->addr);
cmdstr = r_core_cmd_str (core, cmd);
}
@ -96,7 +104,7 @@ static char *r_core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
str[j] = cmdstr[i];
} else {
str[j] = '\\';
str[++j] = cmdstr[i]=='"'? '"': 'l';
str[++j] = cmdstr[i]=='"'? '"': ((is_json)?'n':'l');
}
break;
default:
@ -111,13 +119,45 @@ static char *r_core_anal_graph_label(RCore *core, RAnalBlock *bb, int opts) {
static void r_core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts) {
int is_html = r_cons_singleton ()->is_html;
int is_json = opts & R_CORE_ANAL_JSON;
struct r_anal_bb_t *bbi;
RListIter *iter;
char *str;
int top = 0;
int left = 300;
int count = 0;
if (is_json) {
// TODO: show vars, refs and xrefs
r_cons_printf ("{\"name\":\"%s\"", fcn->name);
r_cons_printf (",\"offset\":%"PFMT64d, fcn->addr);
r_cons_printf (",\"ninstr\":%"PFMT64d, fcn->ninstr);
r_cons_printf (",\"nargs\":%"PFMT64d, fcn->nargs);
r_cons_printf (",\"size\":%d", fcn->size);
r_cons_printf (",\"stack\":%d", fcn->stack);
r_cons_printf (",\"type\":%d", fcn->type); // TODO: output string
//r_cons_printf (",\"cc\":%d", fcn->call); // TODO: calling convention
if (fcn->dsc) r_cons_printf (",\"signature\":\"%s\"", fcn->dsc);
r_cons_printf (",\"blocks\":[");
}
r_list_foreach (fcn->bbs, iter, bbi) {
count ++;
if (is_json) {
if (count>1)
r_cons_printf (",");
r_cons_printf ("{\"offset\":%"PFMT64d",\"size\":%"PFMT64d, bbi->addr, bbi->size);
if (bbi->jump != -1)
r_cons_printf (",\"jump\":%"PFMT64d, bbi->jump);
if (bbi->fail != -1)
r_cons_printf (",\"fail\":%"PFMT64d, bbi->fail);
if ((str = r_core_anal_graph_label (core, bbi, opts))) {
str = r_str_replace (str, "\\ ", "\\\\ ", 1);
r_cons_printf (",\"code\":\"%s\"", str);
free (str);
}
r_cons_printf ("}");
continue;
}
if (bbi->jump != -1) {
if (is_html) {
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
@ -131,7 +171,7 @@ static void r_core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts) {
if (bbi->fail != -1) {
if (is_html) {
r_cons_printf ("<div class=\"connector _0x%08"PFMT64x" _0x%08"PFMT64x"\">\n"
" <img class=\"connector-end\" src=\"img/arrow.gif\" /></div>\n",
" <img class=\"connector-end\" src=\"img/arrow.gif\"/></div>\n",
bbi->addr, bbi->fail);
} else r_cons_printf ("\t\"0x%08"PFMT64x"_0x%08"PFMT64x"\" -> \"0x%08"PFMT64x"_0x%08"PFMT64x"\" "
"[color=\"red\"];\n", fcn->addr, bbi->addr, fcn->addr, bbi->fail);
@ -147,7 +187,7 @@ static void r_core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts) {
fcn->name, bbi->addr);
} else {
if (is_html) {
r_cons_printf ("<p class=\"block draggable\" style=\"top: %dpx; left: %dpx; width: 500px;\" id=\"_0x%08"PFMT64x"\">\n"
r_cons_printf ("<p class=\"block draggable\" style=\"top: %dpx; left: %dpx; width: 400px;\" id=\"_0x%08"PFMT64x"\">\n"
"%s</p>\n", top, left, bbi->addr, str);
left = left? 0: 600;
if (!left) top += 250;
@ -162,6 +202,8 @@ static void r_core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts) {
free (str);
}
}
if (is_json)
r_cons_printf ("]}");
}
R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head) {
@ -704,11 +746,14 @@ R_API RList* r_core_anal_graph_to(RCore *core, ut64 addr, int n) {
R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts) {
const char *font = r_config_get (core->config, "graph.font");
int count = 0;
int is_html = r_cons_singleton ()->is_html;
int is_json = opts & R_CORE_ANAL_JSON;
int reflines, bytes, dwarf;
RAnalFunction *fcni;
RListIter *iter;
opts|=R_CORE_ANAL_GRAPHBODY;
if (r_list_empty (core->anal->fcns))
return R_FALSE;
@ -718,17 +763,25 @@ R_API int r_core_anal_graph(RCore *core, ut64 addr, int opts) {
r_config_set_i (core->config, "asm.lines", 0);
r_config_set_i (core->config, "asm.bytes", 0);
r_config_set_i (core->config, "asm.dwarf", 0);
if (!is_html)
if (!is_html && !is_json)
r_cons_printf ("digraph code {\n"
"\tgraph [bgcolor=white];\n"
"\tnode [color=lightgray, style=filled shape=box"
" fontname=\"%s\" fontsize=\"8\"];\n", font);
if (is_json) {
r_cons_printf ("[");
}
r_cons_flush ();
r_list_foreach (core->anal->fcns, iter, fcni)
if (fcni->type & (R_ANAL_FCN_TYPE_SYM | R_ANAL_FCN_TYPE_FCN) &&
(addr == 0 || addr == fcni->addr))
r_list_foreach (core->anal->fcns, iter, fcni) {
if (fcni->type & (R_ANAL_FCN_TYPE_SYM | R_ANAL_FCN_TYPE_FCN)
&& (addr == 0 || addr == fcni->addr)) {
if (is_json && count++>0) r_cons_printf (",");
r_core_anal_graph_nodes (core, fcni, opts);
if (!is_html) r_cons_printf ("}\n");
}
}
if (!is_html && !is_json) r_cons_printf ("}\n");
if (is_json)
r_cons_printf ("]\n");
r_cons_flush ();
r_config_set_i (core->config, "asm.lines", reflines);
r_config_set_i (core->config, "asm.bytes", bytes);

View File

@ -170,8 +170,10 @@ static int cmd_rap(void *data, const char *input) {
RCore *core = (RCore *)data;
switch (*input) {
case '\0': r_core_rtr_list (core); break;
case 'h': r_core_rtr_http (core, 0); break;
case 'H': r_core_rtr_http (core, 1); break;
case 'h': r_core_rtr_http (core, 0, NULL); break;
case 'H':
while (input[1]==' ') input++;
r_core_rtr_http (core, 1, input+1); break;
case '?': r_core_rtr_help (core); break;
case '+': r_core_rtr_add (core, input+1); break;
case '-': r_core_rtr_remove (core, input+1); break;

View File

@ -590,6 +590,9 @@ static int cmd_anal(void *data, const char *input) {
case 'c':
r_core_anal_refs (core, r_num_math (core->num, input+2), input[2]=='j'? 2: 1);
break;
case 'j':
r_core_anal_graph (core, r_num_math (core->num, input+2), R_CORE_ANAL_JSON);
break;
case 'l':
r_core_anal_graph (core, r_num_math (core->num, input+2), R_CORE_ANAL_GRAPHLINES);
break;
@ -601,6 +604,8 @@ static int cmd_anal(void *data, const char *input) {
R_CORE_ANAL_GRAPHBODY|R_CORE_ANAL_GRAPHDIFF);
break;
case 'v':
r_core_cmd0 (core, "=H /graph/");
#if 0
{
int is_html = (r_config_get_i (core->config, "scr.html"));
const char *cmd = r_config_get (core->config, "cmd.graph");
@ -622,6 +627,7 @@ static int cmd_anal(void *data, const char *input) {
r_core_cmdf (core, "%s", cmd);
free (tmp);
}
#endif
break;
case '?':
r_cons_printf (

View File

@ -2,6 +2,40 @@
#include "r_core.h"
R_API RAnalHint *r_core_hint_begin (RCore *core, RAnalHint* hint, ut64 at) {
// XXX not here
static char *hint_arch = NULL;
static int hint_bits = 0;
if (hint) {
r_anal_hint_free (hint);
hint = NULL;
}
hint = r_anal_hint_get (core->anal, at);
if (hint_arch) {
r_config_set (core->config, "asm.arch", hint_arch);
hint_arch = NULL;
}
if (hint_bits) {
r_config_set_i (core->config, "asm.bits", hint_bits);
hint_bits = 0;
}
if (hint) {
/* arch */
if (hint->arch) {
if (!hint_arch) hint_arch = strdup (
r_config_get (core->config, "asm.arch"));
r_config_set (core->config, "asm.arch", hint->arch);
}
/* bits */
if (hint->bits) {
if (!hint_bits) hint_bits =
r_config_get_i (core->config, "asm.bits");
r_config_set_i (core->config, "asm.bits", hint->bits);
}
}
return hint;
}
static char *filter_refline(const char *str) {
char *p, *s = strdup (str);
p = strstr (s, "->");
@ -36,8 +70,6 @@ static void printoffset(ut64 off, int show_color, int invert, int opt) {
R_API int r_core_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len, int l, int invbreak, int cbytes) {
/* hints */
RAnalHint *hint = NULL;
char *hint_arch = NULL;
int hint_bits = 0;
/* other */
int ret, idx = 0, i, j, k, lines, ostackptr = 0, stackptr = 0;
char *line = NULL, *comment = NULL, *opstr, *osl = NULL; // old source line
@ -175,35 +207,10 @@ toro:
oplen = 1;
for (i=idx=ret=0; idx < len && lines < l; idx+=oplen,i++, lines++) {
ut64 at = addr + idx;
if (hint) {
r_anal_hint_free (hint);
hint = NULL;
}
hint = r_anal_hint_get (core->anal, at);
hint = r_core_hint_begin (core, hint, at);
if (cbytes && idx>=l)
break;
if (hint_arch) {
r_config_set (core->config, "asm.arch", hint_arch);
hint_arch = NULL;
}
if (hint_bits) {
r_config_set_i (core->config, "asm.bits", hint_bits);
hint_bits = 0;
}
if (hint) {
/* arch */
if (hint->arch) {
if (!hint_arch) hint_arch = strdup (
r_config_get (core->config, "asm.arch"));
r_config_set (core->config, "asm.arch", hint->arch);
}
/* bits */
if (hint->bits) {
if (!hint_bits) hint_bits =
r_config_get_i (core->config, "asm.bits");
r_config_set_i (core->config, "asm.bits", hint->bits);
}
}
r_asm_set_pc (core->assembler, at);
if (show_lines) {
line = r_anal_reflines_str (core->anal,
@ -700,7 +707,7 @@ toro:
RFlagItem *flag = r_flag_get_at (core->flags, cc.jump);
if (show_color)
r_cons_printf ("\n%s%s "Color_TURQOISE"; %s (%s+%d)"Color_RESET,
f?pre:"", refline, ccstr, flag? flag->name: "", f? cc.jump-flag->offset: 0);
f?pre:"", refline, ccstr, flag? flag->name: "", (f&&flag)? cc.jump-flag->offset: 0);
else r_cons_printf ("\n%s%s ; %s (%s+%d)",
pre, refline, ccstr,
flag?flag->name:"", flag? cc.jump-flag->offset: 0);
@ -876,14 +883,22 @@ R_API int r_core_print_disasm_instructions (RCore *core, int len, int l) {
const ut8 *buf = core->block;
int bs = core->blocksize;
RAnalOp analop = {0};
RAnalHint *hint = NULL;
int decode = r_config_get_i (core->config, "asm.decode");
ut64 at;
// TODO: add support for anal hints
if (len>core->blocksize)
r_core_block_size (core, len);
if (l==0) l = len;
for (i=j=0; i<bs && i<len && j<len; i+=ret, j++) {
r_asm_set_pc (core->assembler, core->offset+i);
at = core->offset +i;
if (hint) {
r_anal_hint_free (hint);
hint = NULL;
}
hint = r_core_hint_begin (core, hint, at);
r_asm_set_pc (core->assembler, at);
ret = r_asm_disassemble (core->assembler,
&asmop, buf+i, core->blocksize-i);
//r_cons_printf ("0x%08"PFMT64x" ", core->offset+i);
@ -893,7 +908,7 @@ R_API int r_core_print_disasm_instructions (RCore *core, int len, int l) {
} else {
if (decode) {
char *tmpopstr, *opstr;
r_anal_op (core->anal, &analop, core->offset+i,
r_anal_op (core->anal, &analop, at,
buf+i, core->blocksize-i);
tmpopstr = r_anal_op_to_string (core->anal, &analop);
opstr = (tmpopstr)? tmpopstr: strdup (asmop.buf_asm);
@ -902,4 +917,6 @@ R_API int r_core_print_disasm_instructions (RCore *core, int len, int l) {
} else r_cons_printf ("%s\n", asmop.buf_asm);
}
}
if (hint) r_anal_hint_free (hint);
return 0;
}

View File

@ -35,7 +35,7 @@ SECURITY IMPLICATIONS
- follow symlinks
#endif
R_API int r_core_rtr_http(RCore *core, int launch) {
R_API int r_core_rtr_http(RCore *core, int launch, const char *path) {
RSocketHTTPRequest *rs;
int oldsandbox = -1;
int timeout = r_config_get_i (core->config, "http.timeout");
@ -58,8 +58,8 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
if (launch) {
char cmd[128];
const char *browser = r_config_get (core->config, "http.browser");
snprintf (cmd, sizeof (cmd), "%s http://localhost:%d/",
browser, atoi (port));
snprintf (cmd, sizeof (cmd)-1, "%s http://localhost:%d/%s",
browser, atoi (port), path?path:"");
r_sys_cmd (cmd);
}
r_config_set (core->config, "asm.cmtright", "false");
@ -162,7 +162,11 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
int sz = 0;
char *f = r_file_slurp (path, &sz);
if (f) {
r_socket_http_response (rs, 200, f, sz, NULL);
const char *contenttype = NULL;
if (strstr (path, ".js")) contenttype = "Content-Type: application/javascript\n";
if (strstr (path, ".css")) contenttype = "Content-Type: text/css\n";
if (strstr (path, ".html")) contenttype = "Content-Type: text/html\n";
r_socket_http_response (rs, 200, f, sz, contenttype);
free (f);
} else {
r_socket_http_response (rs, 403, "Permission denied", 0, NULL);

View File

@ -32,6 +32,7 @@
#define R_CORE_ANAL_GRAPHLINES 0x1
#define R_CORE_ANAL_GRAPHBODY 0x2
#define R_CORE_ANAL_GRAPHDIFF 0x4
#define R_CORE_ANAL_JSON 0x8
/* rtr */
#define RTR_PROT_RAP 0
@ -293,7 +294,7 @@ R_API void r_core_rtr_add(RCore *core, const char *input);
R_API void r_core_rtr_remove(RCore *core, const char *input);
R_API void r_core_rtr_session(RCore *core, const char *input);
R_API void r_core_rtr_cmd(RCore *core, const char *input);
R_API int r_core_rtr_http(RCore *core, int launch);
R_API int r_core_rtr_http(RCore *core, int launch, const char *path);
R_API void r_core_visual_define (RCore *core);
R_API void r_core_visual_config (RCore *core);

View File

@ -8,7 +8,7 @@ OBJS+=prof.o cache.o sys.o buf.o w32-sys.o base64.o base85.o name.o
OBJS+=list.o flist.o ht.o ht64.o mixed.o btree.o chmod.o graph.o
OBJS+=regex/regcomp.o regex/regerror.o regex/regexec.o uleb128.o
OBJS+=sandbox.o calc.o thread.o lock.o strpool.o bitmap.o strht.o
OBJS+= p_date.o p_disasm.o p_format.o p_print.o p_seven.o
OBJS+= p_date.o p_format.o p_print.o p_seven.o
# DO NOT BUILD r_big api (not yet used and its buggy)
ifeq (1,0)

View File

@ -1,3 +0,0 @@
/* radare - LGPL - Copyright 2010 pancake<nopcode.org> */
/* TODO: import from libr/core/disasm.c */

View File

@ -109,6 +109,7 @@ body{
</script>
</head>
<body onload="onLoad();">
<!--
<table class="main_table" style="height: 100%;">
<tr>
<td colspan=3>
@ -127,18 +128,21 @@ body{
</ul>
</td>
<td style="vertical-align: top; padding: 0px;">
-->
<div id="mainCanvas" class="canvas" style="width: 100%; height: 400px;">
EOF
cat ${DOTFILE} >> $T
cat <<EOF >> $T
<!--
</td>
<td width="1" style="vertical-align: top;" class="menu">
<ul id="menu"> </ul>
</td>
</tr>
</table>
-->
</body>
</html>
EOF

View File

@ -4,5 +4,9 @@ all: index.js
upload:
rsync --safe-links -avz * radare.org:/srv/http/lolcathostorg/b/
debug:
cat js/*.js > index.js
index.js:
# cat js/*.js > index.js
cat js/*.js | uglifyjs > index.js || cat js/*.js > index.js

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta name="viewport" content="width=220, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0" />
<link rel="shortcut icon" href="favicon.ico" />

1
shlr/www/enyo/index.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
enyo.kind({
enyo.kind ({
name: "Assembler",
kind: "Scroller",
// kind: "Scroller",
components: [
{tag: "form", style:"margin-top:8px;margin-left:8px", attributes: {action:"javascript:#"}, components: [
@ -14,12 +15,12 @@ enyo.kind({
]},
{kind: "onyx.InputDecorator", classes: "r2ui-input", components: [
{tag: "font", content: "offset", style:"margin-right:20px;font-weight:bold"},
{kind: "Input", value: 'entry0', style:"width:120px", onkeydown: "assembleOpcode", attributes: {autocapitalize:"off"}, name: "offset"},
{kind: "Input", value: 'entry0', style:"width:120px", onkeydown: "assembleOpcode", attributes: {autocapitalize:"off"}, name: "offset"}
]}
]}
]}
],
assembleOpcode: function(inSender, inEvent) {
assembleOpcode: function (inSender, inEvent) {
if (inEvent.keyCode === 13) {
var arg = inSender.getValue ();
var off = this.$.offset.getValue ();

View File

@ -1,7 +1,6 @@
enyo.kind({
enyo.kind ({
name: "Console",
kind: "Scroller",
tag: "div",
style:"margin-left:8px",
components: [
{tag: "form", attributes: {action:"javascript:#"}, components: [
@ -13,15 +12,15 @@ enyo.kind({
]}
]}
],
runCommand: function(inSender, inEvent) {
runCommand: function (inSender, inEvent) {
if (inEvent.keyCode === 13) {
var cmd = this.$.input.getValue ();;
var cmd = this.$.input.getValue ();
this.$.input.setValue ("");
var out = this.$.output;
r2.cmd (cmd, function(x) {
out.setContent (x);
});
return false;
(function (out) {
r2.cmd (cmd, function (x) {
out.setContent (x);
});
})(this.$.output);
}
}
});

18
shlr/www/enyo/js/graph.js Normal file
View File

@ -0,0 +1,18 @@
enyo.kind ({
name: "Graph",
kind: "Scroller",
style: "background-color:#c0c0c0",
components: [
{tag: "h2", content: "Open graph", style:"margin-left:10px;"},
{kind: "Group", classes: "enyo-border-box group", defaultKind: "onyx.Button", components: [
{content: "Basic blocks", classes: "onyx-dark menu-button", ontap:"openGraphBB" },
{content: "Callgraph", classes: "onyx-dark menu-button", ontap:"openGraphCG" }
]}
],
openGraphBB: function () {
window.open ('/graph/', '_self');
},
openGraphCG: function () {
window.open ('/d3/', '_self');
}
});

View File

@ -1,18 +1,15 @@
enyo.kind({
enyo.kind ({
name: "Hexdump",
kind: "Scroller",
style: "background-color:#f0f0f0",
style: "background-color:#c0c0c0;padding:8px",
components: [
{tag: "center", components: [
{tag: "h1", style: "color:#303030", content: "hexdump"},
{tag: "pre", name: "output"}
]}
{tag: "pre", allowHtml: true, name: "output"}
],
create: function() {
this.inherited (arguments);
var output = this.$.output;
r2.cmd ("px 8192", function(a) {
output.setContent (a);
output.setContent (r2.filter_asm (a, "px"));
});
}
});

View File

@ -10,8 +10,11 @@ enyo.kind ({
{content: "Disassembler", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Disassembler", active: true},
{content: "Assembler", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Assembler" },
{content: "Hexdump", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Hexdump" },
{content: "Graph", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Graph" },
{content: "Search", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Search" },
{content: "Console", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Console" },
{content: "Logs", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Logs" },
{content: "Script", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Script" },
{content: "Settings", classes: "onyx-dark menu-button", ontap:"openPanel", name: "Settings" },
{content: "About", classes: "onyx-dark menu-button" , ontap: "openPanel", name:"About"},
]}

31
shlr/www/enyo/js/logs.js Normal file
View File

@ -0,0 +1,31 @@
enyo.kind ({
name: "Logs",
kind: "Scroller",
style: "background-color:#c0c0c0;margin-left:8px",
components: [
{tag: "form", attributes: {action:"javascript:#"}, components: [
{kind: "FittableRows", fit: true, classes: "fittable-sample-shadow", components: [
{kind: "onyx.InputDecorator", style: "margin-top:8px;background-color:#404040;width: 90%;display:inline-block", components: [
{kind: "Input", style:"width:100%;color:white", value: '', onkeydown: "sendMessage", attributes: {autocapitalize:"off"}, name: "input"},
]},
{tag: "pre", classes:"r2ui-terminal", style:"width:90%;", fit: true, allowHtml: true, name:"output"}
]}
]}
],
logger: null,
create: function() {
this.inherited (arguments);
var out = this.$.output;
this.logger = r2.get_logger ().on ("message", function (msg) {
out.setContent (out.getContent() + msg.text + "\n");
});
this.logger.autorefresh (3);
},
sendMessage: function (inSender, inEvent) {
if (inEvent.keyCode === 13) {
var msg = this.$.input.getValue ();
this.$.input.setValue ("");
this.logger.send (msg);
}
}
});

View File

@ -19,7 +19,10 @@ enyo.kind ({
{ name: "Disassembler", active: true },
{ name: "Assembler" },
{ name: "Hexdump" },
{ name: "Search" },
{ name: "Console" },
{ name: "Logs" },
{ name: "Script" },
{ name: "Settings", separator: true },
{ name: "About" }
];

View File

@ -69,8 +69,11 @@ enyo.kind ({
{kind:"Disassembler", name: "pageDisassembler"},
{kind:"Assembler", name:"pageAssembler"},
{kind:"Hexdump", name: "pageHexdump"},
{kind:"Graph", name: "pageGraph"},
{kind:"Search", name: "pageSearch"},
{kind:"Console", name: "pageConsole"},
{kind:"Logs", name: "pageLogs"},
{kind:"Script", name: "pageScript"},
{kind:"Preferences", name:"pagePreferences"},
{kind:"About", name: "pageAbout"},
]}
@ -99,10 +102,13 @@ enyo.kind ({
case "Disassembler": idx = 0; break;
case "Assembler": idx = 1; break;
case "Hexdump": idx = 2; break;
case "Search": idx = 3; break;
case "Console": idx = 4; break;
case "Settings": idx = 5; break;
case "About": idx = 6; break;
case "Graph": idx = 3; break;
case "Search": idx = 4; break;
case "Console": idx = 5; break;
case "Logs": idx = 6; break;
case "Script": idx = 7; break;
case "Settings": idx = 8; break;
case "About": idx = 9; break;
}
//x.setContent (str);
sp.setIndex (idx);

View File

@ -1,4 +1,4 @@
enyo.kind({
enyo.kind ({
name: "Preferences",
classes: "panels-sample-sliding-content",
kind: "Scroller",
@ -12,10 +12,24 @@ enyo.kind({
{kind: "onyx.PickerDecorator", components: [
{},
{kind: "onyx.Picker", components: [
{content: "x86", active: true},
/* TODO: construct from code */
{content: "arc"},
{content: "arm"},
{content: "avr"},
{content: "ppc"},
{content: "bf"}
{content: "bf"},
{content: "dalvik"},
{content: "dcpu16"},
{content: "i8080"},
{content: "java"},
{content: "m68k"},
{content: "mips"},
{content: "msil"},
{content: "rar"},
{content: "sh"},
{content: "sparc"},
{content: "x86", active: true},
{content: "z80"},
]}
]}
]}
@ -67,4 +81,3 @@ enyo.kind({
,{tag: "div", style: "height:64px"}
]
});

View File

@ -1,34 +1,38 @@
enyo.kind ({
name: "RightPanel",
classes: "onyx onyx-toolbar",
kind: "Control",
classes: "onyx-toolbar",
kind: "Scroller",
style: "width:25px",
ra: null,
components: [
{kind: "FittableColumns", components: [
{kind: "onyx.Button", content: "[", ontap: "closeSidebar", style: "padding:8px;margin-right:8px"},
{kind: "onyx.MenuDecorator", onSelect: "itemSelected", components: [
{content: "List elements"},
{kind: "onyx.Menu", components: [
{content: "symbols", value: "1"},
{content: "imports", value: "1"},
{content: "functions", value: "1"},
{content: "comments", value: "1"},
{classes: "onyx-menu-divider"},
{content: "registers", value: "1"},
{content: "stack", value: "2"},
{content: "backtrace", value: "3"},
{classes: "onyx-menu-divider"},
{content: "flags", value: "2"},
{content: "flagspaces", value: "2"},
]}
]},
{kind: "List", name: "list", style:"height:400px", realtimeFit:false, onSetupItem: "setupItem", components: [
{kind: "onyx.Item", layoutKind: "HFlexLayout", style:"padding:0px", components: [
{tag: "h3", style:"background-color:red",name: "msg", fit:true, active: true, ontap: "rowTap"}
]}
{kind: "FittableColumns", components: [
{kind: "onyx.Button", content: "[", ontap: "closeSidebar", style: "padding:8px;margin-right:8px"},
{kind: "onyx.MenuDecorator", fit:true,onSelect: "itemSelected", components: [
{content: "List elements" },
{kind: "onyx.Menu", maxHeight:290, style:"height:300px", components: [
{content: "flags", value: "2"},
{content: "flagspaces", value: "2"},
{classes: "onyx-menu-divider"},
{content: "symbols", value: "1"},
{content: "imports", value: "1"},
{content: "functions", value: "1"},
{content: "comments", value: "1"},
{classes: "onyx-menu-divider"},
{content: "registers", value: "1"},
{content: "stack", value: "2"},
{content: "backtrace", value: "3"},
]}
]},
{tag:"br"},
{tag:"br"},
{kind: "List", name: "list", style:"height:400px", realtimeFit:true, onSetupItem: "setupItem", components: [
{kind: "onyx.Item", layoutKind: "HFlexLayout", style:"padding:0px", components: [
{name:"separator", tag: "hr", style:"height:1px;visibility:hidden"},
{kind: "onyx.Button", name: "msg", style: "width:100%", fit:true, active: true, ontap: "rowTap"}
]}
]},
{tag: "pre", style:"font-size:10px", allowHtml:true, name: "output", content:".." }
]}
]}
],
rowTap: function () {
/* do something here */
@ -40,20 +44,66 @@ enyo.kind ({
},
data: [],
setupItem: function (inSender, inIndex) {
var idx = inIndex.index;
this.$.msg.setContent (this.data[idx]);
var item = this.data[inIndex.index];
if (!item)
return false;
var msg = item.name + " "+item.offset;
console.log(msg);
this.$.msg.setContent (msg);
return true;
},
refresh: function () {
this.$.list.setCount (this.data.length);
this.$.list.refresh ();
},
itemSelected: function(inSender, inEvent) {
var self = this;
var selected = inEvent.originator.content;
switch (selected) {
case "functions":
r2.cmd ("afl", function(x) {
self.$.output.setContent (x);
});
break;
case "flagspaces":
r2.cmd("fs", function (x) {
self.$.output.setContent (x);
});
break;
case "sections":
r2.bin_sections(function (imp) {
var txt = "List of "+imp.length+"\n\n";
for (var i = 0; i<imp.length; i++)
txt += imp[i].offset + " "+ imp[i].name+"\n";
self.$.output.setContent (txt);
});
break;
case "symbols":
r2.bin_symbols(function (imp) {
var txt = "List of "+imp.length+"\n\n";
for (var i = 0; i<imp.length; i++)
txt += imp[i].offset + " "+ imp[i].name+"\n";
self.$.output.setContent (txt);
});
break;
case "imports":
r2.bin_imports (function (imp) {
var txt = "List of "+imp.length+"\n\n";
for (var i = 0; i<imp.length; i++)
txt += imp[i].offset + " "+ imp[i].name+"\n";
self.$.output.setContent (txt);
});
break;
case "flags":
r2.get_flags (function (flags) {
// trycatch here or wtf
self.data = JSON.parse (flags);
self.data = flags;
self.$.list.setCount (self.data.length);
var txt = "List of "+self.data.length+"\n\n";
for (var i = 0; i<flags.length; i++)
txt += flags[i].offset + " "+ flags[i].name+"\n";
self.$.output.setContent (txt);
self.$.list.refresh();
self.refresh();
});
break;
}

View File

@ -0,0 +1,10 @@
enyo.kind ({
name: "Script",
kind: "Scroller",
style: "background-color:#303030",
components: [
{tag: "center", components: [
{tag: "h1", style: "color:#f0f0f0", content: "TODO: Scripting"}
]}
]
});

View File

@ -4,7 +4,7 @@ enyo.kind ({
style: "background-color:#303030",
components: [
{tag: "center", components: [
{tag: "h1", style: "color:#f0f0f0", content: "TODO: Search"},
{tag: "h1", style: "color:#f0f0f0", content: "TODO: Search"}
]}
]
});

13
shlr/www/enyo/two Normal file
View File

@ -0,0 +1,13 @@
<html>
<body style="border:0;margin:0;background-color:#303030">
<table style="spacing:0;spacing:0px;border:0px;padding:0px;width:100%;height:100%">
<tr height="100%">
<td>
<iframe style="width:100%;height:100%;scroll:overflow" src="/enyo/"></iframe>
</td><td style="margin:0px;border:0">
<iframe style="width:100%;height:100%;scroll:overflow" src="/enyo/#hex"></iframe>
<td>
<tr>
<table>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 B

After

Width:  |  Height:  |  Size: 828 B

View File

@ -1,50 +1,55 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>r2-js-graph.it</title>
<title>r2 code graph</title>
<script type="text/javascript" src="js-graph-it.js"></script>
<link rel="stylesheet" type="text/css" href="js-graph-it.css" />
<link rel="stylesheet" type="text/css" href="sf-homepage.css" />
<style>
p {
white-space: pre;
font-family: monospace;
display: block;
white-space: pre;
font-family: monospace;
display: block;
}
body {
overflow:hidden;
overflow:hidden;
}
</style>
<script>
window.onresize = function () {
resizeCanvas ();
}
function Ajax (method, uri, body, fn) {
var x = new XMLHttpRequest ();
x.open (method, uri, false);
x.onreadystatechange = function (y) {
if (fn) fn (x.responseText);
}
x.send (body);
var x = new XMLHttpRequest ();
x.open (method, uri, false);
x.onreadystatechange = function (y) {
if (x.status == 200) {
if (fn) fn (x.responseText);
}
}
x.send (body);
}
function get_graph() {
Ajax ('GET', "/cmd/ag $$", '', function (x) {
document.getElementById ('mainCanvas').innerHTML = x;
setMenu ();
resizeCanvas ();
initPageObjects ();
});
Ajax ('GET', "/cmd/ag $$", '', function (x) {
document.getElementById ('mainCanvas').innerHTML = x;
setMenu ();
resizeCanvas ();
initPageObjects ();
});
}
function onLoad() {
get_graph ();
get_graph ();
}
/**
* Resizes the main canvas to the maximum visible height.
*/
function resizeCanvas() {
var divElement = document.getElementById("mainCanvas");
var screenHeight = window.innerHeight || document.body.offsetHeight;
divElement.style.height = (screenHeight - 16) + "px";
var divElement = document.getElementById("mainCanvas");
var screenHeight = window.innerHeight || document.body.offsetHeight;
divElement.style.height = (screenHeight - 16) + "px";
}
/**
@ -52,55 +57,35 @@ function resizeCanvas() {
* of the one of the current page ignoring file extension.
* Nice trick!
*/
function setMenu()
{
var url = document.location.href;
// strip extension
url = stripExtension(url);
var ulElement = document.getElementById("menu");
var links = ulElement.getElementsByTagName("A");
var i;
for(i = 0; i < links.length; i++)
{
if(url.indexOf(stripExtension(links[i].href)) == 0)
{
links[i].className = "active_menu";
return;
}
}
function setMenu() {
var url = document.location.href;
// strip extension
url = stripExtension(url);
var ulElement = document.getElementById("menu");
var links = ulElement.getElementsByTagName("A");
var i;
for(i = 0; i < links.length; i++) {
if(url.indexOf(stripExtension(links[i].href)) == 0) {
links[i].className = "active_menu";
return;
}
}
}
/**
* Strips the file extension and everything after from a url
*/
function stripExtension(url) {
var lastDotPos = url.lastIndexOf('.');
return (lastDotPos <= 0)? url:
url.substring(0, lastDotPos - 1);
}
/**
* this function opens a popup to show samples during explanations.
*/
function openSample(url) {
var popup = window.open(url, "sampleWindow", "width=400,height=300");
popup.focus();
return false;
var lastDotPos = url.lastIndexOf('.');
return (lastDotPos <= 0)? url:
url.substring (0, lastDotPos - 1);
}
</script>
</head>
<body onload="onLoad();">
<h1><a href="../"> back</a></h1>
<table class="main_table" style="height: 100%;">
<tr>
<td style="vertical-align: top; padding: 0px;">
<div id="mainCanvas" class="canvas" style="width: 100%; height: 100%;"></div>
</td>
<td width="1" style="vertical-align: top;" class="menu">
<ul id="menu"> </ul>
</td>
</tr>
</table>
<div id="menu"></div>
<div id="mainCanvas" class="canvas" style="width:100%;height:100%;"></div>
<div style="z-index:99999;top:0px;left:5px;position:absolute"><h1><a href="../">back</a></h1></div>
</body>
</html>

View File

@ -1,24 +1,21 @@
.draggable
{
position: absolute;
cursor: move;
z-index: 1;
.draggable {
position: absolute;
cursor: move;
z-index: 1;
}
.connector
{
background-color: black;
.connector {
background-color: red;
}
.dock_point
{
height: 1px;
width: 1px;
overflow: hidden;
padding: 0px !important;
border: none !important;
margin: 0px !important;
position: absolute;
font-size: 1px;
visibility: hidden;
}
.dock_point {
height: 1px;
width: 1px;
overflow: hidden;
padding: 0px !important;
border: none !important;
margin: 0px !important;
position: absolute;
font-size: 1px;
visibility: hidden;
}

View File

@ -108,7 +108,8 @@ function movemouse(e) {
var i;
for(i = 0; i < blocksToMove.length; i++) {
blocksToMove[i].onMove();
if (blocksToMove[i])
blocksToMove[i].onMove();
}
return false;
}
@ -614,22 +615,17 @@ function Segment(id, parentElement)
* If another segment is already appended to this, cascades the operation so
* the given next segment will be appended to the tail of the segments chain.
*/
this.append = function(nextSegment)
{
this.append = function(nextSegment) {
if(!nextSegment)
return;
if(!this.nextSegment)
{
if(!this.nextSegment) {
this.nextSegment = nextSegment;
this.nextSegment.startX = this.getEndX();
this.nextSegment.startY = this.getEndY();
}
else
this.nextSegment.append(nextSegment);
} else this.nextSegment.append(nextSegment);
}
this.detach = function()
{
this.detach = function() {
var s = this.nextSegment;
this.nextSegment = null;
return s;
@ -638,8 +634,7 @@ function Segment(id, parentElement)
/**
* hides this segment and all the following
*/
this.cascadeHide = function()
{
this.cascadeHide = function() {
this.visible = false;
if(this.nextSegment)
this.nextSegment.cascadeHide();
@ -822,13 +817,10 @@ function Connector(htmlElement, canvas)
var segment;
// if the pool contains more objects, borrow the segment, create it otherwise
if(this.segmentsPool)
{
if(this.segmentsPool) {
segment = this.segmentsPool;
this.segmentsPool = this.segmentsPool.detach();
}
else
{
} else {
segment = new Segment(this.id + "_" + (this.segmentsNumber + 1), this.canvas.htmlElement);
segment.htmlElement.className = this.connectorClass;
if(!getStyle(segment.htmlElement, 'background-color'))

6
shlr/www/graph/make.sh Normal file
View File

@ -0,0 +1,6 @@
cd img
for a in *.gif ; do
printf '<img src="data:image/png;base64,'
printf "%s" `base64 $a | tr '\r' ' '`
echo '" alt="'$a'">'
done

View File

@ -43,7 +43,7 @@ body {
font-family: verdana;
font-size: 11px;
color: #33333F;
padding: 3px;
padding: 0px;
margin: 0px;
background-color: black;
}

View File

@ -94,7 +94,7 @@ var nl = "<br />";
var nl2 = "<br /><br />";
function show_popup_about () {
var txt =
"<a href='/new/'>Try new UI</a> (<a href='/new/two'>two panels</a>)<br />"+
"<a href='/enyo/'>Try new UI</a> (<a href='/enyo/two'>two panels</a>)<br />"+
"<a href='/d3/'>Try call graph d3</a><br />"+
"<table class='popup_content'><tr><td valign=top>"+
"Display"+