radare2/libr/egg/egg.c

235 lines
5.6 KiB
C
Raw Normal View History

/* radare - LGPL - Copyright 2011 pancake<@nopcode.org> */
#include <r_egg.h>
extern REggEmit emit_x86;
extern REggEmit emit_x64;
extern REggEmit emit_arm;
extern REggEmit emit_trace;
R_API REgg *r_egg_new () {
REgg *egg = R_NEW0 (REgg);
egg->src = r_buf_new ();
egg->buf = r_buf_new ();
egg->bin = r_buf_new ();
egg->emit = &emit_x86;
egg->syscall = r_syscall_new ();
egg->rasm = r_asm_new ();
egg->bits = 0;
egg->endian = 0;
return egg;
}
R_API char *r_egg_to_string (REgg *egg) {
return strdup ((const char *)egg->buf->buf);
}
R_API void r_egg_free (REgg *egg) {
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
r_buf_free (egg->src);
r_buf_free (egg->buf);
r_buf_free (egg->bin);
r_asm_free (egg->rasm);
r_syscall_free (egg->syscall);
free (egg);
}
R_API void r_egg_reset (REgg *egg) {
r_egg_lang_include_init (egg);
r_buf_free (egg->src);
r_buf_free (egg->buf);
egg->src = r_buf_new ();
egg->buf = r_buf_new ();
}
R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
egg->emit = NULL;
egg->os = os? r_str_hash (os): R_EGG_OS_DEFAULT;
if (!strcmp (arch, "x86")) {
switch (bits) {
case 32:
r_syscall_setup (egg->syscall, arch, os, bits);
egg->emit = &emit_x86;
egg->bits = bits;
break;
case 64:
r_syscall_setup (egg->syscall, arch, os, bits);
egg->emit = &emit_x64;
egg->bits = bits;
break;
}
} else
if (!strcmp (arch, "arm")) {
switch (bits) {
case 16:
case 32:
r_syscall_setup (egg->syscall, arch, os, bits);
egg->emit = &emit_arm;
egg->bits = bits;
egg->endian = endian;
break;
}
} else
if (!strcmp (arch, "trace")) {
//r_syscall_setup (egg->syscall, arch, os, bits);
egg->emit = &emit_trace;
egg->bits = bits;
egg->endian = endian;
}
if (egg->emit) {
if (egg->emit->init)
egg->emit->init (egg);
return 1;
}
return 0;
}
R_API int r_egg_include(REgg *egg, const char *file, int format) {
char *foo = r_file_slurp (file, NULL);
if (!foo)
return 0;
switch (format) {
case 'r': // raw
// TODO: append ("\x102030202303203202", n);
// TODO: r_buf_append_bytes (egg->buf, (const ut8*)foo, strlen (foo));
break;
case 'a': // assembly
r_buf_append_bytes (egg->buf, (const ut8*)foo, strlen (foo));
break;
default:
r_buf_append_bytes (egg->src, (const ut8*)foo, strlen (foo));
}
free (foo);
return 1;
}
R_API void r_egg_load(REgg *egg, const char *code, int format) {
switch (format) {
case 'a': // assembly
r_buf_append_bytes (egg->buf, (const ut8*)code, strlen (code));
break;
default:
r_buf_append_bytes (egg->src, (const ut8*)code, strlen (code));
break;
}
}
R_API void r_egg_syscall(REgg *egg, const char *arg, ...) {
RSyscallItem *item = r_syscall_get (egg->syscall,
r_syscall_get_num (egg->syscall, arg), -1);
if (!strcmp (arg, "close")) {
//egg->emit->syscall_args ();
}
egg->emit->syscall (egg, item->num);
}
R_API void r_egg_alloc(REgg *egg, int n) {
// add esp, n
}
R_API void r_egg_label(REgg *egg, const char *name) {
r_egg_printf (egg, "%s:\n", name);
}
2011-07-27 08:30:23 +00:00
R_API void r_egg_math (REgg *egg) {//, char eq, const char *vs, char type, const char *sr
// TODO
//e->mathop (egg, op, type, eq, p);
}
R_API void r_egg_raw(REgg *egg, const ut8 *b, int len) {
}
// r_egg_block (egg, FRAME | IF | ELSE | ENDIF | FOR | WHILE, sz)
R_API void r_egg_if(REgg *egg, const char *reg, char cmp, int v) {
// egg->depth++;
}
R_API void r_egg_printf(REgg *egg, const char *fmt, ...) {
va_list ap;
int len;
char buf[1024];
va_start (ap, fmt);
len = vsnprintf (buf, sizeof (buf), fmt, ap);
r_buf_append_bytes (egg->buf, (const ut8*)buf, len);
va_end (ap);
}
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
R_API int r_egg_assemble(REgg *egg) {
if (egg->emit == &emit_x86 || egg->emit == &emit_x64) {
RAsmCode *asmcode;
char *code;
//rasm2
r_asm_use (egg->rasm, "x86.nz");
r_asm_set_bits (egg->rasm, egg->bits);
r_asm_set_big_endian (egg->rasm, 0);
r_asm_set_syntax (egg->rasm, R_ASM_SYNTAX_INTEL);
code = r_buf_to_string (egg->buf);
asmcode = r_asm_massemble (egg->rasm, code);
if (asmcode && asmcode->len > 0) {
r_buf_append_bytes (egg->bin, asmcode->buf, asmcode->len);
// LEAK r_asm_code_free (asmcode);
} else eprintf ("fail assembling\n");
free (code);
return (asmcode != NULL);
} else
if (egg->emit == &emit_arm) {
RAsmCode *asmcode;
char *code;
//rasm2
r_asm_use (egg->rasm, "arm");
r_asm_set_bits (egg->rasm, egg->bits);
r_asm_set_big_endian (egg->rasm, egg->endian); // XXX
r_asm_set_syntax (egg->rasm, R_ASM_SYNTAX_INTEL);
code = r_buf_to_string (egg->buf);
asmcode = r_asm_massemble (egg->rasm, code);
if (asmcode) {
r_buf_append_bytes (egg->bin, asmcode->buf, asmcode->len);
// LEAK r_asm_code_free (asmcode);
}
free (code);
return (asmcode != NULL);
}
return R_FALSE;
}
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
R_API int r_egg_compile(REgg *egg) {
const char *b = (const char *)egg->src->buf;
if (!b || !egg->emit)
return R_FALSE;
for (; *b; b++) {
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
r_egg_lang_parsechar (egg, *b);
// XXX: some parse fail errors are false positives :(
}
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
// TODO: handle errors here
return R_TRUE;
}
R_API RBuffer *r_egg_get_bin(REgg *egg) {
// TODO increment reference
return egg->bin;
}
//R_API int r_egg_dump (REgg *egg, const char *file) { }
R_API char *r_egg_get_source(REgg *egg) {
return r_buf_to_string (egg->src);
}
R_API char *r_egg_get_assembly(REgg *egg) {
return r_buf_to_string (egg->buf);
}
2011-07-27 08:30:23 +00:00
R_API void r_egg_append(REgg *egg, const char *src) {
r_buf_append_bytes (egg->src, (const ut8*)src, strlen (src));
}
/* JIT : TODO: accept arguments here */
R_API int r_egg_run(REgg *egg) {
int ret, (*ptr)() = malloc (egg->bin->length);
memcpy (ptr, egg->bin->buf, egg->bin->length);
r_mem_protect (ptr, egg->bin->length, "rx");
ret = ptr ();
free (ptr);
return ret;
}