Beginning to be useful as a disassembler again
This commit is contained in:
parent
4bd2f1c684
commit
91ecd5ab54
1
Makefile
1
Makefile
@ -40,6 +40,7 @@ dist:
|
|||||||
$(PACKAGE)-$(VERSION)/src/parser.c \
|
$(PACKAGE)-$(VERSION)/src/parser.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/token.c \
|
$(PACKAGE)-$(VERSION)/src/token.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/main.c \
|
$(PACKAGE)-$(VERSION)/src/main.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/deasm.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/Makefile \
|
$(PACKAGE)-$(VERSION)/src/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch.h \
|
$(PACKAGE)-$(VERSION)/src/arch.h \
|
||||||
$(PACKAGE)-$(VERSION)/src/asm.h \
|
$(PACKAGE)-$(VERSION)/src/asm.h \
|
||||||
|
@ -179,6 +179,8 @@ typedef struct _ArchPluginHelper
|
|||||||
/* callbacks */
|
/* callbacks */
|
||||||
/* accessors */
|
/* accessors */
|
||||||
char const * (*get_filename)(Arch * arch);
|
char const * (*get_filename)(Arch * arch);
|
||||||
|
ArchInstruction * (*get_instruction_by_opcode)(Arch * arch,
|
||||||
|
uint8_t size, uint32_t opcode);
|
||||||
ArchRegister * (*get_register_by_name_size)(Arch * arch,
|
ArchRegister * (*get_register_by_name_size)(Arch * arch,
|
||||||
char const * name, uint32_t size);
|
char const * name, uint32_t size);
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
.cvsignore
|
.cvsignore
|
||||||
asm
|
asm
|
||||||
|
deasm
|
||||||
|
19
src/Makefile
19
src/Makefile
@ -1,5 +1,5 @@
|
|||||||
SUBDIRS = arch format
|
SUBDIRS = arch format
|
||||||
TARGETS = libasm.a libasm.so asm
|
TARGETS = libasm.a libasm.so asm deasm
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
LIBDIR = $(PREFIX)/lib
|
LIBDIR = $(PREFIX)/lib
|
||||||
@ -42,6 +42,13 @@ asm_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) -L. -Wl,-rpath,$(LIBDIR) -lasm
|
|||||||
asm: $(asm_OBJS) libasm.so
|
asm: $(asm_OBJS) libasm.so
|
||||||
$(CC) -o asm $(asm_OBJS) $(asm_LDFLAGS)
|
$(CC) -o asm $(asm_OBJS) $(asm_LDFLAGS)
|
||||||
|
|
||||||
|
deasm_OBJS = deasm.o
|
||||||
|
deasm_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||||
|
deasm_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) -L. -Wl,-rpath,$(LIBDIR) -lasm
|
||||||
|
|
||||||
|
deasm: $(deasm_OBJS) libasm.so
|
||||||
|
$(CC) -o deasm $(deasm_OBJS) $(deasm_LDFLAGS)
|
||||||
|
|
||||||
arch.o: arch.c arch.h ../config.h
|
arch.o: arch.c arch.h ../config.h
|
||||||
$(CC) $(libasm_CFLAGS) -c arch.c
|
$(CC) $(libasm_CFLAGS) -c arch.c
|
||||||
|
|
||||||
@ -63,13 +70,16 @@ token.o: token.c token.h
|
|||||||
main.o: main.c ../include/Asm.h
|
main.o: main.c ../include/Asm.h
|
||||||
$(CC) $(asm_CFLAGS) -c main.c
|
$(CC) $(asm_CFLAGS) -c main.c
|
||||||
|
|
||||||
|
deasm.o: deasm.c ../include/Asm.h
|
||||||
|
$(CC) $(deasm_CFLAGS) -c deasm.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done
|
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done
|
||||||
$(RM) -- $(libasm_OBJS) $(asm_OBJS)
|
$(RM) -- $(libasm_OBJS) $(asm_OBJS) $(deasm_OBJS)
|
||||||
|
|
||||||
distclean:
|
distclean:
|
||||||
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) distclean) || exit; done
|
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) distclean) || exit; done
|
||||||
$(RM) -- $(libasm_OBJS) $(asm_OBJS)
|
$(RM) -- $(libasm_OBJS) $(asm_OBJS) $(deasm_OBJS)
|
||||||
$(RM) -- $(TARGETS)
|
$(RM) -- $(TARGETS)
|
||||||
|
|
||||||
install: $(TARGETS)
|
install: $(TARGETS)
|
||||||
@ -81,6 +91,8 @@ install: $(TARGETS)
|
|||||||
$(LN) -s -- libasm.so.0.0 $(DESTDIR)$(LIBDIR)/libasm.so
|
$(LN) -s -- libasm.so.0.0 $(DESTDIR)$(LIBDIR)/libasm.so
|
||||||
$(MKDIR) $(DESTDIR)$(BINDIR)
|
$(MKDIR) $(DESTDIR)$(BINDIR)
|
||||||
$(INSTALL) -m 0755 -- asm $(DESTDIR)$(BINDIR)/asm
|
$(INSTALL) -m 0755 -- asm $(DESTDIR)$(BINDIR)/asm
|
||||||
|
$(MKDIR) $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL) -m 0755 -- deasm $(DESTDIR)$(BINDIR)/deasm
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) uninstall) || exit; done
|
@for i in $(SUBDIRS); do (cd $$i && $(MAKE) uninstall) || exit; done
|
||||||
@ -89,5 +101,6 @@ uninstall:
|
|||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so.0
|
$(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so.0
|
||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so
|
$(RM) -- $(DESTDIR)$(LIBDIR)/libasm.so
|
||||||
$(RM) -- $(DESTDIR)$(BINDIR)/asm
|
$(RM) -- $(DESTDIR)$(BINDIR)/asm
|
||||||
|
$(RM) -- $(DESTDIR)$(BINDIR)/deasm
|
||||||
|
|
||||||
.PHONY: all subdirs clean distclean install uninstall
|
.PHONY: all subdirs clean distclean install uninstall
|
||||||
|
12
src/arch.c
12
src/arch.c
@ -172,7 +172,7 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
|
|||||||
for(i = 0; i < arch->instructions_cnt; i++)
|
for(i = 0; i < arch->instructions_cnt; i++)
|
||||||
{
|
{
|
||||||
ai = &arch->plugin->instructions[i];
|
ai = &arch->plugin->instructions[i];
|
||||||
if(AO_GET_SIZE(ai->opcode) != size)
|
if(AO_GET_SIZE(ai->flags) != size)
|
||||||
continue;
|
continue;
|
||||||
if(ai->opcode == opcode)
|
if(ai->opcode == opcode)
|
||||||
return ai;
|
return ai;
|
||||||
@ -457,6 +457,9 @@ static void _decode_print(ArchInstructionCall * call)
|
|||||||
/* arch_exit */
|
/* arch_exit */
|
||||||
int arch_exit(Arch * arch)
|
int arch_exit(Arch * arch)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
arch->filename = NULL;
|
arch->filename = NULL;
|
||||||
arch->fp = NULL;
|
arch->fp = NULL;
|
||||||
arch->buffer = NULL;
|
arch->buffer = NULL;
|
||||||
@ -478,6 +481,7 @@ int arch_init(Arch * arch, char const * filename, FILE * fp)
|
|||||||
arch->fp = fp;
|
arch->fp = fp;
|
||||||
arch->helper.arch = arch;
|
arch->helper.arch = arch;
|
||||||
arch->helper.get_filename = _arch_get_filename;
|
arch->helper.get_filename = _arch_get_filename;
|
||||||
|
arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode;
|
||||||
arch->helper.get_register_by_name_size = arch_get_register_by_name_size;
|
arch->helper.get_register_by_name_size = arch_get_register_by_name_size;
|
||||||
arch->helper.read = NULL;
|
arch->helper.read = NULL;
|
||||||
arch->helper.write = _arch_write;
|
arch->helper.write = _arch_write;
|
||||||
@ -498,6 +502,7 @@ int arch_init_buffer(Arch * arch, char const * buffer, size_t size)
|
|||||||
arch->buffer_pos = 0;
|
arch->buffer_pos = 0;
|
||||||
arch->helper.arch = arch;
|
arch->helper.arch = arch;
|
||||||
arch->helper.get_filename = _arch_get_filename;
|
arch->helper.get_filename = _arch_get_filename;
|
||||||
|
arch->helper.get_instruction_by_opcode = arch_get_instruction_by_opcode;
|
||||||
arch->helper.get_register_by_name_size = arch_get_register_by_name_size;
|
arch->helper.get_register_by_name_size = arch_get_register_by_name_size;
|
||||||
arch->helper.write = NULL;
|
arch->helper.write = NULL;
|
||||||
arch->helper.read = _arch_read_buffer;
|
arch->helper.read = _arch_read_buffer;
|
||||||
@ -531,6 +536,11 @@ static ssize_t _arch_read_buffer(Arch * arch, void * buf, size_t size)
|
|||||||
{
|
{
|
||||||
ssize_t s = min(arch->buffer_cnt - arch->buffer_pos, size);
|
ssize_t s = min(arch->buffer_cnt - arch->buffer_pos, size);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
if(s == 0)
|
||||||
|
return -error_set_code(1, "%s", "End of buffer reached");
|
||||||
memcpy(buf, &arch->buffer[arch->buffer_pos], s);
|
memcpy(buf, &arch->buffer[arch->buffer_pos], s);
|
||||||
arch->buffer_pos += s;
|
arch->buffer_pos += s;
|
||||||
return s;
|
return s;
|
||||||
|
@ -80,5 +80,5 @@ ArchPlugin arch_plugin =
|
|||||||
_amd64_registers,
|
_amd64_registers,
|
||||||
_amd64_instructions,
|
_amd64_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -74,5 +74,5 @@ ArchPlugin arch_plugin =
|
|||||||
_i386_registers,
|
_i386_registers,
|
||||||
_i386_instructions,
|
_i386_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -23,11 +23,33 @@
|
|||||||
/* i386 */
|
/* i386 */
|
||||||
/* private */
|
/* private */
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
|
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call);
|
||||||
static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
ArchInstructionCall * call);
|
ArchInstructionCall * call);
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
|
/* i386_decode */
|
||||||
|
static int _i386_decode(ArchPlugin * plugin, ArchInstructionCall * call)
|
||||||
|
{
|
||||||
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
|
ArchInstruction * ai = NULL;
|
||||||
|
uint8_t opcode;
|
||||||
|
|
||||||
|
/* FIXME really implement */
|
||||||
|
if(helper->read(helper->arch, &opcode, sizeof(opcode))
|
||||||
|
!= sizeof(opcode))
|
||||||
|
return -1;
|
||||||
|
if((ai = helper->get_instruction_by_opcode(helper->arch, 8, opcode))
|
||||||
|
== NULL)
|
||||||
|
/* FIXME return "db" instead */
|
||||||
|
return -1;
|
||||||
|
call->name = ai->name;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* i386_write */
|
||||||
static int _write_constant(ArchPlugin * plugin,
|
static int _write_constant(ArchPlugin * plugin,
|
||||||
ArchOperandDefinition definition, ArchOperand * operand);
|
ArchOperandDefinition definition, ArchOperand * operand);
|
||||||
static int _write_dregister(ArchPlugin * plugin, uint32_t * i,
|
static int _write_dregister(ArchPlugin * plugin, uint32_t * i,
|
||||||
|
@ -75,5 +75,5 @@ ArchPlugin arch_plugin =
|
|||||||
_i386_real_registers,
|
_i386_real_registers,
|
||||||
_i386_real_instructions,
|
_i386_real_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -75,5 +75,5 @@ ArchPlugin arch_plugin =
|
|||||||
_i486_registers,
|
_i486_registers,
|
||||||
_i486_instructions,
|
_i486_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -76,5 +76,5 @@ ArchPlugin arch_plugin =
|
|||||||
_i586_registers,
|
_i586_registers,
|
||||||
_i586_instructions,
|
_i586_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -78,5 +78,5 @@ ArchPlugin arch_plugin =
|
|||||||
_i686_registers,
|
_i686_registers,
|
||||||
_i686_instructions,
|
_i686_instructions,
|
||||||
_i386_write,
|
_i386_write,
|
||||||
NULL
|
_i386_decode
|
||||||
};
|
};
|
||||||
|
@ -89,7 +89,6 @@ As * as_new(char const * arch, char const * format)
|
|||||||
{
|
{
|
||||||
As * as;
|
As * as;
|
||||||
|
|
||||||
/* FIXME add signatures to the format plug-in (for disas too) */
|
|
||||||
if((as = object_new(sizeof(*as))) == NULL)
|
if((as = object_new(sizeof(*as))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if(arch == NULL)
|
if(arch == NULL)
|
||||||
|
547
src/deasm.c
Normal file
547
src/deasm.c
Normal file
@ -0,0 +1,547 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2011 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* 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 <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <System.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.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 */
|
||||||
|
/* private */
|
||||||
|
/* types */
|
||||||
|
typedef struct _DeasmFormat
|
||||||
|
{
|
||||||
|
Plugin * plugin;
|
||||||
|
FormatPlugin * format;
|
||||||
|
} DeasmFormat;
|
||||||
|
|
||||||
|
/* XXX ugly */
|
||||||
|
#define _Deasm _Format
|
||||||
|
typedef struct _Deasm
|
||||||
|
{
|
||||||
|
char const * arch;
|
||||||
|
As * as;
|
||||||
|
|
||||||
|
FormatPluginHelper helper;
|
||||||
|
DeasmFormat * format;
|
||||||
|
size_t format_cnt;
|
||||||
|
|
||||||
|
char const * filename;
|
||||||
|
FILE * fp;
|
||||||
|
} Deasm;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
static int _deasm(char const * arch, char const * format,
|
||||||
|
char const * filename);
|
||||||
|
static int _deasm_buffer(char const * arch, char const * format,
|
||||||
|
char const * buffer, size_t size);
|
||||||
|
static int _deasm_error(char const * message, int ret);
|
||||||
|
static int _deasm_string(char const * arch, char const * format,
|
||||||
|
char const * string);
|
||||||
|
static int _deasm_list(void);
|
||||||
|
|
||||||
|
/* helper */
|
||||||
|
static int _deasm_helper_decode(Format * format, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base);
|
||||||
|
static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size);
|
||||||
|
static off_t _deasm_helper_seek(Format * format, off_t offset, int whence);
|
||||||
|
|
||||||
|
/* format */
|
||||||
|
static DeasmFormat const * _deasm_format_open(Deasm * deasm,
|
||||||
|
char const * format);
|
||||||
|
static int _deasm_format_open_all(Deasm * deasm);
|
||||||
|
static char const * _deasm_format_detect(DeasmFormat const * format);
|
||||||
|
static void _deasm_format_close(DeasmFormat const * format);
|
||||||
|
static void _deasm_format_close_all(Deasm * deasm);
|
||||||
|
|
||||||
|
static int _usage(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
/* deasm */
|
||||||
|
static int _deasm_do_format(Deasm * deasm, char const * format);
|
||||||
|
static int _deasm_do(Deasm * deasm);
|
||||||
|
static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format);
|
||||||
|
#if 0
|
||||||
|
static int _deasm_format_decode(Format * format, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _deasm(char const * arch, char const * format,
|
||||||
|
char const * filename)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
Deasm deasm;
|
||||||
|
|
||||||
|
deasm.arch = arch;
|
||||||
|
deasm.as = NULL;
|
||||||
|
deasm.helper.format = &deasm;
|
||||||
|
deasm.helper.read = _deasm_helper_read;
|
||||||
|
deasm.helper.seek = _deasm_helper_seek;
|
||||||
|
deasm.helper.write = NULL;
|
||||||
|
deasm.helper.decode = _deasm_helper_decode;
|
||||||
|
deasm.format = NULL;
|
||||||
|
deasm.format_cnt = 0;
|
||||||
|
if((deasm.fp = fopen(filename, "r")) == NULL)
|
||||||
|
return -_deasm_error(filename, 1);
|
||||||
|
deasm.filename = filename;
|
||||||
|
if(format != NULL)
|
||||||
|
ret = _deasm_do_format(&deasm, format);
|
||||||
|
else
|
||||||
|
ret = _deasm_do(&deasm);
|
||||||
|
if(deasm.as != NULL)
|
||||||
|
as_delete(deasm.as);
|
||||||
|
fclose(deasm.fp);
|
||||||
|
_deasm_format_close_all(&deasm);
|
||||||
|
if(ret != 0)
|
||||||
|
error_print("deasm");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _deasm_do_format(Deasm * deasm, char const * format)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
size_t i;
|
||||||
|
DeasmFormat const * df;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format);
|
||||||
|
#endif
|
||||||
|
/* check if the plug-in is already opened */
|
||||||
|
for(i = 0; i < deasm->format_cnt; i++)
|
||||||
|
if(strcmp(deasm->format[i].format->name, format) == 0)
|
||||||
|
break;
|
||||||
|
if(i < deasm->format_cnt)
|
||||||
|
df = &deasm->format[i];
|
||||||
|
else if((df = _deasm_format_open(deasm, format)) == NULL)
|
||||||
|
return -1;
|
||||||
|
/* disassemble */
|
||||||
|
ret = _deasm_do_callback(deasm, df->format);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _deasm_do(Deasm * deasm)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
size_t i;
|
||||||
|
size_t s = 0;
|
||||||
|
char * buf;
|
||||||
|
FormatPlugin * format;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
_deasm_format_open_all(deasm);
|
||||||
|
for(i = 0; i < deasm->format_cnt; i++)
|
||||||
|
s = max(s, deasm->format[i].format->signature_len);
|
||||||
|
if((buf = malloc(s)) == NULL)
|
||||||
|
return -_deasm_error(deasm->filename, 1);
|
||||||
|
if(fread(buf, 1, s, deasm->fp) != s)
|
||||||
|
{
|
||||||
|
if(ferror(deasm->fp))
|
||||||
|
ret = -_deasm_error(deasm->filename, 1);
|
||||||
|
else
|
||||||
|
ret = _deasm_do_format(deasm, "flat");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = 0; i < deasm->format_cnt; i++)
|
||||||
|
{
|
||||||
|
format = deasm->format[i].format;
|
||||||
|
if(format->signature_len == 0)
|
||||||
|
continue;
|
||||||
|
if(memcmp(format->signature, buf, format->signature_len)
|
||||||
|
!= 0)
|
||||||
|
continue;
|
||||||
|
if(deasm->arch == NULL)
|
||||||
|
deasm->arch = _deasm_format_detect(
|
||||||
|
&deasm->format[i]);
|
||||||
|
if(deasm->arch == NULL)
|
||||||
|
continue;
|
||||||
|
ret = _deasm_do_callback(deasm, format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i == deasm->format_cnt)
|
||||||
|
ret = _deasm_do_format(deasm, "flat");
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _deasm_do_callback(Deasm * deasm, FormatPlugin * format)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format->name);
|
||||||
|
#endif
|
||||||
|
if(deasm->arch == NULL)
|
||||||
|
{
|
||||||
|
if(format->detect == NULL)
|
||||||
|
return -error_set_code(1, "%s: %s", format->name,
|
||||||
|
"Unable to detect the architecture");
|
||||||
|
if((deasm->arch = format->detect(format)) == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if((deasm->as = as_new(deasm->arch, format->name)) == NULL)
|
||||||
|
return -error_print("deasm");
|
||||||
|
printf("\n%s: %s-%s\n", deasm->filename, format->name,
|
||||||
|
as_get_arch_name(deasm->as));
|
||||||
|
ret = format->decode(format);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_buffer */
|
||||||
|
static int _deasm_buffer(char const * arch, char const * format,
|
||||||
|
char const * buffer, size_t size)
|
||||||
|
{
|
||||||
|
As * as;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
if((as = as_new(arch, format)) == NULL)
|
||||||
|
return -1;
|
||||||
|
if(as_decode(as, buffer, size) != 0)
|
||||||
|
error_print("deasm");
|
||||||
|
as_delete(as);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_error */
|
||||||
|
static int _deasm_error(char const * message, int ret)
|
||||||
|
{
|
||||||
|
fputs("deasm: ", stderr);
|
||||||
|
perror(message);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_string */
|
||||||
|
static int _string_hex2bin(int c);
|
||||||
|
static int _string_ishex(int c);
|
||||||
|
|
||||||
|
static int _deasm_string(char const * arch, char const * format,
|
||||||
|
char const * string)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char * str = (unsigned char *)string;
|
||||||
|
size_t len = strlen(string);
|
||||||
|
char * s;
|
||||||
|
size_t i;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\", \"%s\", \"%s\")\n", __func__, arch,
|
||||||
|
format, string);
|
||||||
|
#endif
|
||||||
|
if((s = malloc(len + 1)) == NULL)
|
||||||
|
return -error_set_print("deasm", 1, "%s", strerror(errno));
|
||||||
|
for(i = 0, j = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if(str[i] != '\\')
|
||||||
|
s[j++] = str[i];
|
||||||
|
else if(str[i + 1] != 'x') /* "\\" */
|
||||||
|
s[j++] = str[++i];
|
||||||
|
else if(i + 3 < len && _string_ishex(str[i + 2])
|
||||||
|
&& _string_ishex(str[i + 3])) /* "\xHH" */
|
||||||
|
{
|
||||||
|
s[j++] = (_string_hex2bin(str[i + 2]) << 4)
|
||||||
|
| _string_hex2bin(str[i + 3]);
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s[j] = '\0'; /* not really necessary */
|
||||||
|
ret = _deasm_buffer(arch, format, s, j);
|
||||||
|
free(s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _string_hex2bin(int c)
|
||||||
|
{
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
if(c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
if(c >= 'A' && c <= 'F')
|
||||||
|
return c - 'A' + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _string_ishex(int c)
|
||||||
|
{
|
||||||
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||||
|
|| (c >= 'A' || c <= 'F');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_list */
|
||||||
|
static int _deasm_list(void)
|
||||||
|
{
|
||||||
|
Deasm deasm;
|
||||||
|
size_t i;
|
||||||
|
char const * sep = "";
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
memset(&deasm, 0, sizeof(deasm));
|
||||||
|
as_plugin_list(ASPT_ARCH);
|
||||||
|
_deasm_format_open_all(&deasm);
|
||||||
|
fputs("\nAvailable format plug-ins:\n", stderr);
|
||||||
|
for(i = 0; i < deasm.format_cnt; i++)
|
||||||
|
{
|
||||||
|
if(deasm.format[i].format->decode == NULL)
|
||||||
|
continue;
|
||||||
|
fprintf(stderr, "%s%s", sep, deasm.format[i].format->name);
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
fputc('\n', stderr);
|
||||||
|
_deasm_format_close_all(&deasm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* helper */
|
||||||
|
/* deasm_helper_decode */
|
||||||
|
static int _deasm_helper_decode(Format * format, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base)
|
||||||
|
{
|
||||||
|
if(section != NULL)
|
||||||
|
printf("\n%s%s:\n", "Disassembly of section ", section);
|
||||||
|
if(fseek(format->fp, offset, SEEK_SET) != 0)
|
||||||
|
return -error_set_code(1, "%s: %s", format->filename,
|
||||||
|
strerror(errno));
|
||||||
|
printf("\n%08lx:\n", (unsigned long)offset + base);
|
||||||
|
/* FIXME implement */
|
||||||
|
if(fseek(format->fp, offset + size, SEEK_SET) != 0)
|
||||||
|
return -error_set_code(1, "%s: %s", format->filename,
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_helper_read */
|
||||||
|
static ssize_t _deasm_helper_read(Format * format, void * buf, size_t size)
|
||||||
|
{
|
||||||
|
if(fread(buf, size, 1, format->fp) == 1)
|
||||||
|
return size;
|
||||||
|
return -error_set_code(1, "%s: %s", format->filename, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_helper_seek */
|
||||||
|
static off_t _deasm_helper_seek(Format * format, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
if(fseek(format->fp, offset, whence) != 0)
|
||||||
|
return -error_set_code(1, "%s: %s", format->filename,
|
||||||
|
strerror(errno));;
|
||||||
|
return ftello(format->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* format */
|
||||||
|
/* deasm_format_open */
|
||||||
|
static DeasmFormat const * _deasm_format_open(Deasm * deasm,
|
||||||
|
char const * format)
|
||||||
|
{
|
||||||
|
DeasmFormat * p;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, format);
|
||||||
|
#endif
|
||||||
|
if((p = realloc(deasm->format, sizeof(*p) * (deasm->format_cnt + 1)))
|
||||||
|
== NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
deasm->format = p;
|
||||||
|
p = &deasm->format[deasm->format_cnt];
|
||||||
|
if((p->plugin = plugin_new(LIBDIR, PACKAGE, "format", format)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if((p->format = plugin_lookup(p->plugin, "format_plugin")) == NULL)
|
||||||
|
{
|
||||||
|
plugin_delete(p->plugin);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(p->format->decode == NULL)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s: %s", format,
|
||||||
|
"Does not support disassembly");
|
||||||
|
plugin_delete(p->plugin);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p->format->helper = &deasm->helper;
|
||||||
|
deasm->format_cnt++;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_format_open_all */
|
||||||
|
static int _deasm_format_open_all(Deasm * deasm)
|
||||||
|
{
|
||||||
|
char const path[] = LIBDIR "/" PACKAGE "/format";
|
||||||
|
DIR * dir;
|
||||||
|
struct dirent * de;
|
||||||
|
size_t len;
|
||||||
|
char const ext[] = ".so";
|
||||||
|
|
||||||
|
if((dir = opendir(path)) == NULL)
|
||||||
|
return -error_set_print("deasm", 1, "%s: %s", path, strerror(
|
||||||
|
errno));
|
||||||
|
while((de = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
if((len = strlen(de->d_name)) < 4)
|
||||||
|
continue;
|
||||||
|
if(strcmp(&de->d_name[len - sizeof(ext) + 1], ext) != 0)
|
||||||
|
continue;
|
||||||
|
de->d_name[len - sizeof(ext) + 1] = '\0';
|
||||||
|
if(_deasm_format_open(deasm, de->d_name) == NULL)
|
||||||
|
error_print("deasm");
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* deasm_format_callback */
|
||||||
|
static int _callback_flat(Deasm * deasm, off_t offset, size_t size, off_t base);
|
||||||
|
|
||||||
|
static int _deasm_format_decode(Format * format, char const * section,
|
||||||
|
off_t offset, size_t size, off_t base)
|
||||||
|
{
|
||||||
|
Deasm * deasm = format;
|
||||||
|
|
||||||
|
if(section != NULL)
|
||||||
|
printf("\n%s%s\n", "Disassembly of section: ", section);
|
||||||
|
return _callback_flat(deasm, offset, size, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _callback_flat(Deasm * deasm, off_t offset, size_t size, off_t base)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s(0x%lx, 0x%lx, 0x%lx)\n", __func__, offset,
|
||||||
|
size, base);
|
||||||
|
#endif
|
||||||
|
if(fseek(deasm->fp, offset, SEEK_SET) != 0)
|
||||||
|
return -_deasm_error(deasm->filename, 1);
|
||||||
|
printf("\n%08lx:\n", offset + base);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_format_detect */
|
||||||
|
static char const * _deasm_format_detect(DeasmFormat const * format)
|
||||||
|
{
|
||||||
|
if(format->format->detect == NULL)
|
||||||
|
return NULL;
|
||||||
|
return format->format->detect(format->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_format_close */
|
||||||
|
static void _deasm_format_close(DeasmFormat const * format)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, format->format->name);
|
||||||
|
#endif
|
||||||
|
plugin_delete(format->plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deasm_format_close_all */
|
||||||
|
static void _deasm_format_close_all(Deasm * deasm)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < deasm->format_cnt; i++)
|
||||||
|
_deasm_format_close(&deasm->format[i]);
|
||||||
|
free(deasm->format);
|
||||||
|
deasm->format = NULL;
|
||||||
|
deasm->format_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* usage */
|
||||||
|
static int _usage(void)
|
||||||
|
{
|
||||||
|
fputs("Usage: deasm [-a arch][-f format] filename\n"
|
||||||
|
" deasm [-a arch][-f format] -s string\n"
|
||||||
|
" deasm -l\n", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
/* functions */
|
||||||
|
/* main */
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
int o;
|
||||||
|
char const * arch = NULL;
|
||||||
|
char const * format = NULL;
|
||||||
|
char const * string = NULL;
|
||||||
|
|
||||||
|
while((o = getopt(argc, argv, "a:f:ls:")) != -1)
|
||||||
|
switch(o)
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
arch = optarg;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
format = optarg;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
return _deasm_list();
|
||||||
|
case 's':
|
||||||
|
string = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return _usage();
|
||||||
|
}
|
||||||
|
if(optind == argc && string != NULL)
|
||||||
|
return _deasm_string(arch, format, string);
|
||||||
|
else if(optind + 1 == argc && string == NULL)
|
||||||
|
return (_deasm(arch, format, argv[optind]) == 0) ? 0 : 2;
|
||||||
|
return _usage();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
subdirs=arch,format
|
subdirs=arch,format
|
||||||
targets=libasm,asm
|
targets=libasm,asm,deasm
|
||||||
cppflags_force=-I ../include
|
cppflags_force=-I ../include
|
||||||
cppflags=
|
cppflags=
|
||||||
cflags_force=-W `pkg-config --cflags cpp`
|
cflags_force=-W `pkg-config --cflags cpp`
|
||||||
@ -21,6 +21,13 @@ depends=libasm.so
|
|||||||
ldflags=-L. -Wl,-rpath,$(LIBDIR) -lasm
|
ldflags=-L. -Wl,-rpath,$(LIBDIR) -lasm
|
||||||
install=$(BINDIR)
|
install=$(BINDIR)
|
||||||
|
|
||||||
|
[deasm]
|
||||||
|
type=binary
|
||||||
|
sources=deasm.c
|
||||||
|
depends=libasm.so
|
||||||
|
ldflags=-L. -Wl,-rpath,$(LIBDIR) -lasm
|
||||||
|
install=$(BINDIR)
|
||||||
|
|
||||||
[arch.c]
|
[arch.c]
|
||||||
depends=arch.h,../config.h
|
depends=arch.h,../config.h
|
||||||
|
|
||||||
@ -30,6 +37,9 @@ depends=../include/Asm.h,code.h,parser.h,asm.h,../config.h
|
|||||||
[code.c]
|
[code.c]
|
||||||
depends=../include/Asm.h,arch.h,code.h
|
depends=../include/Asm.h,arch.h,code.h
|
||||||
|
|
||||||
|
[deasm.c]
|
||||||
|
depends=../include/Asm.h
|
||||||
|
|
||||||
[format.c]
|
[format.c]
|
||||||
depends=format.h,../config.h
|
depends=format.h,../config.h
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user