aboutsummaryrefslogtreecommitdiff
path: root/source/tools/disasm.c
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2020-05-24 16:48:22 +0200
committerToni Uhlig <matzeton@googlemail.com>2020-05-25 21:57:14 +0200
commit31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch)
tree16e789c7d68608831b498f41f54d9482b82a711a /source/tools/disasm.c
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'source/tools/disasm.c')
-rw-r--r--source/tools/disasm.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/source/tools/disasm.c b/source/tools/disasm.c
new file mode 100644
index 0000000..9e5489d
--- /dev/null
+++ b/source/tools/disasm.c
@@ -0,0 +1,234 @@
+// diStorm64 library sample
+// http://ragestorm.net/distorm/
+// Arkon, Stefan, 2005
+// Mikhail, 2006
+// JvW, 2007
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+// For the compilers who don't have sysexits.h, which is not an ISO/ANSI include!
+#define EX_OK 0
+#define EX_USAGE 64
+#define EX_DATAERR 65
+#define EX_NOINPUT 66
+#define EX_NOUSER 67
+#define EX_NOHOST 68
+#define EX_UNAVAILABLE 69
+#define EX_SOFTWARE 70
+#define EX_OSERR 71
+#define EX_OSFILE 72
+#define EX_CANTCREAT 73
+#define EX_IOERR 74
+#define EX_TEMPFAIL 75
+#define EX_PROTOCOL 76
+#define EX_NOPERM 77
+#define EX_CONFIG 78
+
+#include "distorm/distorm.h"
+#include "distorm/mnemonics.h"
+#include "disasm.h"
+
+// The number of the array of instructions the decoder function will use to return the disassembled instructions.
+// Play with this value for performance...
+#define MAX_INSTRUCTIONS (1000)
+
+
+int main(int argc, char **argv)
+{
+ // Holds the result of the decoding.
+ _DecodeResult res;
+ // next is used for instruction's offset synchronization.
+ // decodedInstructionsCount holds the count of filled instructions' array by the decoder.
+ unsigned int decodedInstructionsCount = 0, i, next;
+
+ // Default decoding mode is 32 bits, could be set by command line.
+ _DecodeType dt = Decode32Bits;
+
+ // Default offset for buffer is 0, could be set in command line.
+ _OffsetType offset = 0;
+ char* errch = NULL;
+
+ // Handling file.
+ FILE* f;
+ unsigned long filesize = 0, bytesread = 0;
+ unsigned long long bytesproc = 0, maxbytesproc = (unsigned long long)-1;
+ struct stat st;
+
+ // Buffer to disassemble.
+ unsigned char *buf, *buf2;
+
+ int opt, show_usage_and_die = 0, use_internal_decode = 0;
+ char *filename = NULL;
+ while ((opt = getopt(argc, argv, "b:f:m:ip:")) != -1) {
+ switch (opt) {
+ case 'b':
+ if (strncmp(optarg, "16", 2) == 0) {
+ dt = Decode16Bits;
+ } else if (strncmp(optarg, "32", 2) == 0) {
+ dt = Decode32Bits;
+ } else if (strncmp(optarg, "64", 2) == 0) {
+ dt = Decode64Bits;
+ } else {
+ show_usage_and_die = 1;
+ }
+ break;
+ case 'f':
+ filename = strdup(optarg);
+ break;
+ case 'm':
+#ifdef SUPPORT_64BIT_OFFSET
+ offset = strtoull(optarg, &errch, 16);
+#else
+ offset = strtoul(optarg, &errch, 16);
+#endif
+ break;
+ case 'i':
+ use_internal_decode = 1;
+ break;
+ case 'p':
+ maxbytesproc = strtoull(optarg, &errch, 16);
+ break;
+ }
+ }
+
+ // Check params.
+ if (show_usage_and_die || !filename) {
+ printf("Usage: %s -i -b[16|32|64] -f[filename] -m[memory offset] -p[memory size]\r\n\tRaw disassembler output.\r\n\tMemory offset is origin of binary file in memory (address in hex).\r\n\tDefault decoding mode is -b32.\r\n\texample: %s -b16 demo.com 789a\r\n\tUse internal decoding with -i\r\n", argv[0], argv[0]);
+ return EX_USAGE;
+ }
+
+ f = fopen(filename, "rb");
+ if (f == NULL) {
+ perror("fopen");
+ return EX_NOINPUT;
+ }
+
+ if (fstat(fileno(f), &st) != 0) {
+ perror("fstat");
+ fclose(f);
+ return EX_NOINPUT;
+ }
+ filesize = st.st_size;
+
+ // We read the whole file into memory in order to make life easier,
+ // otherwise we would have to synchronize the code buffer as well (so instructions won't be split).
+ buf2 = buf = malloc(filesize);
+ if (buf == NULL) {
+ perror("File too large.");
+ fclose(f);
+ return EX_UNAVAILABLE;
+ }
+ bytesread = fread(buf, 1, filesize, f);
+ if (bytesread != filesize) {
+ perror("Can't read file into memory.");
+ free(buf);
+ fclose(f);
+ return EX_IOERR;
+ }
+
+ fclose(f);
+
+ buf += offset;
+ filesize -= offset;
+
+ printf("bits: %d\nfilename:%s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, filename);
+#ifdef SUPPORT_64BIT_OFFSET
+ if (dt != Decode64Bits) printf("%" PRIx64 "\n", offset);
+ else printf("%" PRIx64 "\n", offset);
+#else
+ printf("%08x\n", offset);
+#endif
+ printf("size: %" PRIx64 "\n", maxbytesproc);
+
+ if (use_internal_decode) {
+ _DInst instData[MAX_INSTRUCTIONS];
+ while (1) {
+ res = disasm(offset, (const unsigned char*)buf, filesize, dt, instData, MAX_INSTRUCTIONS, &decodedInstructionsCount);
+ for (i = 0; i < decodedInstructionsCount; i++) {
+#ifdef SUPPORT_64BIT_OFFSET
+ printf("%" PRIx64 " (%" PRIu32 ") %04" PRIx16, (uint64_t)instData[i].addr, instData[i].size, instData[i].opcode);
+#else
+ printf("%08x (%02d) %04" PRIx16, instData[i].addr, instData[i].size, instData[i].opcode);
+#endif
+ _InstructionType optype = instData[i].opcode;
+ switch (optype) {
+ case I_DEC: printf("\tDEC"); break;
+ case I_INC: printf("\tINC"); break;
+ case I_ADD: printf("\tADD"); break;
+ case I_SUB: printf("\tSUB"); break;
+ case I_MOV: printf("\tMOV"); break;
+ case I_PUSH: printf("\tPUSH"); break;
+ case I_POP: printf("\tPOP"); break;
+ case I_NOP: printf("\tNOP"); break;
+ case I_JMP: printf("\tJMP"); break;
+ case I_JMP_FAR: printf("\tJMP FAR"); break;
+ case I_CALL: printf("\tCALL"); break;
+ case I_CALL_FAR: printf("\tCALL FAR"); break;
+ case I_RET: printf("\tRET"); break;
+ }
+ printf("\r\n");
+ bytesproc += instData[i].size;
+ if (bytesproc >= maxbytesproc) break;
+ }
+
+ if (res == DECRES_SUCCESS) break;
+ else if (decodedInstructionsCount == 0) break;
+ if (bytesproc >= maxbytesproc) break;
+ next = (unsigned int)(instData[decodedInstructionsCount-1].addr - offset);
+ next += instData[decodedInstructionsCount-1].size;
+ buf += next;
+ filesize -= next;
+ offset += next;
+ }
+ } else {
+ // Decoded instruction information.
+ _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
+ // Decode the buffer at given offset (virtual address).
+ while (1) {
+ // If you get an undefined reference linker error for the following line,
+ // change the SUPPORT_64BIT_OFFSET in distorm.h.
+ res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
+ if (res == DECRES_INPUTERR) {
+ // Null buffer? Decode type not 16/32/64?
+ fputs("Input error, halting!\n", stderr);
+ free(buf2);
+ return EX_SOFTWARE;
+ }
+
+ for (i = 0; i < decodedInstructionsCount; i++) {
+#ifdef SUPPORT_64BIT_OFFSET
+ printf("%" PRIx64 " (%" PRIu64 ") %-24s %s%s%s\r\n", decodedInstructions[i].offset, (long long unsigned int)decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
+#else
+ printf("%08x (%02d) %-24s %s%s%s\r\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
+#endif
+ bytesproc += decodedInstructions[i].size;
+ if (bytesproc >= maxbytesproc) break;
+ }
+
+ if (res == DECRES_SUCCESS) break; // All instructions were decoded.
+ else if (decodedInstructionsCount == 0) break;
+ if (bytesproc >= maxbytesproc) break;
+
+ // Synchronize:
+ next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset);
+ next += decodedInstructions[decodedInstructionsCount-1].size;
+ // Advance ptr and recalc offset.
+ buf += next;
+ filesize -= next;
+ offset += next;
+ }
+ }
+
+ free(filename);
+ // Release buffer
+ free(buf2);
+
+ return EX_OK;
+}