Files

322 lines
6.9 KiB
C

/* cmd.c - MIT - Copyright 2009-2023 -- pancake /at/ nopcode /dot/ org */
#ifndef HAVE_SYSTEM
#define HAVE_SYSTEM 1
#endif
#define USE_DISASM 1
#if USE_DISASM_X86
#include "dis/x86.c"
#elif USE_DISASM_X32
#include "dis/x32.c"
#elif USE_DISASM_8086
#include "dis/8086.c"
#elif USE_DISASM_ARM
#include "dis/arm.c"
#elif USE_DISASM_M68K
// #define M68030 1
// #define M68020 1
// #define M68010 1
#include "dis/m68k.c"
#else
#undef USE_DISASM
#define USE_DISASM 0
#endif
static int cmd_hexdump(const char *arg) {
int len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(buf && len>0) {
hexdump(buf, len, 16);
free(buf);
return 1;
}
return 2;
}
static int cmd_print(const char *arg) {
ut8 *buf;
int len = bsize;
if(*arg) {
buf = getcurblk(arg, &len);
if(!buf) return 2;
print_fmt(buf, arg, len);
free(buf);
} else printf(
"ob/wW/dD/qQ byte (oct,hex), word, dword, qword (lil, big endian)\n"
"i/I/f/F int32 (lil, big), float (lil, big)\n"
"s/S short int16 (lil, big)\n"
"z/Z zero-terminatted string (ascii, wide-ascii)\n"
"./:/* skip 1 or 4 chars, repeat last format instead of cycle\n");
return 1;
}
static int cmd_system(const char *arg) {
int len = bsize;
char str[1024];
ut8 *buf;
if(strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "wb");
if(fd) {
if((buf = getcurblk("", &len))) {
setenv("BLOCK", ".curblk", 1);
fwrite(buf, len, 1, fd);
free(buf);
}
fclose(fd);
}
}
if(strstr(arg, "BSIZE")) {
sprintf(str, "%d", len);
setenv("BSIZE", str, 1);
}
if(strstr(arg, "OFFSET")) {
sprintf(str, "%"LLF"d", curseek);
setenv("OFFSET", str, 1);
}
if(strstr(arg, "XOFFSET")) {
sprintf(str, "0x%"LLF"x", curseek);
setenv("XOFFSET", str, 1);
}
#if HAVE_SYSTEM
if(io_system(arg)<0)
perror("system");
#endif
unlink(".curblk");
return 1;
}
#if USE_DISASM
static int cmd_disasm(const char *arg) {
char output[256];
int i, j, len = bsize, ilen;
int pad = 8;
ut8 *buf = getcurblk(arg, &len);
if (!buf) {
return 2;
}
for(i = 0; i < len ;i++) {
*output = 0;
ilen = disasm(buf + i, len - i, curseek+i, output);
printf("0x%08"LLF"x ", curseek+i);
pad = 10;
if (ilen > 0) {
pad -= ilen;
for(j=i;j < i+ilen && j < len;j++)
printf("%02x", buf[j]);
i += ilen - 1;
if (pad > 0)
for (j = i; j< i+pad;j++)
printf(" ");
} else {
strcpy(output, "invalid");
}
printf("%s\n", output);
}
free(buf);
return 1;
}
#else
static int cmd_disasm(const char *arg) {
return cmd_system("echo X | r0 -n $BLOCK | rasm2 -o $OFFSET -D -"); // |head -n $(($LINES-1))");
}
#endif
static int cmd_bytedump(const char *arg) {
int i, len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(!buf) return 2;
for(i=0;i<len;i++)
printf("%02x", buf[i]);
printf("\n");
free(buf);
return 1;
}
static int cmd_search(const char *arg) {
ut8 *buf, *barg;
size_t len;
int i, hit = 0;
SKIPSPACES(arg);
if(*arg=='"') {
arg++;
barg = (ut8*)strdup(arg);
len = strlen((const char *)barg)-1;
// TODO: ensure last char is '"'
barg[len]='\0';
} else {
barg = (ut8*)strdup(arg);
len = hexstr2raw(barg);
}
if((buf = getcurblk("", &bsize)))
do {
for(i=0;i<bsize;i++) {
if(barg[hit++]!=buf[i]) hit = 0;
else if(hit == len)
printf("0x%"LLF"x\n", curseek+i-len+1);
}
curseek += bsize;
} while(io_read(buf, bsize)>0);
free(buf);
free(barg);
return 1;
}
static int cmd_bsize(const char *arg) {
if(!*arg) printf("%d\n", bsize);
else if(*arg=='+') bsize += (int)calc(arg+1);
else if(*arg=='-') bsize -= (int)calc(arg+1);
else bsize = calc(arg);
if(bsize<1) bsize = 1;
obsize = bsize;
return 1;
}
static int cmd_seek(const char *arg) {
if(!*arg) printf("%"LLF"d\n", curseek);
else if(*arg=='+') curseek += calc(arg+1);
else if(*arg=='-') curseek -= calc(arg+1);
else curseek = calc(arg);
io_seek((oldseek=curseek), 0);
return 1;
}
static int cmd_dump(const char *file) {
int len = bsize;
ut8 *buf = getcurblk("", &len);
if(len<1 || buf) {
FILE *fd = fopen(file, "wb");
if (!fd) {
free (buf);
return -1;
}
if(fwrite(buf, len, 1, fd)<len) {
perror("fwrite");
return -1;
}
fclose(fd);
free(buf);
} else perror("getcurblk");
return 1;
}
static int cmd_load(const char *file) {
FILE *fd = fopen(file, "rb");
if(fd) {
void *buf = malloc(bsize);
if(bsize>0 && buf) {
int len = fread(buf, 1, bsize, fd);
if(len<bsize)
perror("fread");
io_seek (curseek, SEEK_SET);
if(io_write(buf, len)<len) {
perror("io_write");
return -1;
}
} else perror("malloc");
free(buf);
fclose(fd);
} else perror("fopen");
return 1;
}
static int cmd_write(const char *arg) {
ut8 *barg;
int len;
SKIPSPACES(arg);
if(*arg=='"') {
barg = (ut8*)strdup (arg+1);
len = strlen(++arg)-1;
// TODO: ensure last char is "
barg[len] = '\0';
} else {
barg = (ut8*)strdup (arg);
len = hexstr2raw(barg);
}
if (len<2) {
printf ("Invalid hexpair\n");
return 2;
}
io_seek(curseek, SEEK_SET);
if(io_write(barg, len)<len) {
perror("io_write");
return -1;
}
//free ((void*)arg);
return 1;
}
static int cmd_help(const char *arg) {
if(*arg) {
ut64 ret = r_num_calc (NULL, arg, NULL);
printf("0x%"LLF"x %"LLF"d 0%"LLF"o\n", ret, ret, ret);
} else printf(
"s[+-addr] seek to relative or absolute address\n"
"b[+-size] change block size\n"
"w[hex|\"str\"] write hexpair or string\n"
"/[hex|\"str\"] search hexpair or string\n"
"x[size] hexdump\n"
"d[size] disassemble n bytes\n"
"X[size] hexpair dump\n"
"p[fmt] print formatted current block ('p' for help)\n"
"d[size] disasemble\n"
"r[+-[num]] truncate or -remove N bytes\n"
".[file] interpret file\n"
"<[file] load file in current seek\n"
">[file] dump current block to file\n"
"!cmd run shell command\n"
"?expr calculate numeric expression\n"
"q quit\n");
return 1;
}
static int cmd_resize(const char *arg) {
ut8 *buf;
ut64 tail, n;
int i, len, ret = 0;
switch(*arg) {
case '\0':
printf("%"LLF"d\n", (ut64)io_seek(0, SEEK_END));
break;
case '+': // XXX: needs cleanup
n = calc(arg+1);
len = (ut64)io_seek(0, SEEK_END);
tail = len-curseek;
if((buf=malloc(tail))) { // XXX: Use block
io_seek(curseek, SEEK_SET);
i = io_read(buf, tail);
if (i > 0) {
io_seek(curseek+n, SEEK_SET);
if (io_write(buf, tail) < 1)
perror ("write");
free (buf);
}
} else perror("malloc");
break;
case '-':
buf = malloc(bsize);
if(buf) {
n = calc(arg+1);
for(i=0;!ret;i+=len) {
io_seek(curseek+n+i, SEEK_SET);
if((len = io_read(buf, bsize))>0) {
io_seek(curseek+i, SEEK_SET);
if(io_write(buf, len)<len)
perror("io_write"),ret=-1;
} else break; //perror("io_read"), ret=-1;
}
free(buf);
if((ret = io_seek(0, SEEK_END))>n)
ret = io_truncate(ret-n);
} else perror("malloc");
break;
default:
ret = io_truncate(calc(arg));
}
if(ret<0) perror("truncate");
return 1;
}