diff --git a/include/Asm/asm.h b/include/Asm/asm.h index eab8e01..6ef97d6 100644 --- a/include/Asm/asm.h +++ b/include/Asm/asm.h @@ -41,6 +41,7 @@ char const * as_get_format_name(As * as); /* useful */ int as_decode(As * as, char const * buffer, size_t size); +int as_decode_file(As * as, char const * filename, FILE * fp); int as_parse(As * as, char const * infile, char const * outfile); int as_open(As * as, char const * outfile); diff --git a/src/arch.c b/src/arch.c index d8c4003..f380ffd 100644 --- a/src/arch.c +++ b/src/arch.c @@ -63,6 +63,7 @@ struct _Arch /* prototypes */ /* callbacks */ static char const * _arch_get_filename(Arch * arch); +static ssize_t _arch_read(Arch * arch, void * buf, size_t size); static ssize_t _arch_read_buffer(Arch * arch, void * buf, size_t size); static ssize_t _arch_write(Arch * arch, void const * buf, size_t size); @@ -489,6 +490,23 @@ static void _decode_print(ArchInstructionCall * call) } +/* arch_decode_at */ +int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base) +{ + int ret; + + if(arch->fp == NULL) + return -error_set_code(1, "%s", strerror(ENOSYS)); + if(fseek(arch->fp, offset, SEEK_SET) != 0) + return -error_set_code(1, "%s", strerror(errno)); + /* FIXME implement size, consider offset and base */ + if((ret = arch_decode(arch)) == 0 + && fseek(arch->fp, offset + size, SEEK_SET) != 0) + ret = -error_set_code(1, "%s", strerror(errno)); + return ret; +} + + /* arch_exit */ int arch_exit(Arch * arch) { @@ -519,7 +537,7 @@ int arch_init(Arch * arch, char const * filename, FILE * fp) arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode; arch->helper.get_register_by_id_size = arch_get_register_by_id_size; arch->helper.get_register_by_name_size = arch_get_register_by_name_size; - arch->helper.read = NULL; + arch->helper.read = _arch_read; arch->helper.write = _arch_write; arch->plugin->helper = &arch->helper; return 0; @@ -568,6 +586,21 @@ static char const * _arch_get_filename(Arch * arch) } +/* arch_read */ +static ssize_t _arch_read(Arch * arch, void * buf, size_t size) +{ + if(fread(buf, size, 1, arch->fp) == 1) + return size; + if(ferror(arch->fp)) + return -error_set_code(1, "%s: %s", arch->filename, + strerror(errno)); + if(feof(arch->fp)) + return -error_set_code(1, "%s: %s", arch->filename, + "End of file reached"); + return -error_set_code(1, "%s: %s", arch->filename, "Read error"); +} + + /* arch_read_buffer */ static ssize_t _arch_read_buffer(Arch * arch, void * buf, size_t size) { diff --git a/src/arch.h b/src/arch.h index a29be9b..258128c 100644 --- a/src/arch.h +++ b/src/arch.h @@ -60,5 +60,6 @@ int arch_write(Arch * arch, ArchInstruction * instruction, /* disassembly */ int arch_decode(Arch * arch); +int arch_decode_at(Arch * arch, off_t offset, size_t size, off_t base); #endif /* !ASM_ARCH_H */ diff --git a/src/asm.c b/src/asm.c index d906cde..2bde581 100644 --- a/src/asm.c +++ b/src/asm.c @@ -154,6 +154,21 @@ int as_decode(As * as, char const * buffer, size_t size) } +/* as_decode_file */ +int as_decode_file(As * as, char const * filename, FILE * fp) +{ + int ret; + + if(fp != NULL) + return code_decode_file(as->code, filename, fp); + if((fp = fopen(filename, "r")) == NULL) + return -error_set_code(1, "%s: %s", filename, strerror(errno)); + ret = code_decode_file(as->code, filename, fp); + fclose(fp); + return ret; +} + + /* as_parse */ int as_parse(As * as, char const * infile, char const * outfile) { diff --git a/src/code.c b/src/code.c index e0eb1ea..c07a743 100644 --- a/src/code.c +++ b/src/code.c @@ -137,6 +137,35 @@ int code_decode(Code * code, char const * buffer, size_t size) arch_exit(code->arch); return ret; } + + +/* code_decode_file */ +static int _decode_file_callback(void * priv, char const * section, + off_t offset, size_t size, off_t base); + +int code_decode_file(Code * code, char const * filename, FILE * fp) +{ + int ret; + + arch_init(code->arch, filename, fp); + format_init(code->format, filename, fp); + ret = format_decode(code->format, _decode_file_callback, code); + format_exit(code->format); + arch_exit(code->arch); + return ret; +} + +static int _decode_file_callback(void * priv, char const * section, + off_t offset, size_t size, off_t base) +{ + Code * code = priv; + + if(section != NULL) + printf("%s%s:\n", "\nDisassembly of section ", section); + return arch_decode_at(code->arch, offset, size, base); +} + + #if 0 static ArchInstruction * _decode_size(Code * code, size_t * size, ArchInstruction * ai); diff --git a/src/code.h b/src/code.h index ead452d..0fe61e7 100644 --- a/src/code.h +++ b/src/code.h @@ -50,5 +50,6 @@ int code_section(Code * code, char const * section); /* disassembly */ int code_decode(Code * code, char const * buffer, size_t size); +int code_decode_file(Code * code, char const * filename, FILE * fp); #endif /* !ASM_CODE_H */ diff --git a/src/deasm.c b/src/deasm.c index 8c29a22..acc3d98 100644 --- a/src/deasm.c +++ b/src/deasm.c @@ -53,7 +53,6 @@ typedef struct _DeasmFormat typedef struct _Deasm { char const * arch; - As * as; FormatPluginHelper helper; DeasmFormat * format; @@ -108,7 +107,6 @@ static int _deasm(char const * arch, char const * format, Deasm deasm; deasm.arch = arch; - deasm.as = NULL; deasm.helper.format = &deasm; deasm.helper.read = _deasm_helper_read; deasm.helper.seek = _deasm_helper_seek; @@ -123,8 +121,6 @@ static int _deasm(char const * arch, char const * format, 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) @@ -205,6 +201,7 @@ static int _deasm_do(Deasm * deasm) static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format) { int ret; + As * as; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format->name); @@ -217,11 +214,12 @@ static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format) if((deasm->arch = format->detect(format)) == NULL) return -1; } - if((deasm->as = as_new(deasm->arch, format->name)) == NULL) + if((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); + printf("\n%s: %s-%s\n", deasm->filename, format->name, as_get_arch_name( + as)); + ret = as_decode_file(as, deasm->filename, deasm->fp); + as_delete(as); return ret; } diff --git a/src/format.c b/src/format.c index 6f9485b..1354b64 100644 --- a/src/format.c +++ b/src/format.c @@ -39,6 +39,11 @@ struct _Format /* file */ char const * filename; FILE * fp; + + /* diassembly */ + int (*decode_callback)(void * priv, char const * section, off_t offset, + size_t size, off_t base); + void * decode_priv; }; @@ -105,6 +110,37 @@ 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); + +int format_decode(Format * format, int (*callback)(void * priv, + char const * section, off_t offset, size_t size, + off_t base), void * priv) +{ + int ret; + + 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->decode_callback = callback; + format->decode_priv = priv; + ret = format->plugin->decode(format->plugin); + format->decode_callback = NULL; + format->decode_priv = 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) +{ + return format->decode_callback(format->decode_priv, section, offset, + size, base); +} + + /* format_exit */ int format_exit(Format * format) { @@ -116,6 +152,7 @@ int format_exit(Format * format) 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; @@ -144,6 +181,7 @@ int format_init(Format * format, char const * filename, FILE * fp) 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; diff --git a/src/format.h b/src/format.h index 307bc7d..528df34 100644 --- a/src/format.h +++ b/src/format.h @@ -38,4 +38,9 @@ int format_exit(Format * format); int format_function(Format * format, char const * function); int format_section(Format * format, char const * section); +/* disassembly */ +int format_decode(Format * format, int (*callback)(void * priv, + char const * section, off_t offset, size_t size, + off_t base), void * priv); + #endif /* !ASM_FORMAT_H */