From d16f99ebbbfb1a6ddc0a72e20f4c4b88b36ee4da Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sun, 1 May 2011 20:07:15 +0000 Subject: [PATCH] Moved detection of file format and architecture for deassembling into libasm --- src/Makefile | 4 +- src/asm.c | 14 ++- src/code.c | 278 ++++++++++++++++++++++++++-------------- src/code.h | 7 +- src/deasm.c | 315 ++-------------------------------------------- src/format.c | 198 ++++++++++++++++++----------- src/format.h | 7 +- src/format/elf.c | 64 +++++++++- src/format/java.c | 5 + src/format/pe.c | 2 + src/project.conf | 4 +- 11 files changed, 403 insertions(+), 495 deletions(-) diff --git a/src/Makefile b/src/Makefile index 8aabd78..70d7f02 100644 --- a/src/Makefile +++ b/src/Makefile @@ -60,7 +60,7 @@ arch.o: arch.c ../include/Asm/arch.h ../include/Asm/asm.h arch.h code.h ../confi asm.o: asm.c ../include/Asm.h code.h parser.h ../config.h $(CC) $(libasm_CFLAGS) -c asm.c -code.o: code.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h arch.h code.h format.h +code.o: code.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h arch.h code.h format.h ../config.h $(CC) $(libasm_CFLAGS) -c code.c format.o: format.c ../include/Asm/asm.h ../include/Asm/format.h code.h format.h ../config.h @@ -75,7 +75,7 @@ token.o: token.c common.h token.h main.o: main.c ../include/Asm/asm.h ../config.h $(CC) $(asm_CFLAGS) -c main.c -deasm.o: deasm.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h ../config.h +deasm.o: deasm.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h $(CC) $(deasm_CFLAGS) -c deasm.c clean: diff --git a/src/asm.c b/src/asm.c index 1b4c1a9..da2eb39 100644 --- a/src/asm.c +++ b/src/asm.c @@ -183,7 +183,7 @@ int asm_deassemble(Asm * a, char const * buffer, size_t size) if(_asm_open(a, NULL) != 0) return -1; - ret = code_decode(a->code, buffer, size); + ret = code_decode_buffer(a->code, buffer, size); asm_close(a); return ret; } @@ -252,9 +252,17 @@ int asm_open_assemble(Asm * a, char const * outfile) /* asm_open_deassemble */ int asm_open_deassemble(Asm * a, char const * filename) { - if(_asm_open(a, NULL) != 0) +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename); +#endif + if(a->code != NULL) + return -error_set_code(1, "%s: Operation in progress", + code_get_filename(a->code)); + if((a->code = code_new_file(a->arch, a->format, filename)) == NULL) return -1; - return code_decode_file(a->code, filename); + if(code_decode(a->code) != 0) + return -1; + return 0; } diff --git a/src/code.c b/src/code.c index 05a3631..878cf75 100644 --- a/src/code.c +++ b/src/code.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "arch.h" #include "format.h" #include "code.h" +#include "../config.h" /* Code */ @@ -77,7 +79,7 @@ Code * code_new(char const * arch, char const * format) if((code->arch = arch_new(arch)) != NULL && format == NULL) format = arch_get_format(code->arch); if(format != NULL) - code->format = format_new(format, arch); + code->format = format_new(format); if(code->arch == NULL || code->format == NULL) { code_delete(code); @@ -88,6 +90,101 @@ Code * code_new(char const * arch, char const * format) } +/* code_new_file */ +static Format * _new_file_format(char const * filename, FILE * fp); + +Code * code_new_file(char const * arch, char const * format, + char const * filename) +{ + Code * code; + FILE * fp; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename); +#endif + if((fp = fopen(filename, "r")) == NULL) + { + error_set_code(1, "%s: %s", filename, strerror(errno)); + return NULL; + } + if((code = object_new(sizeof(*code))) == NULL) + { + fclose(fp); + return NULL; + } + memset(code, 0, sizeof(*code)); + if(format == NULL) + code->format = _new_file_format(filename, fp); + else if((code->format = format_new(format)) != NULL + && format_init(code->format, NULL, filename, fp) != 0) + { + format_delete(code->format); + code->format = NULL; + } + if(arch == NULL && code->format != NULL) + arch = format_detect_arch(code->format); + if(arch != NULL && (code->arch = arch_new(arch)) != NULL + && arch_init(code->arch, filename, fp) != 0) + { + arch_delete(code->arch); + code->arch = NULL; + } + if(code->arch == NULL || code->format == NULL) + { + code_delete(code); + return NULL; + } + code->description = arch_get_description(code->arch); + return code; +} + +static Format * _new_file_format(char const * filename, FILE * fp) +{ + char const path[] = LIBDIR "/" PACKAGE "/format"; + DIR * dir; + struct dirent * de; + size_t len; + char const ext[] = ".so"; + int hasflat = 0; + Format * format = NULL; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename); +#endif + if((dir = opendir(path)) == NULL) + { + error_set_code(1, "%s: %s", path, strerror(errno)); + return NULL; + } + 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(strcmp(de->d_name, "flat") == 0) + hasflat = 1; + if((format = format_new(de->d_name)) == NULL) + continue; + if(format_init(format, NULL, filename, fp) == 0 + && format_match(format) == 1) + break; + format_delete(format); + format = NULL; + } + closedir(dir); + /* fallback on the "flat" format plug-in if necessary and available */ + if(format == NULL && hasflat && (format = format_new("flat")) != NULL + && format_init(format, NULL, filename, fp) != 0) + { + format_delete(format); + format = NULL; + } + return format; +} + + /* code_delete */ int code_delete(Code * code) { @@ -187,10 +284,36 @@ int code_close(Code * code) /* code_decode */ -static int _decode_print(Code * code, ArchInstructionCall * call); -static void _decode_print_immediate(Code * code, ArchOperand * ao); +int code_decode(Code * code) +{ + return format_decode(code->format, code); +} -int code_decode(Code * code, char const * buffer, size_t size) + +/* code_decode_at */ +int code_decode_at(Code * code, char const * section, off_t offset, + size_t size, off_t base) +{ + ArchInstructionCall * calls = NULL; + size_t calls_cnt = 0; + size_t i; + + if(section != NULL) + printf("%s%s:\n", "\nDisassembly of section ", section); + if(arch_decode_at(code->arch, code, &calls, &calls_cnt, offset, size, + base) != 0) + return -1; + if(size != 0) + printf("\n%08lx:\n", (long)offset + (long)base); + for(i = 0; i < calls_cnt; i++) + code_print(code, &calls[i]); + free(calls); + return 0; +} + + +/* code_decode_buffer */ +int code_decode_buffer(Code * code, char const * buffer, size_t size) { int ret; ArchInstructionCall * calls = NULL; @@ -202,14 +325,66 @@ int code_decode(Code * code, char const * buffer, size_t size) { fprintf(stderr, "DEBUG: %lu\n", calls_cnt); for(i = 0; i < calls_cnt; i++) - _decode_print(code, &calls[i]); + code_print(code, &calls[i]); free(calls); } arch_exit(code->arch); return ret; } -static int _decode_print(Code * code, ArchInstructionCall * call) + +/* code_function */ +int code_function(Code * code, char const * function) +{ + return format_function(code->format, function); +} + + +/* code_instruction */ +int code_instruction(Code * code, ArchInstructionCall * call) +{ + ArchInstruction * ai; + + if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL) + return -1; +#ifdef DEBUG + fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x" + ", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2, + ai->op3); +#endif + return arch_write(code->arch, ai, call); +} + + +/* code_open */ +int code_open(Code * code, char const * filename) +{ + if(code->filename != NULL || code->fp != NULL) + return -error_set_code(1, "A file is already opened"); + if((code->filename = string_new(filename)) == NULL) + return -1; + if((code->fp = fopen(filename, "w+")) == NULL) + return -error_set_code(1, "%s: %s", filename, strerror(errno)); + if(arch_init(code->arch, code->filename, code->fp) == 0) + { + if(format_init(code->format, arch_get_name(code->arch), + code->filename, code->fp) == 0) + return 0; + arch_exit(code->arch); + } + fclose(code->fp); + code->fp = NULL; + unlink(code->filename); /* XXX may fail */ + string_delete(code->filename); + code->filename = NULL; + return -1; +} + + +/* code_print */ +static void _print_immediate(ArchOperand * ao); + +int code_print(Code * code, ArchInstructionCall * call) { char const * sep = " "; size_t i; @@ -251,7 +426,7 @@ static int _decode_print(Code * code, ArchInstructionCall * call) ao->value.dregister2.name2); break; case AOT_IMMEDIATE: - _decode_print_immediate(code, ao); + _print_immediate(ao); break; case AOT_REGISTER: name = call->operands[i].value._register.name; @@ -264,7 +439,7 @@ static int _decode_print(Code * code, ArchInstructionCall * call) return 0; } -static void _decode_print_immediate(Code * code, ArchOperand * ao) +static void _print_immediate(ArchOperand * ao) { printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "", ao->value.immediate.value); @@ -285,93 +460,6 @@ static void _decode_print_immediate(Code * code, ArchOperand * ao) } -/* code_decode_at */ -int code_decode_at(Code * code, char const * section, off_t offset, - size_t size, off_t base) -{ - ArchInstructionCall * calls = NULL; - size_t calls_cnt = 0; - size_t i; - - if(section != NULL) - printf("%s%s:\n", "\nDisassembly of section ", section); - if(arch_decode_at(code->arch, code, &calls, &calls_cnt, offset, size, - base) != 0) - return -1; - if(size != 0) - printf("\n%08lx:\n", (long)offset + (long)base); - for(i = 0; i < calls_cnt; i++) - _decode_print(code, &calls[i]); - free(calls); - return 0; -} - - -/* code_decode_file */ -int code_decode_file(Code * code, char const * filename) -{ - int ret; - FILE * fp; - - if((fp = fopen(filename, "r")) == NULL) - return -error_set_code(1, "%s: %s", filename, strerror(errno)); - arch_init(code->arch, filename, fp); - format_init(code->format, filename, fp); - ret = format_decode(code->format, code); - format_exit(code->format); - arch_exit(code->arch); - if(fclose(fp) != 0 && ret == 0) - ret = -error_set_code(1, "%s: %s", filename, strerror(errno)); - return ret; -} - - -/* code_function */ -int code_function(Code * code, char const * function) -{ - return format_function(code->format, function); -} - - -/* code_instruction */ -int code_instruction(Code * code, ArchInstructionCall * call) -{ - ArchInstruction * ai; - - if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL) - return -1; -#ifdef DEBUG - fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x" - ", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2, - ai->op3); -#endif - return arch_write(code->arch, ai, call); -} - - -/* code_open */ -int code_open(Code * code, char const * filename) -{ - if(code->filename != NULL || code->fp != NULL) - return -error_set_code(1, "A file is already opened"); - if((code->filename = string_new(filename)) == NULL) - return -1; - if((code->fp = fopen(filename, "w+")) == NULL) - return -error_set_code(1, "%s: %s", filename, strerror(errno)); - if(format_init(code->format, code->filename, code->fp) != 0 - || arch_init(code->arch, code->filename, code->fp) != 0) - { - fclose(code->fp); - code->fp = NULL; - unlink(code->filename); /* XXX may fail */ - string_delete(code->filename); - code->filename = NULL; - return -1; - } - return 0; -} - - /* code_section */ int code_section(Code * code, char const * section) { diff --git a/src/code.h b/src/code.h index e8c75a3..8013be6 100644 --- a/src/code.h +++ b/src/code.h @@ -28,6 +28,8 @@ typedef struct _Code Code; /* functions */ Code * code_new(char const * arch, char const * format); +Code * code_new_file(char const * arch, char const * format, + char const * filename); int code_delete(Code * code); /* accessors */ @@ -54,9 +56,10 @@ int code_instruction(Code * code, ArchInstructionCall * call); int code_section(Code * code, char const * section); /* disassembly */ -int code_decode(Code * code, char const * buffer, size_t size); +int code_decode(Code * code); int code_decode_at(Code * code, char const * section, off_t offset, size_t size, off_t base); -int code_decode_file(Code * code, char const * filename); +int code_decode_buffer(Code * code, char const * buffer, size_t size); +int code_print(Code * code, ArchInstructionCall * call); #endif /* !ASM_CODE_H */ diff --git a/src/deasm.c b/src/deasm.c index 2a6669d..f3c23ae 100644 --- a/src/deasm.c +++ b/src/deasm.c @@ -23,194 +23,35 @@ #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; - - 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 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); - -static int _deasm(char const * arch, char const * format, - char const * filename) -{ - int ret = 1; - Deasm deasm; - - deasm.arch = arch; - memset(&deasm.helper, 0, sizeof(deasm.helper)); - deasm.helper.format = &deasm; - deasm.helper.read = _deasm_helper_read; - deasm.helper.seek = _deasm_helper_seek; - 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); - 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) +static int _deasm(char const * arch, char const * format, char const * filename) { int ret; Asm * a; -#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", deasm->filename, - "Unable to detect the architecture"); - if((deasm->arch = format->detect(format)) == NULL) - return -1; - } - if((a = asm_new(deasm->arch, format->name)) == NULL) + if((a = asm_new(arch, format)) == NULL) return -error_print("deasm"); - printf("\n%s: %s-%s\n", deasm->filename, format->name, asm_get_arch(a)); - ret = asm_open_deassemble(a, deasm->filename); + if((ret = asm_open_deassemble(a, filename)) != 0) + error_print("deasm"); + else + asm_close(a); asm_delete(a); return ret; } @@ -234,15 +75,6 @@ static int _deasm_buffer(char const * arch, char const * format, } -/* 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); @@ -304,148 +136,15 @@ static int _string_ishex(int c) /* 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)); asm_plugin_list(APT_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); + asm_plugin_list(APT_FORMAT); return 0; } - -/* helper */ -/* 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; -} - - -/* 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) { diff --git a/src/format.c b/src/format.c index 7f7176f..3b1fc85 100644 --- a/src/format.c +++ b/src/format.c @@ -30,7 +30,6 @@ /* types */ struct _Format { - char * arch; FormatPluginHelper helper; Plugin * handle; FormatPlugin * plugin; @@ -46,24 +45,34 @@ struct _Format /* prototypes */ -/* callbacks */ -static char const * _format_get_filename(Format * format); +/* helpers */ +static char const * _format_helper_get_filename(Format * format); +static AsmString * _format_helper_get_string_by_id(Format * format, AsmId id); +static int _format_helper_set_function(Format * format, int id, + char const * name, off_t offset, ssize_t size); +static int _format_helper_set_string(Format * format, int id, char const * name, + off_t offset, ssize_t size); -static ssize_t _format_read(Format * format, void * buf, size_t size); -static off_t _format_seek(Format * format, off_t offset, int whence); - -static ssize_t _format_write(Format * format, void const * buf, size_t size); +static int _format_helper_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base); +static ssize_t _format_helper_read(Format * format, void * buf, size_t size); +static off_t _format_helper_seek(Format * format, off_t offset, int whence); +static ssize_t _format_helper_write(Format * format, void const * buf, + size_t size); /* public */ /* functions */ /* format_new */ -Format * format_new(char const * format, char const * arch) +Format * format_new(char const * format) { Format * f; Plugin * handle; FormatPlugin * plugin; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format); +#endif if(format == NULL) { error_set_code(1, "%s", strerror(EINVAL)); @@ -77,15 +86,18 @@ Format * format_new(char const * format, char const * arch) plugin_delete(handle); return NULL; } - f->arch = string_new(arch); - memset(&f->helper, 0, sizeof(f->helper)); - f->plugin = plugin; f->handle = handle; - if(f->arch == NULL) - { - format_delete(f); - return NULL; - } + f->plugin = plugin; + memset(&f->helper, 0, sizeof(f->helper)); + f->helper.format = f; + f->helper.decode = _format_helper_decode; + f->helper.get_filename = _format_helper_get_filename; + f->helper.get_string_by_id = _format_helper_get_string_by_id; + f->helper.set_function = _format_helper_set_function; + f->helper.set_string = _format_helper_set_string; + f->helper.read = _format_helper_read; + f->helper.seek = _format_helper_seek; + f->helper.write = _format_helper_write; return f; } @@ -94,12 +106,20 @@ Format * format_new(char const * format, char const * arch) void format_delete(Format * format) { plugin_delete(format->handle); - string_delete(format->arch); object_delete(format); } /* accessors */ +/* format_get_arch */ +char const * format_get_arch(Format * format) +{ + if(format->plugin->detect == NULL) + return NULL; + return format->plugin->detect(format->plugin); +} + + /* format_get_name */ char const * format_get_name(Format * format) { @@ -109,14 +129,6 @@ char const * format_get_name(Format * format) /* useful */ /* format_decode */ -static int _decode_callback(Format * format, char const * section, - off_t offset, size_t size, off_t base); -static AsmString * _get_string_by_id_callback(Format * format, AsmId id); -static int _set_function_callback(Format * format, int id, char const * name, - off_t offset, ssize_t size); -static int _set_string_callback(Format * format, int id, char const * name, - off_t offset, ssize_t size); - int format_decode(Format * format, Code * code) { int ret; @@ -124,45 +136,23 @@ int format_decode(Format * format, Code * code) if(format->plugin->decode == NULL) return error_set_code(1, "%s: %s", format_get_name(format), "Disassembly is not supported"); - format->helper.decode = _decode_callback; - format->helper.get_string_by_id = _get_string_by_id_callback; - format->helper.set_function = _set_string_callback; - format->helper.set_string = _set_string_callback; format->code = code; ret = format->plugin->decode(format->plugin); format->code = NULL; - format->helper.set_string = NULL; - format->helper.set_function = NULL; - format->helper.get_string_by_id = NULL; - format->helper.decode = NULL; return ret; } -static int _decode_callback(Format * format, char const * section, - off_t offset, size_t size, off_t base) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__, - section, offset, size, base); -#endif - return code_decode_at(format->code, section, offset, size, base); -} -static AsmString * _get_string_by_id_callback(Format * format, AsmId id) +/* format_detect_arch */ +char const * format_detect_arch(Format * format) { - return code_get_string_by_id(format->code, id); -} - -static int _set_function_callback(Format * format, int id, char const * name, - off_t offset, ssize_t size) -{ - return code_set_function(format->code, id, name, offset, size); -} - -static int _set_string_callback(Format * format, int id, char const * name, - off_t offset, ssize_t size) -{ - return code_set_string(format->code, id, name, offset, size); + if(format->plugin->detect == NULL) + { + error_set_code(1, "%s: %s", format->plugin->name, + "Unable to detect the architecture"); + return NULL; + } + return format->plugin->detect(format->plugin); } @@ -176,10 +166,6 @@ int format_exit(Format * format) #endif if(format->plugin->exit != NULL) ret = format->plugin->exit(format->plugin); - format->helper.format = NULL; - format->helper.decode = NULL; - format->helper.read = NULL; - format->helper.seek = NULL; format->plugin->helper = NULL; format->fp = NULL; format->filename = NULL; @@ -197,7 +183,8 @@ int format_function(Format * format, char const * function) /* format_init */ -int format_init(Format * format, char const * filename, FILE * fp) +int format_init(Format * format, char const * arch, char const * filename, + FILE * fp) { #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename, @@ -205,19 +192,41 @@ int format_init(Format * format, char const * filename, FILE * fp) #endif format->filename = filename; format->fp = fp; - format->helper.format = format; - format->helper.decode = NULL; - format->helper.get_filename = _format_get_filename; - format->helper.read = _format_read; - format->helper.seek = _format_seek; - format->helper.write = _format_write; format->plugin->helper = &format->helper; if(format->plugin->init != NULL) - return format->plugin->init(format->plugin, format->arch); + return format->plugin->init(format->plugin, arch); return 0; } +/* format_match */ +int format_match(Format * format) +{ + int ret = 0; + char const * s = format->plugin->signature; + ssize_t s_len = format->plugin->signature_len; + char * buf = NULL; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(s_len > 0) + if((buf = malloc(s_len)) == NULL) + ret = -error_set_code(1, "%s", strerror(errno)); + if(buf != NULL) + { + if(_format_helper_seek(format, 0, SEEK_SET) != 0) + ret = -1; + else if(_format_helper_read(format, buf, s_len) != s_len) + ret = -1; + else if(memcmp(buf, s, s_len) == 0) + ret = 1; + free(buf); + } + return ret; +} + + /* format_section */ int format_section(Format * format, char const * section) { @@ -229,15 +238,51 @@ int format_section(Format * format, char const * section) /* private */ /* functions */ -/* format_get_filename */ -static char const * _format_get_filename(Format * format) +/* helpers */ +/* format_helper_get_filename */ +static char const * _format_helper_get_filename(Format * format) { return format->filename; } -/* format_read */ -static ssize_t _format_read(Format * format, void * buf, size_t size) +/* format_helper_get_string_by_id */ +static AsmString * _format_helper_get_string_by_id(Format * format, AsmId id) +{ + return code_get_string_by_id(format->code, id); +} + + +/* format_helper_set_function */ +static int _format_helper_set_function(Format * format, int id, + char const * name, off_t offset, ssize_t size) +{ + return code_set_function(format->code, id, name, offset, size); +} + + +/* format_helper_set_string */ +static int _format_helper_set_string(Format * format, int id, char const * name, + off_t offset, ssize_t size) +{ + return code_set_string(format->code, id, name, offset, size); +} + + +/* format_helper_decode */ +static int _format_helper_decode(Format * format, char const * section, + off_t offset, size_t size, off_t base) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__, + section, offset, size, base); +#endif + return code_decode_at(format->code, section, offset, size, base); +} + + +/* format_helper_read */ +static ssize_t _format_helper_read(Format * format, void * buf, size_t size) { if(fread(buf, size, 1, format->fp) == 1) return size; @@ -251,8 +296,8 @@ static ssize_t _format_read(Format * format, void * buf, size_t size) } -/* format_seek */ -static off_t _format_seek(Format * format, off_t offset, int whence) +/* format_helper_seek */ +static off_t _format_helper_seek(Format * format, off_t offset, int whence) { if(whence == SEEK_SET) { @@ -271,8 +316,9 @@ static off_t _format_seek(Format * format, off_t offset, int whence) } -/* format_write */ -static ssize_t _format_write(Format * format, void const * buf, size_t size) +/* format_helper_write */ +static ssize_t _format_helper_write(Format * format, void const * buf, + size_t size) { if(fwrite(buf, size, 1, format->fp) == 1) return size; diff --git a/src/format.h b/src/format.h index 2c7a3db..8009876 100644 --- a/src/format.h +++ b/src/format.h @@ -34,7 +34,7 @@ typedef int (*FormatSetStringCallback)(void * priv, int id, char const * name, off_t offset, ssize_t length); /* functions */ -Format * format_new(char const * format, char const * arch); +Format * format_new(char const * format); void format_delete(Format * format); /* accessors */ @@ -42,7 +42,8 @@ char const * format_get_name(Format * format); /* useful */ /* assembly */ -int format_init(Format * format, char const * filename, FILE * fp); +int format_init(Format * format, char const * arch, char const * filename, + FILE * fp); int format_exit(Format * format); int format_function(Format * format, char const * function); @@ -50,5 +51,7 @@ int format_section(Format * format, char const * section); /* disassembly */ int format_decode(Format * format, Code * code); +char const * format_detect_arch(Format * format); +int format_match(Format * format); #endif /* !ASM_FORMAT_H */ diff --git a/src/format/elf.c b/src/format/elf.c index f1b0913..f2ae327 100644 --- a/src/format/elf.c +++ b/src/format/elf.c @@ -54,12 +54,18 @@ typedef struct _ElfStrtab size_t cnt; } ElfStrtab; +typedef struct _Elf +{ + ElfArch * arch; +} Elf; + /* prototypes */ static int _elf_error(FormatPlugin * format); /* plug-in */ static int _elf_init(FormatPlugin * format, char const * arch); +static int _elf_exit(FormatPlugin * format); static char const * _elf_detect(FormatPlugin * format); static int _elf_decode(FormatPlugin * format); static int _elf_decode32(FormatPlugin * format); @@ -92,7 +98,6 @@ static ElfArch elf_arch[] = { "sparc64", EM_SPARCV9, ELFCLASS64, ELFDATA2MSB }, { NULL, '\0', '\0', '\0' } }; -static ElfArch * ea; static ElfSectionValues elf_section_values[] = { @@ -134,7 +139,7 @@ FormatPlugin format_plugin = ELFMAG, SELFMAG, _elf_init, - NULL, + _elf_exit, NULL, NULL, _elf_detect, @@ -158,16 +163,32 @@ static ElfArch * _init_arch(char const * arch); static int _elf_init(FormatPlugin * format, char const * arch) { - if((ea = _init_arch(arch)) == NULL) + Elf * elf; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, arch); +#endif + if((elf = object_new(sizeof(*elf))) == NULL) return -1; - if(ea->capacity == ELFCLASS32) + format->priv = elf; + if(arch == NULL) + { + elf->arch = NULL; + return 0; + } + if((elf->arch = _init_arch(arch)) == NULL) + { + object_delete(elf); + return -1; + } + if(elf->arch->capacity == ELFCLASS32) { if(_init_32(format) != 0) return -1; format->exit = _exit_32; format->section = _section_32; } - else if(ea->capacity == ELFCLASS64) + else if(elf->arch->capacity == ELFCLASS64) { if(_init_64(format) != 0) return -1; @@ -191,6 +212,19 @@ static ElfArch * _init_arch(char const * arch) } +/* elf_exit */ +static int _elf_exit(FormatPlugin * format) +{ + Elf * elf = format->priv; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + object_delete(elf); + return 0; +} + + /* elf_detect */ static char const * _detect_32(FormatPlugin * format, Elf32_Ehdr * ehdr); static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr); @@ -555,8 +589,13 @@ static int es32_cnt = 0; static int _init_32(FormatPlugin * format) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; Elf32_Ehdr hdr; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif memset(&hdr, 0, sizeof(hdr)); memcpy(&hdr.e_ident, ELFMAG, SELFMAG); hdr.e_ident[EI_CLASS] = ELFCLASS32; @@ -612,12 +651,15 @@ static int _exit_32(FormatPlugin * format) free(shstrtab.buf); shstrtab.buf = NULL; shstrtab.cnt = 0; + ret |= _elf_exit(format); return ret; } static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; Elf32_Ehdr hdr; if(es32_cnt == 0) @@ -648,6 +690,8 @@ static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset) static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; Elf32_Shdr hdr; int i; @@ -721,8 +765,13 @@ static int es64_cnt = 0; static int _init_64(FormatPlugin * format) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; Elf64_Ehdr hdr; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif memset(&hdr, 0, sizeof(hdr)); memcpy(&hdr.e_ident, ELFMAG, SELFMAG); hdr.e_ident[EI_CLASS] = ELFCLASS64; @@ -777,12 +826,15 @@ static int _exit_64(FormatPlugin * format) free(shstrtab.buf); shstrtab.buf = NULL; shstrtab.cnt = 0; + ret |= _elf_exit(format); return ret; } static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; Elf64_Ehdr hdr; if(es64_cnt == 0) @@ -813,6 +865,8 @@ static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset) static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset) { FormatPluginHelper * helper = format->helper; + Elf * elf = format->priv; + ElfArch * ea = elf->arch; int i; if(helper->seek(helper->format, 0, SEEK_END) < 0) diff --git a/src/format/java.c b/src/format/java.c index fdb5295..a3c3a33 100644 --- a/src/format/java.c +++ b/src/format/java.c @@ -138,6 +138,11 @@ static int _java_init(FormatPlugin * format, char const * arch) JavaHeader jh; JavaPlugin * java; + if(arch == NULL) + { + format->priv = NULL; + return 0; + } if(strcmp(arch, "java") != 0) return error_set_code(1, "%s: %s", arch, "Unsupported architecture for java"); diff --git a/src/format/pe.c b/src/format/pe.c index a805fca..909e234 100644 --- a/src/format/pe.c +++ b/src/format/pe.c @@ -124,6 +124,8 @@ static int _pe_init(FormatPlugin * format, char const * arch) struct pe_msdos pm; struct pe_header ph; + if(arch == NULL) + return 0; if((machine = _pe_get_machine(arch)) < 0) return -1; memset(&pm, 0, sizeof(pm)); diff --git a/src/project.conf b/src/project.conf index 195e91f..f9135b5 100644 --- a/src/project.conf +++ b/src/project.conf @@ -40,10 +40,10 @@ depends=../include/Asm/arch.h,../include/Asm/asm.h,arch.h,code.h,../config.h depends=../include/Asm.h,code.h,parser.h,../config.h [code.c] -depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,arch.h,code.h,format.h +depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,arch.h,code.h,format.h,../config.h [deasm.c] -depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,../config.h +depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h [format.c] depends=../include/Asm/asm.h,../include/Asm/format.h,code.h,format.h,../config.h