Moved detection of file format and architecture for deassembling into libasm
This commit is contained in:
parent
8c4cb8cce7
commit
d16f99ebbb
@ -60,7 +60,7 @@ arch.o: arch.c ../include/Asm/arch.h ../include/Asm/asm.h arch.h code.h ../confi
|
|||||||
asm.o: asm.c ../include/Asm.h code.h parser.h ../config.h
|
asm.o: asm.c ../include/Asm.h code.h parser.h ../config.h
|
||||||
$(CC) $(libasm_CFLAGS) -c asm.c
|
$(CC) $(libasm_CFLAGS) -c asm.c
|
||||||
|
|
||||||
code.o: code.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h arch.h code.h format.h
|
code.o: code.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h arch.h code.h format.h ../config.h
|
||||||
$(CC) $(libasm_CFLAGS) -c code.c
|
$(CC) $(libasm_CFLAGS) -c code.c
|
||||||
|
|
||||||
format.o: format.c ../include/Asm/asm.h ../include/Asm/format.h code.h format.h ../config.h
|
format.o: format.c ../include/Asm/asm.h ../include/Asm/format.h code.h format.h ../config.h
|
||||||
@ -75,7 +75,7 @@ token.o: token.c common.h token.h
|
|||||||
main.o: main.c ../include/Asm/asm.h ../config.h
|
main.o: main.c ../include/Asm/asm.h ../config.h
|
||||||
$(CC) $(asm_CFLAGS) -c main.c
|
$(CC) $(asm_CFLAGS) -c main.c
|
||||||
|
|
||||||
deasm.o: deasm.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h ../config.h
|
deasm.o: deasm.c ../include/Asm.h ../include/Asm/arch.h ../include/Asm/asm.h ../include/Asm/format.h
|
||||||
$(CC) $(deasm_CFLAGS) -c deasm.c
|
$(CC) $(deasm_CFLAGS) -c deasm.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
14
src/asm.c
14
src/asm.c
@ -183,7 +183,7 @@ int asm_deassemble(Asm * a, char const * buffer, size_t size)
|
|||||||
|
|
||||||
if(_asm_open(a, NULL) != 0)
|
if(_asm_open(a, NULL) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
ret = code_decode(a->code, buffer, size);
|
ret = code_decode_buffer(a->code, buffer, size);
|
||||||
asm_close(a);
|
asm_close(a);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -252,9 +252,17 @@ int asm_open_assemble(Asm * a, char const * outfile)
|
|||||||
/* asm_open_deassemble */
|
/* asm_open_deassemble */
|
||||||
int asm_open_deassemble(Asm * a, char const * filename)
|
int asm_open_deassemble(Asm * a, char const * filename)
|
||||||
{
|
{
|
||||||
if(_asm_open(a, NULL) != 0)
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename);
|
||||||
|
#endif
|
||||||
|
if(a->code != NULL)
|
||||||
|
return -error_set_code(1, "%s: Operation in progress",
|
||||||
|
code_get_filename(a->code));
|
||||||
|
if((a->code = code_new_file(a->arch, a->format, filename)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return code_decode_file(a->code, filename);
|
if(code_decode(a->code) != 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
278
src/code.c
278
src/code.c
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <System.h>
|
#include <System.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -26,6 +27,7 @@
|
|||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "code.h"
|
#include "code.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
|
||||||
/* Code */
|
/* Code */
|
||||||
@ -77,7 +79,7 @@ Code * code_new(char const * arch, char const * format)
|
|||||||
if((code->arch = arch_new(arch)) != NULL && format == NULL)
|
if((code->arch = arch_new(arch)) != NULL && format == NULL)
|
||||||
format = arch_get_format(code->arch);
|
format = arch_get_format(code->arch);
|
||||||
if(format != NULL)
|
if(format != NULL)
|
||||||
code->format = format_new(format, arch);
|
code->format = format_new(format);
|
||||||
if(code->arch == NULL || code->format == NULL)
|
if(code->arch == NULL || code->format == NULL)
|
||||||
{
|
{
|
||||||
code_delete(code);
|
code_delete(code);
|
||||||
@ -88,6 +90,101 @@ Code * code_new(char const * arch, char const * format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_new_file */
|
||||||
|
static Format * _new_file_format(char const * filename, FILE * fp);
|
||||||
|
|
||||||
|
Code * code_new_file(char const * arch, char const * format,
|
||||||
|
char const * filename)
|
||||||
|
{
|
||||||
|
Code * code;
|
||||||
|
FILE * fp;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename);
|
||||||
|
#endif
|
||||||
|
if((fp = fopen(filename, "r")) == NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s: %s", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if((code = object_new(sizeof(*code))) == NULL)
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(code, 0, sizeof(*code));
|
||||||
|
if(format == NULL)
|
||||||
|
code->format = _new_file_format(filename, fp);
|
||||||
|
else if((code->format = format_new(format)) != NULL
|
||||||
|
&& format_init(code->format, NULL, filename, fp) != 0)
|
||||||
|
{
|
||||||
|
format_delete(code->format);
|
||||||
|
code->format = NULL;
|
||||||
|
}
|
||||||
|
if(arch == NULL && code->format != NULL)
|
||||||
|
arch = format_detect_arch(code->format);
|
||||||
|
if(arch != NULL && (code->arch = arch_new(arch)) != NULL
|
||||||
|
&& arch_init(code->arch, filename, fp) != 0)
|
||||||
|
{
|
||||||
|
arch_delete(code->arch);
|
||||||
|
code->arch = NULL;
|
||||||
|
}
|
||||||
|
if(code->arch == NULL || code->format == NULL)
|
||||||
|
{
|
||||||
|
code_delete(code);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
code->description = arch_get_description(code->arch);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Format * _new_file_format(char const * filename, FILE * fp)
|
||||||
|
{
|
||||||
|
char const path[] = LIBDIR "/" PACKAGE "/format";
|
||||||
|
DIR * dir;
|
||||||
|
struct dirent * de;
|
||||||
|
size_t len;
|
||||||
|
char const ext[] = ".so";
|
||||||
|
int hasflat = 0;
|
||||||
|
Format * format = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, filename);
|
||||||
|
#endif
|
||||||
|
if((dir = opendir(path)) == NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s: %s", path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
while((de = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
if((len = strlen(de->d_name)) < 4)
|
||||||
|
continue;
|
||||||
|
if(strcmp(&de->d_name[len - sizeof(ext) + 1], ext) != 0)
|
||||||
|
continue;
|
||||||
|
de->d_name[len - sizeof(ext) + 1] = '\0';
|
||||||
|
if(strcmp(de->d_name, "flat") == 0)
|
||||||
|
hasflat = 1;
|
||||||
|
if((format = format_new(de->d_name)) == NULL)
|
||||||
|
continue;
|
||||||
|
if(format_init(format, NULL, filename, fp) == 0
|
||||||
|
&& format_match(format) == 1)
|
||||||
|
break;
|
||||||
|
format_delete(format);
|
||||||
|
format = NULL;
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
/* fallback on the "flat" format plug-in if necessary and available */
|
||||||
|
if(format == NULL && hasflat && (format = format_new("flat")) != NULL
|
||||||
|
&& format_init(format, NULL, filename, fp) != 0)
|
||||||
|
{
|
||||||
|
format_delete(format);
|
||||||
|
format = NULL;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* code_delete */
|
/* code_delete */
|
||||||
int code_delete(Code * code)
|
int code_delete(Code * code)
|
||||||
{
|
{
|
||||||
@ -187,10 +284,36 @@ int code_close(Code * code)
|
|||||||
|
|
||||||
|
|
||||||
/* code_decode */
|
/* code_decode */
|
||||||
static int _decode_print(Code * code, ArchInstructionCall * call);
|
int code_decode(Code * code)
|
||||||
static void _decode_print_immediate(Code * code, ArchOperand * ao);
|
{
|
||||||
|
return format_decode(code->format, code);
|
||||||
|
}
|
||||||
|
|
||||||
int code_decode(Code * code, char const * buffer, size_t size)
|
|
||||||
|
/* code_decode_at */
|
||||||
|
int code_decode_at(Code * code, char const * section, off_t offset,
|
||||||
|
size_t size, off_t base)
|
||||||
|
{
|
||||||
|
ArchInstructionCall * calls = NULL;
|
||||||
|
size_t calls_cnt = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if(section != NULL)
|
||||||
|
printf("%s%s:\n", "\nDisassembly of section ", section);
|
||||||
|
if(arch_decode_at(code->arch, code, &calls, &calls_cnt, offset, size,
|
||||||
|
base) != 0)
|
||||||
|
return -1;
|
||||||
|
if(size != 0)
|
||||||
|
printf("\n%08lx:\n", (long)offset + (long)base);
|
||||||
|
for(i = 0; i < calls_cnt; i++)
|
||||||
|
code_print(code, &calls[i]);
|
||||||
|
free(calls);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_decode_buffer */
|
||||||
|
int code_decode_buffer(Code * code, char const * buffer, size_t size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ArchInstructionCall * calls = NULL;
|
ArchInstructionCall * calls = NULL;
|
||||||
@ -202,14 +325,66 @@ int code_decode(Code * code, char const * buffer, size_t size)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "DEBUG: %lu\n", calls_cnt);
|
fprintf(stderr, "DEBUG: %lu\n", calls_cnt);
|
||||||
for(i = 0; i < calls_cnt; i++)
|
for(i = 0; i < calls_cnt; i++)
|
||||||
_decode_print(code, &calls[i]);
|
code_print(code, &calls[i]);
|
||||||
free(calls);
|
free(calls);
|
||||||
}
|
}
|
||||||
arch_exit(code->arch);
|
arch_exit(code->arch);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _decode_print(Code * code, ArchInstructionCall * call)
|
|
||||||
|
/* code_function */
|
||||||
|
int code_function(Code * code, char const * function)
|
||||||
|
{
|
||||||
|
return format_function(code->format, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_instruction */
|
||||||
|
int code_instruction(Code * code, ArchInstructionCall * call)
|
||||||
|
{
|
||||||
|
ArchInstruction * ai;
|
||||||
|
|
||||||
|
if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL)
|
||||||
|
return -1;
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x"
|
||||||
|
", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2,
|
||||||
|
ai->op3);
|
||||||
|
#endif
|
||||||
|
return arch_write(code->arch, ai, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_open */
|
||||||
|
int code_open(Code * code, char const * filename)
|
||||||
|
{
|
||||||
|
if(code->filename != NULL || code->fp != NULL)
|
||||||
|
return -error_set_code(1, "A file is already opened");
|
||||||
|
if((code->filename = string_new(filename)) == NULL)
|
||||||
|
return -1;
|
||||||
|
if((code->fp = fopen(filename, "w+")) == NULL)
|
||||||
|
return -error_set_code(1, "%s: %s", filename, strerror(errno));
|
||||||
|
if(arch_init(code->arch, code->filename, code->fp) == 0)
|
||||||
|
{
|
||||||
|
if(format_init(code->format, arch_get_name(code->arch),
|
||||||
|
code->filename, code->fp) == 0)
|
||||||
|
return 0;
|
||||||
|
arch_exit(code->arch);
|
||||||
|
}
|
||||||
|
fclose(code->fp);
|
||||||
|
code->fp = NULL;
|
||||||
|
unlink(code->filename); /* XXX may fail */
|
||||||
|
string_delete(code->filename);
|
||||||
|
code->filename = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* code_print */
|
||||||
|
static void _print_immediate(ArchOperand * ao);
|
||||||
|
|
||||||
|
int code_print(Code * code, ArchInstructionCall * call)
|
||||||
{
|
{
|
||||||
char const * sep = " ";
|
char const * sep = " ";
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -251,7 +426,7 @@ static int _decode_print(Code * code, ArchInstructionCall * call)
|
|||||||
ao->value.dregister2.name2);
|
ao->value.dregister2.name2);
|
||||||
break;
|
break;
|
||||||
case AOT_IMMEDIATE:
|
case AOT_IMMEDIATE:
|
||||||
_decode_print_immediate(code, ao);
|
_print_immediate(ao);
|
||||||
break;
|
break;
|
||||||
case AOT_REGISTER:
|
case AOT_REGISTER:
|
||||||
name = call->operands[i].value._register.name;
|
name = call->operands[i].value._register.name;
|
||||||
@ -264,7 +439,7 @@ static int _decode_print(Code * code, ArchInstructionCall * call)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _decode_print_immediate(Code * code, ArchOperand * ao)
|
static void _print_immediate(ArchOperand * ao)
|
||||||
{
|
{
|
||||||
printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "",
|
printf("%s$0x%lx", ao->value.immediate.negative ? "-" : "",
|
||||||
ao->value.immediate.value);
|
ao->value.immediate.value);
|
||||||
@ -285,93 +460,6 @@ static void _decode_print_immediate(Code * code, ArchOperand * ao)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* code_decode_at */
|
|
||||||
int code_decode_at(Code * code, char const * section, off_t offset,
|
|
||||||
size_t size, off_t base)
|
|
||||||
{
|
|
||||||
ArchInstructionCall * calls = NULL;
|
|
||||||
size_t calls_cnt = 0;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if(section != NULL)
|
|
||||||
printf("%s%s:\n", "\nDisassembly of section ", section);
|
|
||||||
if(arch_decode_at(code->arch, code, &calls, &calls_cnt, offset, size,
|
|
||||||
base) != 0)
|
|
||||||
return -1;
|
|
||||||
if(size != 0)
|
|
||||||
printf("\n%08lx:\n", (long)offset + (long)base);
|
|
||||||
for(i = 0; i < calls_cnt; i++)
|
|
||||||
_decode_print(code, &calls[i]);
|
|
||||||
free(calls);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* code_decode_file */
|
|
||||||
int code_decode_file(Code * code, char const * filename)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
FILE * fp;
|
|
||||||
|
|
||||||
if((fp = fopen(filename, "r")) == NULL)
|
|
||||||
return -error_set_code(1, "%s: %s", filename, strerror(errno));
|
|
||||||
arch_init(code->arch, filename, fp);
|
|
||||||
format_init(code->format, filename, fp);
|
|
||||||
ret = format_decode(code->format, code);
|
|
||||||
format_exit(code->format);
|
|
||||||
arch_exit(code->arch);
|
|
||||||
if(fclose(fp) != 0 && ret == 0)
|
|
||||||
ret = -error_set_code(1, "%s: %s", filename, strerror(errno));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* code_function */
|
|
||||||
int code_function(Code * code, char const * function)
|
|
||||||
{
|
|
||||||
return format_function(code->format, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* code_instruction */
|
|
||||||
int code_instruction(Code * code, ArchInstructionCall * call)
|
|
||||||
{
|
|
||||||
ArchInstruction * ai;
|
|
||||||
|
|
||||||
if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL)
|
|
||||||
return -1;
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x"
|
|
||||||
", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2,
|
|
||||||
ai->op3);
|
|
||||||
#endif
|
|
||||||
return arch_write(code->arch, ai, call);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* code_open */
|
|
||||||
int code_open(Code * code, char const * filename)
|
|
||||||
{
|
|
||||||
if(code->filename != NULL || code->fp != NULL)
|
|
||||||
return -error_set_code(1, "A file is already opened");
|
|
||||||
if((code->filename = string_new(filename)) == NULL)
|
|
||||||
return -1;
|
|
||||||
if((code->fp = fopen(filename, "w+")) == NULL)
|
|
||||||
return -error_set_code(1, "%s: %s", filename, strerror(errno));
|
|
||||||
if(format_init(code->format, code->filename, code->fp) != 0
|
|
||||||
|| arch_init(code->arch, code->filename, code->fp) != 0)
|
|
||||||
{
|
|
||||||
fclose(code->fp);
|
|
||||||
code->fp = NULL;
|
|
||||||
unlink(code->filename); /* XXX may fail */
|
|
||||||
string_delete(code->filename);
|
|
||||||
code->filename = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* code_section */
|
/* code_section */
|
||||||
int code_section(Code * code, char const * section)
|
int code_section(Code * code, char const * section)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@ typedef struct _Code Code;
|
|||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
Code * code_new(char const * arch, char const * format);
|
Code * code_new(char const * arch, char const * format);
|
||||||
|
Code * code_new_file(char const * arch, char const * format,
|
||||||
|
char const * filename);
|
||||||
int code_delete(Code * code);
|
int code_delete(Code * code);
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
@ -54,9 +56,10 @@ int code_instruction(Code * code, ArchInstructionCall * call);
|
|||||||
int code_section(Code * code, char const * section);
|
int code_section(Code * code, char const * section);
|
||||||
|
|
||||||
/* disassembly */
|
/* disassembly */
|
||||||
int code_decode(Code * code, char const * buffer, size_t size);
|
int code_decode(Code * code);
|
||||||
int code_decode_at(Code * code, char const * section, off_t offset,
|
int code_decode_at(Code * code, char const * section, off_t offset,
|
||||||
size_t size, off_t base);
|
size_t size, off_t base);
|
||||||
int code_decode_file(Code * code, char const * filename);
|
int code_decode_buffer(Code * code, char const * buffer, size_t size);
|
||||||
|
int code_print(Code * code, ArchInstructionCall * call);
|
||||||
|
|
||||||
#endif /* !ASM_CODE_H */
|
#endif /* !ASM_CODE_H */
|
||||||
|
315
src/deasm.c
315
src/deasm.c
@ -23,194 +23,35 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "Asm.h"
|
#include "Asm.h"
|
||||||
#include "../config.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* constants */
|
|
||||||
#ifndef PREFIX
|
|
||||||
# define PREFIX "/usr/local"
|
|
||||||
#endif
|
|
||||||
#ifndef LIBDIR
|
|
||||||
# define LIBDIR PREFIX "/lib"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* macros */
|
|
||||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm */
|
/* deasm */
|
||||||
/* private */
|
/* private */
|
||||||
/* types */
|
|
||||||
typedef struct _DeasmFormat
|
|
||||||
{
|
|
||||||
Plugin * plugin;
|
|
||||||
FormatPlugin * format;
|
|
||||||
} DeasmFormat;
|
|
||||||
|
|
||||||
/* XXX ugly */
|
|
||||||
#define _Deasm _Format
|
|
||||||
typedef struct _Deasm
|
|
||||||
{
|
|
||||||
char const * arch;
|
|
||||||
|
|
||||||
FormatPluginHelper helper;
|
|
||||||
DeasmFormat * format;
|
|
||||||
size_t format_cnt;
|
|
||||||
|
|
||||||
char const * filename;
|
|
||||||
FILE * fp;
|
|
||||||
} Deasm;
|
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static int _deasm(char const * arch, char const * format,
|
static int _deasm(char const * arch, char const * format,
|
||||||
char const * filename);
|
char const * filename);
|
||||||
static int _deasm_buffer(char const * arch, char const * format,
|
static int _deasm_buffer(char const * arch, char const * format,
|
||||||
char const * buffer, size_t size);
|
char const * buffer, size_t size);
|
||||||
static int _deasm_error(char const * message, int ret);
|
|
||||||
static int _deasm_string(char const * arch, char const * format,
|
static int _deasm_string(char const * arch, char const * format,
|
||||||
char const * string);
|
char const * string);
|
||||||
static int _deasm_list(void);
|
static int _deasm_list(void);
|
||||||
|
|
||||||
/* helper */
|
|
||||||
static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size);
|
|
||||||
static off_t _deasm_helper_seek(Format * format, off_t offset, int whence);
|
|
||||||
|
|
||||||
/* format */
|
|
||||||
static DeasmFormat const * _deasm_format_open(Deasm * deasm,
|
|
||||||
char const * format);
|
|
||||||
static int _deasm_format_open_all(Deasm * deasm);
|
|
||||||
static char const * _deasm_format_detect(DeasmFormat const * format);
|
|
||||||
static void _deasm_format_close(DeasmFormat const * format);
|
|
||||||
static void _deasm_format_close_all(Deasm * deasm);
|
|
||||||
|
|
||||||
static int _usage(void);
|
static int _usage(void);
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
/* deasm */
|
/* deasm */
|
||||||
static int _deasm_do_format(Deasm * deasm, char const * format);
|
static int _deasm(char const * arch, char const * format, char const * filename)
|
||||||
static int _deasm_do(Deasm * deasm);
|
|
||||||
static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format);
|
|
||||||
|
|
||||||
static int _deasm(char const * arch, char const * format,
|
|
||||||
char const * filename)
|
|
||||||
{
|
|
||||||
int ret = 1;
|
|
||||||
Deasm deasm;
|
|
||||||
|
|
||||||
deasm.arch = arch;
|
|
||||||
memset(&deasm.helper, 0, sizeof(deasm.helper));
|
|
||||||
deasm.helper.format = &deasm;
|
|
||||||
deasm.helper.read = _deasm_helper_read;
|
|
||||||
deasm.helper.seek = _deasm_helper_seek;
|
|
||||||
deasm.format = NULL;
|
|
||||||
deasm.format_cnt = 0;
|
|
||||||
if((deasm.fp = fopen(filename, "r")) == NULL)
|
|
||||||
return -_deasm_error(filename, 1);
|
|
||||||
deasm.filename = filename;
|
|
||||||
if(format != NULL)
|
|
||||||
ret = _deasm_do_format(&deasm, format);
|
|
||||||
else
|
|
||||||
ret = _deasm_do(&deasm);
|
|
||||||
fclose(deasm.fp);
|
|
||||||
_deasm_format_close_all(&deasm);
|
|
||||||
if(ret != 0)
|
|
||||||
error_print("deasm");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _deasm_do_format(Deasm * deasm, char const * format)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
size_t i;
|
|
||||||
DeasmFormat const * df;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format);
|
|
||||||
#endif
|
|
||||||
/* check if the plug-in is already opened */
|
|
||||||
for(i = 0; i < deasm->format_cnt; i++)
|
|
||||||
if(strcmp(deasm->format[i].format->name, format) == 0)
|
|
||||||
break;
|
|
||||||
if(i < deasm->format_cnt)
|
|
||||||
df = &deasm->format[i];
|
|
||||||
else if((df = _deasm_format_open(deasm, format)) == NULL)
|
|
||||||
return -1;
|
|
||||||
/* disassemble */
|
|
||||||
ret = _deasm_do_callback(deasm, df->format);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _deasm_do(Deasm * deasm)
|
|
||||||
{
|
|
||||||
int ret = 1;
|
|
||||||
size_t i;
|
|
||||||
size_t s = 0;
|
|
||||||
char * buf;
|
|
||||||
FormatPlugin * format;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
|
||||||
#endif
|
|
||||||
_deasm_format_open_all(deasm);
|
|
||||||
for(i = 0; i < deasm->format_cnt; i++)
|
|
||||||
s = max(s, deasm->format[i].format->signature_len);
|
|
||||||
if((buf = malloc(s)) == NULL)
|
|
||||||
return -_deasm_error(deasm->filename, 1);
|
|
||||||
if(fread(buf, 1, s, deasm->fp) != s)
|
|
||||||
{
|
|
||||||
if(ferror(deasm->fp))
|
|
||||||
ret = -_deasm_error(deasm->filename, 1);
|
|
||||||
else
|
|
||||||
ret = _deasm_do_format(deasm, "flat");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(i = 0; i < deasm->format_cnt; i++)
|
|
||||||
{
|
|
||||||
format = deasm->format[i].format;
|
|
||||||
if(format->signature_len == 0)
|
|
||||||
continue;
|
|
||||||
if(memcmp(format->signature, buf, format->signature_len)
|
|
||||||
!= 0)
|
|
||||||
continue;
|
|
||||||
if(deasm->arch == NULL)
|
|
||||||
deasm->arch = _deasm_format_detect(
|
|
||||||
&deasm->format[i]);
|
|
||||||
if(deasm->arch == NULL)
|
|
||||||
continue;
|
|
||||||
ret = _deasm_do_callback(deasm, format);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(i == deasm->format_cnt)
|
|
||||||
ret = _deasm_do_format(deasm, "flat");
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
Asm * a;
|
Asm * a;
|
||||||
|
|
||||||
#ifdef DEBUG
|
if((a = asm_new(arch, format)) == NULL)
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format->name);
|
|
||||||
#endif
|
|
||||||
if(deasm->arch == NULL)
|
|
||||||
{
|
|
||||||
if(format->detect == NULL)
|
|
||||||
return -error_set_code(1, "%s: %s", deasm->filename,
|
|
||||||
"Unable to detect the architecture");
|
|
||||||
if((deasm->arch = format->detect(format)) == NULL)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if((a = asm_new(deasm->arch, format->name)) == NULL)
|
|
||||||
return -error_print("deasm");
|
return -error_print("deasm");
|
||||||
printf("\n%s: %s-%s\n", deasm->filename, format->name, asm_get_arch(a));
|
if((ret = asm_open_deassemble(a, filename)) != 0)
|
||||||
ret = asm_open_deassemble(a, deasm->filename);
|
error_print("deasm");
|
||||||
|
else
|
||||||
|
asm_close(a);
|
||||||
asm_delete(a);
|
asm_delete(a);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -234,15 +75,6 @@ static int _deasm_buffer(char const * arch, char const * format,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* deasm_error */
|
|
||||||
static int _deasm_error(char const * message, int ret)
|
|
||||||
{
|
|
||||||
fputs("deasm: ", stderr);
|
|
||||||
perror(message);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_string */
|
/* deasm_string */
|
||||||
static int _string_hex2bin(int c);
|
static int _string_hex2bin(int c);
|
||||||
static int _string_ishex(int c);
|
static int _string_ishex(int c);
|
||||||
@ -304,148 +136,15 @@ static int _string_ishex(int c)
|
|||||||
/* deasm_list */
|
/* deasm_list */
|
||||||
static int _deasm_list(void)
|
static int _deasm_list(void)
|
||||||
{
|
{
|
||||||
Deasm deasm;
|
|
||||||
size_t i;
|
|
||||||
char const * sep = "";
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
#endif
|
#endif
|
||||||
memset(&deasm, 0, sizeof(deasm));
|
|
||||||
asm_plugin_list(APT_ARCH);
|
asm_plugin_list(APT_ARCH);
|
||||||
_deasm_format_open_all(&deasm);
|
asm_plugin_list(APT_FORMAT);
|
||||||
fputs("\nAvailable format plug-ins:\n", stderr);
|
|
||||||
for(i = 0; i < deasm.format_cnt; i++)
|
|
||||||
{
|
|
||||||
if(deasm.format[i].format->decode == NULL)
|
|
||||||
continue;
|
|
||||||
fprintf(stderr, "%s%s", sep, deasm.format[i].format->name);
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
fputc('\n', stderr);
|
|
||||||
_deasm_format_close_all(&deasm);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* helper */
|
|
||||||
/* deasm_helper_read */
|
|
||||||
static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size)
|
|
||||||
{
|
|
||||||
if(fread(buf, size, 1, format->fp) == 1)
|
|
||||||
return size;
|
|
||||||
return -error_set_code(1, "%s: %s", format->filename, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_helper_seek */
|
|
||||||
static off_t _deasm_helper_seek(Format * format, off_t offset, int whence)
|
|
||||||
{
|
|
||||||
if(fseek(format->fp, offset, whence) != 0)
|
|
||||||
return -error_set_code(1, "%s: %s", format->filename,
|
|
||||||
strerror(errno));;
|
|
||||||
return ftello(format->fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* format */
|
|
||||||
/* deasm_format_open */
|
|
||||||
static DeasmFormat const * _deasm_format_open(Deasm * deasm,
|
|
||||||
char const * format)
|
|
||||||
{
|
|
||||||
DeasmFormat * p;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format);
|
|
||||||
#endif
|
|
||||||
if((p = realloc(deasm->format, sizeof(*p) * (deasm->format_cnt + 1)))
|
|
||||||
== NULL)
|
|
||||||
{
|
|
||||||
error_set_code(1, "%s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
deasm->format = p;
|
|
||||||
p = &deasm->format[deasm->format_cnt];
|
|
||||||
if((p->plugin = plugin_new(LIBDIR, PACKAGE, "format", format)) == NULL)
|
|
||||||
return NULL;
|
|
||||||
if((p->format = plugin_lookup(p->plugin, "format_plugin")) == NULL)
|
|
||||||
{
|
|
||||||
plugin_delete(p->plugin);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(p->format->decode == NULL)
|
|
||||||
{
|
|
||||||
error_set_code(1, "%s: %s", format,
|
|
||||||
"Does not support disassembly");
|
|
||||||
plugin_delete(p->plugin);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
p->format->helper = &deasm->helper;
|
|
||||||
deasm->format_cnt++;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_format_open_all */
|
|
||||||
static int _deasm_format_open_all(Deasm * deasm)
|
|
||||||
{
|
|
||||||
char const path[] = LIBDIR "/" PACKAGE "/format";
|
|
||||||
DIR * dir;
|
|
||||||
struct dirent * de;
|
|
||||||
size_t len;
|
|
||||||
char const ext[] = ".so";
|
|
||||||
|
|
||||||
if((dir = opendir(path)) == NULL)
|
|
||||||
return -error_set_print("deasm", 1, "%s: %s", path, strerror(
|
|
||||||
errno));
|
|
||||||
while((de = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
if((len = strlen(de->d_name)) < 4)
|
|
||||||
continue;
|
|
||||||
if(strcmp(&de->d_name[len - sizeof(ext) + 1], ext) != 0)
|
|
||||||
continue;
|
|
||||||
de->d_name[len - sizeof(ext) + 1] = '\0';
|
|
||||||
if(_deasm_format_open(deasm, de->d_name) == NULL)
|
|
||||||
error_print("deasm");
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_format_detect */
|
|
||||||
static char const * _deasm_format_detect(DeasmFormat const * format)
|
|
||||||
{
|
|
||||||
if(format->format->detect == NULL)
|
|
||||||
return NULL;
|
|
||||||
return format->format->detect(format->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_format_close */
|
|
||||||
static void _deasm_format_close(DeasmFormat const * format)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, format->format->name);
|
|
||||||
#endif
|
|
||||||
plugin_delete(format->plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* deasm_format_close_all */
|
|
||||||
static void _deasm_format_close_all(Deasm * deasm)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for(i = 0; i < deasm->format_cnt; i++)
|
|
||||||
_deasm_format_close(&deasm->format[i]);
|
|
||||||
free(deasm->format);
|
|
||||||
deasm->format = NULL;
|
|
||||||
deasm->format_cnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* usage */
|
/* usage */
|
||||||
static int _usage(void)
|
static int _usage(void)
|
||||||
{
|
{
|
||||||
|
196
src/format.c
196
src/format.c
@ -30,7 +30,6 @@
|
|||||||
/* types */
|
/* types */
|
||||||
struct _Format
|
struct _Format
|
||||||
{
|
{
|
||||||
char * arch;
|
|
||||||
FormatPluginHelper helper;
|
FormatPluginHelper helper;
|
||||||
Plugin * handle;
|
Plugin * handle;
|
||||||
FormatPlugin * plugin;
|
FormatPlugin * plugin;
|
||||||
@ -46,24 +45,34 @@ struct _Format
|
|||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
/* callbacks */
|
/* helpers */
|
||||||
static char const * _format_get_filename(Format * format);
|
static char const * _format_helper_get_filename(Format * format);
|
||||||
|
static AsmString * _format_helper_get_string_by_id(Format * format, AsmId id);
|
||||||
|
static int _format_helper_set_function(Format * format, int id,
|
||||||
|
char const * name, off_t offset, ssize_t size);
|
||||||
|
static int _format_helper_set_string(Format * format, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size);
|
||||||
|
|
||||||
static ssize_t _format_read(Format * format, void * buf, size_t size);
|
static int _format_helper_decode(Format * format, char const * section,
|
||||||
static off_t _format_seek(Format * format, off_t offset, int whence);
|
off_t offset, size_t size, off_t base);
|
||||||
|
static ssize_t _format_helper_read(Format * format, void * buf, size_t size);
|
||||||
static ssize_t _format_write(Format * format, void const * buf, size_t size);
|
static off_t _format_helper_seek(Format * format, off_t offset, int whence);
|
||||||
|
static ssize_t _format_helper_write(Format * format, void const * buf,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
|
||||||
/* public */
|
/* public */
|
||||||
/* functions */
|
/* functions */
|
||||||
/* format_new */
|
/* format_new */
|
||||||
Format * format_new(char const * format, char const * arch)
|
Format * format_new(char const * format)
|
||||||
{
|
{
|
||||||
Format * f;
|
Format * f;
|
||||||
Plugin * handle;
|
Plugin * handle;
|
||||||
FormatPlugin * plugin;
|
FormatPlugin * plugin;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format);
|
||||||
|
#endif
|
||||||
if(format == NULL)
|
if(format == NULL)
|
||||||
{
|
{
|
||||||
error_set_code(1, "%s", strerror(EINVAL));
|
error_set_code(1, "%s", strerror(EINVAL));
|
||||||
@ -77,15 +86,18 @@ Format * format_new(char const * format, char const * arch)
|
|||||||
plugin_delete(handle);
|
plugin_delete(handle);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
f->arch = string_new(arch);
|
|
||||||
memset(&f->helper, 0, sizeof(f->helper));
|
|
||||||
f->plugin = plugin;
|
|
||||||
f->handle = handle;
|
f->handle = handle;
|
||||||
if(f->arch == NULL)
|
f->plugin = plugin;
|
||||||
{
|
memset(&f->helper, 0, sizeof(f->helper));
|
||||||
format_delete(f);
|
f->helper.format = f;
|
||||||
return NULL;
|
f->helper.decode = _format_helper_decode;
|
||||||
}
|
f->helper.get_filename = _format_helper_get_filename;
|
||||||
|
f->helper.get_string_by_id = _format_helper_get_string_by_id;
|
||||||
|
f->helper.set_function = _format_helper_set_function;
|
||||||
|
f->helper.set_string = _format_helper_set_string;
|
||||||
|
f->helper.read = _format_helper_read;
|
||||||
|
f->helper.seek = _format_helper_seek;
|
||||||
|
f->helper.write = _format_helper_write;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,12 +106,20 @@ Format * format_new(char const * format, char const * arch)
|
|||||||
void format_delete(Format * format)
|
void format_delete(Format * format)
|
||||||
{
|
{
|
||||||
plugin_delete(format->handle);
|
plugin_delete(format->handle);
|
||||||
string_delete(format->arch);
|
|
||||||
object_delete(format);
|
object_delete(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
|
/* format_get_arch */
|
||||||
|
char const * format_get_arch(Format * format)
|
||||||
|
{
|
||||||
|
if(format->plugin->detect == NULL)
|
||||||
|
return NULL;
|
||||||
|
return format->plugin->detect(format->plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_get_name */
|
/* format_get_name */
|
||||||
char const * format_get_name(Format * format)
|
char const * format_get_name(Format * format)
|
||||||
{
|
{
|
||||||
@ -109,14 +129,6 @@ char const * format_get_name(Format * format)
|
|||||||
|
|
||||||
/* useful */
|
/* useful */
|
||||||
/* format_decode */
|
/* format_decode */
|
||||||
static int _decode_callback(Format * format, char const * section,
|
|
||||||
off_t offset, size_t size, off_t base);
|
|
||||||
static AsmString * _get_string_by_id_callback(Format * format, AsmId id);
|
|
||||||
static int _set_function_callback(Format * format, int id, char const * name,
|
|
||||||
off_t offset, ssize_t size);
|
|
||||||
static int _set_string_callback(Format * format, int id, char const * name,
|
|
||||||
off_t offset, ssize_t size);
|
|
||||||
|
|
||||||
int format_decode(Format * format, Code * code)
|
int format_decode(Format * format, Code * code)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -124,45 +136,23 @@ int format_decode(Format * format, Code * code)
|
|||||||
if(format->plugin->decode == NULL)
|
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");
|
"Disassembly is not supported");
|
||||||
format->helper.decode = _decode_callback;
|
|
||||||
format->helper.get_string_by_id = _get_string_by_id_callback;
|
|
||||||
format->helper.set_function = _set_string_callback;
|
|
||||||
format->helper.set_string = _set_string_callback;
|
|
||||||
format->code = code;
|
format->code = code;
|
||||||
ret = format->plugin->decode(format->plugin);
|
ret = format->plugin->decode(format->plugin);
|
||||||
format->code = NULL;
|
format->code = NULL;
|
||||||
format->helper.set_string = NULL;
|
|
||||||
format->helper.set_function = NULL;
|
|
||||||
format->helper.get_string_by_id = NULL;
|
|
||||||
format->helper.decode = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _decode_callback(Format * format, char const * section,
|
|
||||||
off_t offset, size_t size, off_t base)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__,
|
|
||||||
section, offset, size, base);
|
|
||||||
#endif
|
|
||||||
return code_decode_at(format->code, section, offset, size, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static AsmString * _get_string_by_id_callback(Format * format, AsmId id)
|
/* format_detect_arch */
|
||||||
|
char const * format_detect_arch(Format * format)
|
||||||
{
|
{
|
||||||
return code_get_string_by_id(format->code, id);
|
if(format->plugin->detect == NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s: %s", format->plugin->name,
|
||||||
|
"Unable to detect the architecture");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return format->plugin->detect(format->plugin);
|
||||||
static int _set_function_callback(Format * format, int id, char const * name,
|
|
||||||
off_t offset, ssize_t size)
|
|
||||||
{
|
|
||||||
return code_set_function(format->code, id, name, offset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _set_string_callback(Format * format, int id, char const * name,
|
|
||||||
off_t offset, ssize_t size)
|
|
||||||
{
|
|
||||||
return code_set_string(format->code, id, name, offset, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -176,10 +166,6 @@ int format_exit(Format * format)
|
|||||||
#endif
|
#endif
|
||||||
if(format->plugin->exit != NULL)
|
if(format->plugin->exit != NULL)
|
||||||
ret = format->plugin->exit(format->plugin);
|
ret = format->plugin->exit(format->plugin);
|
||||||
format->helper.format = NULL;
|
|
||||||
format->helper.decode = NULL;
|
|
||||||
format->helper.read = NULL;
|
|
||||||
format->helper.seek = NULL;
|
|
||||||
format->plugin->helper = NULL;
|
format->plugin->helper = NULL;
|
||||||
format->fp = NULL;
|
format->fp = NULL;
|
||||||
format->filename = NULL;
|
format->filename = NULL;
|
||||||
@ -197,7 +183,8 @@ int format_function(Format * format, char const * function)
|
|||||||
|
|
||||||
|
|
||||||
/* format_init */
|
/* format_init */
|
||||||
int format_init(Format * format, char const * filename, FILE * fp)
|
int format_init(Format * format, char const * arch, char const * filename,
|
||||||
|
FILE * fp)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename,
|
fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename,
|
||||||
@ -205,19 +192,41 @@ int format_init(Format * format, char const * filename, FILE * fp)
|
|||||||
#endif
|
#endif
|
||||||
format->filename = filename;
|
format->filename = filename;
|
||||||
format->fp = fp;
|
format->fp = fp;
|
||||||
format->helper.format = format;
|
|
||||||
format->helper.decode = NULL;
|
|
||||||
format->helper.get_filename = _format_get_filename;
|
|
||||||
format->helper.read = _format_read;
|
|
||||||
format->helper.seek = _format_seek;
|
|
||||||
format->helper.write = _format_write;
|
|
||||||
format->plugin->helper = &format->helper;
|
format->plugin->helper = &format->helper;
|
||||||
if(format->plugin->init != NULL)
|
if(format->plugin->init != NULL)
|
||||||
return format->plugin->init(format->plugin, format->arch);
|
return format->plugin->init(format->plugin, arch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format_match */
|
||||||
|
int format_match(Format * format)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
char const * s = format->plugin->signature;
|
||||||
|
ssize_t s_len = format->plugin->signature_len;
|
||||||
|
char * buf = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
if(s_len > 0)
|
||||||
|
if((buf = malloc(s_len)) == NULL)
|
||||||
|
ret = -error_set_code(1, "%s", strerror(errno));
|
||||||
|
if(buf != NULL)
|
||||||
|
{
|
||||||
|
if(_format_helper_seek(format, 0, SEEK_SET) != 0)
|
||||||
|
ret = -1;
|
||||||
|
else if(_format_helper_read(format, buf, s_len) != s_len)
|
||||||
|
ret = -1;
|
||||||
|
else if(memcmp(buf, s, s_len) == 0)
|
||||||
|
ret = 1;
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_section */
|
/* format_section */
|
||||||
int format_section(Format * format, char const * section)
|
int format_section(Format * format, char const * section)
|
||||||
{
|
{
|
||||||
@ -229,15 +238,51 @@ int format_section(Format * format, char const * section)
|
|||||||
|
|
||||||
/* private */
|
/* private */
|
||||||
/* functions */
|
/* functions */
|
||||||
/* format_get_filename */
|
/* helpers */
|
||||||
static char const * _format_get_filename(Format * format)
|
/* format_helper_get_filename */
|
||||||
|
static char const * _format_helper_get_filename(Format * format)
|
||||||
{
|
{
|
||||||
return format->filename;
|
return format->filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_read */
|
/* format_helper_get_string_by_id */
|
||||||
static ssize_t _format_read(Format * format, void * buf, size_t size)
|
static AsmString * _format_helper_get_string_by_id(Format * format, AsmId id)
|
||||||
|
{
|
||||||
|
return code_get_string_by_id(format->code, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format_helper_set_function */
|
||||||
|
static int _format_helper_set_function(Format * format, int id,
|
||||||
|
char const * name, off_t offset, ssize_t size)
|
||||||
|
{
|
||||||
|
return code_set_function(format->code, id, name, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format_helper_set_string */
|
||||||
|
static int _format_helper_set_string(Format * format, int id, char const * name,
|
||||||
|
off_t offset, ssize_t size)
|
||||||
|
{
|
||||||
|
return code_set_string(format->code, id, name, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format_helper_decode */
|
||||||
|
static int _format_helper_decode(Format * format, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%lx, 0x%lx, 0x%lx)\n", __func__,
|
||||||
|
section, offset, size, base);
|
||||||
|
#endif
|
||||||
|
return code_decode_at(format->code, section, offset, size, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format_helper_read */
|
||||||
|
static ssize_t _format_helper_read(Format * format, void * buf, size_t size)
|
||||||
{
|
{
|
||||||
if(fread(buf, size, 1, format->fp) == 1)
|
if(fread(buf, size, 1, format->fp) == 1)
|
||||||
return size;
|
return size;
|
||||||
@ -251,8 +296,8 @@ static ssize_t _format_read(Format * format, void * buf, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_seek */
|
/* format_helper_seek */
|
||||||
static off_t _format_seek(Format * format, off_t offset, int whence)
|
static off_t _format_helper_seek(Format * format, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
if(whence == SEEK_SET)
|
if(whence == SEEK_SET)
|
||||||
{
|
{
|
||||||
@ -271,8 +316,9 @@ static off_t _format_seek(Format * format, off_t offset, int whence)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* format_write */
|
/* format_helper_write */
|
||||||
static ssize_t _format_write(Format * format, void const * buf, size_t size)
|
static ssize_t _format_helper_write(Format * format, void const * buf,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
if(fwrite(buf, size, 1, format->fp) == 1)
|
if(fwrite(buf, size, 1, format->fp) == 1)
|
||||||
return size;
|
return size;
|
||||||
|
@ -34,7 +34,7 @@ typedef int (*FormatSetStringCallback)(void * priv, int id, char const * name,
|
|||||||
off_t offset, ssize_t length);
|
off_t offset, ssize_t length);
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
Format * format_new(char const * format, char const * arch);
|
Format * format_new(char const * format);
|
||||||
void format_delete(Format * format);
|
void format_delete(Format * format);
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
@ -42,7 +42,8 @@ char const * format_get_name(Format * format);
|
|||||||
|
|
||||||
/* useful */
|
/* useful */
|
||||||
/* assembly */
|
/* assembly */
|
||||||
int format_init(Format * format, char const * filename, FILE * fp);
|
int format_init(Format * format, char const * arch, char const * filename,
|
||||||
|
FILE * fp);
|
||||||
int format_exit(Format * format);
|
int format_exit(Format * format);
|
||||||
|
|
||||||
int format_function(Format * format, char const * function);
|
int format_function(Format * format, char const * function);
|
||||||
@ -50,5 +51,7 @@ int format_section(Format * format, char const * section);
|
|||||||
|
|
||||||
/* disassembly */
|
/* disassembly */
|
||||||
int format_decode(Format * format, Code * code);
|
int format_decode(Format * format, Code * code);
|
||||||
|
char const * format_detect_arch(Format * format);
|
||||||
|
int format_match(Format * format);
|
||||||
|
|
||||||
#endif /* !ASM_FORMAT_H */
|
#endif /* !ASM_FORMAT_H */
|
||||||
|
@ -54,12 +54,18 @@ typedef struct _ElfStrtab
|
|||||||
size_t cnt;
|
size_t cnt;
|
||||||
} ElfStrtab;
|
} ElfStrtab;
|
||||||
|
|
||||||
|
typedef struct _Elf
|
||||||
|
{
|
||||||
|
ElfArch * arch;
|
||||||
|
} Elf;
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static int _elf_error(FormatPlugin * format);
|
static int _elf_error(FormatPlugin * format);
|
||||||
|
|
||||||
/* plug-in */
|
/* plug-in */
|
||||||
static int _elf_init(FormatPlugin * format, char const * arch);
|
static int _elf_init(FormatPlugin * format, char const * arch);
|
||||||
|
static int _elf_exit(FormatPlugin * format);
|
||||||
static char const * _elf_detect(FormatPlugin * format);
|
static char const * _elf_detect(FormatPlugin * format);
|
||||||
static int _elf_decode(FormatPlugin * format);
|
static int _elf_decode(FormatPlugin * format);
|
||||||
static int _elf_decode32(FormatPlugin * format);
|
static int _elf_decode32(FormatPlugin * format);
|
||||||
@ -92,7 +98,6 @@ static ElfArch elf_arch[] =
|
|||||||
{ "sparc64", EM_SPARCV9, ELFCLASS64, ELFDATA2MSB },
|
{ "sparc64", EM_SPARCV9, ELFCLASS64, ELFDATA2MSB },
|
||||||
{ NULL, '\0', '\0', '\0' }
|
{ NULL, '\0', '\0', '\0' }
|
||||||
};
|
};
|
||||||
static ElfArch * ea;
|
|
||||||
|
|
||||||
static ElfSectionValues elf_section_values[] =
|
static ElfSectionValues elf_section_values[] =
|
||||||
{
|
{
|
||||||
@ -134,7 +139,7 @@ FormatPlugin format_plugin =
|
|||||||
ELFMAG,
|
ELFMAG,
|
||||||
SELFMAG,
|
SELFMAG,
|
||||||
_elf_init,
|
_elf_init,
|
||||||
NULL,
|
_elf_exit,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
_elf_detect,
|
_elf_detect,
|
||||||
@ -158,16 +163,32 @@ static ElfArch * _init_arch(char const * arch);
|
|||||||
|
|
||||||
static int _elf_init(FormatPlugin * format, char const * arch)
|
static int _elf_init(FormatPlugin * format, char const * arch)
|
||||||
{
|
{
|
||||||
if((ea = _init_arch(arch)) == NULL)
|
Elf * elf;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, arch);
|
||||||
|
#endif
|
||||||
|
if((elf = object_new(sizeof(*elf))) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if(ea->capacity == ELFCLASS32)
|
format->priv = elf;
|
||||||
|
if(arch == NULL)
|
||||||
|
{
|
||||||
|
elf->arch = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if((elf->arch = _init_arch(arch)) == NULL)
|
||||||
|
{
|
||||||
|
object_delete(elf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(elf->arch->capacity == ELFCLASS32)
|
||||||
{
|
{
|
||||||
if(_init_32(format) != 0)
|
if(_init_32(format) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
format->exit = _exit_32;
|
format->exit = _exit_32;
|
||||||
format->section = _section_32;
|
format->section = _section_32;
|
||||||
}
|
}
|
||||||
else if(ea->capacity == ELFCLASS64)
|
else if(elf->arch->capacity == ELFCLASS64)
|
||||||
{
|
{
|
||||||
if(_init_64(format) != 0)
|
if(_init_64(format) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -191,6 +212,19 @@ static ElfArch * _init_arch(char const * arch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* elf_exit */
|
||||||
|
static int _elf_exit(FormatPlugin * format)
|
||||||
|
{
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
object_delete(elf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* elf_detect */
|
/* elf_detect */
|
||||||
static char const * _detect_32(FormatPlugin * format, Elf32_Ehdr * ehdr);
|
static char const * _detect_32(FormatPlugin * format, Elf32_Ehdr * ehdr);
|
||||||
static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr);
|
static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr);
|
||||||
@ -555,8 +589,13 @@ static int es32_cnt = 0;
|
|||||||
static int _init_32(FormatPlugin * format)
|
static int _init_32(FormatPlugin * format)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
Elf32_Ehdr hdr;
|
Elf32_Ehdr hdr;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
memset(&hdr, 0, sizeof(hdr));
|
memset(&hdr, 0, sizeof(hdr));
|
||||||
memcpy(&hdr.e_ident, ELFMAG, SELFMAG);
|
memcpy(&hdr.e_ident, ELFMAG, SELFMAG);
|
||||||
hdr.e_ident[EI_CLASS] = ELFCLASS32;
|
hdr.e_ident[EI_CLASS] = ELFCLASS32;
|
||||||
@ -612,12 +651,15 @@ static int _exit_32(FormatPlugin * format)
|
|||||||
free(shstrtab.buf);
|
free(shstrtab.buf);
|
||||||
shstrtab.buf = NULL;
|
shstrtab.buf = NULL;
|
||||||
shstrtab.cnt = 0;
|
shstrtab.cnt = 0;
|
||||||
|
ret |= _elf_exit(format);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset)
|
static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
Elf32_Ehdr hdr;
|
Elf32_Ehdr hdr;
|
||||||
|
|
||||||
if(es32_cnt == 0)
|
if(es32_cnt == 0)
|
||||||
@ -648,6 +690,8 @@ static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset)
|
|||||||
static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset)
|
static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
Elf32_Shdr hdr;
|
Elf32_Shdr hdr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -721,8 +765,13 @@ static int es64_cnt = 0;
|
|||||||
static int _init_64(FormatPlugin * format)
|
static int _init_64(FormatPlugin * format)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
Elf64_Ehdr hdr;
|
Elf64_Ehdr hdr;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
memset(&hdr, 0, sizeof(hdr));
|
memset(&hdr, 0, sizeof(hdr));
|
||||||
memcpy(&hdr.e_ident, ELFMAG, SELFMAG);
|
memcpy(&hdr.e_ident, ELFMAG, SELFMAG);
|
||||||
hdr.e_ident[EI_CLASS] = ELFCLASS64;
|
hdr.e_ident[EI_CLASS] = ELFCLASS64;
|
||||||
@ -777,12 +826,15 @@ static int _exit_64(FormatPlugin * format)
|
|||||||
free(shstrtab.buf);
|
free(shstrtab.buf);
|
||||||
shstrtab.buf = NULL;
|
shstrtab.buf = NULL;
|
||||||
shstrtab.cnt = 0;
|
shstrtab.cnt = 0;
|
||||||
|
ret |= _elf_exit(format);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset)
|
static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
Elf64_Ehdr hdr;
|
Elf64_Ehdr hdr;
|
||||||
|
|
||||||
if(es64_cnt == 0)
|
if(es64_cnt == 0)
|
||||||
@ -813,6 +865,8 @@ static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset)
|
|||||||
static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset)
|
static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset)
|
||||||
{
|
{
|
||||||
FormatPluginHelper * helper = format->helper;
|
FormatPluginHelper * helper = format->helper;
|
||||||
|
Elf * elf = format->priv;
|
||||||
|
ElfArch * ea = elf->arch;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(helper->seek(helper->format, 0, SEEK_END) < 0)
|
if(helper->seek(helper->format, 0, SEEK_END) < 0)
|
||||||
|
@ -138,6 +138,11 @@ static int _java_init(FormatPlugin * format, char const * arch)
|
|||||||
JavaHeader jh;
|
JavaHeader jh;
|
||||||
JavaPlugin * java;
|
JavaPlugin * java;
|
||||||
|
|
||||||
|
if(arch == NULL)
|
||||||
|
{
|
||||||
|
format->priv = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(strcmp(arch, "java") != 0)
|
if(strcmp(arch, "java") != 0)
|
||||||
return error_set_code(1, "%s: %s", arch,
|
return error_set_code(1, "%s: %s", arch,
|
||||||
"Unsupported architecture for java");
|
"Unsupported architecture for java");
|
||||||
|
@ -124,6 +124,8 @@ static int _pe_init(FormatPlugin * format, char const * arch)
|
|||||||
struct pe_msdos pm;
|
struct pe_msdos pm;
|
||||||
struct pe_header ph;
|
struct pe_header ph;
|
||||||
|
|
||||||
|
if(arch == NULL)
|
||||||
|
return 0;
|
||||||
if((machine = _pe_get_machine(arch)) < 0)
|
if((machine = _pe_get_machine(arch)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
memset(&pm, 0, sizeof(pm));
|
memset(&pm, 0, sizeof(pm));
|
||||||
|
@ -40,10 +40,10 @@ depends=../include/Asm/arch.h,../include/Asm/asm.h,arch.h,code.h,../config.h
|
|||||||
depends=../include/Asm.h,code.h,parser.h,../config.h
|
depends=../include/Asm.h,code.h,parser.h,../config.h
|
||||||
|
|
||||||
[code.c]
|
[code.c]
|
||||||
depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,arch.h,code.h,format.h
|
depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,arch.h,code.h,format.h,../config.h
|
||||||
|
|
||||||
[deasm.c]
|
[deasm.c]
|
||||||
depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h,../config.h
|
depends=../include/Asm.h,../include/Asm/arch.h,../include/Asm/asm.h,../include/Asm/format.h
|
||||||
|
|
||||||
[format.c]
|
[format.c]
|
||||||
depends=../include/Asm/asm.h,../include/Asm/format.h,code.h,format.h,../config.h
|
depends=../include/Asm/asm.h,../include/Asm/format.h,code.h,format.h,../config.h
|
||||||
|
Loading…
Reference in New Issue
Block a user