diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-12 15:14:36 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-12 15:14:36 +0900 |
commit | 993d65531741fccf26fc10fc5789a5c9fca8c5ae (patch) | |
tree | 996be9095a97ff2aac0d98963b6044d47a0ec60c /ndisasm.c | |
parent | 65c26d26fb72cec0d43d199c72ed27513d17f4c9 (diff) | |
download | nasm-993d65531741fccf26fc10fc5789a5c9fca8c5ae.tar.gz nasm-993d65531741fccf26fc10fc5789a5c9fca8c5ae.tar.bz2 nasm-993d65531741fccf26fc10fc5789a5c9fca8c5ae.zip |
Tizen 2.1 basesubmit/tizen_2.2/20130710.072957submit/tizen_2.1/20130423.103612accepted/tizen_2.1/20130423.1515012.1b_releasetizen_2.1
Diffstat (limited to 'ndisasm.c')
-rw-r--r-- | ndisasm.c | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/ndisasm.c b/ndisasm.c new file mode 100644 index 0000000..710d1f0 --- /dev/null +++ b/ndisasm.c @@ -0,0 +1,390 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * ndisasm.c the Netwide Disassembler main module + */ + +#include "compiler.h" + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> + +#include "insns.h" +#include "nasm.h" +#include "nasmlib.h" +#include "sync.h" +#include "disasm.h" + +#define BPL 8 /* bytes per line of hex dump */ + +static const char *help = + "usage: ndisasm [-a] [-i] [-h] [-r] [-u] [-b bits] [-o origin] [-s sync...]\n" + " [-e bytes] [-k start,bytes] [-p vendor] file\n" + " -a or -i activates auto (intelligent) sync\n" + " -u same as -b 32\n" + " -b 16, -b 32 or -b 64 sets the processor mode\n" + " -h displays this text\n" + " -r or -v displays the version number\n" + " -e skips <bytes> bytes of header\n" + " -k avoids disassembling <bytes> bytes from position <start>\n" + " -p selects the preferred vendor instruction set (intel, amd, cyrix, idt)\n"; + +static void output_ins(uint32_t, uint8_t *, int, char *); +static void skip(uint32_t dist, FILE * fp); + +static void ndisasm_verror(int severity, const char *fmt, va_list va) +{ + vfprintf(stderr, fmt, va); + + if (severity & ERR_FATAL) + exit(1); +} + +int main(int argc, char **argv) +{ + char buffer[INSN_MAX * 2], *p, *ep, *q; + char outbuf[256]; + char *pname = *argv; + char *filename = NULL; + uint32_t nextsync, synclen, initskip = 0L; + int lenread; + int32_t lendis; + bool autosync = false; + int bits = 16, b; + bool eof = false; + uint32_t prefer = 0; + bool rn_error; + int32_t offset; + FILE *fp; + + tolower_init(); + nasm_set_verror(ndisasm_verror); + nasm_init_malloc_error(); + + offset = 0; + init_sync(); + + while (--argc) { + char *v, *vv, *p = *++argv; + if (*p == '-' && p[1]) { + p++; + while (*p) + switch (nasm_tolower(*p)) { + case 'a': /* auto or intelligent sync */ + case 'i': + autosync = true; + p++; + break; + case 'h': + fputs(help, stderr); + return 0; + case 'r': + case 'v': + fprintf(stderr, + "NDISASM version %s compiled on %s\n", + nasm_version, nasm_date); + return 0; + case 'u': /* -u for -b 32, -uu for -b 64 */ + if (bits < 64) + bits <<= 1; + p++; + break; + case 'b': /* bits */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-b' requires an argument\n", + pname); + return 1; + } + b = strtoul(v, &ep, 10); + if (*ep || !(bits == 16 || bits == 32 || bits == 64)) { + fprintf(stderr, "%s: argument to `-b' should" + " be 16, 32 or 64\n", pname); + } else { + bits = b; + } + p = ""; /* force to next argument */ + break; + case 'o': /* origin */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-o' requires an argument\n", + pname); + return 1; + } + offset = readnum(v, &rn_error); + if (rn_error) { + fprintf(stderr, + "%s: `-o' requires a numeric argument\n", + pname); + return 1; + } + p = ""; /* force to next argument */ + break; + case 's': /* sync point */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-s' requires an argument\n", + pname); + return 1; + } + add_sync(readnum(v, &rn_error), 0L); + if (rn_error) { + fprintf(stderr, + "%s: `-s' requires a numeric argument\n", + pname); + return 1; + } + p = ""; /* force to next argument */ + break; + case 'e': /* skip a header */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-e' requires an argument\n", + pname); + return 1; + } + initskip = readnum(v, &rn_error); + if (rn_error) { + fprintf(stderr, + "%s: `-e' requires a numeric argument\n", + pname); + return 1; + } + p = ""; /* force to next argument */ + break; + case 'k': /* skip a region */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-k' requires an argument\n", + pname); + return 1; + } + vv = strchr(v, ','); + if (!vv) { + fprintf(stderr, + "%s: `-k' requires two numbers separated" + " by a comma\n", pname); + return 1; + } + *vv++ = '\0'; + nextsync = readnum(v, &rn_error); + if (rn_error) { + fprintf(stderr, + "%s: `-k' requires numeric arguments\n", + pname); + return 1; + } + synclen = readnum(vv, &rn_error); + if (rn_error) { + fprintf(stderr, + "%s: `-k' requires numeric arguments\n", + pname); + return 1; + } + add_sync(nextsync, synclen); + p = ""; /* force to next argument */ + break; + case 'p': /* preferred vendor */ + v = p[1] ? p + 1 : --argc ? *++argv : NULL; + if (!v) { + fprintf(stderr, "%s: `-p' requires an argument\n", + pname); + return 1; + } + if (!strcmp(v, "intel")) { + prefer = 0; /* Default */ + } else if (!strcmp(v, "amd")) { + prefer = IF_AMD | IF_3DNOW; + } else if (!strcmp(v, "cyrix")) { + prefer = IF_CYRIX | IF_3DNOW; + } else if (!strcmp(v, "idt") || !strcmp(v, "centaur") + || !strcmp(v, "winchip")) { + prefer = IF_3DNOW; + } else { + fprintf(stderr, + "%s: unknown vendor `%s' specified with `-p'\n", + pname, v); + return 1; + } + p = ""; /* force to next argument */ + break; + default: /*bf */ + fprintf(stderr, "%s: unrecognised option `-%c'\n", + pname, *p); + return 1; + } + } else if (!filename) { + filename = p; + } else { + fprintf(stderr, "%s: more than one filename specified\n", + pname); + return 1; + } + } + + if (!filename) { + fprintf(stderr, help, pname); + return 0; + } + + if (strcmp(filename, "-")) { + fp = fopen(filename, "rb"); + if (!fp) { + fprintf(stderr, "%s: unable to open `%s': %s\n", + pname, filename, strerror(errno)); + return 1; + } + } else + fp = stdin; + + if (initskip > 0) + skip(initskip, fp); + + /* + * This main loop is really horrible, and wants rewriting with + * an axe. It'll stay the way it is for a while though, until I + * find the energy... + */ + + p = q = buffer; + nextsync = next_sync(offset, &synclen); + do { + uint32_t to_read = buffer + sizeof(buffer) - p; + if ((nextsync || synclen) && + to_read > nextsync - offset - (p - q)) + to_read = nextsync - offset - (p - q); + if (to_read) { + lenread = fread(p, 1, to_read, fp); + if (lenread == 0) + eof = true; /* help along systems with bad feof */ + } else + lenread = 0; + p += lenread; + if ((nextsync || synclen) && + (uint32_t)offset == nextsync) { + if (synclen) { + fprintf(stdout, "%08"PRIX32" skipping 0x%"PRIX32" bytes\n", + offset, synclen); + offset += synclen; + skip(synclen, fp); + } + p = q = buffer; + nextsync = next_sync(offset, &synclen); + } + while (p > q && (p - q >= INSN_MAX || lenread == 0)) { + lendis = + disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits, + offset, autosync, prefer); + if (!lendis || lendis > (p - q) + || ((nextsync || synclen) && + (uint32_t)lendis > nextsync - offset)) + lendis = eatbyte((uint8_t *) q, outbuf, sizeof(outbuf), bits); + output_ins(offset, (uint8_t *) q, lendis, outbuf); + q += lendis; + offset += lendis; + } + if (q >= buffer + INSN_MAX) { + uint8_t *r = (uint8_t *) buffer, *s = (uint8_t *) q; + int count = p - q; + while (count--) + *r++ = *s++; + p -= (q - buffer); + q = buffer; + } + } while (lenread > 0 || !(eof || feof(fp))); + + if (fp != stdin) + fclose(fp); + + return 0; +} + +static void output_ins(uint32_t offset, uint8_t *data, + int datalen, char *insn) +{ + int bytes; + fprintf(stdout, "%08"PRIX32" ", offset); + + bytes = 0; + while (datalen > 0 && bytes < BPL) { + fprintf(stdout, "%02X", *data++); + bytes++; + datalen--; + } + + fprintf(stdout, "%*s%s\n", (BPL + 1 - bytes) * 2, "", insn); + + while (datalen > 0) { + fprintf(stdout, " -"); + bytes = 0; + while (datalen > 0 && bytes < BPL) { + fprintf(stdout, "%02X", *data++); + bytes++; + datalen--; + } + fprintf(stdout, "\n"); + } +} + +/* + * Skip a certain amount of data in a file, either by seeking if + * possible, or if that fails then by reading and discarding. + */ +static void skip(uint32_t dist, FILE * fp) +{ + char buffer[256]; /* should fit on most stacks :-) */ + + /* + * Got to be careful with fseek: at least one fseek I've tried + * doesn't approve of SEEK_CUR. So I'll use SEEK_SET and + * ftell... horrible but apparently necessary. + */ + if (fseek(fp, dist + ftell(fp), SEEK_SET)) { + while (dist > 0) { + uint32_t len = (dist < sizeof(buffer) ? + dist : sizeof(buffer)); + if (fread(buffer, 1, len, fp) < len) { + perror("fread"); + exit(1); + } + dist -= len; + } + } +} |