diff --git a/Makefile b/Makefile index edfddc1..95113ad 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ dist: $(PACKAGE)-$(VERSION)/src/parser.c \ $(PACKAGE)-$(VERSION)/src/token.c \ $(PACKAGE)-$(VERSION)/src/main.c \ + $(PACKAGE)-$(VERSION)/src/deasm.c \ $(PACKAGE)-$(VERSION)/src/Makefile \ $(PACKAGE)-$(VERSION)/src/arch.h \ $(PACKAGE)-$(VERSION)/src/asm.h \ diff --git a/include/Asm/arch.h b/include/Asm/arch.h index 1e52e2f..5d8115e 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -179,6 +179,8 @@ typedef struct _ArchPluginHelper /* callbacks */ /* accessors */ char const * (*get_filename)(Arch * arch); + ArchInstruction * (*get_instruction_by_opcode)(Arch * arch, + uint8_t size, uint32_t opcode); ArchRegister * (*get_register_by_name_size)(Arch * arch, char const * name, uint32_t size); diff --git a/src/.cvsignore b/src/.cvsignore index 038879a..2312efe 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -1,2 +1,3 @@ .cvsignore asm +deasm diff --git a/src/Makefile b/src/Makefile index 5ab1c7a..16e12e0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ SUBDIRS = arch format -TARGETS = libasm.a libasm.so asm +TARGETS = libasm.a libasm.so asm deasm PREFIX = /usr/local DESTDIR = LIBDIR = $(PREFIX)/lib @@ -42,6 +42,13 @@ asm_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) -L. -Wl,-rpath,$(LIBDIR) -lasm asm: $(asm_OBJS) libasm.so $(CC) -o asm $(asm_OBJS) $(asm_LDFLAGS) +deasm_OBJS = deasm.o +deasm_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) +deasm_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) -L. -Wl,-rpath,$(LIBDIR) -lasm + +deasm: $(deasm_OBJS) libasm.so + $(CC) -o deasm $(deasm_OBJS) $(deasm_LDFLAGS) + arch.o: arch.c arch.h ../config.h $(CC) $(libasm_CFLAGS) -c arch.c @@ -63,13 +70,16 @@ token.o: token.c token.h main.o: main.c ../include/Asm.h $(CC) $(asm_CFLAGS) -c main.c +deasm.o: deasm.c ../include/Asm.h + $(CC) $(deasm_CFLAGS) -c deasm.c + clean: @for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done - $(RM) -- $(libasm_OBJS) $(asm_OBJS) + $(RM) -- $(libasm_OBJS) $(asm_OBJS) $(deasm_OBJS) distclean: @for i in $(SUBDIRS); do (cd $$i && $(MAKE) distclean) || exit; done - $(RM) -- $(libasm_OBJS) $(asm_OBJS) + $(RM) -- $(libasm_OBJS) $(asm_OBJS) $(deasm_OBJS) $(RM) -- $(TARGETS) install: $(TARGETS) @@ -81,6 +91,8 @@ install: $(TARGETS) $(LN) -s -- libasm.so.0.0 $(DESTDIR)$(LIBDIR)/libasm.so $(MKDIR) $(DESTDIR)$(BINDIR) $(INSTALL) -m 0755 -- asm $(DESTDIR)$(BINDIR)/asm + $(MKDIR) $(DESTDIR)$(BINDIR) + $(INSTALL) -m 0755 -- deasm $(DESTDIR)$(BINDIR)/deasm uninstall: @for i in $(SUBDIRS); do (cd $$i && $(MAKE) uninstall) || exit; done @@ -89,5 +101,6 @@ uninstall: $(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so.0 $(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so $(RM) -- $(DESTDIR)$(BINDIR)/asm + $(RM) -- $(DESTDIR)$(BINDIR)/deasm .PHONY: all subdirs clean distclean install uninstall diff --git a/src/arch.c b/src/arch.c index c357725..17d8f4a 100644 --- a/src/arch.c +++ b/src/arch.c @@ -172,7 +172,7 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, for(i = 0; i < arch->instructions_cnt; i++) { ai = &arch->plugin->instructions[i]; - if(AO_GET_SIZE(ai->opcode) != size) + if(AO_GET_SIZE(ai->flags) != size) continue; if(ai->opcode == opcode) return ai; @@ -457,6 +457,9 @@ static void _decode_print(ArchInstructionCall * call) /* arch_exit */ int arch_exit(Arch * arch) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif arch->filename = NULL; arch->fp = NULL; arch->buffer = NULL; @@ -478,6 +481,7 @@ int arch_init(Arch * arch, char const * filename, FILE * fp) arch->fp = fp; arch->helper.arch = arch; arch->helper.get_filename = _arch_get_filename; + arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode; arch->helper.get_register_by_name_size = arch_get_register_by_name_size; arch->helper.read = NULL; arch->helper.write = _arch_write; @@ -498,6 +502,7 @@ int arch_init_buffer(Arch * arch, char const * buffer, size_t size) arch->buffer_pos = 0; arch->helper.arch = arch; arch->helper.get_filename = _arch_get_filename; + arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode; arch->helper.get_register_by_name_size = arch_get_register_by_name_size; arch->helper.write = NULL; arch->helper.read = _arch_read_buffer; @@ -531,6 +536,11 @@ static ssize_t _arch_read_buffer(Arch * arch, void * buf, size_t size) { ssize_t s = min(arch->buffer_cnt - arch->buffer_pos, size); +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(s == 0) + return -error_set_code(1, "%s", "End of buffer reached"); memcpy(buf, &arch->buffer[arch->buffer_pos], s); arch->buffer_pos += s; return s; diff --git a/src/arch/amd64.c b/src/arch/amd64.c index 5381525..c87dbd6 100644 --- a/src/arch/amd64.c +++ b/src/arch/amd64.c @@ -80,5 +80,5 @@ ArchPlugin arch_plugin = _amd64_registers, _amd64_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/arch/i386.c b/src/arch/i386.c index f7469b6..55492a1 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -74,5 +74,5 @@ ArchPlugin arch_plugin = _i386_registers, _i386_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/arch/i386.h b/src/arch/i386.h index ba137a5..09e2f84 100644 --- a/src/arch/i386.h +++ b/src/arch/i386.h @@ -23,11 +23,33 @@ /* i386 */ /* private */ /* prototypes */ +static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call); static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); /* functions */ +/* i386_decode */ +static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call) +{ + ArchPluginHelper * helper = plugin->helper; + ArchInstruction * ai = NULL; + uint8_t opcode; + + /* FIXME really implement */ + if(helper->read(helper->arch, &opcode, sizeof(opcode)) + != sizeof(opcode)) + return -1; + if((ai = helper->get_instruction_by_opcode(helper->arch, 8, opcode)) + == NULL) + /* FIXME return "db" instead */ + return -1; + call->name = ai->name; + return 0; +} + + +/* i386_write */ static int _write_constant(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand); static int _write_dregister(ArchPlugin * plugin, uint32_t * i, diff --git a/src/arch/i386_real.c b/src/arch/i386_real.c index 5c8088e..e486319 100644 --- a/src/arch/i386_real.c +++ b/src/arch/i386_real.c @@ -75,5 +75,5 @@ ArchPlugin arch_plugin = _i386_real_registers, _i386_real_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/arch/i486.c b/src/arch/i486.c index 3b530d7..e2b58aa 100644 --- a/src/arch/i486.c +++ b/src/arch/i486.c @@ -75,5 +75,5 @@ ArchPlugin arch_plugin = _i486_registers, _i486_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/arch/i586.c b/src/arch/i586.c index d4b8667..09a766c 100644 --- a/src/arch/i586.c +++ b/src/arch/i586.c @@ -76,5 +76,5 @@ ArchPlugin arch_plugin = _i586_registers, _i586_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/arch/i686.c b/src/arch/i686.c index 9f7d4a2..f8e86d6 100644 --- a/src/arch/i686.c +++ b/src/arch/i686.c @@ -78,5 +78,5 @@ ArchPlugin arch_plugin = _i686_registers, _i686_instructions, _i386_write, - NULL + _i386_decode }; diff --git a/src/asm.c b/src/asm.c index 8fcd393..d906cde 100644 --- a/src/asm.c +++ b/src/asm.c @@ -89,7 +89,6 @@ As * as_new(char const * arch, char const * format) { As * as; - /* FIXME add signatures to the format plug-in (for disas too) */ if((as = object_new(sizeof(*as))) == NULL) return NULL; if(arch == NULL) diff --git a/src/deasm.c b/src/deasm.c new file mode 100644 index 0000000..8c29a22 --- /dev/null +++ b/src/deasm.c @@ -0,0 +1,547 @@ +/* $Id$ */ +/* Copyright (c) 2011 Pierre Pronchery */ +/* This file is part of DeforaOS Devel asm */ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + + + +#include +#include +#include +#include +#include +#include +#include +#include "Asm.h" +#include "../config.h" + + +/* constants */ +#ifndef PREFIX +# define PREFIX "/usr/local" +#endif +#ifndef LIBDIR +# define LIBDIR PREFIX "/lib" +#endif + + +/* macros */ +#define max(a, b) ((a) > (b) ? (a) : (b)) + + +/* deasm */ +/* private */ +/* types */ +typedef struct _DeasmFormat +{ + Plugin * plugin; + FormatPlugin * format; +} DeasmFormat; + +/* XXX ugly */ +#define _Deasm _Format +typedef struct _Deasm +{ + char const * arch; + As * as; + + FormatPluginHelper helper; + DeasmFormat * format; + size_t format_cnt; + + char const * filename; + FILE * fp; +} Deasm; + + +/* prototypes */ +static int _deasm(char const * arch, char const * format, + char const * filename); +static int _deasm_buffer(char const * arch, char const * format, + char const * buffer, size_t size); +static int _deasm_error(char const * message, int ret); +static int _deasm_string(char const * arch, char const * format, + char const * string); +static int _deasm_list(void); + +/* helper */ +static int _deasm_helper_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base); +static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size); +static off_t _deasm_helper_seek(Format * format, off_t offset, int whence); + +/* format */ +static DeasmFormat const * _deasm_format_open(Deasm * deasm, + char const * format); +static int _deasm_format_open_all(Deasm * deasm); +static char const * _deasm_format_detect(DeasmFormat const * format); +static void _deasm_format_close(DeasmFormat const * format); +static void _deasm_format_close_all(Deasm * deasm); + +static int _usage(void); + + +/* functions */ +/* deasm */ +static int _deasm_do_format(Deasm * deasm, char const * format); +static int _deasm_do(Deasm * deasm); +static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format); +#if 0 +static int _deasm_format_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base); +#endif + +static int _deasm(char const * arch, char const * format, + char const * filename) +{ + int ret = 1; + Deasm deasm; + + deasm.arch = arch; + deasm.as = NULL; + deasm.helper.format = &deasm; + deasm.helper.read = _deasm_helper_read; + deasm.helper.seek = _deasm_helper_seek; + deasm.helper.write = NULL; + deasm.helper.decode = _deasm_helper_decode; + deasm.format = NULL; + deasm.format_cnt = 0; + if((deasm.fp = fopen(filename, "r")) == NULL) + return -_deasm_error(filename, 1); + deasm.filename = filename; + if(format != NULL) + ret = _deasm_do_format(&deasm, format); + else + ret = _deasm_do(&deasm); + if(deasm.as != NULL) + as_delete(deasm.as); + fclose(deasm.fp); + _deasm_format_close_all(&deasm); + if(ret != 0) + error_print("deasm"); + return ret; +} + +static int _deasm_do_format(Deasm * deasm, char const * format) +{ + int ret; + size_t i; + DeasmFormat const * df; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format); +#endif + /* check if the plug-in is already opened */ + for(i = 0; i < deasm->format_cnt; i++) + if(strcmp(deasm->format[i].format->name, format) == 0) + break; + if(i < deasm->format_cnt) + df = &deasm->format[i]; + else if((df = _deasm_format_open(deasm, format)) == NULL) + return -1; + /* disassemble */ + ret = _deasm_do_callback(deasm, df->format); + return ret; +} + +static int _deasm_do(Deasm * deasm) +{ + int ret = 1; + size_t i; + size_t s = 0; + char * buf; + FormatPlugin * format; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + _deasm_format_open_all(deasm); + for(i = 0; i < deasm->format_cnt; i++) + s = max(s, deasm->format[i].format->signature_len); + if((buf = malloc(s)) == NULL) + return -_deasm_error(deasm->filename, 1); + if(fread(buf, 1, s, deasm->fp) != s) + { + if(ferror(deasm->fp)) + ret = -_deasm_error(deasm->filename, 1); + else + ret = _deasm_do_format(deasm, "flat"); + } + else + { + for(i = 0; i < deasm->format_cnt; i++) + { + format = deasm->format[i].format; + if(format->signature_len == 0) + continue; + if(memcmp(format->signature, buf, format->signature_len) + != 0) + continue; + if(deasm->arch == NULL) + deasm->arch = _deasm_format_detect( + &deasm->format[i]); + if(deasm->arch == NULL) + continue; + ret = _deasm_do_callback(deasm, format); + break; + } + if(i == deasm->format_cnt) + ret = _deasm_do_format(deasm, "flat"); + } + free(buf); + return ret; +} + +static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format) +{ + int ret; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format->name); +#endif + if(deasm->arch == NULL) + { + if(format->detect == NULL) + return -error_set_code(1, "%s: %s", format->name, + "Unable to detect the architecture"); + if((deasm->arch = format->detect(format)) == NULL) + return -1; + } + if((deasm->as = as_new(deasm->arch, format->name)) == NULL) + return -error_print("deasm"); + printf("\n%s: %s-%s\n", deasm->filename, format->name, + as_get_arch_name(deasm->as)); + ret = format->decode(format); + return ret; +} + + +/* deasm_buffer */ +static int _deasm_buffer(char const * arch, char const * format, + char const * buffer, size_t size) +{ + As * as; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if((as = as_new(arch, format)) == NULL) + return -1; + if(as_decode(as, buffer, size) != 0) + error_print("deasm"); + as_delete(as); + return 0; +} + + +/* deasm_error */ +static int _deasm_error(char const * message, int ret) +{ + fputs("deasm: ", stderr); + perror(message); + return ret; +} + + +/* deasm_string */ +static int _string_hex2bin(int c); +static int _string_ishex(int c); + +static int _deasm_string(char const * arch, char const * format, + char const * string) +{ + int ret; + unsigned char * str = (unsigned char *)string; + size_t len = strlen(string); + char * s; + size_t i; + size_t j; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\", \"%s\", \"%s\")\n", __func__, arch, + format, string); +#endif + if((s = malloc(len + 1)) == NULL) + return -error_set_print("deasm", 1, "%s", strerror(errno)); + for(i = 0, j = 0; i < len; i++) + { + if(str[i] != '\\') + s[j++] = str[i]; + else if(str[i + 1] != 'x') /* "\\" */ + s[j++] = str[++i]; + else if(i + 3 < len && _string_ishex(str[i + 2]) + && _string_ishex(str[i + 3])) /* "\xHH" */ + { + s[j++] = (_string_hex2bin(str[i + 2]) << 4) + | _string_hex2bin(str[i + 3]); + i += 3; + } + } + s[j] = '\0'; /* not really necessary */ + ret = _deasm_buffer(arch, format, s, j); + free(s); + return ret; +} + +static int _string_hex2bin(int c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int _string_ishex(int c) +{ + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') + || (c >= 'A' || c <= 'F'); +} + + +/* deasm_list */ +static int _deasm_list(void) +{ + Deasm deasm; + size_t i; + char const * sep = ""; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + memset(&deasm, 0, sizeof(deasm)); + as_plugin_list(ASPT_ARCH); + _deasm_format_open_all(&deasm); + fputs("\nAvailable format plug-ins:\n", stderr); + for(i = 0; i < deasm.format_cnt; i++) + { + if(deasm.format[i].format->decode == NULL) + continue; + fprintf(stderr, "%s%s", sep, deasm.format[i].format->name); + sep = ", "; + } + fputc('\n', stderr); + _deasm_format_close_all(&deasm); + return 0; +} + + + +/* helper */ +/* deasm_helper_decode */ +static int _deasm_helper_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base) +{ + if(section != NULL) + printf("\n%s%s:\n", "Disassembly of section ", section); + if(fseek(format->fp, offset, SEEK_SET) != 0) + return -error_set_code(1, "%s: %s", format->filename, + strerror(errno)); + printf("\n%08lx:\n", (unsigned long)offset + base); + /* FIXME implement */ + if(fseek(format->fp, offset + size, SEEK_SET) != 0) + return -error_set_code(1, "%s: %s", format->filename, + strerror(errno)); + return 0; +} + + +/* deasm_helper_read */ +static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size) +{ + if(fread(buf, size, 1, format->fp) == 1) + return size; + return -error_set_code(1, "%s: %s", format->filename, strerror(errno)); +} + + +/* deasm_helper_seek */ +static off_t _deasm_helper_seek(Format * format, off_t offset, int whence) +{ + if(fseek(format->fp, offset, whence) != 0) + return -error_set_code(1, "%s: %s", format->filename, + strerror(errno));; + return ftello(format->fp); +} + + +/* format */ +/* deasm_format_open */ +static DeasmFormat const * _deasm_format_open(Deasm * deasm, + char const * format) +{ + DeasmFormat * p; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format); +#endif + if((p = realloc(deasm->format, sizeof(*p) * (deasm->format_cnt + 1))) + == NULL) + { + error_set_code(1, "%s", strerror(errno)); + return NULL; + } + deasm->format = p; + p = &deasm->format[deasm->format_cnt]; + if((p->plugin = plugin_new(LIBDIR, PACKAGE, "format", format)) == NULL) + return NULL; + if((p->format = plugin_lookup(p->plugin, "format_plugin")) == NULL) + { + plugin_delete(p->plugin); + return NULL; + } + if(p->format->decode == NULL) + { + error_set_code(1, "%s: %s", format, + "Does not support disassembly"); + plugin_delete(p->plugin); + return NULL; + } + p->format->helper = &deasm->helper; + deasm->format_cnt++; + return p; +} + + +/* deasm_format_open_all */ +static int _deasm_format_open_all(Deasm * deasm) +{ + char const path[] = LIBDIR "/" PACKAGE "/format"; + DIR * dir; + struct dirent * de; + size_t len; + char const ext[] = ".so"; + + if((dir = opendir(path)) == NULL) + return -error_set_print("deasm", 1, "%s: %s", path, strerror( + errno)); + while((de = readdir(dir)) != NULL) + { + if((len = strlen(de->d_name)) < 4) + continue; + if(strcmp(&de->d_name[len - sizeof(ext) + 1], ext) != 0) + continue; + de->d_name[len - sizeof(ext) + 1] = '\0'; + if(_deasm_format_open(deasm, de->d_name) == NULL) + error_print("deasm"); + } + closedir(dir); + return 0; +} + + +#if 0 +/* deasm_format_callback */ +static int _callback_flat(Deasm * deasm, off_t offset, size_t size, off_t base); + +static int _deasm_format_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base) +{ + Deasm * deasm = format; + + if(section != NULL) + printf("\n%s%s\n", "Disassembly of section: ", section); + return _callback_flat(deasm, offset, size, base); +} + +static int _callback_flat(Deasm * deasm, off_t offset, size_t size, off_t base) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(0x%lx, 0x%lx, 0x%lx)\n", __func__, offset, + size, base); +#endif + if(fseek(deasm->fp, offset, SEEK_SET) != 0) + return -_deasm_error(deasm->filename, 1); + printf("\n%08lx:\n", offset + base); + return 0; +} +#endif + + +/* deasm_format_detect */ +static char const * _deasm_format_detect(DeasmFormat const * format) +{ + if(format->format->detect == NULL) + return NULL; + return format->format->detect(format->format); +} + + +/* deasm_format_close */ +static void _deasm_format_close(DeasmFormat const * format) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, format->format->name); +#endif + plugin_delete(format->plugin); +} + + +/* deasm_format_close_all */ +static void _deasm_format_close_all(Deasm * deasm) +{ + size_t i; + + for(i = 0; i < deasm->format_cnt; i++) + _deasm_format_close(&deasm->format[i]); + free(deasm->format); + deasm->format = NULL; + deasm->format_cnt = 0; +} + + +/* usage */ +static int _usage(void) +{ + fputs("Usage: deasm [-a arch][-f format] filename\n" +" deasm [-a arch][-f format] -s string\n" +" deasm -l\n", stderr); + return 1; +} + + +/* public */ +/* functions */ +/* main */ +int main(int argc, char * argv[]) +{ + int o; + char const * arch = NULL; + char const * format = NULL; + char const * string = NULL; + + while((o = getopt(argc, argv, "a:f:ls:")) != -1) + switch(o) + { + case 'a': + arch = optarg; + break; + case 'f': + format = optarg; + break; + case 'l': + return _deasm_list(); + case 's': + string = optarg; + break; + default: + return _usage(); + } + if(optind == argc && string != NULL) + return _deasm_string(arch, format, string); + else if(optind + 1 == argc && string == NULL) + return (_deasm(arch, format, argv[optind]) == 0) ? 0 : 2; + return _usage(); +} diff --git a/src/project.conf b/src/project.conf index 9c95050..d747363 100644 --- a/src/project.conf +++ b/src/project.conf @@ -1,5 +1,5 @@ subdirs=arch,format -targets=libasm,asm +targets=libasm,asm,deasm cppflags_force=-I ../include cppflags= cflags_force=-W `pkg-config --cflags cpp` @@ -21,6 +21,13 @@ depends=libasm.so ldflags=-L. -Wl,-rpath,$(LIBDIR) -lasm install=$(BINDIR) +[deasm] +type=binary +sources=deasm.c +depends=libasm.so +ldflags=-L. -Wl,-rpath,$(LIBDIR) -lasm +install=$(BINDIR) + [arch.c] depends=arch.h,../config.h @@ -30,6 +37,9 @@ depends=../include/Asm.h,code.h,parser.h,asm.h,../config.h [code.c] depends=../include/Asm.h,arch.h,code.h +[deasm.c] +depends=../include/Asm.h + [format.c] depends=format.h,../config.h