From 389f82aef4a989df45a5b927b840f73f9f05a048 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sun, 27 Nov 2011 21:02:46 +0000 Subject: [PATCH] Major re-design to facilitate code re-use from the library --- Makefile | 9 + include/Asm.h | 3 +- include/Asm/Makefile | 3 + include/Asm/arch.h | 8 +- include/Asm/asm.h | 29 +-- include/Asm/code.h | 76 ++++++ include/Asm/common.h | 43 ++-- include/Asm/format.h | 15 +- include/Asm/project.conf | 5 +- src/arch.c | 76 +++--- src/arch.h | 14 +- src/arch/Makefile | 56 +++- src/arch/amd64.c | 2 +- src/arch/arm.c | 10 +- src/arch/arm.h | 6 +- src/arch/armeb.c | 19 ++ src/arch/armel.c | 19 ++ src/arch/dalvik.c | 8 +- src/arch/i386.c | 2 +- src/arch/i386.h | 78 +++--- src/arch/i386_real.c | 2 +- src/arch/i486.c | 2 +- src/arch/i586.c | 2 +- src/arch/i686.c | 2 +- src/arch/java.c | 6 +- src/arch/mips.c | 8 +- src/arch/mips.h | 6 +- src/arch/mipseb.c | 19 ++ src/arch/mipsel.c | 19 ++ src/arch/project.conf | 34 ++- src/arch/sparc.c | 2 +- src/arch/sparc.h | 30 +-- src/arch/sparc64.c | 2 +- src/arch/yasep.c | 20 +- src/asm.c | 101 +++++--- src/code.c | 536 +++++++++++++++++++++------------------ src/code.h | 50 ++-- src/deasm.c | 70 ++++- src/format.c | 109 ++++++-- src/format.h | 17 +- src/format/dex.c | 151 ++++++----- src/format/elf.c | 78 +++++- src/format/flat.c | 23 +- src/format/java.c | 17 +- src/format/pe.c | 21 +- src/main.c | 53 +++- src/parser.c | 44 +++- src/parser.h | 4 +- test/Makefile | 28 +- test/armeb.S | 2 + test/armel.S | 2 + test/mipseb.S | 2 + test/mipsel.S | 2 + test/project.conf | 34 ++- 54 files changed, 1362 insertions(+), 617 deletions(-) create mode 100644 include/Asm/code.h create mode 100644 src/arch/armeb.c create mode 100644 src/arch/armel.c create mode 100644 src/arch/mipseb.c create mode 100644 src/arch/mipsel.c create mode 100644 test/armeb.S create mode 100644 test/armel.S create mode 100644 test/mipseb.S create mode 100644 test/mipsel.S diff --git a/Makefile b/Makefile index a79ef3f..6c52f71 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ dist: $(PACKAGE)-$(VERSION)/include/project.conf \ $(PACKAGE)-$(VERSION)/include/Asm/arch.h \ $(PACKAGE)-$(VERSION)/include/Asm/asm.h \ + $(PACKAGE)-$(VERSION)/include/Asm/code.h \ $(PACKAGE)-$(VERSION)/include/Asm/common.h \ $(PACKAGE)-$(VERSION)/include/Asm/format.h \ $(PACKAGE)-$(VERSION)/include/Asm/Makefile \ @@ -55,6 +56,8 @@ dist: $(PACKAGE)-$(VERSION)/src/project.conf \ $(PACKAGE)-$(VERSION)/src/arch/amd64.c \ $(PACKAGE)-$(VERSION)/src/arch/arm.c \ + $(PACKAGE)-$(VERSION)/src/arch/armeb.c \ + $(PACKAGE)-$(VERSION)/src/arch/armel.c \ $(PACKAGE)-$(VERSION)/src/arch/dalvik.c \ $(PACKAGE)-$(VERSION)/src/arch/i386.c \ $(PACKAGE)-$(VERSION)/src/arch/i386_real.c \ @@ -63,6 +66,8 @@ dist: $(PACKAGE)-$(VERSION)/src/arch/i686.c \ $(PACKAGE)-$(VERSION)/src/arch/java.c \ $(PACKAGE)-$(VERSION)/src/arch/mips.c \ + $(PACKAGE)-$(VERSION)/src/arch/mipseb.c \ + $(PACKAGE)-$(VERSION)/src/arch/mipsel.c \ $(PACKAGE)-$(VERSION)/src/arch/sparc.c \ $(PACKAGE)-$(VERSION)/src/arch/sparc64.c \ $(PACKAGE)-$(VERSION)/src/arch/yasep.c \ @@ -101,6 +106,8 @@ dist: $(PACKAGE)-$(VERSION)/src/format/project.conf \ $(PACKAGE)-$(VERSION)/test/amd64.S \ $(PACKAGE)-$(VERSION)/test/arm.S \ + $(PACKAGE)-$(VERSION)/test/armeb.S \ + $(PACKAGE)-$(VERSION)/test/armel.S \ $(PACKAGE)-$(VERSION)/test/dalvik.S \ $(PACKAGE)-$(VERSION)/test/i386.S \ $(PACKAGE)-$(VERSION)/test/i386_real.S \ @@ -108,6 +115,8 @@ dist: $(PACKAGE)-$(VERSION)/test/i586.S \ $(PACKAGE)-$(VERSION)/test/i686.S \ $(PACKAGE)-$(VERSION)/test/mips.S \ + $(PACKAGE)-$(VERSION)/test/mipseb.S \ + $(PACKAGE)-$(VERSION)/test/mipsel.S \ $(PACKAGE)-$(VERSION)/test/java.S \ $(PACKAGE)-$(VERSION)/test/sparc.S \ $(PACKAGE)-$(VERSION)/test/sparc64.S \ diff --git a/include/Asm.h b/include/Asm.h index 4cdd93d..d2f896e 100644 --- a/include/Asm.h +++ b/include/Asm.h @@ -27,9 +27,9 @@ # define _LITTLE_ENDIAN __LITTLE_ENDIAN # endif -# include "Asm/common.h" # include "Asm/arch.h" # include "Asm/asm.h" +# include "Asm/code.h" # include "Asm/format.h" @@ -70,5 +70,4 @@ # warning "Could not determine endian on your system" # endif - #endif /* !DEVEL_ASM_H */ diff --git a/include/Asm/Makefile b/include/Asm/Makefile index 73a8fff..76cb295 100644 --- a/include/Asm/Makefile +++ b/include/Asm/Makefile @@ -19,6 +19,8 @@ install: $(MKDIR) $(DESTDIR)$(PREFIX)/include/Devel/Asm $(INSTALL) -m 0644 -- asm.h $(DESTDIR)$(PREFIX)/include/Devel/Asm/asm.h $(MKDIR) $(DESTDIR)$(PREFIX)/include/Devel/Asm + $(INSTALL) -m 0644 -- code.h $(DESTDIR)$(PREFIX)/include/Devel/Asm/code.h + $(MKDIR) $(DESTDIR)$(PREFIX)/include/Devel/Asm $(INSTALL) -m 0644 -- common.h $(DESTDIR)$(PREFIX)/include/Devel/Asm/common.h $(MKDIR) $(DESTDIR)$(PREFIX)/include/Devel/Asm $(INSTALL) -m 0644 -- format.h $(DESTDIR)$(PREFIX)/include/Devel/Asm/format.h @@ -26,6 +28,7 @@ install: uninstall: $(RM) -- $(DESTDIR)$(PREFIX)/include/Devel/Asm/arch.h $(RM) -- $(DESTDIR)$(PREFIX)/include/Devel/Asm/asm.h + $(RM) -- $(DESTDIR)$(PREFIX)/include/Devel/Asm/code.h $(RM) -- $(DESTDIR)$(PREFIX)/include/Devel/Asm/common.h $(RM) -- $(DESTDIR)$(PREFIX)/include/Devel/Asm/format.h diff --git a/include/Asm/arch.h b/include/Asm/arch.h index 3a6031c..fa7aa38 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -20,7 +20,7 @@ # include # include -# include "asm.h" +# include "common.h" /* AsmArch */ @@ -198,14 +198,14 @@ typedef struct _ArchPluginHelper /* callbacks */ /* accessors */ char const * (*get_filename)(Arch * arch); - AsmFunction * (*get_function_by_id)(Arch * arch, AsmId id); + AsmFunction * (*get_function_by_id)(Arch * arch, AsmFunctionId id); ArchInstruction * (*get_instruction_by_opcode)(Arch * arch, uint8_t size, uint32_t opcode); ArchRegister * (*get_register_by_id_size)(Arch * arch, uint32_t id, uint32_t size); ArchRegister * (*get_register_by_name_size)(Arch * arch, char const * name, uint32_t size); - AsmString * (*get_string_by_id)(Arch * arch, AsmId id); + AsmString * (*get_string_by_id)(Arch * arch, AsmStringId id); /* assembly */ ssize_t (*write)(Arch * arch, void const * buf, size_t size); @@ -230,7 +230,7 @@ struct _ArchPlugin int (*init)(ArchPlugin * arch); void (*exit)(ArchPlugin * arch); - int (*write)(ArchPlugin * arch, ArchInstruction * instruction, + int (*encode)(ArchPlugin * arch, ArchInstruction * instruction, ArchInstructionCall * call); int (*decode)(ArchPlugin * arch, ArchInstructionCall * call); }; diff --git a/include/Asm/asm.h b/include/Asm/asm.h index 702d662..646d73b 100644 --- a/include/Asm/asm.h +++ b/include/Asm/asm.h @@ -18,7 +18,7 @@ #ifndef DEVEL_ASM_ASM_H # define DEVEL_ASM_ASM_H -# include "common.h" +# include "code.h" /* Asm */ @@ -47,24 +47,6 @@ int asm_set_arch(Asm * a, char const * arch); char const * asm_get_format(Asm * a); int asm_set_format(Asm * a, char const * format); -/* functions */ -AsmFunction * asm_get_function_by_name(Asm * a, char const * name); -int asm_set_function(Asm * a, char const * name, off_t offset, ssize_t size); - -/* labels */ -AsmLabel * asm_get_label_by_name(Asm * a, char const * label); -AsmLabel * asm_get_label_by_offset(Asm * a, off_t offset); -int asm_set_label(Asm * a, char const * label, off_t offset); - -/* sections */ -int asm_set_section(Asm * a, char const * name, off_t offset, ssize_t size); - -/* strings */ -AsmString * asm_get_string_by_id(Asm * a, AsmId id); -AsmString * asm_get_string_by_name(Asm * a, char const * name); -int asm_set_string(Asm * a, int id, char const * name, off_t offset, - ssize_t length); - /* useful */ /* detection */ @@ -84,10 +66,11 @@ int asm_open_assemble(Asm * a, char const * outfile); int asm_instruction(Asm * a, char const * name, unsigned int operands_cnt, ...); /* deassemble */ -int asm_deassemble(Asm * a, char const * buffer, size_t size); -int asm_open_deassemble(Asm * a, char const * filename, int raw); +AsmCode * asm_deassemble(Asm * a, char const * buffer, size_t size, + ArchInstructionCall ** calls, size_t * calls_cnt); +AsmCode * asm_open_deassemble(Asm * a, char const * filename, int raw); /* plug-in helpers */ -int asm_plugin_list(AsmPluginType type); +int asm_plugin_list(AsmPluginType type, int decode); -#endif /* !DEVEL_ASM_AS_H */ +#endif /* !DEVEL_ASM_COMMON_H */ diff --git a/include/Asm/code.h b/include/Asm/code.h new file mode 100644 index 0000000..0dfe4eb --- /dev/null +++ b/include/Asm/code.h @@ -0,0 +1,76 @@ +/* $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 . */ + + + +#ifndef DEVEL_ASM_CODE_H +# define DEVEL_ASM_CODE_H + +# include +# include "common.h" +# include "arch.h" + + +/* AsmCode */ +/* types */ +typedef struct _AsmCode AsmCode; + + +/* functions */ +/* accessors */ +char const * asmcode_get_arch(AsmCode * code); +ArchDescription * asmcode_get_arch_description(AsmCode * code); +char const * asmcode_get_filename(AsmCode * code); +char const * asmcode_get_format(AsmCode * code); + +int asmcode_set_function(AsmCode * code, int id, char const * name, + off_t offset, ssize_t size); +int asmcode_set_section(AsmCode * code, int id, char const * name, off_t offset, + ssize_t size, off_t base); +int asmcode_set_string(AsmCode * code, int id, char const * name, off_t offset, + ssize_t length); + +/* functions */ +AsmFunction * asmcode_get_function_by_id(AsmCode * code, AsmFunctionId id); +void asmcode_get_functions(AsmCode * code, AsmFunction ** functions, + size_t * functions_cnt); + +/* sections */ +AsmSection * asmcode_get_section_by_id(AsmCode * code, AsmSectionId id); +AsmSection * asmcode_get_section_by_name(AsmCode * code, char const * name); +void asmcode_get_sections(AsmCode * code, AsmSection ** sections, + size_t * sections_cnt); + +/* strings */ +AsmString * asmcode_get_string_by_id(AsmCode * code, AsmStringId id); + + +/* useful */ +/* assembly */ +int asmcode_function(AsmCode * code, char const * function); +int asmcode_instruction(AsmCode * code, ArchInstructionCall * call); +int asmcode_section(AsmCode * code, char const * section); + +/* deassembly */ +int asmcode_decode(AsmCode * code, int raw); +int asmcode_decode_at(AsmCode * code, off_t offset, size_t size, off_t base, + ArchInstructionCall ** calls, size_t * calls_cnt); +int asmcode_decode_buffer(AsmCode * code, char const * buffer, size_t size, + ArchInstructionCall ** calls, size_t * calls_cnt); +int asmcode_decode_section(AsmCode * code, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); +int asmcode_print(AsmCode * code, ArchInstructionCall * call); + +#endif /* !DEVEL_ASM_CODE_H */ diff --git a/include/Asm/common.h b/include/Asm/common.h index 88cfe45..698e951 100644 --- a/include/Asm/common.h +++ b/include/Asm/common.h @@ -23,28 +23,37 @@ /* common */ /* types */ -typedef unsigned int AsmId; +typedef int AsmElementId; -typedef struct _AsmFunction +typedef struct _AsmElement { - AsmId id; - char const * name; + AsmElementId id; + char * name; off_t offset; ssize_t size; -} AsmFunction; + off_t base; +} AsmElement; -typedef struct _AsmLabel +typedef enum _AsmElementType { - char const * name; - off_t offset; -} AsmLabel; + AET_FUNCTION, + AET_LABEL, + AET_SECTION, + AET_STRING +} AsmElementType; +# define AET_LAST AET_STRING +# define AET_COUNT (AET_LAST + 1) -typedef struct _AsmString -{ - int id; - char const * name; - off_t offset; - ssize_t length; -} AsmString; +typedef AsmElementId AsmFunctionId; +typedef struct _AsmElement AsmFunction; -#endif /* !DEVEL_ASM_AS_H */ +typedef AsmElementId AsmLabelId; +typedef struct _AsmElement AsmLabel; + +typedef AsmElementId AsmSectionId; +typedef struct _AsmElement AsmSection; + +typedef AsmElementId AsmStringId; +typedef struct _AsmElement AsmString; + +#endif /* !DEVEL_ASM_COMMON_H */ diff --git a/include/Asm/format.h b/include/Asm/format.h index 1f0aa1f..158e56c 100644 --- a/include/Asm/format.h +++ b/include/Asm/format.h @@ -35,6 +35,8 @@ typedef struct _FormatPluginHelper /* callbacks */ /* accessors */ char const * (*get_filename)(Format * format); + void (*get_functions)(Format * format, AsmFunction ** functions, + size_t * functions_cnt); /* useful */ ssize_t (*read)(Format * format, void * buf, size_t size); @@ -44,14 +46,17 @@ typedef struct _FormatPluginHelper ssize_t (*write)(Format * format, void const * buf, size_t size); /* disassembly */ - /* FIXME let a different architecture be specified in the callback */ - AsmString * (*get_string_by_id)(Format * format, AsmId id); + /* FIXME let a different architecture be specified in the callback? */ + AsmSection * (*get_section_by_id)(Format * format, AsmSectionId id); + AsmString * (*get_string_by_id)(Format * format, AsmStringId id); int (*set_function)(Format * format, int id, char const * name, off_t offset, ssize_t size); + int (*set_section)(Format * format, int id, char const * name, + off_t offset, ssize_t size, off_t base); int (*set_string)(Format * format, int id, char const * name, off_t offset, ssize_t size); - int (*decode)(Format * format, char const * section, - off_t offset, size_t size, off_t base); + int (*decode)(Format * format, off_t offset, size_t size, off_t base, + ArchInstructionCall ** calls, size_t * calls_cnt); } FormatPluginHelper; struct _FormatPlugin @@ -70,6 +75,8 @@ struct _FormatPlugin char const * (*detect)(FormatPlugin * format); int (*decode)(FormatPlugin * format, int raw); + int (*decode_section)(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); void * priv; }; diff --git a/include/Asm/project.conf b/include/Asm/project.conf index dee8b44..5677345 100644 --- a/include/Asm/project.conf +++ b/include/Asm/project.conf @@ -1,4 +1,4 @@ -includes=arch.h,asm.h,common.h,format.h +includes=arch.h,asm.h,code.h,common.h,format.h dist=Makefile [arch.h] @@ -7,6 +7,9 @@ install=$(PREFIX)/include/Devel/Asm [asm.h] install=$(PREFIX)/include/Devel/Asm +[code.h] +install=$(PREFIX)/include/Devel/Asm + [common.h] install=$(PREFIX)/include/Devel/Asm diff --git a/src/arch.c b/src/arch.c index 7e7a9e0..2d0ff67 100644 --- a/src/arch.c +++ b/src/arch.c @@ -46,7 +46,7 @@ struct _Arch size_t registers_cnt; /* internal */ - Code * code; + AsmCode * code; off_t base; char const * filename; FILE * fp; @@ -59,8 +59,8 @@ struct _Arch /* prototypes */ /* callbacks */ static char const * _arch_get_filename(Arch * arch); -static AsmFunction * _arch_get_function_by_id(Arch * arch, AsmId id); -static AsmString * _arch_get_string_by_id(Arch * arch, AsmId id); +static AsmFunction * _arch_get_function_by_id(Arch * arch, AsmFunctionId id); +static AsmString * _arch_get_string_by_id(Arch * arch, AsmStringId id); static ssize_t _arch_peek(Arch * arch, void * buf, size_t size); static ssize_t _arch_read(Arch * arch, void * buf, size_t size); static ssize_t _arch_peek_buffer(Arch * arch, void * buf, size_t size); @@ -127,6 +127,13 @@ void arch_delete(Arch * arch) /* accessors */ +/* arch_can_decode */ +int arch_can_decode(Arch * arch) +{ + return arch->plugin->decode != NULL; +} + + /* arch_get_description */ ArchDescription * arch_get_description(Arch * arch) { @@ -445,15 +452,18 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, /* useful */ /* arch_decode */ -int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt, off_t base) +int arch_decode(Arch * arch, AsmCode * code, off_t base, + ArchInstructionCall ** calls, size_t * calls_cnt) { int ret = 0; - ArchInstructionCall * c = NULL; - size_t c_cnt = 0; + ArchInstructionCall * c = *calls; + size_t c_cnt = *calls_cnt; ArchInstructionCall * p; size_t offset = 0; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%ld)\n", __func__, base); +#endif if(arch->plugin->decode == NULL) return -error_set_code(1, "%s: %s", arch->plugin->name, "Disassembly not supported"); @@ -477,22 +487,23 @@ int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, offset += p->size; c_cnt++; } - if(ret == 0) - { - *calls = c; - *calls_cnt = c_cnt; - } + *calls = c; + *calls_cnt = c_cnt; arch->code = NULL; return ret; } /* arch_decode_at */ -int arch_decode_at(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt, off_t offset, size_t size, off_t base) +int arch_decode_at(Arch * arch, AsmCode * code, off_t offset, size_t size, + off_t base, ArchInstructionCall ** calls, size_t * calls_cnt) { int ret; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%ld, %lu, %ld)\n", __func__, offset, size, + base); +#endif /* FIXME this only works for files */ if(arch->fp == NULL) return -error_set_code(1, "%s", strerror(ENOSYS)); @@ -503,7 +514,7 @@ int arch_decode_at(Arch * arch, Code * code, ArchInstructionCall ** calls, arch->code = code; arch->buffer_pos = offset; arch->buffer_cnt = offset + size; - if((ret = arch_decode(arch, code, calls, calls_cnt, base)) == 0 + if((ret = arch_decode(arch, code, base, calls, calls_cnt)) == 0 && fseek(arch->fp, offset + size, SEEK_SET) != 0) { free(*calls); /* XXX the pointer was updated anyway... */ @@ -513,6 +524,17 @@ int arch_decode_at(Arch * arch, Code * code, ArchInstructionCall ** calls, } +/* arch_encode */ +int arch_encode(Arch * arch, ArchInstruction * instruction, + ArchInstructionCall * call) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); +#endif + return arch->plugin->encode(arch->plugin, instruction, call); +} + + /* arch_exit */ int arch_exit(Arch * arch) { @@ -613,17 +635,6 @@ off_t arch_seek(Arch * arch, off_t offset, int whence) } -/* arch_write */ -int arch_write(Arch * arch, ArchInstruction * instruction, - ArchInstructionCall * call) -{ -#ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); -#endif - return arch->plugin->write(arch->plugin, instruction, call); -} - - /* private */ /* callbacks */ /* arch_get_filename */ @@ -634,16 +645,16 @@ static char const * _arch_get_filename(Arch * arch) /* arch_get_function_by_id */ -static AsmFunction * _arch_get_function_by_id(Arch * arch, AsmId id) +static AsmFunction * _arch_get_function_by_id(Arch * arch, AsmFunctionId id) { - return code_get_function_by_id(arch->code, id); + return asmcode_get_function_by_id(arch->code, id); } /* arch_get_string_by_id */ -static AsmString * _arch_get_string_by_id(Arch * arch, AsmId id) +static AsmString * _arch_get_string_by_id(Arch * arch, AsmStringId id) { - return code_get_string_by_id(arch->code, id); + return asmcode_get_string_by_id(arch->code, id); } @@ -653,7 +664,7 @@ static ssize_t _arch_peek(Arch * arch, void * buf, size_t size) ssize_t s; #ifdef DEBUG - fprintf(stderr, "DEBUG: %s(arch, %p, %zu)\n", __func__, buf, size); + fprintf(stderr, "DEBUG: %s(arch, %p, %lu)\n", __func__, buf, size); #endif if((s = _arch_read(arch, buf, size)) == -1) return -1; @@ -729,6 +740,9 @@ static off_t _arch_seek(Arch * arch, off_t offset, int whence) /* arch_seek_buffer */ static off_t _arch_seek_buffer(Arch * arch, off_t offset, int whence) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(arch, %ld, %d)\n", __func__, offset, whence); +#endif if(whence == SEEK_SET) { if(offset < 0 || (size_t)offset >= arch->buffer_cnt) diff --git a/src/arch.h b/src/arch.h index 6dbdf07..797ed1a 100644 --- a/src/arch.h +++ b/src/arch.h @@ -32,6 +32,8 @@ void arch_delete(Arch * arch); /* accessors */ +int arch_can_decode(Arch * arch); + ArchDescription * arch_get_description(Arch * arch); char const * arch_get_format(Arch * arch); char const * arch_get_name(Arch * arch); @@ -56,14 +58,14 @@ int arch_init_buffer(Arch * arch, char const * buffer, size_t size); int arch_exit(Arch * arch); /* assembly */ -int arch_write(Arch * arch, ArchInstruction * instruction, +int arch_encode(Arch * arch, ArchInstruction * instruction, ArchInstructionCall * call); -/* disassembly */ -int arch_decode(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt, off_t base); -int arch_decode_at(Arch * arch, Code * code, ArchInstructionCall ** calls, - size_t * calls_cnt, off_t offset, size_t size, off_t base); +/* deassembly */ +int arch_decode(Arch * arch, AsmCode * code, off_t base, + ArchInstructionCall ** calls, size_t * calls_cnt); +int arch_decode_at(Arch * arch, AsmCode * code, off_t offset, size_t size, + off_t base, ArchInstructionCall ** calls, size_t * calls_cnt); ssize_t arch_read(Arch * arch, void * buf, size_t cnt); off_t arch_seek(Arch * arch, off_t offset, int whence); diff --git a/src/arch/Makefile b/src/arch/Makefile index 3e2aff7..de2e65c 100644 --- a/src/arch/Makefile +++ b/src/arch/Makefile @@ -1,4 +1,4 @@ -TARGETS = amd64.so arm.so dalvik.so i386.so i386_real.so i486.so i586.so i686.so java.so mips.so sparc.so sparc64.so yasep.so +TARGETS = amd64.so arm.so armeb.so armel.so dalvik.so i386.so i386_real.so i486.so i586.so i686.so java.so mips.so mipseb.so mipsel.so sparc.so sparc64.so yasep.so PREFIX = /usr/local DESTDIR = LIBDIR = $(PREFIX)/lib @@ -32,6 +32,20 @@ arm_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) arm.so: $(arm_OBJS) $(CCSHARED) -o arm.so $(arm_OBJS) $(arm_LDFLAGS) +armeb_OBJS = armeb.o +armeb_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) +armeb_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) + +armeb.so: $(armeb_OBJS) + $(CCSHARED) -o armeb.so $(armeb_OBJS) $(armeb_LDFLAGS) + +armel_OBJS = armel.o +armel_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) +armel_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) + +armel.so: $(armel_OBJS) + $(CCSHARED) -o armel.so $(armel_OBJS) $(armel_LDFLAGS) + dalvik_OBJS = dalvik.o dalvik_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) dalvik_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) @@ -88,6 +102,20 @@ mips_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) mips.so: $(mips_OBJS) $(CCSHARED) -o mips.so $(mips_OBJS) $(mips_LDFLAGS) +mipseb_OBJS = mipseb.o +mipseb_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) +mipseb_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) + +mipseb.so: $(mipseb_OBJS) + $(CCSHARED) -o mipseb.so $(mipseb_OBJS) $(mipseb_LDFLAGS) + +mipsel_OBJS = mipsel.o +mipsel_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) +mipsel_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) + +mipsel.so: $(mipsel_OBJS) + $(CCSHARED) -o mipsel.so $(mipsel_OBJS) $(mipsel_LDFLAGS) + sparc_OBJS = sparc.o sparc_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) sparc_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) @@ -115,6 +143,12 @@ amd64.o: amd64.c amd64.ins amd64.reg common.ins null.ins i386.h i386.ins i386.re arm.o: arm.c arm.h arm.ins arm.reg common.ins null.ins $(CC) $(arm_CFLAGS) -c arm.c +armeb.o: armeb.c arm.o + $(CC) $(armeb_CFLAGS) -c armeb.c + +armel.o: armel.c arm.o + $(CC) $(armel_CFLAGS) -c armel.c + dalvik.o: dalvik.c common.ins null.ins dalvik.ins dalvik.reg $(CC) $(dalvik_CFLAGS) -c dalvik.c @@ -139,6 +173,12 @@ java.o: java.c common.ins null.ins mips.o: mips.c common.ins null.ins mips.h mips.ins mips.reg $(CC) $(mips_CFLAGS) -c mips.c +mipseb.o: mipseb.c mips.o + $(CC) $(mipseb_CFLAGS) -c mipseb.c + +mipsel.o: mipsel.c mips.o + $(CC) $(mipsel_CFLAGS) -c mipsel.c + sparc.o: sparc.c common.ins null.ins sparc.h sparc.ins sparc.reg $(CC) $(sparc_CFLAGS) -c sparc.c @@ -149,7 +189,7 @@ yasep.o: yasep.c common.ins null.ins yasep.ins yasep.reg $(CC) $(yasep_CFLAGS) -c yasep.c clean: - $(RM) -- $(amd64_OBJS) $(arm_OBJS) $(dalvik_OBJS) $(i386_OBJS) $(i386_real_OBJS) $(i486_OBJS) $(i586_OBJS) $(i686_OBJS) $(java_OBJS) $(mips_OBJS) $(sparc_OBJS) $(sparc64_OBJS) $(yasep_OBJS) + $(RM) -- $(amd64_OBJS) $(arm_OBJS) $(armeb_OBJS) $(armel_OBJS) $(dalvik_OBJS) $(i386_OBJS) $(i386_real_OBJS) $(i486_OBJS) $(i586_OBJS) $(i686_OBJS) $(java_OBJS) $(mips_OBJS) $(mipseb_OBJS) $(mipsel_OBJS) $(sparc_OBJS) $(sparc64_OBJS) $(yasep_OBJS) distclean: clean $(RM) -- $(TARGETS) @@ -160,6 +200,10 @@ install: $(TARGETS) $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- arm.so $(DESTDIR)$(LIBDIR)/asm/arch/arm.so $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch + $(INSTALL) -m 0644 -- armeb.so $(DESTDIR)$(LIBDIR)/asm/arch/armeb.so + $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch + $(INSTALL) -m 0644 -- armel.so $(DESTDIR)$(LIBDIR)/asm/arch/armel.so + $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- dalvik.so $(DESTDIR)$(LIBDIR)/asm/arch/dalvik.so $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- i386.so $(DESTDIR)$(LIBDIR)/asm/arch/i386.so @@ -176,6 +220,10 @@ install: $(TARGETS) $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- mips.so $(DESTDIR)$(LIBDIR)/asm/arch/mips.so $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch + $(INSTALL) -m 0644 -- mipseb.so $(DESTDIR)$(LIBDIR)/asm/arch/mipseb.so + $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch + $(INSTALL) -m 0644 -- mipsel.so $(DESTDIR)$(LIBDIR)/asm/arch/mipsel.so + $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- sparc.so $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so $(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch $(INSTALL) -m 0644 -- sparc64.so $(DESTDIR)$(LIBDIR)/asm/arch/sparc64.so @@ -185,6 +233,8 @@ install: $(TARGETS) uninstall: $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/amd64.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/arm.so + $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/armeb.so + $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/armel.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/dalvik.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i386.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i386_real.so @@ -193,6 +243,8 @@ uninstall: $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i686.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/java.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/mips.so + $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/mipseb.so + $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/mipsel.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc64.so $(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/yasep.so diff --git a/src/arch/amd64.c b/src/arch/amd64.c index d6b66e2..831c40a 100644 --- a/src/arch/amd64.c +++ b/src/arch/amd64.c @@ -88,6 +88,6 @@ ArchPlugin arch_plugin = _amd64_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/arm.c b/src/arch/arm.c index 0e0e1cc..9d33aff 100644 --- a/src/arch/arm.c +++ b/src/arch/arm.c @@ -19,6 +19,12 @@ #include "Asm.h" +/* constants */ +#ifndef ARCH_ENDIAN +# define ARCH_ENDIAN ARCH_ENDIAN_BOTH +#endif + + /* arm */ /* private */ /* types */ @@ -35,7 +41,7 @@ enum /* variables */ static ArchDescription _arm_description = { - "elf", ARCH_ENDIAN_BOTH, 32, 32, 32 + "elf", ARCH_ENDIAN, 32, 32, 32 }; #define REG(name, size, id) { "" # name, size, id }, @@ -70,6 +76,6 @@ ArchPlugin arch_plugin = _arm_instructions, NULL, NULL, - _arm_write, + _arm_encode, NULL }; diff --git a/src/arch/arm.h b/src/arch/arm.h index 3c1ed70..642c7fe 100644 --- a/src/arch/arm.h +++ b/src/arch/arm.h @@ -22,14 +22,14 @@ /* private */ /* prototypes */ /* plug-in */ -static int _arm_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _arm_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); /* functions */ /* plug-in */ -/* arm_write */ -static int _arm_write(ArchPlugin * plugin, ArchInstruction * instruction, +/* arm_encode */ +static int _arm_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/armeb.c b/src/arch/armeb.c new file mode 100644 index 0000000..1351320 --- /dev/null +++ b/src/arch/armeb.c @@ -0,0 +1,19 @@ +/* $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 . */ + + + +#define ARCH_ENDIAN ARCH_ENDIAN_BIG +#include "arm.c" diff --git a/src/arch/armel.c b/src/arch/armel.c new file mode 100644 index 0000000..8d61562 --- /dev/null +++ b/src/arch/armel.c @@ -0,0 +1,19 @@ +/* $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 . */ + + + +#define ARCH_ENDIAN ARCH_ENDIAN_LITTLE +#include "arm.c" diff --git a/src/arch/dalvik.c b/src/arch/dalvik.c index 570640a..5bd5fdd 100644 --- a/src/arch/dalvik.c +++ b/src/arch/dalvik.c @@ -79,7 +79,7 @@ static ArchInstruction _dalvik_instructions[] = /* prototypes */ /* plug-in */ -static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _dalvik_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); static int _dalvik_decode(ArchPlugin * plugin, ArchInstructionCall * call); @@ -95,15 +95,15 @@ ArchPlugin arch_plugin = _dalvik_instructions, NULL, NULL, - _dalvik_write, + _dalvik_encode, _dalvik_decode }; /* private */ /* functions */ -/* dalvik_write */ -static int _dalvik_write(ArchPlugin * plugin, ArchInstruction * instruction, +/* dalvik_encode */ +static int _dalvik_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/i386.c b/src/arch/i386.c index d05cf52..4492000 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -80,6 +80,6 @@ ArchPlugin arch_plugin = _i386_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/i386.h b/src/arch/i386.h index 72511a4..4161b6e 100644 --- a/src/arch/i386.h +++ b/src/arch/i386.h @@ -24,7 +24,7 @@ /* private */ /* prototypes */ static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call); -static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _i386_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); @@ -442,23 +442,23 @@ static int _decode_register(ArchPlugin * plugin, ArchInstructionCall * call, } -/* i386_write */ -static int _write_constant(ArchPlugin * plugin, +/* i386_encode */ +static int _encode_constant(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand); -static int _write_dregister(ArchPlugin * plugin, uint32_t * i, +static int _encode_dregister(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands); -static int _write_immediate(ArchPlugin * plugin, ArchOperand * operand); -static int _write_immediate8(ArchPlugin * plugin, uint8_t value); -static int _write_immediate16(ArchPlugin * plugin, uint16_t value); -static int _write_immediate24(ArchPlugin * plugin, uint32_t value); -static int _write_immediate32(ArchPlugin * plugin, uint32_t value); -static int _write_opcode(ArchPlugin * plugin, ArchInstruction * instruction); -static int _write_operand(ArchPlugin * plugin, uint32_t * i, +static int _encode_immediate(ArchPlugin * plugin, ArchOperand * operand); +static int _encode_immediate8(ArchPlugin * plugin, uint8_t value); +static int _encode_immediate16(ArchPlugin * plugin, uint16_t value); +static int _encode_immediate24(ArchPlugin * plugin, uint32_t value); +static int _encode_immediate32(ArchPlugin * plugin, uint32_t value); +static int _encode_opcode(ArchPlugin * plugin, ArchInstruction * instruction); +static int _encode_operand(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands); -static int _write_register(ArchPlugin * plugin, uint32_t * i, +static int _encode_register(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands); -static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _i386_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { uint32_t i; @@ -467,18 +467,18 @@ static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); #endif - if(_write_opcode(plugin, instruction) != 0) + if(_encode_opcode(plugin, instruction) != 0) return -1; definitions[0] = instruction->op1; definitions[1] = instruction->op2; definitions[2] = instruction->op3; for(i = 0; i < call->operands_cnt; i++) - if(_write_operand(plugin, &i, definitions, call->operands) != 0) + if(_encode_operand(plugin, &i, definitions, call->operands) != 0) return -1; return 0; } -static int _write_constant(ArchPlugin * plugin, +static int _encode_constant(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand) { ArchOperand ao; @@ -487,10 +487,10 @@ static int _write_constant(ArchPlugin * plugin, return 0; ao = *operand; ao.definition &= ~(AOM_FLAGS); - return _write_immediate(plugin, &ao); + return _encode_immediate(plugin, &ao); } -static int _write_dregister(ArchPlugin * plugin, uint32_t * i, +static int _encode_dregister(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands) { ArchPluginHelper * helper = plugin->helper; @@ -526,7 +526,7 @@ static int _write_dregister(ArchPlugin * plugin, uint32_t * i, << 3); if(operand->value.dregister.offset == 0) /* there is no offset */ - return _write_immediate(plugin, &ioperand); + return _encode_immediate(plugin, &ioperand); /* declare offset */ switch(AO_GET_OFFSET(definition) >> 3) { @@ -539,15 +539,15 @@ static int _write_dregister(ArchPlugin * plugin, uint32_t * i, default: return -error_set_code(1, "%s", "Invalid offset"); } - if(_write_immediate(plugin, &ioperand) != 0) + if(_encode_immediate(plugin, &ioperand) != 0) return -1; /* write offset */ ioperand.definition = AO_IMMEDIATE(0, AO_GET_OFFSET(definition), 0); ioperand.value.immediate.value = operand->value.dregister.offset; - return _write_immediate(plugin, &ioperand); + return _encode_immediate(plugin, &ioperand); } -static int _write_immediate(ArchPlugin * plugin, ArchOperand * operand) +static int _encode_immediate(ArchPlugin * plugin, ArchOperand * operand) { uint64_t value = operand->value.immediate.value; @@ -559,18 +559,18 @@ static int _write_immediate(ArchPlugin * plugin, ArchOperand * operand) case 0: return 0; case sizeof(uint8_t): - return _write_immediate8(plugin, value); + return _encode_immediate8(plugin, value); case sizeof(uint16_t): - return _write_immediate16(plugin, value); + return _encode_immediate16(plugin, value); case 3: - return _write_immediate24(plugin, value); + return _encode_immediate24(plugin, value); case sizeof(uint32_t): - return _write_immediate32(plugin, value); + return _encode_immediate32(plugin, value); } return -error_set_code(1, "%s", "Invalid size"); } -static int _write_immediate8(ArchPlugin * plugin, uint8_t value) +static int _encode_immediate8(ArchPlugin * plugin, uint8_t value) { ArchPluginHelper * helper = plugin->helper; @@ -579,7 +579,7 @@ static int _write_immediate8(ArchPlugin * plugin, uint8_t value) return 0; } -static int _write_immediate16(ArchPlugin * plugin, uint16_t value) +static int _encode_immediate16(ArchPlugin * plugin, uint16_t value) { ArchPluginHelper * helper = plugin->helper; @@ -589,7 +589,7 @@ static int _write_immediate16(ArchPlugin * plugin, uint16_t value) return 0; } -static int _write_immediate24(ArchPlugin * plugin, uint32_t value) +static int _encode_immediate24(ArchPlugin * plugin, uint32_t value) { ArchPluginHelper * helper = plugin->helper; @@ -599,7 +599,7 @@ static int _write_immediate24(ArchPlugin * plugin, uint32_t value) return 0; } -static int _write_immediate32(ArchPlugin * plugin, uint32_t value) +static int _encode_immediate32(ArchPlugin * plugin, uint32_t value) { ArchPluginHelper * helper = plugin->helper; @@ -609,7 +609,7 @@ static int _write_immediate32(ArchPlugin * plugin, uint32_t value) return 0; } -static int _write_opcode(ArchPlugin * plugin, ArchInstruction * instruction) +static int _encode_opcode(ArchPlugin * plugin, ArchInstruction * instruction) { ArchOperand operand; @@ -639,24 +639,24 @@ static int _write_opcode(ArchPlugin * plugin, ArchInstruction * instruction) default: return -error_set_code(1, "%s", "Invalid size"); } - return _write_immediate(plugin, &operand); + return _encode_immediate(plugin, &operand); } -static int _write_operand(ArchPlugin * plugin, uint32_t * i, +static int _encode_operand(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands) { switch(operands[*i].definition) { case AOT_CONSTANT: - return _write_constant(plugin, definitions[*i], + return _encode_constant(plugin, definitions[*i], &operands[*i]); case AOT_DREGISTER: - return _write_dregister(plugin, i, definitions, + return _encode_dregister(plugin, i, definitions, operands); case AOT_IMMEDIATE: - return _write_immediate(plugin, &operands[*i]); + return _encode_immediate(plugin, &operands[*i]); case AOT_REGISTER: - return _write_register(plugin, i, definitions, + return _encode_register(plugin, i, definitions, operands); case AOT_NONE: case AOT_DREGISTER2: @@ -666,7 +666,7 @@ static int _write_operand(ArchPlugin * plugin, uint32_t * i, return 0; } -static int _write_register(ArchPlugin * plugin, uint32_t * i, +static int _encode_register(ArchPlugin * plugin, uint32_t * i, ArchOperandDefinition * definitions, ArchOperand * operands) { ArchPluginHelper * helper = plugin->helper; @@ -703,5 +703,5 @@ static int _write_register(ArchPlugin * plugin, uint32_t * i, | (AO_GET_VALUE(definition) << 3); else ioperand.value.immediate.value = ar->id; - return _write_immediate(plugin, &ioperand); + return _encode_immediate(plugin, &ioperand); } diff --git a/src/arch/i386_real.c b/src/arch/i386_real.c index 2180d83..1860630 100644 --- a/src/arch/i386_real.c +++ b/src/arch/i386_real.c @@ -81,6 +81,6 @@ ArchPlugin arch_plugin = _i386_real_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/i486.c b/src/arch/i486.c index a07206c..fad841c 100644 --- a/src/arch/i486.c +++ b/src/arch/i486.c @@ -81,6 +81,6 @@ ArchPlugin arch_plugin = _i486_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/i586.c b/src/arch/i586.c index a3434c7..fe9c52d 100644 --- a/src/arch/i586.c +++ b/src/arch/i586.c @@ -82,6 +82,6 @@ ArchPlugin arch_plugin = _i586_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/i686.c b/src/arch/i686.c index 4a234e4..fca01a9 100644 --- a/src/arch/i686.c +++ b/src/arch/i686.c @@ -84,6 +84,6 @@ ArchPlugin arch_plugin = _i686_instructions, NULL, NULL, - _i386_write, + _i386_encode, _i386_decode }; diff --git a/src/arch/java.c b/src/arch/java.c index 07fa4ec..cbcc5d8 100644 --- a/src/arch/java.c +++ b/src/arch/java.c @@ -251,7 +251,7 @@ static ArchInstruction _java_instructions[] = /* prototypes */ /* plug-in */ -static int _java_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _java_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); static int _java_decode(ArchPlugin * plugin, ArchInstructionCall * call); @@ -267,7 +267,7 @@ ArchPlugin arch_plugin = _java_instructions, NULL, NULL, - _java_write, + _java_encode, _java_decode }; @@ -275,7 +275,7 @@ ArchPlugin arch_plugin = /* private */ /* functions */ /* plug-in */ -static int _java_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _java_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/mips.c b/src/arch/mips.c index 4ed41fe..08728ef 100644 --- a/src/arch/mips.c +++ b/src/arch/mips.c @@ -18,13 +18,17 @@ #include #include "Asm.h" +#ifndef ARCH_ENDIAN +# define ARCH_ENDIAN ARCH_ENDIAN_BOTH +#endif + /* mips */ /* private */ /* variables */ static ArchDescription _mips_description = { - "elf", ARCH_ENDIAN_BOTH, 32, 32, 32 + "elf", ARCH_ENDIAN, 32, 32, 32 }; #define REG(name, size, id) { "" # name, size, id }, @@ -59,6 +63,6 @@ ArchPlugin arch_plugin = _mips_instructions, NULL, NULL, - _mips_write, + _mips_encode, NULL }; diff --git a/src/arch/mips.h b/src/arch/mips.h index acce2c7..665b603 100644 --- a/src/arch/mips.h +++ b/src/arch/mips.h @@ -22,14 +22,14 @@ /* private */ /* prototypes */ /* plug-in */ -static int _mips_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _mips_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); /* functions */ /* plug-in */ -/* mips_write */ -static int _mips_write(ArchPlugin * plugin, ArchInstruction * instruction, +/* mips_encode */ +static int _mips_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/mipseb.c b/src/arch/mipseb.c new file mode 100644 index 0000000..9636e5f --- /dev/null +++ b/src/arch/mipseb.c @@ -0,0 +1,19 @@ +/* $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 . */ + + + +#define ARCH_ENDIAN ARCH_ENDIAN_BIG +#include "mips.c" diff --git a/src/arch/mipsel.c b/src/arch/mipsel.c new file mode 100644 index 0000000..acf5ae0 --- /dev/null +++ b/src/arch/mipsel.c @@ -0,0 +1,19 @@ +/* $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 . */ + + + +#define ARCH_ENDIAN ARCH_ENDIAN_LITTLE +#include "mips.c" diff --git a/src/arch/project.conf b/src/arch/project.conf index f3c11dd..6a13f47 100644 --- a/src/arch/project.conf +++ b/src/arch/project.conf @@ -1,4 +1,4 @@ -targets=amd64,arm,dalvik,i386,i386_real,i486,i586,i686,java,mips,sparc,sparc64,yasep +targets=amd64,arm,armeb,armel,dalvik,i386,i386_real,i486,i586,i686,java,mips,mipseb,mipsel,sparc,sparc64,yasep cppflags_force=-I ../../include cflags_force=-W `pkg-config --cflags libSystem` cflags=-Wall -g -O2 -fPIC -pedantic @@ -20,6 +20,22 @@ install=$(LIBDIR)/asm/arch [arm.c] depends=arm.h,arm.ins,arm.reg,common.ins,null.ins +[armeb] +type=plugin +sources=armeb.c +install=$(LIBDIR)/asm/arch + +[armeb.c] +depends=arm.o + +[armel] +type=plugin +sources=armel.c +install=$(LIBDIR)/asm/arch + +[armel.c] +depends=arm.o + [dalvik] type=plugin sources=dalvik.c @@ -84,6 +100,22 @@ install=$(LIBDIR)/asm/arch [mips.c] depends=common.ins,null.ins,mips.h,mips.ins,mips.reg +[mipseb] +type=plugin +sources=mipseb.c +install=$(LIBDIR)/asm/arch + +[mipseb.c] +depends=mips.o + +[mipsel] +type=plugin +sources=mipsel.c +install=$(LIBDIR)/asm/arch + +[mipsel.c] +depends=mips.o + [sparc] type=plugin sources=sparc.c diff --git a/src/arch/sparc.c b/src/arch/sparc.c index e524140..0319da1 100644 --- a/src/arch/sparc.c +++ b/src/arch/sparc.c @@ -59,6 +59,6 @@ ArchPlugin arch_plugin = _sparc_instructions, NULL, NULL, - _sparc_write, + _sparc_encode, _sparc_decode }; diff --git a/src/arch/sparc.h b/src/arch/sparc.h index 3752418..e3dbb8f 100644 --- a/src/arch/sparc.h +++ b/src/arch/sparc.h @@ -23,7 +23,7 @@ /* prototypes */ /* plug-in */ static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call); -static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _sparc_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); @@ -71,17 +71,17 @@ static int _sparc_decode(ArchPlugin * plugin, ArchInstructionCall * call) } -/* sparc_write */ -static int _write_branch(ArchInstruction * instruction, +/* sparc_encode */ +static int _encode_branch(ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode); -static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_integer(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode); -static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_loadstore(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode); -static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_sethi(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode); -static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _sparc_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; @@ -89,22 +89,22 @@ static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, if((opcode & 0xc0000000) == 0xc0000000) { - if(_write_loadstore(plugin, instruction, call, &opcode) != 0) + if(_encode_loadstore(plugin, instruction, call, &opcode) != 0) return -1; } else if((opcode & 0xc1c00000) == 0x01000000) { - if(_write_sethi(plugin, instruction, call, &opcode) != 0) + if(_encode_sethi(plugin, instruction, call, &opcode) != 0) return -1; } else if((opcode & 0xc0000000) == 0x80000000) { - if(_write_integer(plugin, instruction, call, &opcode) != 0) + if(_encode_integer(plugin, instruction, call, &opcode) != 0) return -1; } else if((opcode & 0xc1c00000) == 0x00800000) { - if(_write_branch(instruction, call, &opcode) != 0) + if(_encode_branch(instruction, call, &opcode) != 0) return -1; } else @@ -116,7 +116,7 @@ static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction, return 0; } -static int _write_branch(ArchInstruction * instruction, +static int _encode_branch(ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode) { uint32_t disp; @@ -131,7 +131,7 @@ static int _write_branch(ArchInstruction * instruction, return 0; } -static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_integer(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode) { ArchPluginHelper * helper = plugin->helper; @@ -180,7 +180,7 @@ static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction, return 0; } -static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_loadstore(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode) { ArchPluginHelper * helper = plugin->helper; @@ -266,7 +266,7 @@ static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction, return 0; } -static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_sethi(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call, uint32_t * opcode) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/arch/sparc64.c b/src/arch/sparc64.c index bbe96d1..31724db 100644 --- a/src/arch/sparc64.c +++ b/src/arch/sparc64.c @@ -58,6 +58,6 @@ ArchPlugin arch_plugin = _sparc64_instructions, NULL, NULL, - _sparc_write, + _sparc_encode, _sparc_decode }; diff --git a/src/arch/yasep.c b/src/arch/yasep.c index 0ea6999..05d7ea9 100644 --- a/src/arch/yasep.c +++ b/src/arch/yasep.c @@ -41,7 +41,7 @@ static ArchInstruction _yasep_instructions[] = /* prototypes */ /* plug-in */ -static int _yasep_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _yasep_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); @@ -56,7 +56,7 @@ ArchPlugin arch_plugin = _yasep_instructions, NULL, NULL, - _yasep_write, + _yasep_encode, NULL }; @@ -64,21 +64,21 @@ ArchPlugin arch_plugin = /* private */ /* functions */ /* plug-in */ -/* yasep_write */ -static int _write_16(ArchPlugin * plugin, ArchInstruction * instruction, +/* yasep_encode */ +static int _encode_16(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); -static int _write_32(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_32(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call); -static int _yasep_write(ArchPlugin * plugin, ArchInstruction * instruction, +static int _yasep_encode(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { return (instruction->opcode & 0x1) - ? _write_32(plugin, instruction, call) - : _write_16(plugin, instruction, call); + ? _encode_32(plugin, instruction, call) + : _encode_16(plugin, instruction, call); } -static int _write_16(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_16(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; @@ -91,7 +91,7 @@ static int _write_16(ArchPlugin * plugin, ArchInstruction * instruction, return 0; } -static int _write_32(ArchPlugin * plugin, ArchInstruction * instruction, +static int _encode_32(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { ArchPluginHelper * helper = plugin->helper; diff --git a/src/asm.c b/src/asm.c index 5da6220..3ea5fdf 100644 --- a/src/asm.c +++ b/src/asm.c @@ -24,7 +24,10 @@ #include #include #include +#include "Asm/asm.h" +#include "arch.h" #include "code.h" +#include "format.h" #include "parser.h" #include "../config.h" @@ -34,10 +37,12 @@ /* types */ struct _Asm { +#if 1 /* FIXME probably useless now */ char * arch; char * format; +#endif - Code * code; + AsmCode * code; }; typedef struct _AsmPluginDescription @@ -96,7 +101,7 @@ void asm_delete(Asm * a) fprintf(stderr, "DEBUG: %s()\n", __func__); #endif if(a->code != NULL) - code_delete(a->code); + asmcode_delete(a->code); string_delete(a->format); string_delete(a->arch); object_delete(a); @@ -107,6 +112,8 @@ void asm_delete(Asm * a) /* asm_get_arch */ char const * asm_get_arch(Asm * a) { + if(a->code != NULL) + return asmcode_get_arch(a->code); return a->arch; } @@ -114,6 +121,8 @@ char const * asm_get_arch(Asm * a) /* asm_get_format */ char const * asm_get_format(Asm * a) { + if(a->code != NULL) + return asmcode_get_format(a->code); return a->format; } @@ -147,15 +156,7 @@ int asm_set_format(Asm * a, char const * format) /* asm_set_function */ int asm_set_function(Asm * a, char const * name, off_t offset, ssize_t size) { - return code_set_function(a->code, -1, name, offset, size); -} - - -/* asm_set_section */ -int asm_set_section(Asm * a, char const * name, off_t offset, ssize_t size) -{ - /* FIXME fully implement */ - return code_section(a->code, name); + return asmcode_set_function(a->code, -1, name, offset, size); } @@ -176,6 +177,21 @@ int asm_assemble(Asm * a, AsmPrefs * prefs, char const * infile, } +/* asm_assemble_string */ +int asm_assemble_string(Asm * a, AsmPrefs * prefs, char const * outfile, + char const * string) +{ + int ret; + + /* FIXME should also allow standard output, or return a buffer */ + if(_asm_open(a, outfile) != 0) + return -1; + ret = parser_string(prefs, a->code, string); + ret |= asm_close(a); + return ret; +} + + /* asm_close */ int asm_close(Asm * a) { @@ -183,29 +199,28 @@ int asm_close(Asm * a) if(a->code == NULL) return -error_set_code(1, "%s", "No file opened"); - ret = code_close(a->code); + ret = asmcode_close(a->code); a->code = NULL; return ret; } /* asm_deassemble */ -int asm_deassemble(Asm * a, char const * buffer, size_t size) +AsmCode * asm_deassemble(Asm * a, char const * buffer, size_t size, + ArchInstructionCall ** calls, size_t * calls_cnt) { - int ret; - if(_asm_open(a, NULL) != 0) - return -1; - ret = code_decode_buffer(a->code, buffer, size); - asm_close(a); - return ret; + return NULL; + if(asmcode_decode_buffer(a->code, buffer, size, calls, calls_cnt) != 0) + return NULL; + return a->code; } /* asm_function */ int asm_function(Asm * a, char const * name) { - return code_function(a->code, name); + return asmcode_function(a->code, name); } @@ -240,7 +255,7 @@ int asm_instruction(Asm * a, char const * name, unsigned int operands_cnt, ...) } va_end(ap); } - return code_instruction(a->code, &call); + return asmcode_instruction(a->code, &call); } @@ -252,24 +267,26 @@ int asm_open_assemble(Asm * a, char const * outfile) /* asm_open_deassemble */ -int asm_open_deassemble(Asm * a, char const * filename, int raw) +AsmCode * asm_open_deassemble(Asm * a, char const * filename, int raw) { #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; - if(code_decode(a->code, raw) != 0) - return -1; - return 0; + { + error_set_code(1, "%s: Operation in progress", + asmcode_get_filename(a->code)); + return NULL; + } + if((a->code = asmcode_new_file(a->arch, a->format, filename)) == NULL + || asmcode_decode(a->code, raw) != 0) + return NULL; + return a->code; } /* asm_plugin_list */ -int asm_plugin_list(AsmPluginType type) +int asm_plugin_list(AsmPluginType type, int decode) { AsmPluginDescription const * aspd; char * path; @@ -277,6 +294,8 @@ int asm_plugin_list(AsmPluginType type) struct dirent * de; size_t len; char const * sep = ""; + Arch * arch; + Format * format; aspd = &_asm_plugin_description[type]; fprintf(stderr, "%s%s%s", "Available ", aspd->description, @@ -303,7 +322,21 @@ int asm_plugin_list(AsmPluginType type) if(strcmp(".so", &de->d_name[len - 3]) != 0) continue; de->d_name[len - 3] = '\0'; - fprintf(stderr, "%s%s", sep, de->d_name); + if(type == APT_ARCH && (arch = arch_new(de->d_name)) != NULL + && (decode == 0 || arch_can_decode(arch))) + { + fprintf(stderr, "%s%s", sep, de->d_name); + arch_delete(arch); + } + else if(type == APT_FORMAT && (format = format_new(de->d_name)) + != NULL && (decode == 0 + || format_can_decode(format))) + { + fprintf(stderr, "%s%s", sep, de->d_name); + format_delete(format); + } + else + continue; sep = ", "; } free(path); @@ -344,10 +377,10 @@ static int _asm_open(Asm * a, char const * outfile) return -1; if(a->code != NULL) return -error_set_code(1, "%s: Operation in progress", - code_get_filename(a->code)); - if((a->code = code_new(arch, format)) == NULL) + asmcode_get_filename(a->code)); + if((a->code = asmcode_new(arch, format)) == NULL) return -1; if(outfile == NULL) return 0; - return code_open(a->code, outfile); + return asmcode_open(a->code, outfile); } diff --git a/src/code.c b/src/code.c index c378cab..0a5ae10 100644 --- a/src/code.c +++ b/src/code.c @@ -12,6 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +/* TODO: + * - lookup if a symbol is defined for each offset + * - derive functions/labels/etc from symbols (type, id, name, union) */ @@ -30,26 +33,10 @@ #include "../config.h" -/* Code */ +/* AsmCode */ /* private */ /* types */ -typedef struct _CodeString -{ - int id; - char * name; - off_t offset; - ssize_t length; -} CodeString; - -typedef struct _CodeFunction -{ - int id; - char * name; - off_t offset; - ssize_t size; -} CodeFunction; - -struct _Code +struct _AsmCode { Arch * arch; ArchDescription * description; @@ -57,42 +44,53 @@ struct _Code char * filename; FILE * fp; - /* functions */ - CodeFunction * functions; - size_t functions_cnt; - - /* strings */ - CodeString * strings; - size_t strings_cnt; + /* elements */ + AsmElement * elements[AET_COUNT]; + size_t elements_cnt[AET_COUNT]; }; /* prototypes */ -/* functions */ -static void _code_function_delete_all(Code * code); +/* elements */ +static void _asmcode_element_delete_all(AsmCode * code, AsmElementType type); -static CodeFunction * _code_function_get_by_id(Code * code, AsmId id); -static int _code_function_set(CodeFunction * codefunction, int id, +static AsmElement * _asmcode_element_get_by_id(AsmCode * code, + AsmElementType type, AsmElementId id); +static int _asmcode_element_set(AsmElement * element, AsmElementId id, + char const * name, off_t offset, ssize_t size, off_t base); + +/* functions */ +static void _asmcode_function_delete_all(AsmCode * code); +static AsmFunction * _asmcode_function_get_by_id(AsmCode * code, + AsmFunctionId id); +static int _asmcode_function_set(AsmFunction * codefunction, AsmFunctionId id, char const * name, off_t offset, ssize_t size); -static CodeFunction * _code_function_append(Code * code); +static AsmFunction * _asmcode_function_append(AsmCode * code); + +/* sections */ +static AsmSection * _asmcode_section_get_by_id(AsmCode * code, AsmSectionId id); +static int _asmcode_section_set(AsmSection * section, int id, char const * name, + off_t offset, ssize_t size, off_t base); + +static AsmSection * _asmcode_section_append(AsmCode * code); /* strings */ -static void _code_string_delete_all(Code * code); +static void _asmcode_string_delete_all(AsmCode * code); -static CodeString * _code_string_get_by_id(Code * code, AsmId id); -static int _code_string_set(CodeString * codestring, int id, char const * name, - off_t offset, ssize_t length); +static AsmString * _asmcode_string_get_by_id(AsmCode * code, AsmStringId id); +static int _asmcode_string_set(AsmString * codestring, + int id, char const * name, off_t offset, ssize_t length); -static CodeString * _code_string_append(Code * code); -static int _code_string_read(Code * code, CodeString * codestring); +static AsmString * _asmcode_string_append(AsmCode * code); +static int _asmcode_string_read(AsmCode * code, AsmString * codestring); /* functions */ -/* code_new */ -Code * code_new(char const * arch, char const * format) +/* asmcode_new */ +AsmCode * asmcode_new(char const * arch, char const * format) { - Code * code; + AsmCode * code; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\", \"%s\")\n", __func__, arch, format); @@ -105,7 +103,7 @@ Code * code_new(char const * arch, char const * format) code->format = format_new(format); if(code->arch == NULL) { - code_delete(code); + asmcode_delete(code); return NULL; } code->description = arch_get_description(code->arch); @@ -113,13 +111,13 @@ Code * code_new(char const * arch, char const * format) } -/* code_new_file */ +/* asmcode_new_file */ static Format * _new_file_format(char const * filename, FILE * fp); -Code * code_new_file(char const * arch, char const * format, +AsmCode * asmcode_new_file(char const * arch, char const * format, char const * filename) { - Code * code; + AsmCode * code; FILE * fp; #ifdef DEBUG @@ -155,7 +153,7 @@ Code * code_new_file(char const * arch, char const * format, } if(code->filename == NULL || code->arch == NULL || code->format == NULL) { - code_delete(code); + asmcode_delete(code); return NULL; } code->description = arch_get_description(code->arch); @@ -209,8 +207,8 @@ static Format * _new_file_format(char const * filename, FILE * fp) } -/* code_delete */ -int code_delete(Code * code) +/* asmcode_delete */ +int asmcode_delete(AsmCode * code) { int ret = 0; @@ -231,71 +229,133 @@ int code_delete(Code * code) /* accessors */ -/* code_get_arch */ -char const * code_get_arch(Code * code) +/* asmcode_get_arch */ +char const * asmcode_get_arch(AsmCode * code) { return arch_get_name(code->arch); } -/* code_get_filename */ -char const * code_get_filename(Code * code) +/* asmcode_get_arch_description */ +ArchDescription * asmcode_get_arch_description(AsmCode * code) +{ + return arch_get_description(code->arch); +} + + +/* asmcode_get_filename */ +char const * asmcode_get_filename(AsmCode * code) { return code->filename; } -/* code_get_format */ -char const * code_get_format(Code * code) +/* asmcode_get_format */ +char const * asmcode_get_format(AsmCode * code) { return format_get_name(code->format); } -/* code_get_function_by_id */ -AsmFunction * code_get_function_by_id(Code * code, AsmId id) +/* asmcode_get_function_by_id */ +AsmFunction * asmcode_get_function_by_id(AsmCode * code, AsmFunctionId id) { - /* XXX CodeFunction has to be exactly like an AsmFunction */ - return _code_function_get_by_id(code, id); + return _asmcode_element_get_by_id(code, AET_FUNCTION, id); } -/* code_get_string_by_id */ -AsmString * code_get_string_by_id(Code * code, AsmId id) +/* asmcode_get_functions */ +void asmcode_get_functions(AsmCode * code, AsmFunction ** functions, + size_t * functions_cnt) { - /* XXX CodeString has to be exactly like an AsmString */ - return _code_string_get_by_id(code, id); +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + *functions = code->elements[AET_FUNCTION]; + *functions_cnt = code->elements_cnt[AET_FUNCTION]; } -/* code_set_function */ -int code_set_function(Code * code, int id, char const * name, off_t offset, - ssize_t size) +/* asmcode_get_section_by_id */ +AsmSection * asmcode_get_section_by_id(AsmCode * code, AsmSectionId id) { - CodeFunction * cf = NULL; + return _asmcode_element_get_by_id(code, AET_SECTION, id); +} + +/* asmcode_get_sections */ +void asmcode_get_sections(AsmCode * code, AsmSection ** sections, + size_t * sections_cnt) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + *sections = code->elements[AET_SECTION]; + *sections_cnt = code->elements_cnt[AET_SECTION]; +} + + +/* asmcode_get_string_by_id */ +AsmString * asmcode_get_string_by_id(AsmCode * code, AsmStringId id) +{ + return _asmcode_element_get_by_id(code, AET_STRING, id); +} + + +/* asmcode_set_function */ +int asmcode_set_function(AsmCode * code, int id, char const * name, + off_t offset, ssize_t size) +{ + AsmFunction * cf = NULL; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%u, \"%s\", %ld, %ld)\n", __func__, id, name, + offset, size); +#endif if(id >= 0) - cf = _code_function_get_by_id(code, id); + cf = _asmcode_function_get_by_id(code, id); if(cf == NULL) - cf = _code_function_append(code); - if(cf == NULL || _code_function_set(cf, id, name, offset, size) != 0) + cf = _asmcode_function_append(code); + if(cf == NULL || _asmcode_function_set(cf, id, name, offset, size) != 0) return -1; /* FIXME isn't it considered an error if no ID is known yet? */ return cf->id; } -/* code_set_string */ -int code_set_string(Code * code, int id, char const * name, off_t offset, +/* asmcode_set_section */ +int asmcode_set_section(AsmCode * code, int id, char const * name, off_t offset, + ssize_t size, off_t base) +{ + AsmSection * cs = NULL; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%u, \"%s\", %ld, %ld)\n", __func__, id, name, + offset, size); +#endif + if(id >= 0) + cs = _asmcode_section_get_by_id(code, id); + if(cs == NULL) + cs = _asmcode_section_append(code); + if(cs == NULL || _asmcode_section_set(cs, id, name, offset, size, base) + != 0) + return -1; + /* FIXME isn't it considered an error if no ID is known yet? */ + return cs->id; +} + + +/* asmcode_set_string */ +int asmcode_set_string(AsmCode * code, int id, char const * name, off_t offset, ssize_t length) { - CodeString * cs = NULL; + AsmString * cs = NULL; if(id >= 0) - cs = _code_string_get_by_id(code, id); + cs = _asmcode_string_get_by_id(code, id); if(cs == NULL) - cs = _code_string_append(code); - if(cs == NULL || _code_string_set(cs, id, name, offset, length) != 0) + cs = _asmcode_string_append(code); + if(cs == NULL || _asmcode_string_set(cs, id, name, offset, length) != 0) return -1; /* FIXME isn't it considered an error if no ID is known yet? */ return cs->id; @@ -303,8 +363,8 @@ int code_set_string(Code * code, int id, char const * name, off_t offset, /* useful */ -/* code_close */ -int code_close(Code * code) +/* asmcode_close */ +int asmcode_close(AsmCode * code) { int ret = 0; @@ -318,101 +378,67 @@ int code_close(Code * code) ret |= -error_set_code(1, "%s: %s", code->filename, strerror(errno)); code->fp = NULL; - _code_string_delete_all(code); - _code_function_delete_all(code); + _asmcode_string_delete_all(code); + _asmcode_function_delete_all(code); return ret; } -/* code_decode */ -int code_decode(Code * code, int raw) +/* asmcode_decode */ +int asmcode_decode(AsmCode * code, int raw) { - printf("%s: %s-%s\n", code->filename, format_get_name(code->format), - arch_get_name(code->arch)); return format_decode(code->format, code, raw); } -/* code_decode_at */ -static void _decode_at_print_address(ArchDescription * description, - unsigned long address); - -int code_decode_at(Code * code, char const * section, off_t offset, - size_t size, off_t base) +/* asmcode_decode_at */ +int asmcode_decode_at(AsmCode * code, off_t offset, size_t size, off_t base, + ArchInstructionCall ** calls, size_t * calls_cnt) { - ArchDescription * description; - 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; - description = arch_get_description(code->arch); - if(size != 0) - _decode_at_print_address(description, base); - for(i = 0; i < calls_cnt; i++) - code_print(code, description, &calls[i]); - free(calls); - if(arch_seek(code->arch, offset + size, SEEK_SET) < 0) +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%ld, %lu, %ld)\n", __func__, offset, size, + base); +#endif + if(arch_decode_at(code->arch, code, offset, size, base, calls, + calls_cnt) != 0) return -1; return 0; } -static void _decode_at_print_address(ArchDescription * description, - unsigned long address) -{ - uint32_t size = (description != NULL) ? description->address_size : 32; - char const * format = "\n%08lx:\n"; - switch(size) - { - case 64: - format = "\n%016lx:\n"; - break; - case 20: - format = "\n%05lx:\n"; - break; - default: - break; - } - printf(format, address); -} - - -/* code_decode_buffer */ -int code_decode_buffer(Code * code, char const * buffer, size_t size) +/* asmcode_decode_buffer */ +int asmcode_decode_buffer(AsmCode * code, char const * buffer, size_t size, + ArchInstructionCall ** calls, size_t * calls_cnt) { int ret; ArchDescription * description; - ArchInstructionCall * calls = NULL; - size_t calls_cnt = 0; - size_t i; arch_init_buffer(code->arch, buffer, size); description = arch_get_description(code->arch); - if((ret = arch_decode(code->arch, code, &calls, &calls_cnt, 0)) == 0) - { - for(i = 0; i < calls_cnt; i++) - code_print(code, description, &calls[i]); - free(calls); - } + ret = arch_decode(code->arch, code, 0, calls, calls_cnt); arch_exit(code->arch); return ret; } -/* code_function */ -int code_function(Code * code, char const * function) +/* asmcode_decode_section */ +int asmcode_decode_section(AsmCode * code, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + return format_decode_section(code->format, code, section, calls, + calls_cnt); +} + + +/* asmcode_function */ +int asmcode_function(AsmCode * code, char const * function) { return format_function(code->format, function); } -/* code_instruction */ -int code_instruction(Code * code, ArchInstructionCall * call) +/* asmcode_instruction */ +int asmcode_instruction(AsmCode * code, ArchInstructionCall * call) { ArchInstruction * ai; @@ -423,12 +449,12 @@ int code_instruction(Code * code, ArchInstructionCall * call) ", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2, ai->op3); #endif - return arch_write(code->arch, ai, call); + return arch_encode(code->arch, ai, call); } -/* code_open */ -int code_open(Code * code, char const * filename) +/* asmcode_open */ +int asmcode_open(AsmCode * code, char const * filename) { if(code->filename != NULL || code->fp != NULL) return -error_set_code(1, "A file is already opened"); @@ -455,22 +481,21 @@ int code_open(Code * code, char const * filename) } -/* code_print */ +/* asmcode_print */ static void _print_address(ArchDescription * description, unsigned long address); static void _print_immediate(ArchOperand * ao); -int code_print(Code * code, ArchDescription * description, - ArchInstructionCall * call) +int asmcode_print(AsmCode * code, ArchInstructionCall * call) { + ArchDescription * description; char const * sep = " "; size_t i; uint8_t u8; ArchOperand * ao; char const * name; - if(description == NULL) - description = arch_get_description(code->arch); + description = arch_get_description(code->arch); if(arch_seek(code->arch, call->offset, SEEK_SET) < 0) return -1; _print_address(description, call->base); @@ -558,8 +583,8 @@ static void _print_immediate(ArchOperand * ao) } -/* code_section */ -int code_section(Code * code, char const * section) +/* asmcode_section */ +int asmcode_section(AsmCode * code, char const * section) { #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, section); @@ -569,38 +594,89 @@ int code_section(Code * code, char const * section) /* private */ -/* functions */ -/* functions */ -/* code_function_delete_all */ -static void _code_function_delete_all(Code * code) +/* elements */ +/* asmcode_element_set */ +static int _asmcode_element_set(AsmElement * element, AsmElementId id, + char const * name, off_t offset, ssize_t size, off_t base) { - size_t i; + char * p = NULL; - for(i = 0; i < code->functions_cnt; i++) - free(code->functions[i].name); - code->functions_cnt = 0; - free(code->functions); - code->functions = NULL; + if(name != NULL && (p = string_new(name)) == NULL) + return -1; + element->id = id; + free(element->name); + element->name = p; + element->offset = offset; + element->size = size; + element->base = base; + return 0; } -/* code_function_get_by_id */ -static CodeFunction * _code_function_get_by_id(Code * code, AsmId id) +static AsmElement * _asmcode_element_append(AsmCode * code, AsmElementType type) { - size_t i; + AsmElement * p = code->elements[type]; + size_t cnt = code->elements_cnt[type]; - for(i = 0; i < code->functions_cnt; i++) - if(code->functions[i].id >= 0 - && (AsmId)code->functions[i].id == id) - break; - if(i == code->functions_cnt) + if((p = realloc(p, sizeof(*p) * (cnt + 1))) == NULL) + { + error_set_code(1, "%s", strerror(errno)); return NULL; - return &code->functions[i]; + } + code->elements[type] = p; + p = &code->elements[type][cnt]; + code->elements_cnt[type]++; + p->id = -1; + p->name = NULL; + p->offset = -1; + p->size = -1; + return p; } -/* code_function_set */ -static int _code_function_set(CodeFunction * codefunction, int id, +static void _asmcode_element_delete_all(AsmCode * code, AsmElementType type) +{ + size_t i; + + for(i = 0; i < code->elements_cnt[type]; i++) + free(code->elements[type][i].name); + code->elements_cnt[type] = 0; + free(code->elements[type]); + code->elements[type] = NULL; +} + + +static AsmElement * _asmcode_element_get_by_id(AsmCode * code, + AsmElementType type, AsmElementId id) +{ + size_t i; + + for(i = 0; i < code->elements_cnt[type]; i++) + if(code->elements[type][i].id >= 0 + && code->elements[type][i].id == id) + return &code->elements[type][i]; + return NULL; +} + + +/* functions */ +/* asmcode_function_delete_all */ +static void _asmcode_function_delete_all(AsmCode * code) +{ + _asmcode_element_delete_all(code, AET_FUNCTION); +} + + +/* asmcode_function_get_by_id */ +static AsmFunction * _asmcode_function_get_by_id(AsmCode * code, + AsmFunctionId id) +{ + return _asmcode_element_get_by_id(code, AET_FUNCTION, id); +} + + +/* asmcode_function_set */ +static int _asmcode_function_set(AsmFunction * codefunction, AsmFunctionId id, char const * name, off_t offset, ssize_t size) { char * p = NULL; @@ -616,118 +692,96 @@ static int _code_function_set(CodeFunction * codefunction, int id, } -/* code_function_append */ -static CodeFunction * _code_function_append(Code * code) +/* asmcode_function_append */ +static AsmFunction * _asmcode_function_append(AsmCode * code) { - CodeFunction * p; + return _asmcode_element_append(code, AET_FUNCTION); +} - if((p = realloc(code->functions, sizeof(*p) * (code->functions_cnt - + 1))) == NULL) - { - error_set_code(1, "%s", strerror(errno)); - return NULL; - } - code->functions = p; - p = &code->functions[code->functions_cnt++]; - p->id = -1; - p->name = NULL; - p->offset = -1; - p->size = -1; - return p; + +/* sections */ +/* asmcode_section_get_by_id */ +static AsmSection * _asmcode_section_get_by_id(AsmCode * code, AsmSectionId id) +{ + return _asmcode_element_get_by_id(code, AET_SECTION, id); +} + + +/* asmcode_section_set */ +static int _asmcode_section_set(AsmSection * section, int id, char const * name, + off_t offset, ssize_t size, off_t base) +{ + return _asmcode_element_set(section, id, name, offset, size, base); +} + + +/* asmcode_section_append */ +static AsmSection * _asmcode_section_append(AsmCode * code) +{ + return _asmcode_element_append(code, AET_SECTION); } /* strings */ -/* code_string_delete_all */ -static void _code_string_delete_all(Code * code) +/* asmcode_string_delete_all */ +static void _asmcode_string_delete_all(AsmCode * code) { - size_t i; - - for(i = 0; i < code->strings_cnt; i++) - free(code->strings[i].name); - code->strings_cnt = 0; - free(code->strings); - code->strings = NULL; + _asmcode_element_delete_all(code, AET_STRING); } -/* code_string_get_by_id */ -static CodeString * _code_string_get_by_id(Code * code, AsmId id) +/* asmcode_string_get_by_id */ +static AsmString * _asmcode_string_get_by_id(AsmCode * code, AsmStringId id) { - size_t i; + AsmString * ret; - for(i = 0; i < code->strings_cnt; i++) - if(code->strings[i].id >= 0 && (AsmId)code->strings[i].id == id) - break; - if(i == code->strings_cnt) + if((ret = _asmcode_element_get_by_id(code, AET_STRING, id)) == NULL) return NULL; - if(code->strings[i].name == NULL) - _code_string_read(code, &code->strings[i]); - return &code->strings[i]; + if(ret->name == NULL) + _asmcode_string_read(code, ret); + return ret; } -/* code_string_set */ -static int _code_string_set(CodeString * codestring, int id, char const * name, - off_t offset, ssize_t length) +/* asmcode_string_set */ +static int _asmcode_string_set(AsmString * codestring, int id, + char const * name, off_t offset, ssize_t length) { - char * p = NULL; - - if(name != NULL && (p = string_new(name)) == NULL) - return -error_set_code(1, "%s", strerror(errno)); - codestring->id = id; - free(codestring->name); - codestring->name = p; - codestring->offset = offset; - codestring->length = length; - return 0; + return _asmcode_element_set(codestring, id, name, offset, length, 0); } -/* code_string_append */ -static CodeString * _code_string_append(Code * code) +/* asmcode_string_append */ +static AsmString * _asmcode_string_append(AsmCode * code) { - CodeString * p; - - if((p = realloc(code->strings, sizeof(*p) * (code->strings_cnt + 1))) - == NULL) - { - error_set_code(1, "%s", strerror(errno)); - return NULL; - } - code->strings = p; - p = &code->strings[code->strings_cnt++]; - p->id = -1; - p->name = NULL; - p->offset = -1; - p->length = -1; - return p; + return _asmcode_element_append(code, AET_STRING); } -/* code_string_read */ -static int _code_string_read(Code * code, CodeString * codestring) +/* asmcode_string_read */ +static int _asmcode_string_read(AsmCode * code, AsmString * codestring) { off_t offset; /* XXX should not have to be kept */ char * buf; - if(codestring->offset < 0 || codestring->length < 0) + /* FIXME if offset < 0 read until '\0' */ + if(codestring->offset < 0 || codestring->size < 0) return -error_set_code(1, "%s", "Insufficient information to" " read string"); if((offset = arch_seek(code->arch, 0, SEEK_CUR)) < 0) return -1; - if((buf = malloc(codestring->length + 1)) == NULL) + if((buf = malloc(codestring->size + 1)) == NULL) return -error_set_code(1, "%s", strerror(errno)); if(arch_seek(code->arch, codestring->offset, SEEK_SET) != codestring->offset) return -1; - if(arch_read(code->arch, buf, codestring->length) != codestring->length) + if(arch_read(code->arch, buf, codestring->size) != codestring->size) { free(buf); arch_seek(code->arch, offset, SEEK_SET); return -1; } - buf[codestring->length] = '\0'; + buf[codestring->size] = '\0'; free(codestring->name); codestring->name = buf; arch_seek(code->arch, offset, SEEK_SET); diff --git a/src/code.h b/src/code.h index 2c5bba3..c721690 100644 --- a/src/code.h +++ b/src/code.h @@ -19,48 +19,28 @@ # define ASM_CODE_H # include -# include "Asm/arch.h" - - -/* types */ -typedef struct _Code Code; +# include "Asm/code.h" /* functions */ -Code * code_new(char const * arch, char const * format); -Code * code_new_file(char const * arch, char const * format, +AsmCode * asmcode_new(char const * arch, char const * format); +AsmCode * asmcode_new_file(char const * arch, char const * format, char const * filename); -int code_delete(Code * code); - -/* accessors */ -char const * code_get_arch(Code * code); -char const * code_get_filename(Code * code); -char const * code_get_format(Code * code); - -AsmFunction * code_get_function_by_id(Code * code, AsmId id); -AsmString * code_get_string_by_id(Code * code, AsmId id); - -int code_set_function(Code * code, int id, char const * name, off_t offset, - ssize_t size); -int code_set_string(Code * code, int id, char const * name, off_t offset, - ssize_t length); +int asmcode_delete(AsmCode * code); /* useful */ /* common */ -int code_open(Code * code, char const * filename); -int code_close(Code * code); +int asmcode_open(AsmCode * code, char const * filename); +int asmcode_close(AsmCode * code); -/* assembly */ -int code_function(Code * code, char const * function); -int code_instruction(Code * code, ArchInstructionCall * call); -int code_section(Code * code, char const * section); - -/* disassembly */ -int code_decode(Code * code, int raw); -int code_decode_at(Code * code, char const * section, off_t offset, - size_t size, off_t base); -int code_decode_buffer(Code * code, char const * buffer, size_t size); -int code_print(Code * code, ArchDescription * description, - ArchInstructionCall * call); +/* elements */ +AsmElement * asmcode_get_element_by_id(AsmCode * a, AsmElementType type, + AsmElementId id); +AsmElement * asmcode_get_element_by_name(AsmCode * af, AsmElementType type, + char const * name); +AsmElement * asmcode_get_element_by_offset(AsmCode * af, AsmElementType type, + off_t offset); +int asmcode_get_elements(AsmCode * af, AsmElementType type, + AsmElement ** elements, size_t * count); #endif /* !ASM_CODE_H */ diff --git a/src/deasm.c b/src/deasm.c index 8e9d1bc..9eb6c57 100644 --- a/src/deasm.c +++ b/src/deasm.c @@ -40,35 +40,89 @@ static int _usage(void); /* functions */ /* deasm */ +static int _deasm_section(AsmCode * code, AsmSection * section); + static int _deasm(char const * arch, char const * format, char const * filename, int raw) { int ret; Asm * a; + AsmCode * code; + AsmSection * sections; + size_t sections_cnt; + size_t i; if((a = asm_new(arch, format)) == NULL) return -error_print("deasm"); - if((ret = asm_open_deassemble(a, filename, raw)) != 0) + if((code = asm_open_deassemble(a, filename, raw)) == NULL) error_print("deasm"); else + { + printf("%s: %s-%s\n", filename, asm_get_format(a), + asm_get_arch(a)); + asmcode_get_sections(code, §ions, §ions_cnt); + for(i = 0; i < sections_cnt; i++) + if((ret = _deasm_section(code, §ions[i])) != 0) + break; asm_close(a); + } asm_delete(a); return ret; } +static int _deasm_section(AsmCode * code, AsmSection * section) +{ + ArchDescription * description; + size_t size; + ArchInstructionCall * calls = NULL; + size_t calls_cnt = 0; + size_t i; + + printf("\nDisassembly of section %s:\n", section->name); + if(asmcode_decode_section(code, section, &calls, &calls_cnt) != 0) + { + error_print("deasm"); + return -1; + } + description = asmcode_get_arch_description(code); + size = (description != NULL) ? description->address_size : 32; + switch(size) + { + case 64: + printf("\n%016lx:\n", section->base); + break; + case 20: + printf("\n%05lx:\n", section->base); + break; + case 32: + default: + printf("\n%08lx:\n", section->base); + break; + } + for(i = 0; i < calls_cnt; i++) + asmcode_print(code, &calls[i]); + free(calls); + return 0; +} + /* deasm_buffer */ static int _deasm_buffer(char const * arch, char const * buffer, size_t size) { Asm * a; + AsmCode * code; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif if((a = asm_new(arch, NULL)) == NULL) return -1; - if(asm_deassemble(a, buffer, size) != 0) + if((code = asm_deassemble(a, buffer, size, NULL, NULL)) == NULL) error_print("deasm"); + else + { + /* FIXME implement */ + } asm_delete(a); return 0; } @@ -138,8 +192,8 @@ static int _deasm_list(void) #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif - asm_plugin_list(APT_ARCH); - asm_plugin_list(APT_FORMAT); + asm_plugin_list(APT_ARCH, 1); + asm_plugin_list(APT_FORMAT, 1); return 0; } @@ -147,9 +201,13 @@ static int _deasm_list(void) /* usage */ static int _usage(void) { - fputs("Usage: deasm [-a arch][-f format] filename\n" + fputs("Usage: deasm [-a arch][-f format][-D] filename\n" " deasm [-a arch] -s string\n" -" deasm -l\n", stderr); +" deasm -l\n" +" -a Force the given architecture\n" +" -f Force the given file format\n" +" -D Deassemble all sections\n" +" -l List all the architectures and file formats available\n", stderr); return 1; } diff --git a/src/format.c b/src/format.c index 6da8719..a82b5f3 100644 --- a/src/format.c +++ b/src/format.c @@ -40,21 +40,28 @@ struct _Format FILE * fp; /* deassembly */ - Code * code; + AsmCode * code; }; /* prototypes */ /* 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, +static void _format_helper_get_functions(Format * format, + AsmFunction ** functions, size_t * functions_cnt); +static AsmSection * _format_helper_get_section_by_id(Format * format, + AsmSectionId id); +static AsmString * _format_helper_get_string_by_id(Format * format, + AsmStringId id); +static int _format_helper_set_function(Format * format, AsmFunctionId id, + char const * name, off_t offset, ssize_t size); +static int _format_helper_set_section(Format * format, AsmSectionId id, + char const * name, off_t offset, ssize_t size, off_t base); +static int _format_helper_set_string(Format * format, AsmStringId 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 int _format_helper_decode(Format * format, char const * section, - off_t offset, size_t size, off_t base); +static int _format_helper_decode(Format * format, off_t offset, size_t size, + off_t base, ArchInstructionCall ** calls, size_t * calls_cnt); 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, @@ -92,8 +99,11 @@ Format * format_new(char const * format) f->helper.format = f; f->helper.decode = _format_helper_decode; f->helper.get_filename = _format_helper_get_filename; + f->helper.get_functions = _format_helper_get_functions; + f->helper.get_section_by_id = _format_helper_get_section_by_id; f->helper.get_string_by_id = _format_helper_get_string_by_id; f->helper.set_function = _format_helper_set_function; + f->helper.set_section = _format_helper_set_section; f->helper.set_string = _format_helper_set_string; f->helper.read = _format_helper_read; f->helper.seek = _format_helper_seek; @@ -115,6 +125,14 @@ void format_delete(Format * format) /* accessors */ +/* format_can_decode */ +int format_can_decode(Format * format) +{ + return format->plugin->decode != NULL + /* && format->plugin->decode_section != NULL */; +} + + /* format_get_arch */ char const * format_get_arch(Format * format) { @@ -133,12 +151,12 @@ char const * format_get_name(Format * format) /* useful */ /* format_decode */ -int format_decode(Format * format, Code * code, int raw) +int format_decode(Format * format, AsmCode * code, int raw) { int ret; if(format->plugin->decode == NULL) - return error_set_code(1, "%s: %s", format_get_name(format), + return -error_set_code(1, "%s: %s", format_get_name(format), "Disassembly is not supported"); format->code = code; ret = format->plugin->decode(format->plugin, raw); @@ -147,6 +165,26 @@ int format_decode(Format * format, Code * code, int raw) } +/* format_decode_section */ +int format_decode_section(Format * format, AsmCode * code, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + int ret; + + if(format->plugin->decode_section == NULL) + return -error_set_code(1, "%s: %s", format_get_name(format), + "Disassembly is not supported"); + if(section == NULL || section->id < 0) + return -error_set_code(1, "%s: %s", format_get_name(format), + "Invalid argument"); + format->code = code; + ret = format->plugin->decode_section(format->plugin, section, calls, + calls_cnt); + format->code = NULL; + return ret; +} + + /* format_detect_arch */ char const * format_detect_arch(Format * format) { @@ -255,41 +293,66 @@ static char const * _format_helper_get_filename(Format * format) } -/* format_helper_get_string_by_id */ -static AsmString * _format_helper_get_string_by_id(Format * format, AsmId id) +/* format_helper_get_functions */ +static void _format_helper_get_functions(Format * format, + AsmFunction ** functions, size_t * functions_cnt) { - return code_get_string_by_id(format->code, id); + asmcode_get_functions(format->code, functions, functions_cnt); +} + + +/* format_helper_get_section_by_id */ +static AsmSection * _format_helper_get_section_by_id(Format * format, + AsmSectionId id) +{ + return asmcode_get_section_by_id(format->code, id); +} + + +/* format_helper_get_string_by_id */ +static AsmString * _format_helper_get_string_by_id(Format * format, + AsmStringId id) +{ + return asmcode_get_string_by_id(format->code, id); } /* format_helper_set_function */ -static int _format_helper_set_function(Format * format, int id, +static int _format_helper_set_function(Format * format, AsmFunctionId id, char const * name, off_t offset, ssize_t size) { - return code_set_function(format->code, id, name, offset, size); + return asmcode_set_function(format->code, id, name, offset, size); +} + + +/* format_helper_set_section */ +static int _format_helper_set_section(Format * format, AsmSectionId id, + char const * name, off_t offset, ssize_t size, off_t base) +{ + return asmcode_set_section(format->code, id, name, offset, size, base); } /* format_helper_set_string */ -static int _format_helper_set_string(Format * format, int id, char const * name, - off_t offset, ssize_t size) +static int _format_helper_set_string(Format * format, AsmStringId id, + char const * name, off_t offset, ssize_t size) { - return code_set_string(format->code, id, name, offset, size); + return asmcode_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) +static int _format_helper_decode(Format * format, off_t offset, size_t size, + off_t base, ArchInstructionCall ** calls, size_t * calls_cnt) { int ret; #ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__, - section, offset, size, base); + fprintf(stderr, "DEBUG: %s(0x%lx, 0x%lx, 0x%lx)\n", __func__, offset, + size, base); #endif - if((ret = code_decode_at(format->code, section, offset, size, base)) - != 0) + if((ret = asmcode_decode_at(format->code, offset, size, base, + calls, calls_cnt)) != 0) error_print("deasm"); return ret; } diff --git a/src/format.h b/src/format.h index c2ffa2e..d35bd7f 100644 --- a/src/format.h +++ b/src/format.h @@ -18,6 +18,7 @@ #ifndef ASM_FORMAT_H # define ASM_FORMAT_H +# include "Asm/common.h" # include "Asm/format.h" # include "code.h" @@ -27,17 +28,19 @@ /* types */ typedef int (*FormatDecodeCallback)(void * priv, char const * section, off_t offset, size_t size, off_t base); -typedef AsmString * (*FormatGetStringByIdCallback)(void * priv, AsmId id); -typedef int (*FormatSetFunctionCallback)(void * priv, int id, char const * name, - off_t offset, ssize_t length); -typedef int (*FormatSetStringCallback)(void * priv, int id, char const * name, - off_t offset, ssize_t length); +typedef AsmString * (*FormatGetStringByIdCallback)(void * priv, AsmStringId id); +typedef int (*FormatSetFunctionCallback)(void * priv, AsmFunctionId id, + char const * name, off_t offset, ssize_t length); +typedef int (*FormatSetStringCallback)(void * priv, AsmStringId id, + char const * name, off_t offset, ssize_t length); /* functions */ Format * format_new(char const * format); void format_delete(Format * format); /* accessors */ +int format_can_decode(Format * format); + char const * format_get_name(Format * format); /* useful */ @@ -50,7 +53,9 @@ int format_function(Format * format, char const * function); int format_section(Format * format, char const * section); /* disassembly */ -int format_decode(Format * format, Code * code, int raw); +int format_decode(Format * format, AsmCode * code, int raw); +int format_decode_section(Format * format, AsmCode * code, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); char const * format_detect_arch(Format * format); int format_match(Format * format); diff --git a/src/format/dex.c b/src/format/dex.c index b610315..688ba6c 100644 --- a/src/format/dex.c +++ b/src/format/dex.c @@ -126,6 +126,8 @@ static int _dex_init(FormatPlugin * format, char const * arch); static int _dex_exit(FormatPlugin * format); static char const * _dex_detect(FormatPlugin * format); static int _dex_decode(FormatPlugin * format, int raw); +static int _dex_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); /* public */ @@ -142,6 +144,7 @@ FormatPlugin format_plugin = NULL, _dex_detect, _dex_decode, + _dex_decode_section, NULL }; @@ -183,14 +186,15 @@ static int _dex_exit(FormatPlugin * format) /* dex_detect */ static char const * _dex_detect(FormatPlugin * format) { - /* FIXME some sections might contain native code */ + /* XXX some sections might contain native code */ return "dalvik"; } /* dex_decode */ -static int _decode_map(FormatPlugin * format, DexHeader * dh); -static int _decode_map_code(FormatPlugin * format, off_t offset, size_t size); +static int _decode_map(FormatPlugin * format, DexHeader * dh, int raw); +static int _decode_map_code(FormatPlugin * format, size_t id, off_t offset, + size_t size); static int _decode_map_method_id(FormatPlugin * format, off_t offset, size_t size); static int _decode_map_string_id(FormatPlugin * format, off_t offset, @@ -201,17 +205,20 @@ static int _dex_decode(FormatPlugin * format, int raw) FormatPluginHelper * helper = format->helper; DexHeader dh; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%d)\n", __func__, raw); +#endif if(helper->seek(helper->format, 0, SEEK_SET) != 0) return -1; if(helper->read(helper->format, &dh, sizeof(dh)) != sizeof(dh)) return -1; dh.map_off = _htol32(dh.map_off); - if(_decode_map(format, &dh) != 0) + if(_decode_map(format, &dh, raw) != 0) return -1; return 0; } -static int _decode_map(FormatPlugin * format, DexHeader * dh) +static int _decode_map(FormatPlugin * format, DexHeader * dh, int raw) { int ret = 0; FormatPluginHelper * helper = format->helper; @@ -247,7 +254,7 @@ static int _decode_map(FormatPlugin * format, DexHeader * dh) switch(dmi.type) { case TYPE_CODE_ITEM: - ret |= _decode_map_code(format, dmi.offset, + ret |= _decode_map_code(format, i, dmi.offset, dmi.size); break; case TYPE_METHOD_ID_ITEM: @@ -267,64 +274,17 @@ static int _decode_map(FormatPlugin * format, DexHeader * dh) return ret; } -static int _decode_map_code(FormatPlugin * format, off_t offset, size_t size) +static int _decode_map_code(FormatPlugin * format, size_t id, off_t offset, + size_t size) { FormatPluginHelper * helper = format->helper; - DexMapCodeItem dmci; - size_t i; - off_t seek; - size_t j; - DexMapTryItem dmti; - ssize_t s; - if(helper->decode(helper->format, ".text", offset, 0, offset) != 0) - return -1; - for(i = 0; i < size; i++) - { - s = sizeof(dmci); - if(helper->read(helper->format, &dmci, s) != s) - return -1; - dmci.registers_size = _htol16(dmci.registers_size); - dmci.ins_size = _htol16(dmci.ins_size); - dmci.outs_size = _htol16(dmci.outs_size); - dmci.tries_size = _htol16(dmci.tries_size); - dmci.debug_info_off = _htol32(dmci.debug_info_off); - dmci.insns_size = _htol32(dmci.insns_size); - seek = helper->seek(helper->format, 0, SEEK_CUR); - if(helper->decode(helper->format, NULL, seek, - dmci.insns_size * 2, seek) != 0) - return -1; - /* skip padding and try_items */ - seek = (dmci.insns_size & 0x1) == 0x1 ? 2 : 0; #ifdef DEBUG - fprintf(stderr, "DEBUG: code item %lu, offset 0x%lx" - ", registers 0x%x, size 0x%x, debug @0x%x" - ", tries 0x%x, seek 0x%lx\n", i, - helper->seek(helper->format, 0, SEEK_CUR), - dmci.registers_size, dmci.insns_size * 2, - dmci.debug_info_off, dmci.tries_size, seek); + fprintf(stderr, "DEBUG: %s(%lu, %ld, %lu)\n", __func__, id, offset, + size); #endif - if(seek != 0 && helper->seek(helper->format, seek, SEEK_CUR) - < 0) - return -1; - if(dmci.tries_size > 0) - { - for(j = 0; j < dmci.tries_size; j++) - { - s = sizeof(dmti); - if(helper->read(helper->format, &dmti, s) != s) - return -1; - dmti.start_addr = _htol32(dmti.start_addr); - dmti.insn_count = _htol16(dmti.insn_count); - dmti.handler_off = _htol16(dmti.handler_off); - } - seek = helper->seek(helper->format, 0, SEEK_CUR); - if(helper->decode(helper->format, NULL, seek, 8, seek) - != 0) - return -1; - } - } - return 0; + return (helper->set_section(helper->format, id, ".text", offset, size, + 0) == id) ? 0 : -1; } static int _decode_map_method_id(FormatPlugin * format, off_t offset, @@ -337,6 +297,9 @@ static int _decode_map_method_id(FormatPlugin * format, off_t offset, AsmString * string; char const * name; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%ld, %lu)\n", __func__, offset, size); +#endif if(dex->dmii != NULL) return 0; /* already parsed */ if(helper->seek(helper->format, offset, SEEK_SET) != offset) @@ -372,6 +335,9 @@ static int _decode_map_string_id(FormatPlugin * format, off_t offset, size_t i; uint8_t u8; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%ld, %lu)\n", __func__, offset, size); +#endif if(helper->seek(helper->format, offset, SEEK_SET) != offset) return -1; s = sizeof(*dsii) * size; @@ -396,3 +362,70 @@ static int _decode_map_string_id(FormatPlugin * format, off_t offset, free(dsii); return (i == size) ? 0 : -1; } + + +/* dex_decode_section */ +static int _dex_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + FormatPluginHelper * helper = format->helper; + DexMapCodeItem dmci; + size_t i; + off_t seek; + size_t j; + DexMapTryItem dmti; + ssize_t s; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(helper->seek(helper->format, section->offset, SEEK_SET) + != section->offset) + return -1; + for(i = 0; i < section->size; i++) + { + s = sizeof(dmci); + if(helper->read(helper->format, &dmci, s) != s) + return -1; + dmci.registers_size = _htol16(dmci.registers_size); + dmci.ins_size = _htol16(dmci.ins_size); + dmci.outs_size = _htol16(dmci.outs_size); + dmci.tries_size = _htol16(dmci.tries_size); + dmci.debug_info_off = _htol32(dmci.debug_info_off); + dmci.insns_size = _htol32(dmci.insns_size); + seek = helper->seek(helper->format, 0, SEEK_CUR); + if(helper->decode(helper->format, seek, dmci.insns_size * 2, + seek, calls, calls_cnt) != 0) + return -1; + /* skip padding and try_items */ + seek = (dmci.insns_size & 0x1) == 0x1 ? 2 : 0; +#ifdef DEBUG + fprintf(stderr, "DEBUG: code item %lu, offset 0x%lx" + ", registers 0x%x, size 0x%x, debug @0x%x" + ", tries 0x%x, seek 0x%lx\n", i, + helper->seek(helper->format, 0, SEEK_CUR), + dmci.registers_size, dmci.insns_size * 2, + dmci.debug_info_off, dmci.tries_size, seek); +#endif + if(seek != 0 && helper->seek(helper->format, seek, SEEK_CUR) + < 0) + return -1; + if(dmci.tries_size > 0) + { + for(j = 0; j < dmci.tries_size; j++) + { + s = sizeof(dmti); + if(helper->read(helper->format, &dmti, s) != s) + return -1; + dmti.start_addr = _htol32(dmti.start_addr); + dmti.insn_count = _htol16(dmti.insn_count); + dmti.handler_off = _htol16(dmti.handler_off); + } + seek = helper->seek(helper->format, 0, SEEK_CUR); + if(helper->decode(helper->format, seek, 8, seek, calls, + calls_cnt) != 0) + return -1; + } + } + return 0; +} diff --git a/src/format/elf.c b/src/format/elf.c index a20ebad..12e6ce4 100644 --- a/src/format/elf.c +++ b/src/format/elf.c @@ -12,6 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +/* FIXME: + * - ensure the first section output is of type SHN_UNDEF + * - use set_string() to store and remember strings? */ @@ -79,6 +82,8 @@ static char const * _elf_detect(FormatPlugin * format); static int _elf_decode(FormatPlugin * format, int raw); static int _elf_decode32(FormatPlugin * format, int raw); static int _elf_decode64(FormatPlugin * format, int raw); +static int _elf_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); /* ELF32 */ static int _init_32(FormatPlugin * format); @@ -106,11 +111,15 @@ static ElfArch elf_arch[] = { { "amd64", EM_X86_64, ELFCLASS64, ELFDATA2LSB, 0x4 }, { "arm", EM_ARM, ELFCLASS32, ELFDATA2LSB, 0x0 }, + { "armeb", EM_ARM, ELFCLASS32, ELFDATA2MSB, 0x0 }, + { "armel", EM_ARM, ELFCLASS32, ELFDATA2LSB, 0x0 }, { "i386", EM_386, ELFCLASS32, ELFDATA2LSB, 0x4 }, { "i486", EM_386, ELFCLASS32, ELFDATA2LSB, 0x4 }, { "i586", EM_386, ELFCLASS32, ELFDATA2LSB, 0x4 }, { "i686", EM_386, ELFCLASS32, ELFDATA2LSB, 0x4 }, { "mips", EM_MIPS, ELFCLASS32, ELFDATA2MSB, 0x0 }, + { "mipseb", EM_MIPS, ELFCLASS32, ELFDATA2MSB, 0x0 }, + { "mipsel", EM_MIPS, ELFCLASS32, ELFDATA2LSB, 0x0 }, { "sparc", EM_SPARC, ELFCLASS32, ELFDATA2MSB, 0x0 }, { "sparc64", EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, 0x0 }, { NULL, '\0', '\0', '\0', 0x0 } @@ -174,6 +183,7 @@ FormatPlugin format_plugin = NULL, _elf_detect, _elf_decode, + _elf_decode_section, NULL }; @@ -202,7 +212,9 @@ static int _elf_init(FormatPlugin * format, char const * arch) return -1; format->priv = elf; elf->es32 = NULL; + elf->es32_cnt = 0; elf->es64 = NULL; + elf->es64_cnt = 0; if(arch == NULL) { elf->arch = NULL; @@ -336,6 +348,9 @@ static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr) /* elf_decode */ static int _elf_decode(FormatPlugin * format, int raw) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(%d)\n", __func__, raw); +#endif if(_elf_detect(format) == NULL) return -1; return format->decode(format, raw); @@ -394,16 +409,17 @@ static int _elf_decode32(FormatPlugin * format, int raw) { if(shdr[i].sh_name >= shstrtab_cnt) continue; - if(raw || (shdr[i].sh_type == SHT_PROGBITS - && shdr[i].sh_flags & SHF_EXECINSTR)) - helper->decode(helper->format, + if((raw || (shdr[i].sh_type == SHT_PROGBITS && shdr[i].sh_flags + & SHF_EXECINSTR)) + && helper->set_section(helper->format, i, &shstrtab[shdr[i].sh_name], shdr[i].sh_offset, shdr[i].sh_size, - base + shdr[i].sh_offset); + base + shdr[i].sh_offset) < 0) + break; } free(shstrtab); free(shdr); - return 0; + return (i == ehdr.e_shnum) ? 0 : -1; } static int _decode32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr, @@ -583,16 +599,17 @@ static int _elf_decode64(FormatPlugin * format, int raw) { if(shdr[i].sh_name >= shstrtab_cnt) continue; - if(raw || (shdr[i].sh_type == SHT_PROGBITS - && shdr[i].sh_flags & SHF_EXECINSTR)) - helper->decode(helper->format, + if((raw || (shdr[i].sh_type == SHT_PROGBITS && shdr[i].sh_flags + & SHF_EXECINSTR)) + && helper->set_section(helper->format, i, &shstrtab[shdr[i].sh_name], shdr[i].sh_offset, shdr[i].sh_size, - base + shdr[i].sh_offset); + base + shdr[i].sh_offset) < 0) + break; } free(shstrtab); free(shdr); - return 0; + return (i == ehdr.e_shnum) ? 0 : -1; } static int _decode64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr, @@ -722,12 +739,26 @@ static int _decode64_symtab(FormatPlugin * format, Elf64_Shdr * shdr, } +/* elf_decode_section */ +static int _elf_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + FormatPluginHelper * helper = format->helper; + + return helper->decode(helper->format, section->offset, section->size, + section->base, calls, calls_cnt); +} + + /* section_values */ static ElfSectionValues * _section_values(char const * name) { ElfSectionValues * esv; int cmp; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name); +#endif for(esv = elf_section_values; esv->name != NULL; esv++) if((cmp = strcmp(esv->name, name)) == 0) return esv; @@ -789,6 +820,9 @@ static int _exit_32(FormatPlugin * format) FormatPluginHelper * helper = format->helper; long offset; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif if(_section_32(format, ".shstrtab") != 0) ret = -1; else if(helper->write(helper->format, shstrtab.buf, shstrtab.cnt) @@ -813,6 +847,9 @@ static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset) ElfArch * ea = elf->arch; Elf32_Ehdr hdr; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif if(elf->es32_cnt == 0) return 0; if(helper->seek(helper->format, 0, SEEK_SET) != 0) @@ -848,6 +885,9 @@ static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset) Elf32_Shdr hdr; int i; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif if(helper->seek(helper->format, 0, SEEK_END) < 0) return _elf_error(format); memset(&hdr, 0, sizeof(hdr)); @@ -865,6 +905,9 @@ static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset) return -1; for(i = 0; i < elf->es32_cnt; i++) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() %d\n", __func__, i); +#endif if(i + 1 == elf->es32_cnt) es32[i].sh_size = offset - es32[i].sh_offset; else @@ -895,6 +938,9 @@ static int _section_32(FormatPlugin * format, char const * name) ElfSectionValues * esv; long offset; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name); +#endif if((ss = _elfstrtab_set(format, &shstrtab, name)) < 0) return -1; if((p = realloc(elf->es32, sizeof(*p) * (elf->es32_cnt + 1))) == NULL) @@ -906,8 +952,14 @@ static int _section_32(FormatPlugin * format, char const * name) p->sh_name = ss; p->sh_type = esv->type; p->sh_flags = esv->flags; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() %s\n", __func__, "before seek()"); +#endif if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0) return -1; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() %s\n", __func__, "after seek()"); +#endif p->sh_offset = offset; p->sh_link = SHN_UNDEF; /* FIXME */ return 0; @@ -1130,8 +1182,14 @@ static int _section_64(FormatPlugin * format, char const * name) p->sh_name = ss; p->sh_type = esv->type; p->sh_flags = esv->flags; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() %s\n", __func__, "before seek()"); +#endif if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0) return -1; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() %s\n", __func__, "after seek()"); +#endif p->sh_offset = offset; p->sh_link = SHN_UNDEF; /* FIXME */ return 0; diff --git a/src/format/flat.c b/src/format/flat.c index b98b465..9ff95f8 100644 --- a/src/format/flat.c +++ b/src/format/flat.c @@ -25,6 +25,8 @@ /* prototypes */ /* plug-in */ static int _flat_decode(FormatPlugin * format, int raw); +static int _flat_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); /* public */ @@ -41,6 +43,7 @@ FormatPlugin format_plugin = NULL, NULL, _flat_decode, + _flat_decode_section, NULL }; @@ -54,7 +57,21 @@ static int _flat_decode(FormatPlugin * format, int raw) FormatPluginHelper * helper = format->helper; off_t offset; - if((offset = helper->seek(helper->format, 0, SEEK_END)) < 0) - return -1; - return helper->decode(helper->format, ".data", 0, offset, 0); + if((offset = helper->seek(helper->format, 0, SEEK_END)) >= 0) + return helper->set_section(helper->format, 0, ".text", 0, + offset, 0); + return -1; +} + + +/* flat_decode_section */ +static int _flat_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + FormatPluginHelper * helper = format->helper; + + if(section->id != 0) + return -1; + return helper->decode(helper->format, section->offset, section->size, + section->base, calls, calls_cnt); } diff --git a/src/format/java.c b/src/format/java.c index b29a1e7..9a7f799 100644 --- a/src/format/java.c +++ b/src/format/java.c @@ -106,6 +106,8 @@ static int _java_init(FormatPlugin * format, char const * arch); static int _java_exit(FormatPlugin * format); static char const * _java_detect(FormatPlugin * format); static int _java_decode(FormatPlugin * format, int raw); +static int _java_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); /* public */ @@ -123,6 +125,7 @@ FormatPlugin format_plugin = NULL, _java_detect, _java_decode, + _java_decode_section, NULL }; @@ -325,7 +328,8 @@ static int _java_decode(FormatPlugin * format, int raw) || (end = helper->seek(helper->format, 0, SEEK_END)) < 0) return -1; - return helper->decode(helper->format, NULL, offset, end - offset, 0); + return helper->set_section(helper->format, 0, ".text", offset, + end - offset, 0); } static int _decode_skip_attributes(FormatPlugin * format, uint16_t cnt) @@ -448,3 +452,14 @@ static int _decode_skip_interfaces(FormatPlugin * format, uint16_t cnt) return -1; return 0; } + + +/* java_decode_section */ +static int _java_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + FormatPluginHelper * helper = format->helper; + + return helper->decode(helper->format, section->offset, section->size, + section->base, calls, calls_cnt); +} diff --git a/src/format/pe.c b/src/format/pe.c index c5f849c..b2a2034 100644 --- a/src/format/pe.c +++ b/src/format/pe.c @@ -213,6 +213,8 @@ static char const _pe_header_signature[4] = "PE\0\0"; static int _pe_init(FormatPlugin * format, char const * arch); static char const * _pe_detect(FormatPlugin * format); static int _pe_decode(FormatPlugin * format, int raw); +static int _pe_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt); /* useful */ static char const * _pe_get_arch(uint16_t machine); @@ -233,6 +235,7 @@ FormatPlugin format_plugin = NULL, _pe_detect, _pe_decode, + _pe_decode_section, NULL }; @@ -385,7 +388,7 @@ static int _pe_decode(FormatPlugin * format, int raw) i) != 0) break; /* XXX report error */ } - /* read and decode each section */ + /* read and record each section */ offset = pm.offset + sizeof(_pe_header_signature) + sizeof(ph) + ph.opthdr_size; if(ph.opthdr_size != 0 && helper->seek(helper->format, offset, SEEK_SET) @@ -409,8 +412,9 @@ static int _pe_decode(FormatPlugin * format, int raw) /* the $ sign has a special meaning for the linker */ if((q = strchr(psh.name, '$')) != NULL) *q = '\0'; - if(helper->decode(helper->format, psh.name, psh.raw_offset, - psh.raw_size, psh.vaddr + base) != 0) + if(helper->set_section(helper->format, i, psh.name, + psh.raw_offset, psh.raw_size, + psh.vaddr + base) != 0) break; if(helper->seek(helper->format, offset, SEEK_SET) != offset) break; @@ -554,6 +558,17 @@ static char * _decode_string(FormatPlugin * format, off_t offset) } +/* pe_decode_section */ +static int _pe_decode_section(FormatPlugin * format, AsmSection * section, + ArchInstructionCall ** calls, size_t * calls_cnt) +{ + FormatPluginHelper * helper = format->helper; + + return helper->decode(helper->format, section->offset, section->size, + section->base, calls, calls_cnt); +} + + /* accessors */ /* pe_get_arch */ static char const * _pe_get_arch(uint16_t machine) diff --git a/src/main.c b/src/main.c index 97892a8..73881c0 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,13 @@ # define ASM_FILENAME_DEFAULT "a.out" +/* prototypes */ +static int _asm(AsmPrefs * prefs, char const * arch, char const * format, + char const * infile, char const * outfile); +static int _asm_string(AsmPrefs * prefs, char const * arch, char const * format, + char const * outfile, char const * string); + + /* functions */ /* asm */ static int _asm(AsmPrefs * prefs, char const * arch, char const * format, @@ -48,10 +55,27 @@ static int _asm(AsmPrefs * prefs, char const * arch, char const * format, } +/* asm_string */ +static int _asm_string(AsmPrefs * prefs, char const * arch, char const * format, + char const * outfile, char const * string) +{ + int ret = 0; + Asm * a; + + if((a = asm_new(arch, format)) == NULL) + return error_print(PACKAGE); + if(asm_assemble_string(a, prefs, outfile, string) != 0) + ret = error_print(PACKAGE); + asm_delete(a); + return ret; +} + + /* usage */ static unsigned int _usage(void) { fputs("Usage: asm [-D name][-a arch][-f format][-o file] file\n" +" asm [-D name][-a arch][-f format][-o file] -s string\n" " asm -l\n" " -D Set a variable in the pre-processor\n" " -a Target architecture\n" @@ -74,9 +98,10 @@ int main(int argc, char * argv[]) char * outfile = ASM_FILENAME_DEFAULT; char const * arch = NULL; char const * format = NULL; + char const * string = NULL; memset(&prefs, 0, sizeof(prefs)); - while((o = getopt(argc, argv, "a:D:f:o:l")) != -1) + while((o = getopt(argc, argv, "a:D:f:o:ls:")) != -1) switch(o) { case 'a': @@ -94,21 +119,35 @@ int main(int argc, char * argv[]) break; case 'l': o = 0; - if(asm_plugin_list(APT_ARCH) != 0) + if(asm_plugin_list(APT_ARCH, 0) != 0) o = error_print(PACKAGE); else putchar('\n'); - if(asm_plugin_list(APT_FORMAT) != 0) + if(asm_plugin_list(APT_FORMAT, 0) != 0) o = error_print(PACKAGE); return (o == 0) ? 0 : 2; + case 's': + string = optarg; + break; default: + free(prefs.defines); return _usage(); } - if(optind + 1 != argc) - return _usage(); - ret = _asm(&prefs, arch, format, argv[optind], outfile); + if(string != NULL) + { + if(optind != argc) + ret = _usage(); + else + ret = (_asm_string(&prefs, arch, format, outfile, + string) == 0) ? 0 : 2; + } + else if(optind == argc - 1) + ret = (_asm(&prefs, arch, format, argv[optind], outfile) == 0) + ? 0 : 2; + else + ret = _usage(); free(prefs.defines); - return (ret == 0) ? 0 : 2; + return ret; } static int _main_add_define(AsmPrefs * prefs, char * define) diff --git a/src/parser.c b/src/parser.c index d64365b..72dd6ac 100644 --- a/src/parser.c +++ b/src/parser.c @@ -34,7 +34,7 @@ typedef struct _State Token * token; unsigned int error_cnt; unsigned int warning_cnt; - Code * code; + AsmCode * code; ArchInstructionCall call; } State; @@ -157,6 +157,7 @@ static int _parser_error(State * state, char const * format, ...) fputs("asm: ", stderr); if(state->cpp != NULL && state->token != NULL) + /* FIXME will be wrong when string-based input is supported */ fprintf(stderr, "%s%s%u: ", cpp_get_filename(state->cpp), ", line ", token_get_line(state->token)); va_start(ap, format); @@ -174,6 +175,7 @@ static int _parser_warning(State * state, char const * format, ...) fputs("asm: ", stderr); if(state->cpp != NULL && state->token != NULL) + /* FIXME will be wrong when string-based input is supported */ fprintf(stderr, "%s%s%u: ", cpp_get_filename(state->cpp), ", line ", token_get_line(state->token)); va_start(ap, format); @@ -187,7 +189,7 @@ static int _parser_warning(State * state, char const * format, ...) /* protected */ /* functions */ /* parser */ -int parser(AsmPrefs * ap, Code * code, char const * infile) +int parser(AsmPrefs * ap, AsmCode * code, char const * infile) { CppPrefs prefs; State state; @@ -217,6 +219,38 @@ int parser(AsmPrefs * ap, Code * code, char const * infile) } +/* parser_string */ +int parser_string(AsmPrefs * ap, AsmCode * code, char const * string) +{ + CppPrefs prefs; + State state; + size_t i; + + memset(&prefs, 0, sizeof(prefs)); +#if 0 + prefs.filename = infile; +#endif + prefs.filters = CPP_FILTER_COMMENT; + memset(&state, 0, sizeof(state)); + state.code = code; + if((state.cpp = cpp_new(&prefs)) == NULL) + return -1; + if(ap != NULL) + for(i = 0; i < ap->defines_cnt; i++) + /* FIXME check errors */ + cpp_define_add(state.cpp, ap->defines[i], NULL); + if(_parser_scan(&state) != 0) + return _parser_error(&state, "%s", error_get()); + if(_program(&state) != 0) + error_set_code(1, "%s%u%s%u%s", "Compilation failed with ", + state.error_cnt, " error(s) and ", + state.warning_cnt, " warning(s)"); + if(state.token != NULL) + token_delete(state.token); + return state.error_cnt; +} + + /* grammar */ /* program */ static int _program(State * state) @@ -318,7 +352,7 @@ static int _section(State * state) #ifdef DEBUG fprintf(stderr, "%s\"%s\"\n", "DEBUG: section ", section); #endif - if(code_section(state->code, section) != 0) + if(asmcode_section(state->code, section) != 0) ret |= _parser_error(state, "%s", error_get()); free(section); } @@ -376,7 +410,7 @@ static int _function(State * state) #ifdef DEBUG fprintf(stderr, "DEBUG: %s \"%s\"\n", "function", function); #endif - if(code_function(state->code, function) != 0) + if(asmcode_function(state->code, function) != 0) ret |= _parser_error(state, "%s", error_get()); free(function); } @@ -403,7 +437,7 @@ static int _instruction(State * state) } if(state->call.name != NULL) { - if(code_instruction(state->code, &state->call) != 0) + if(asmcode_instruction(state->code, &state->call) != 0) ret |= _parser_error(state, "%s", error_get()); free(state->call.name); } diff --git a/src/parser.h b/src/parser.h index c59172d..0495710 100644 --- a/src/parser.h +++ b/src/parser.h @@ -18,9 +18,11 @@ #ifndef ASM_PARSER_H # define ASM_PARSER_H +# include "Asm/asm.h" # include "code.h" -int parser(AsmPrefs * prefs, Code * code, char const * infile); +int parser(AsmPrefs * prefs, AsmCode * code, char const * infile); +int parser_string(AsmPrefs * prefs, AsmCode * code, char const * string); #endif /* !ASM_PARSER_H */ diff --git a/test/Makefile b/test/Makefile index e312ef9..9d9a31b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,4 @@ -TARGETS = amd64.o arm.o dalvik.o i386.o i386_real.o i486.o i586.o i686.o mips.o java.o sparc.o sparc64.o yasep.o +TARGETS = amd64.o arm.o armeb.o armel.o dalvik.o i386.o i386_real.o i486.o i586.o i686.o mips.o mipseb.o mipsel.o java.o sparc.o sparc64.o yasep.o PREFIX = /usr/local DESTDIR = BINDIR = $(PREFIX)/bin @@ -18,6 +18,12 @@ amd64.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a amd64 arm.o_OBJS = arm.o arm.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a arm +armeb.o_OBJS = armeb.o +armeb.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a armeb + +armel.o_OBJS = armel.o +armel.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a armel + dalvik.o_OBJS = dalvik.o dalvik.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a dalvik -f flat @@ -39,6 +45,12 @@ i686.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a i686 mips.o_OBJS = mips.o mips.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a mips +mipseb.o_OBJS = mipseb.o +mipseb.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a mipseb + +mipsel.o_OBJS = mipsel.o +mipsel.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a mipsel + java.o_OBJS = java.o java.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a java -f flat @@ -57,6 +69,12 @@ amd64.o: amd64.S ../src/asm arm.o: arm.S ../src/asm $(AS) $(arm.o_ASFLAGS) -o arm.o arm.S +armeb.o: armeb.S arm.S ../src/asm + $(AS) $(armeb.o_ASFLAGS) -o armeb.o armeb.S + +armel.o: armel.S arm.S ../src/asm + $(AS) $(armel.o_ASFLAGS) -o armel.o armel.S + dalvik.o: dalvik.S ../src/asm $(AS) $(dalvik.o_ASFLAGS) -o dalvik.o dalvik.S @@ -78,6 +96,12 @@ i686.o: i686.S ../src/asm mips.o: mips.S ../src/asm $(AS) $(mips.o_ASFLAGS) -o mips.o mips.S +mipseb.o: mipseb.S mips.S ../src/asm + $(AS) $(mipseb.o_ASFLAGS) -o mipseb.o mipseb.S + +mipsel.o: mipsel.S mips.S ../src/asm + $(AS) $(mipsel.o_ASFLAGS) -o mipsel.o mipsel.S + java.o: java.S ../src/asm $(AS) $(java.o_ASFLAGS) -o java.o java.S @@ -91,7 +115,7 @@ yasep.o: yasep.S ../src/asm $(AS) $(yasep.o_ASFLAGS) -o yasep.o yasep.S clean: - $(RM) -- $(amd64.o_OBJS) $(arm.o_OBJS) $(dalvik.o_OBJS) $(i386.o_OBJS) $(i386_real.o_OBJS) $(i486.o_OBJS) $(i586.o_OBJS) $(i686.o_OBJS) $(mips.o_OBJS) $(java.o_OBJS) $(sparc.o_OBJS) $(sparc64.o_OBJS) $(yasep.o_OBJS) + $(RM) -- $(amd64.o_OBJS) $(arm.o_OBJS) $(armeb.o_OBJS) $(armel.o_OBJS) $(dalvik.o_OBJS) $(i386.o_OBJS) $(i386_real.o_OBJS) $(i486.o_OBJS) $(i586.o_OBJS) $(i686.o_OBJS) $(mips.o_OBJS) $(mipseb.o_OBJS) $(mipsel.o_OBJS) $(java.o_OBJS) $(sparc.o_OBJS) $(sparc64.o_OBJS) $(yasep.o_OBJS) distclean: clean $(RM) -- $(TARGETS) diff --git a/test/armeb.S b/test/armeb.S new file mode 100644 index 0000000..962f447 --- /dev/null +++ b/test/armeb.S @@ -0,0 +1,2 @@ +/* $Id$ */ +#include "arm.S" diff --git a/test/armel.S b/test/armel.S new file mode 100644 index 0000000..962f447 --- /dev/null +++ b/test/armel.S @@ -0,0 +1,2 @@ +/* $Id$ */ +#include "arm.S" diff --git a/test/mipseb.S b/test/mipseb.S new file mode 100644 index 0000000..6b1b7ff --- /dev/null +++ b/test/mipseb.S @@ -0,0 +1,2 @@ +/* $Id$ */ +#include "mips.S" diff --git a/test/mipsel.S b/test/mipsel.S new file mode 100644 index 0000000..6b1b7ff --- /dev/null +++ b/test/mipsel.S @@ -0,0 +1,2 @@ +/* $Id$ */ +#include "mips.S" diff --git a/test/project.conf b/test/project.conf index 4f70251..9facf7a 100644 --- a/test/project.conf +++ b/test/project.conf @@ -1,4 +1,4 @@ -targets=amd64.o,arm.o,dalvik.o,i386.o,i386_real.o,i486.o,i586.o,i686.o,mips.o,java.o,sparc.o,sparc64.o,yasep.o +targets=amd64.o,arm.o,armeb.o,armel.o,dalvik.o,i386.o,i386_real.o,i486.o,i586.o,i686.o,mips.o,mipseb.o,mipsel.o,java.o,sparc.o,sparc64.o,yasep.o as=../src/asm-static dist=Makefile @@ -18,6 +18,22 @@ sources=arm.S asflags=-a arm depends=../src/asm +[armeb.o] +type=object +sources=armeb.S + +[armeb.S] +asflags=-a armeb +depends=arm.S,../src/asm + +[armel.o] +type=object +sources=armel.S + +[armel.S] +asflags=-a armel +depends=arm.S,../src/asm + [dalvik.o] type=object sources=dalvik.S @@ -82,6 +98,22 @@ sources=mips.S asflags=-a mips depends=../src/asm +[mipseb.o] +type=object +sources=mipseb.S + +[mipseb.S] +asflags=-a mipseb +depends=mips.S,../src/asm + +[mipsel.o] +type=object +sources=mipsel.S + +[mipsel.S] +asflags=-a mipsel +depends=mips.S,../src/asm + [sparc.o] type=object sources=sparc.S