Using callbacks for file operations

This commit is contained in:
Pierre Pronchery 2011-04-22 02:29:44 +00:00
parent 0f1d52fbb9
commit 2bb09ddb7d
8 changed files with 431 additions and 337 deletions

View File

@ -23,15 +23,31 @@
/* AsmFormat */
/* types */
typedef struct _FormatPluginHelper
{
char const * filename;
FILE * fp;
void * priv;
} FormatPluginHelper;
typedef struct _Format Format;
typedef struct _FormatPlugin FormatPlugin;
typedef struct _FormatPluginHelper
{
Format * format;
/* callbacks */
/* accessors */
char const * (*get_filename)(Format * format);
/* useful */
ssize_t (*read)(Format * format, void * buf, size_t size);
off_t (*seek)(Format * format, off_t offset, int whence);
/* assembly */
ssize_t (*write)(Format * format, void const * buf, size_t size);
/* disassembly */
/* FIXME let a different architecture be specified in the callback */
int (*disas)(Format * format, char const * section,
off_t offset, size_t size, off_t base);
} FormatPluginHelper;
struct _FormatPlugin
{
FormatPluginHelper * helper;
@ -47,12 +63,7 @@ struct _FormatPlugin
int (*section)(FormatPlugin * format, char const * section);
char const * (*detect)(FormatPlugin * format);
/* FIXME:
* - put the callback in the helper structure
* - let a different architecture be specified in the callback */
int (*disas)(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
int (*disas)(FormatPlugin * format);
void * priv;
};

View File

@ -34,9 +34,24 @@ struct _Format
FormatPluginHelper helper;
Plugin * handle;
FormatPlugin * plugin;
/* internal */
/* file */
char const * filename;
FILE * fp;
};
/* prototypes */
/* callbacks */
static char const * _format_get_filename(Format * format);
static ssize_t _format_read(Format * format, void * buf, size_t size);
static off_t _format_seek(Format * format, off_t offset, int whence);
static ssize_t _format_write(Format * format, void const * buf, size_t size);
/* public */
/* functions */
/* format_new */
@ -100,10 +115,12 @@ int format_exit(Format * format)
#endif
if(format->plugin->exit != NULL)
ret = format->plugin->exit(format->plugin);
format->helper.format = NULL;
format->helper.read = NULL;
format->helper.seek = NULL;
format->plugin->helper = NULL;
format->helper.fp = NULL;
format->helper.filename = NULL;
format->helper.priv = NULL;
format->fp = NULL;
format->filename = NULL;
return ret;
}
@ -124,9 +141,13 @@ int format_init(Format * format, char const * filename, FILE * fp)
fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename,
(void *)fp);
#endif
format->helper.filename = filename;
format->helper.fp = fp;
format->helper.priv = NULL;
format->filename = filename;
format->fp = fp;
format->helper.format = format;
format->helper.get_filename = _format_get_filename;
format->helper.read = _format_read;
format->helper.seek = _format_seek;
format->helper.write = _format_write;
format->plugin->helper = &format->helper;
if(format->plugin->init != NULL)
return format->plugin->init(format->plugin, format->arch);
@ -141,3 +162,62 @@ int format_section(Format * format, char const * section)
return 0;
return format->plugin->section(format->plugin, section);
}
/* private */
/* functions */
/* format_get_filename */
static char const * _format_get_filename(Format * format)
{
return format->filename;
}
/* format_read */
static ssize_t _format_read(Format * format, void * buf, size_t size)
{
if(fread(buf, size, 1, format->fp) == 1)
return size;
if(ferror(format->fp))
return -error_set_code(1, "%s: %s", format->filename,
strerror(errno));
if(feof(format->fp))
return -error_set_code(1, "%s: %s", format->filename,
"End of file reached");
return -error_set_code(1, "%s: %s", format->filename, "Read error");
}
/* format_seek */
static off_t _format_seek(Format * format, off_t offset, int whence)
{
if(whence == SEEK_SET)
{
if(fseek(format->fp, offset, whence) == 0)
return offset;
}
else if(whence == SEEK_CUR || whence == SEEK_END)
{
if(fseek(format->fp, offset, whence) == 0)
return ftello(format->fp);
}
else
return -error_set_code(1, "%s: %s", format->filename,
"Invalid argument for seeking");
return -error_set_code(1, "%s: %s", format->filename, strerror(errno));
}
/* format_write */
static ssize_t _format_write(Format * format, void const * buf, size_t size)
{
if(fwrite(buf, size, 1, format->fp) == 1)
return size;
if(ferror(format->fp))
return -error_set_code(1, "%s: %s", format->filename,
strerror(errno));
if(feof(format->fp))
return -error_set_code(1, "%s: %s", format->filename,
"End of file reached");
return -error_set_code(1, "%s: %s", format->filename, "Write error");
}

View File

@ -18,15 +18,11 @@
#ifndef ASM_FORMAT_H
# define ASM_FORMAT_H
# include <stdio.h>
# include "Asm/format.h"
/* Format */
/* public */
/* types */
typedef struct _Format Format;
/* functions */
Format * format_new(char const * format, char const * arch);
void format_delete(Format * format);

View File

@ -117,12 +117,9 @@ static char _dex_signature[4] = "dex\n";
static int _dex_init(FormatPlugin * format, char const * arch);
static int _dex_destroy(FormatPlugin * format);
static char const * _dex_detect(FormatPlugin * format);
static int _dex_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _dex_disas(FormatPlugin * format);
static int _dex_error(FormatPlugin * format);
static int _dex_error_fread(FormatPlugin * format);
/* public */
@ -189,59 +186,52 @@ static char const * _dex_detect(FormatPlugin * format)
/* dex_disas */
static int _disas_map(FormatPlugin * format, DexHeader * dh, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size,
int (*callback)(FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _disas_map(FormatPlugin * format, DexHeader * dh);
static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size);
static int _disas_map_string_id(FormatPlugin * format, off_t offset,
size_t size);
static int _dex_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _dex_disas(FormatPlugin * format)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
DexHeader dh;
if(fseek(fp, 0, SEEK_SET) != 0)
return -_dex_error(format);
if(fread(&dh, sizeof(dh), 1, fp) != 1)
return _dex_error_fread(format);
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(_disas_map(format, &dh, callback) != 0)
if(_disas_map(format, &dh) != 0)
return -1;
return 0;
}
static int _disas_map(FormatPlugin * format, DexHeader * dh, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _disas_map(FormatPlugin * format, DexHeader * dh)
{
int ret = 0;
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
uint32_t size;
uint32_t i;
fpos_t pos;
off_t offset;
DexMapItem dmi;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
if(fseek(fp, dh->map_off, SEEK_SET) != 0)
return -_dex_error(format);
if(fread(&size, sizeof(size), 1, fp) != 1)
return -_dex_error_fread(format);
if(helper->seek(helper->format, dh->map_off, SEEK_SET) != dh->map_off)
return -1;
if(helper->read(helper->format, &size, sizeof(size)) != sizeof(size))
return -1;
size = _htol32(size);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %u items\n", __func__, size);
#endif
for(i = 0; i < size; i++)
{
if(fread(&dmi, sizeof(dmi), 1, fp) != 1)
return -_dex_error_fread(format);
fgetpos(fp, &pos);
if(helper->read(helper->format, &dmi, sizeof(dmi))
!= sizeof(dmi))
return -1;
offset = helper->seek(helper->format, 0, SEEK_CUR);
dmi.type = _htol16(dmi.type);
dmi.size = _htol32(dmi.size);
dmi.offset = _htol32(dmi.offset);
@ -253,44 +243,48 @@ static int _disas_map(FormatPlugin * format, DexHeader * dh, int (*callback)(
{
case TYPE_CODE_ITEM:
ret |= _disas_map_code(format, dmi.offset,
dmi.size, callback);
dmi.size);
break;
case TYPE_STRING_ID_ITEM:
ret |= _disas_map_string_id(format, dmi.offset,
dmi.size);
}
fsetpos(fp, &pos);
if(helper->seek(helper->format, offset, SEEK_SET) != offset)
return -1;
if(ret != 0)
break;
}
return ret;
}
static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size,
int (*callback)(FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
DexMapCodeItem dmci;
size_t i;
off_t seek;
size_t j;
DexMapTryItem dmti;
ssize_t s;
if(fseek(fp, offset, SEEK_SET) != 0)
return -_dex_error(format);
callback(format, ".text", ftello(fp), 0, 0);
if(helper->disas(helper->format, ".text", offset, 0, 0) != 0)
return -1;
for(i = 0; i < size; i++)
{
if(fread(&dmci, sizeof(dmci), 1, fp) != 1)
return -_dex_error_fread(format);
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 = (dmci.insns_size & 0x1) == 0x1 ? 2 : 0; /* padding */
seek = helper->seek(helper->format, 0, SEEK_CUR);
helper->disas(helper->format, NULL, seek, dmci.insns_size * 2,
0);
/* skip padding and try_items */
seek = (dmci.insns_size & 0x1) == 0x1 ? 2 : 0;
#ifdef DEBUG
fprintf(stderr, "DEBUG: code item %lu, registers 0x%x"
", size 0x%x, debug @0x%x, tries 0x%x"
@ -298,21 +292,22 @@ static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size,
dmci.insns_size * 2, dmci.debug_info_off,
dmci.tries_size, seek);
#endif
callback(format, NULL, ftello(fp), dmci.insns_size * 2, 0);
/* skip padding and try_items */
if(seek != 0 && fseek(fp, seek, SEEK_CUR) != 0)
return -_dex_error(format);
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++)
{
if(fread(&dmti, sizeof(dmti), 1, fp) != 1)
return -_dex_error_fread(format);
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);
}
callback(format, NULL, ftello(fp), 8, 0);
seek = helper->seek(helper->format, 0, SEEK_CUR);
helper->disas(helper->format, NULL, seek, 8, 0);
}
}
return 0;
@ -321,21 +316,23 @@ static int _disas_map_code(FormatPlugin * format, off_t offset, size_t size,
static int _disas_map_string_id(FormatPlugin * format, off_t offset,
size_t size)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
Dex * dex = format->priv;
size_t i;
DexStringIdItem dsii;
ssize_t s;
if(dex->strings_cnt != 0)
return -error_set_code(1, "%s: %s", "dex",
"String section already parsed");
if(fseek(fp, offset, SEEK_SET) != 0)
return -_dex_error(format);
if(helper->seek(helper->format, offset, SEEK_SET) != offset)
return -1;
if((dex->strings = malloc(sizeof(*dex->strings) * size)) == NULL)
return -_dex_error(format);
for(i = 0; i < size; i++)
{
if(fread(&dsii, sizeof(dsii), 1, fp) != 1)
s = sizeof(dsii);
if(helper->read(helper->format, &dsii, s) != s)
break;
dsii.string_data_off = _htol32(dsii.string_data_off);
#ifdef DEBUG
@ -349,7 +346,7 @@ static int _disas_map_string_id(FormatPlugin * format, off_t offset,
{
free(dex->strings);
dex->strings = NULL;
return -_dex_error_fread(format);
return -1;
}
dex->strings_cnt = size;
return 0;
@ -359,16 +356,8 @@ static int _disas_map_string_id(FormatPlugin * format, off_t offset,
/* dex_error */
static int _dex_error(FormatPlugin * format)
{
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
}
FormatPluginHelper * helper = format->helper;
/* dex_error_fread */
static int _dex_error_fread(FormatPlugin * format)
{
if(ferror(format->helper->fp))
return _dex_error(format);
return -error_set_code(1, "%s: %s", format->helper->filename,
"End of file reached");
return -error_set_code(1, "%s: %s",
helper->get_filename(helper->format), strerror(errno));
}

View File

@ -56,18 +56,14 @@ typedef struct _ElfStrtab
/* prototypes */
static int _elf_error(FormatPlugin * format);
/* plug-in */
static int _elf_init(FormatPlugin * format, char const * arch);
static char const * _elf_detect(FormatPlugin * format);
static int _elf_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _elf_disas32(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _elf_disas64(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _elf_disas(FormatPlugin * format);
static int _elf_disas32(FormatPlugin * format);
static int _elf_disas64(FormatPlugin * format);
/* ELF32 */
static int _init_32(FormatPlugin * format);
@ -152,8 +148,8 @@ FormatPlugin format_plugin =
/* elf_error */
static int _elf_error(FormatPlugin * format)
{
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
return -error_set_code(1, "%s: %s", format->helper->get_filename(
format->helper->format), strerror(errno));
}
@ -196,22 +192,22 @@ static ElfArch * _init_arch(char const * arch)
/* elf_detect */
static char const * _detect_error(FormatPlugin * format);
static char const * _detect_32(FormatPlugin * format, Elf32_Ehdr * ehdr);
static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr);
static char const * _elf_detect(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
union
{
Elf32_Ehdr ehdr32;
Elf64_Ehdr ehdr64;
} ehdr;
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _detect_error(format);
if(fread(&ehdr, sizeof(ehdr), 1, format->helper->fp) != 1)
return _detect_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return NULL;
if(helper->read(helper->format, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
return NULL;
switch(ehdr.ehdr32.e_ident[EI_CLASS])
{
case ELFCLASS32:
@ -219,17 +215,11 @@ static char const * _elf_detect(FormatPlugin * format)
case ELFCLASS64:
return _detect_64(format, &ehdr.ehdr64);
}
error_set_code(1, "%s: %s 0x%x\n", format->helper->filename,
error_set_code(1, "%s: %s 0x%x\n", helper->get_filename(helper->format),
"Unsupported ELF class", ehdr.ehdr32.e_ident[EI_CLASS]);
return NULL;
}
static char const * _detect_error(FormatPlugin * format)
{
error_set_code(1, "%s: %s", format->helper->filename, strerror(errno));
return NULL;
}
static char const * _detect_32(FormatPlugin * format, Elf32_Ehdr * ehdr)
{
format->disas = _elf_disas32;
@ -272,13 +262,11 @@ static char const * _detect_64(FormatPlugin * format, Elf64_Ehdr * ehdr)
/* elf_disas */
static int _elf_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _elf_disas(FormatPlugin * format)
{
if(_elf_detect(format) == NULL)
return -1;
return format->disas(format, callback);
return format->disas(format);
}
@ -291,10 +279,9 @@ static int _disas32_strtab(FormatPlugin * format, Elf32_Shdr * shdr,
size_t shdr_cnt, uint16_t ndx, char ** strtab,
size_t * strtab_cnt);
static int _elf_disas32(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _elf_disas32(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
Elf32_Ehdr ehdr;
Elf32_Shdr * shdr = NULL;
Elf32_Addr base = 0x0;
@ -306,10 +293,10 @@ static int _elf_disas32(FormatPlugin * format, int (*callback)(
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__,
format->helper->filename);
#endif
if(fseek(format->helper->fp, 0, SEEK_SET) != 0
|| fread(&ehdr, sizeof(ehdr), 1, format->helper->fp)
!= 1)
return -_elf_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0
|| helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr))
return -1;
if(_disas32_shdr(format, &ehdr, &shdr) != 0)
return -1;
if(_disas32_addr(format, &ehdr, &base) != 0
@ -326,7 +313,8 @@ static int _elf_disas32(FormatPlugin * format, int (*callback)(
continue;
if(shdr[i].sh_type == SHT_PROGBITS
&& shdr[i].sh_flags & SHF_EXECINSTR)
callback(format, &shstrtab[shdr[i].sh_name],
helper->disas(helper->format,
&shstrtab[shdr[i].sh_name],
shdr[i].sh_offset, shdr[i].sh_size,
base);
}
@ -338,24 +326,27 @@ static int _elf_disas32(FormatPlugin * format, int (*callback)(
static int _disas32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
Elf32_Shdr ** shdr)
{
FormatPluginHelper * helper = format->helper;
ssize_t size;
if(ehdr->e_shentsize == 0)
{
*shdr = NULL;
return 0;
}
if(ehdr->e_shentsize != sizeof(**shdr))
return -error_set_code(1, "%s: %s", format->helper->filename,
return -error_set_code(1, "%s: %s",
helper->get_filename(helper->format),
"Invalid section header size");
if(fseek(format->helper->fp, ehdr->e_shoff, SEEK_SET) != 0
|| (*shdr = malloc(ehdr->e_shentsize * ehdr->e_shnum))
== NULL)
if(helper->seek(helper->format, ehdr->e_shoff, SEEK_SET) < 0)
return -1;
size = sizeof(**shdr) * ehdr->e_shnum;
if((*shdr = malloc(size)) == NULL)
return -_elf_error(format);
if(fread(*shdr, sizeof(**shdr), ehdr->e_shnum, format->helper->fp)
!= ehdr->e_shnum)
if(helper->read(helper->format, *shdr, size) != size)
{
free(*shdr);
return -error_set_code(1, "%s: %s", format->helper->filename,
"Short read");
return -1;
}
return 0;
}
@ -363,14 +354,16 @@ static int _disas32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
static int _disas32_addr(FormatPlugin * format, Elf32_Ehdr * ehdr,
Elf32_Addr * addr)
{
FormatPluginHelper * helper = format->helper;
Elf32_Half i;
Elf32_Phdr phdr;
if(fseek(format->helper->fp, ehdr->e_phoff, SEEK_SET) != 0)
return -_elf_error(format);
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1;
for(i = 0; i < ehdr->e_phnum; i++)
if(fread(&phdr, sizeof(phdr), 1, format->helper->fp) != 1)
return -_elf_error(format);
if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr))
return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{
*addr = phdr.p_vaddr;
@ -384,19 +377,22 @@ static int _disas32_strtab(FormatPlugin * format, Elf32_Shdr * shdr,
size_t shdr_cnt, uint16_t ndx, char ** strtab,
size_t * strtab_cnt)
{
FormatPluginHelper * helper = format->helper;
if(ndx >= shdr_cnt)
return -error_set_code(1, "%s: %s", format->helper->filename,
return -error_set_code(1, "%s: %s",
helper->get_filename(helper->format),
"Unable to read the string table");
shdr = &shdr[ndx];
if(fseek(format->helper->fp, shdr->sh_offset, SEEK_SET) != 0
|| (*strtab = malloc(shdr->sh_size)) == NULL)
if(helper->seek(helper->format, shdr->sh_offset, SEEK_SET) < 0)
return -1;
if((*strtab = malloc(shdr->sh_size)) == NULL)
return -_elf_error(format);
if(fread(*strtab, sizeof(**strtab), shdr->sh_size, format->helper->fp)
if(helper->read(helper->format, *strtab, shdr->sh_size)
!= shdr->sh_size)
{
free(*strtab);
return -error_set_code(1, "%s: %s", format->helper->filename,
"Short read");
return -1;
}
*strtab_cnt = shdr->sh_size;
return 0;
@ -412,10 +408,9 @@ static int _disas64_strtab(FormatPlugin * format, Elf64_Shdr * shdr,
size_t shdr_cnt, uint16_t ndx, char ** strtab,
size_t * strtab_cnt);
static int _elf_disas64(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _elf_disas64(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
Elf64_Ehdr ehdr;
Elf64_Shdr * shdr = NULL;
Elf64_Addr base = 0x0;
@ -425,12 +420,12 @@ static int _elf_disas64(FormatPlugin * format, int (*callback)(
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__,
format->helper->filename);
helper->get_filename(helper->format));
#endif
if(fseek(format->helper->fp, 0, SEEK_SET) != 0
|| fread(&ehdr, sizeof(ehdr), 1, format->helper->fp)
!= 1)
return -_elf_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0
|| helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr))
return -1;
if(_disas64_shdr(format, &ehdr, &shdr) != 0)
return -1;
if(_disas64_addr(format, &ehdr, &base) != 0
@ -447,7 +442,8 @@ static int _elf_disas64(FormatPlugin * format, int (*callback)(
continue;
if(shdr[i].sh_type == SHT_PROGBITS
&& shdr[i].sh_flags & SHF_EXECINSTR)
callback(format, &shstrtab[shdr[i].sh_name],
helper->disas(helper->format,
&shstrtab[shdr[i].sh_name],
shdr[i].sh_offset, shdr[i].sh_size,
base);
}
@ -459,24 +455,27 @@ static int _elf_disas64(FormatPlugin * format, int (*callback)(
static int _disas64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
Elf64_Shdr ** shdr)
{
FormatPluginHelper * helper = format->helper;
ssize_t size;
if(ehdr->e_shentsize == 0)
{
*shdr = NULL;
return 0;
}
if(ehdr->e_shentsize != sizeof(**shdr))
return -error_set_code(1, "%s: %s", format->helper->filename,
return -error_set_code(1, "%s: %s",
helper->get_filename(helper->format),
"Invalid section header size");
if(fseek(format->helper->fp, ehdr->e_shoff, SEEK_SET) != 0
|| (*shdr = malloc(ehdr->e_shentsize * ehdr->e_shnum))
== NULL)
if(helper->seek(helper->format, ehdr->e_shoff, SEEK_SET) < 0)
return -1;
size = sizeof(**shdr) * ehdr->e_shnum;
if((*shdr = malloc(size)) == NULL)
return -_elf_error(format);
if(fread(*shdr, sizeof(**shdr), ehdr->e_shnum, format->helper->fp)
!= ehdr->e_shnum)
if(helper->read(helper->format, *shdr, size) != size)
{
free(*shdr);
return -error_set_code(1, "%s: %s", format->helper->filename,
"Short read");
return -1;
}
return 0;
}
@ -484,14 +483,16 @@ static int _disas64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
static int _disas64_addr(FormatPlugin * format, Elf64_Ehdr * ehdr,
Elf64_Addr * addr)
{
FormatPluginHelper * helper = format->helper;
Elf64_Quarter i;
Elf64_Phdr phdr;
if(fseek(format->helper->fp, ehdr->e_phoff, SEEK_SET) != 0)
return -_elf_error(format);
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1;
for(i = 0; i < ehdr->e_phnum; i++)
if(fread(&phdr, sizeof(phdr), 1, format->helper->fp) != 1)
return -_elf_error(format);
if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr))
return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{
*addr = phdr.p_vaddr;
@ -505,19 +506,23 @@ static int _disas64_strtab(FormatPlugin * format, Elf64_Shdr * shdr,
size_t shdr_cnt, uint16_t ndx, char ** strtab,
size_t * strtab_cnt)
{
FormatPluginHelper * helper = format->helper;
ssize_t size;
if(ndx >= shdr_cnt)
return -error_set_code(1, "%s: %s", format->helper->filename,
return -error_set_code(1, "%s: %s",
helper->get_filename(helper->format),
"Unable to read the string table");
shdr = &shdr[ndx];
if(fseek(format->helper->fp, shdr->sh_offset, SEEK_SET) != 0
|| (*strtab = malloc(shdr->sh_size)) == NULL)
if(helper->seek(helper->format, shdr->sh_offset, SEEK_SET) < 0)
return -1;
size = sizeof(**strtab) * shdr->sh_size;
if((*strtab = malloc(size)) == NULL)
return -_elf_error(format);
if(fread(*strtab, sizeof(**strtab), shdr->sh_size, format->helper->fp)
!= shdr->sh_size)
if(helper->read(helper->format, *strtab, size) != size)
{
free(*strtab);
return -error_set_code(1, "%s: %s", format->helper->filename,
"Short read");
return -1;
}
*strtab_cnt = shdr->sh_size;
return 0;
@ -549,6 +554,7 @@ static int es32_cnt = 0;
/* init_32 */
static int _init_32(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
Elf32_Ehdr hdr;
memset(&hdr, 0, sizeof(hdr));
@ -574,7 +580,7 @@ static int _init_32(FormatPlugin * format)
hdr.e_shentsize = _htol16(sizeof(Elf32_Shdr));
hdr.e_shstrndx = _htol16(SHN_UNDEF);
}
if(fwrite(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return _elf_error(format);
return 0;
}
@ -587,18 +593,19 @@ static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset);
static int _exit_32(FormatPlugin * format)
{
int ret = 0;
FormatPluginHelper * helper = format->helper;
long offset;
if(_section_32(format, ".shstrtab") != 0)
ret = 1;
else if(fwrite(shstrtab.buf, sizeof(char), shstrtab.cnt,
format->helper->fp) != shstrtab.cnt)
ret = _elf_error(format);
else if((offset = ftell(format->helper->fp)) == -1)
ret = _elf_error(format);
ret = -1;
else if(helper->write(helper->format, shstrtab.buf, shstrtab.cnt)
!= (ssize_t)shstrtab.cnt)
ret = -1;
else if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0)
ret = -1;
else if(_exit_32_phdr(format, offset) != 0
|| _exit_32_shdr(format, offset) != 0)
ret = 1;
ret = -1;
free(es32);
es32 = NULL;
es32_cnt = 0;
@ -610,13 +617,14 @@ static int _exit_32(FormatPlugin * format)
static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset)
{
FormatPluginHelper * helper = format->helper;
Elf32_Ehdr hdr;
if(es32_cnt == 0)
return 0;
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _elf_error(format);
if(fread(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return -1;
if(helper->read(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return _elf_error(format);
if(ea->endian == ELFDATA2MSB)
{
@ -630,19 +638,20 @@ static int _exit_32_phdr(FormatPlugin * format, Elf32_Off offset)
hdr.e_shnum = _htol16(es32_cnt + 1);
hdr.e_shstrndx = _htol16(es32_cnt);
}
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _elf_error(format);
if(fwrite(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
return _elf_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return -1;
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
return 0;
}
static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset)
{
FormatPluginHelper * helper = format->helper;
Elf32_Shdr hdr;
int i;
if(fseek(format->helper->fp, 0, SEEK_END) != 0)
if(helper->seek(helper->format, 0, SEEK_END) < 0)
return _elf_error(format);
memset(&hdr, 0, sizeof(hdr));
if(ea->endian == ELFDATA2MSB)
@ -655,20 +664,20 @@ static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset)
hdr.sh_type = _htol32(SHT_NULL);
hdr.sh_link = _htol32(SHN_UNDEF);
}
if(fwrite(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
return _elf_error(format);
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
for(i = 0; i < es32_cnt; i++)
{
if(i+1 == es32_cnt)
if(i + 1 == es32_cnt)
es32[i].sh_size = offset - es32[i].sh_offset;
else
es32[i].sh_size = es32[i + 1].sh_offset
- es32[i].sh_offset;
es32[i].sh_size = ea->endian == ELFDATA2MSB
? _htob32(es32[i].sh_size) : _htol32(es32[i].sh_size);
if(fwrite(&es32[i], sizeof(Elf32_Shdr), 1, format->helper->fp)
!= 1)
return _elf_error(format);
if(helper->write(helper->format, &es32[i], sizeof(Elf32_Shdr))
!= sizeof(Elf32_Shdr))
return -1;
}
return 0;
}
@ -677,13 +686,14 @@ static int _exit_32_shdr(FormatPlugin * format, Elf32_Off offset)
/* section_32 */
static int _section_32(FormatPlugin * format, char const * name)
{
FormatPluginHelper * helper = format->helper;
int ss;
Elf32_Shdr * p;
ElfSectionValues * esv;
long offset;
if((ss = _elfstrtab_set(format, &shstrtab, name)) < 0)
return 1;
return -1;
if((p = realloc(es32, sizeof(*es32) * (es32_cnt + 1))) == NULL)
return _elf_error(format);
es32 = p;
@ -693,8 +703,8 @@ static int _section_32(FormatPlugin * format, char const * name)
p->sh_name = ss;
p->sh_type = esv->type;
p->sh_flags = esv->flags;
if((offset = ftell(format->helper->fp)) == -1)
return _elf_error(format);
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0)
return -1;
p->sh_offset = offset;
p->sh_link = SHN_UNDEF; /* FIXME */
return 0;
@ -710,6 +720,7 @@ static int es64_cnt = 0;
/* init_64 */
static int _init_64(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
Elf64_Ehdr hdr;
memset(&hdr, 0, sizeof(hdr));
@ -734,8 +745,8 @@ static int _init_64(FormatPlugin * format)
hdr.e_shentsize = _htol16(sizeof(Elf64_Shdr));
}
hdr.e_shstrndx = SHN_UNDEF;
if(fwrite(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
return _elf_error(format);
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
return 0;
}
@ -747,15 +758,16 @@ static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset);
static int _exit_64(FormatPlugin * format)
{
int ret = 0;
FormatPluginHelper * helper = format->helper;
long offset;
if(_section_64(format, ".shstrtab") != 0)
ret = 1;
else if(fwrite(shstrtab.buf, sizeof(char), shstrtab.cnt,
format->helper->fp) != shstrtab.cnt)
ret = _elf_error(format);
else if((offset = ftell(format->helper->fp)) == -1)
ret = _elf_error(format);
else if(helper->write(helper->format, shstrtab.buf, shstrtab.cnt)
!= (ssize_t)shstrtab.cnt)
ret = -1;
else if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0)
ret = -1;
else if(_exit_64_phdr(format, offset) != 0
|| _exit_64_shdr(format, offset) != 0)
ret = 1;
@ -770,14 +782,15 @@ static int _exit_64(FormatPlugin * format)
static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset)
{
FormatPluginHelper * helper = format->helper;
Elf64_Ehdr hdr;
if(es64_cnt == 0)
return 0;
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _elf_error(format);
if(fread(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
return _elf_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return -1;
if(helper->read(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
if(ea->endian == ELFDATA2MSB)
{
hdr.e_shoff = _htob64(offset);
@ -790,19 +803,20 @@ static int _exit_64_phdr(FormatPlugin * format, Elf64_Off offset)
hdr.e_shnum = _htol16(es64_cnt);
hdr.e_shstrndx = _htol16(es64_cnt - 1);
}
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _elf_error(format);
if(fwrite(&hdr, sizeof(hdr), 1, format->helper->fp) != 1)
return _elf_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return -1;
if(helper->write(helper->format, &hdr, sizeof(hdr)) != sizeof(hdr))
return -1;
return 0;
}
static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset)
{
FormatPluginHelper * helper = format->helper;
int i;
if(fseek(format->helper->fp, 0, SEEK_END) != 0)
return _elf_error(format);
if(helper->seek(helper->format, 0, SEEK_END) < 0)
return -1;
for(i = 0; i < es64_cnt; i++)
{
if(i + 1 == es64_cnt)
@ -812,9 +826,9 @@ static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset)
- es64[i].sh_offset;
es64[i].sh_size = ea->endian == ELFDATA2MSB
? _htob64(es64[i].sh_size) : _htol64(es64[i].sh_size);
if(fwrite(&es64[i], sizeof(Elf64_Shdr), 1, format->helper->fp)
!= 1)
return _elf_error(format);
if(helper->write(helper->format, &es64[i], sizeof(Elf64_Shdr))
!= sizeof(Elf64_Shdr))
return -1;
}
return 0;
}
@ -823,6 +837,7 @@ static int _exit_64_shdr(FormatPlugin * format, Elf64_Off offset)
/* section_64 */
static int _section_64(FormatPlugin * format, char const * name)
{
FormatPluginHelper * helper = format->helper;
int ss;
Elf64_Shdr * p;
ElfSectionValues * esv;
@ -839,8 +854,8 @@ static int _section_64(FormatPlugin * format, char const * name)
p->sh_name = ss;
p->sh_type = esv->type;
p->sh_flags = esv->flags;
if((offset = ftell(format->helper->fp)) == -1)
return _elf_error(format);
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0)
return -1;
p->sh_offset = offset;
p->sh_link = SHN_UNDEF; /* FIXME */
return 0;

View File

@ -16,9 +16,7 @@
#include <System.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include "Asm.h"
@ -26,9 +24,7 @@
/* private */
/* prototypes */
/* plug-in */
static int _flat_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _flat_disas(FormatPlugin * format);
/* public */
@ -53,14 +49,12 @@ FormatPlugin format_plugin =
/* functions */
/* plug-in */
/* flat_disas */
static int _flat_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _flat_disas(FormatPlugin * format)
{
struct stat st;
FormatPluginHelper * helper = format->helper;
off_t offset;
if(fstat(fileno(format->helper->fp), &st) != 0)
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
return callback(format, ".data", 0, st.st_size, 0);
if((offset = helper->seek(helper->format, 0, SEEK_END)) < 0)
return -1;
return helper->disas(helper->format, ".data", 0, offset, 0);
}

View File

@ -105,12 +105,9 @@ static char _java_signature[4] = "\xca\xfe\xba\xbe";
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_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _java_disas(FormatPlugin * format);
static int _java_error(FormatPlugin * format);
static int _java_error_fread(FormatPlugin * format);
/* public */
@ -137,6 +134,7 @@ FormatPlugin format_plugin =
/* java_init */
static int _java_init(FormatPlugin * format, char const * arch)
{
FormatPluginHelper * helper = format->helper;
JavaHeader jh;
JavaPlugin * java;
@ -147,8 +145,8 @@ static int _java_init(FormatPlugin * format, char const * arch)
jh.minor = _htob16(0);
jh.major = _htob16(0x32); /* XXX choose a more appropriate version */
jh.cp_cnt = _htob16(0);
if(fwrite(&jh, sizeof(jh), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return -1;
if((java = malloc(sizeof(*java))) == NULL)
return -_java_error(format);
memset(java, 0, sizeof(*java));
@ -186,85 +184,96 @@ static int _java_exit(FormatPlugin * format)
static int _exit_constant_pool(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t cnt = _htob16(java->constants_cnt + 1);
if(fwrite(&cnt, sizeof(cnt), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &cnt, sizeof(cnt)) != sizeof(cnt))
return -1;
/* XXX output the constants */
return 0;
}
static int _exit_access_flags(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t flags = _htob16(java->access_flags);
if(fwrite(&flags, sizeof(flags), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &flags, sizeof(flags))
!= sizeof(flags))
return -1;
return 0;
}
static int _exit_class_name(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
uint16_t index = _htob16(0);
/* FIXME really implement */
if(fwrite(&index, sizeof(index), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &index, sizeof(index))
!= sizeof(index))
return -1;
return 0;
}
static int _exit_super_name(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
uint16_t index = _htob16(0);
/* FIXME really implement */
if(fwrite(&index, sizeof(index), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &index, sizeof(index))
!= sizeof(index))
return -1;
return 0;
}
static int _exit_interface_table(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t cnt = _htob16(java->interfaces_cnt);
if(fwrite(&cnt, sizeof(cnt), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &cnt, sizeof(cnt)) != sizeof(cnt))
return -1;
/* XXX output the interfaces */
return 0;
}
static int _exit_field_table(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t cnt = _htob16(java->fields_cnt);
if(fwrite(&cnt, sizeof(cnt), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &cnt, sizeof(cnt)) != sizeof(cnt))
return -1;
/* XXX output the fields */
return 0;
}
static int _exit_method_table(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t cnt = _htob16(java->methods_cnt);
if(fwrite(&cnt, sizeof(cnt), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &cnt, sizeof(cnt)) != sizeof(cnt))
return -1;
/* XXX output the methods */
return 0;
}
static int _exit_attribute_table(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
uint16_t cnt = _htob16(java->attributes_cnt);
if(fwrite(&cnt, sizeof(cnt), 1, format->helper->fp) != 1)
return -_java_error(format);
if(helper->write(helper->format, &cnt, sizeof(cnt)) != sizeof(cnt))
return -1;
/* XXX output the attributes */
return 0;
}
@ -283,48 +292,47 @@ static int _disas_skip_constants(FormatPlugin * format, uint16_t cnt);
static int _disas_skip_fields(FormatPlugin * format, uint16_t cnt);
static int _disas_skip_interfaces(FormatPlugin * format, uint16_t cnt);
static int _java_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _java_disas(FormatPlugin * format)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
JavaHeader jh;
JavaHeader2 jh2;
uint16_t u16;
off_t offset;
off_t end;
if(fseek(fp, sizeof(JavaHeader), SEEK_SET) != 0)
return -_java_error(format);
if(fread(&jh, sizeof(jh), 1, fp) != 1)
return -_java_error_fread(format);
/* FIXME can this be correct? */
if(helper->seek(helper->format, sizeof(jh), SEEK_SET) != sizeof(jh))
return -1;
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return -1;
/* skip constants */
jh.cp_cnt = _htob16(jh.cp_cnt);
if(jh.cp_cnt > 1 && _disas_skip_constants(format, jh.cp_cnt) != 0)
return -1;
/* skip interfaces */
if(fread(&jh2, sizeof(jh2), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &jh2, sizeof(jh2)) != sizeof(jh2))
return -1;
jh2.interfaces_cnt = _htob16(jh2.interfaces_cnt);
if(_disas_skip_interfaces(format, jh2.interfaces_cnt) != 0)
return -1;
/* skip fields */
if(fread(&u16, sizeof(u16), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
return -1;
u16 = _htob16(u16);
if(_disas_skip_fields(format, u16) != 0)
return -1;
/* disassemble the rest */
if((offset = ftello(fp)) == -1
|| fseek(fp, 0, SEEK_END) != 0
|| (end = ftello(fp)) == -1)
return -_java_error(format);
return callback(format, NULL, offset, end - offset, 0);
if((offset = helper->seek(helper->format, 0, SEEK_CUR)) < 0
|| (end = helper->seek(helper->format, 0, SEEK_END))
< 0)
return -1;
return helper->disas(helper->format, NULL, offset, end - offset, 0);
}
static int _disas_skip_attributes(FormatPlugin * format, uint16_t cnt)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
size_t i;
JavaAttributeInfo jai;
@ -333,22 +341,23 @@ static int _disas_skip_attributes(FormatPlugin * format, uint16_t cnt)
#endif
for(i = 0; i < cnt; i++)
{
if(fread(&jai, sizeof(jai), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &jai, sizeof(jai))
!= sizeof(jai))
return -1;
jai.length = _htob32(jai.length);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() length=%u\n", __func__,
jai.length);
#endif
if(fseek(fp, jai.length, SEEK_CUR) != 0)
return -_java_error(format);
if(helper->seek(helper->format, jai.length, SEEK_CUR) < 0)
return -1;
}
return 0;
}
static int _disas_skip_constants(FormatPlugin * format, uint16_t cnt)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
size_t i;
JavaCpInfo jci;
size_t size;
@ -360,8 +369,9 @@ static int _disas_skip_constants(FormatPlugin * format, uint16_t cnt)
#endif
for(i = 0; i < cnt; i++)
{
if(fread(&jci, sizeof(jci), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &jci, sizeof(jci))
!= sizeof(jci))
return -1;
switch(jci.tag)
{
case CONSTANT_Double:
@ -381,28 +391,33 @@ static int _disas_skip_constants(FormatPlugin * format, uint16_t cnt)
size = 2;
break;
case CONSTANT_Utf8:
if(fread(&u16, sizeof(u16), 1, fp) != 1)
return -_java_error_fread(format);
size = sizeof(u16);
if(helper->read(helper->format, &u16, size)
!= (ssize_t)size)
return -1;
u16 = _htob16(u16);
if(fseek(fp, u16, SEEK_CUR) != 0)
return -_java_error(format);
if(helper->seek(helper->format, u16, SEEK_CUR)
< 0)
return -1;
size = 0;
break;
default:
return -error_set_code(1, "%s: %s 0x%x",
format->helper->filename,
helper->get_filename(
helper->format),
"Unknown constant tag",
jci.tag);
}
if(size != 0 && fread(buf, sizeof(*buf), size, fp) != size)
return -_java_error_fread(format);
if(size != 0 && helper->read(helper->format, buf, size)
!= (ssize_t)size)
return -1;
}
return 0;
}
static int _disas_skip_fields(FormatPlugin * format, uint16_t cnt)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
size_t i;
JavaFieldInfo jfi;
@ -411,8 +426,9 @@ static int _disas_skip_fields(FormatPlugin * format, uint16_t cnt)
#endif
for(i = 0; i < cnt; i++)
{
if(fread(&jfi, sizeof(jfi), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &jfi, sizeof(jfi))
!= sizeof(jfi))
return -1;
jfi.attributes_cnt = _htob16(jfi.attributes_cnt);
_disas_skip_attributes(format, jfi.attributes_cnt);
}
@ -421,7 +437,7 @@ static int _disas_skip_fields(FormatPlugin * format, uint16_t cnt)
static int _disas_skip_interfaces(FormatPlugin * format, uint16_t cnt)
{
FILE * fp = format->helper->fp;
FormatPluginHelper * helper = format->helper;
size_t i;
uint16_t u16;
@ -429,8 +445,9 @@ static int _disas_skip_interfaces(FormatPlugin * format, uint16_t cnt)
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
#endif
for(i = 0; i < cnt; i++)
if(fread(&u16, sizeof(u16), 1, fp) != 1)
return -_java_error_fread(format);
if(helper->read(helper->format, &u16, sizeof(u16))
!= sizeof(u16))
return -1;
return 0;
}
@ -438,16 +455,6 @@ static int _disas_skip_interfaces(FormatPlugin * format, uint16_t cnt)
/* java_error */
static int _java_error(FormatPlugin * format)
{
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
}
/* java_error_fread */
static int _java_error_fread(FormatPlugin * format)
{
if(ferror(format->helper->fp))
return _java_error(format);
return -error_set_code(1, "%s: %s", format->helper->filename,
"End of file reached");
return -error_set_code(1, "%s: %s", format->helper->get_filename(
format->helper->format), strerror(errno));
}

View File

@ -89,9 +89,7 @@ static char const _pe_header_signature[4] = "PE\0\0";
/* plug-in */
static int _pe_init(FormatPlugin * format, char const * arch);
static char const * _pe_detect(FormatPlugin * format);
static int _pe_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base));
static int _pe_disas(FormatPlugin * format);
/* useful */
static char const * _pe_get_arch(uint16_t machine);
@ -121,6 +119,7 @@ FormatPlugin format_plugin =
/* pe_init */
static int _pe_init(FormatPlugin * format, char const * arch)
{
FormatPluginHelper * helper = format->helper;
int machine;
struct pe_msdos pm;
struct pe_header ph;
@ -135,12 +134,10 @@ static int _pe_init(FormatPlugin * format, char const * arch)
ph.machine = _htol16(machine);
ph.timestamp = _htol32(time(NULL));
/* FIXME update the section and symbol lists */
if(fwrite(&pm, sizeof(pm), 1, format->helper->fp) != 1)
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
if(fwrite(&ph, sizeof(ph), 1, format->helper->fp) != 1)
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
if(helper->write(helper->format, &pm, sizeof(pm)) != sizeof(pm))
return -1;
if(helper->write(helper->format, &ph, sizeof(ph)) != sizeof(ph))
return -1;
return 0;
}
@ -150,25 +147,28 @@ static char const * _detect_error(FormatPlugin * format);
static char const * _pe_detect(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
struct pe_msdos pm;
struct pe_header ph;
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _detect_error(format);
if(fread(&pm, sizeof(pm), 1, format->helper->fp) != 1)
return _detect_error(format);
if((pm.offset = _htol16(pm.offset)) != sizeof(pm)
&& fseek(format->helper->fp, pm.offset, SEEK_SET) != 0)
return _detect_error(format);
if(fread(&ph, sizeof(ph), 1, format->helper->fp) != 1)
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return NULL;
if(helper->read(helper->format, &pm, sizeof(pm)) != sizeof(pm))
return NULL;
if((pm.offset = _htol16(pm.offset)) != sizeof(pm))
return _detect_error(format);
if(helper->seek(helper->format, pm.offset, SEEK_SET) != pm.offset)
return NULL;
if(helper->read(helper->format, &ph, sizeof(ph)) != sizeof(ph))
return NULL;
ph.machine = _htol16(ph.machine);
return _pe_get_arch(ph.machine);
}
static char const * _detect_error(FormatPlugin * format)
{
error_set_code(1, "%s: %s", format->helper->filename, strerror(errno));
error_set_code(1, "%s: %s", format->helper->get_filename(
format->helper->format), strerror(errno));
return NULL;
}
@ -176,47 +176,49 @@ static char const * _detect_error(FormatPlugin * format)
/* pe_disas */
static int _disas_error(FormatPlugin * format);
static int _pe_disas(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base))
static int _pe_disas(FormatPlugin * format)
{
FormatPluginHelper * helper = format->helper;
struct pe_msdos pm;
struct pe_header ph;
size_t i;
struct pe_section_header psh;
if(fseek(format->helper->fp, 0, SEEK_SET) != 0)
return _disas_error(format);
if(fread(&pm, sizeof(pm), 1, format->helper->fp) != 1)
return _disas_error(format);
if(helper->seek(helper->format, 0, SEEK_SET) != 0)
return -1;
if(helper->read(helper->format, &pm, sizeof(pm)) != sizeof(pm))
return -1;
if((pm.offset = _htol16(pm.offset)) != sizeof(pm)
&& fseek(format->helper->fp, pm.offset, SEEK_SET) != 0)
return _disas_error(format);
if(fread(&ph, sizeof(ph), 1, format->helper->fp) != 1)
&& helper->seek(helper->format, pm.offset, SEEK_SET)
!= pm.offset)
return -1;
if(helper->read(helper->format, &ph, sizeof(ph)) != sizeof(ph))
return _disas_error(format);
ph.section_cnt = _htol16(ph.section_cnt);
ph.opthdr_size = _htol16(ph.opthdr_size);
if(ph.section_cnt > 0 && ph.opthdr_size != 0
&& fseek(format->helper->fp, ph.opthdr_size, SEEK_CUR))
&& helper->seek(helper->format, ph.opthdr_size,
SEEK_CUR) < 0)
return _disas_error(format);
for(i = 0; i < ph.section_cnt; i++)
{
if(fread(&psh, sizeof(psh), 1, format->helper->fp) != 1)
return _disas_error(format);
if(helper->read(helper->format, &psh, sizeof(psh))
!= sizeof(psh))
return -1;
psh.name[sizeof(psh.name) - 1] = '\0';
psh.vaddr = _htol32(psh.vaddr);
psh.raw_size = _htol32(psh.raw_size);
psh.raw_offset = _htol32(psh.raw_offset);
callback(format, psh.name, psh.raw_offset, psh.raw_size,
psh.vaddr);
helper->disas(helper->format, psh.name, psh.raw_offset,
psh.raw_size, psh.vaddr);
}
return 0;
}
static int _disas_error(FormatPlugin * format)
{
return -error_set_code(1, "%s: %s", format->helper->filename,
strerror(errno));
return -error_set_code(1, "%s: %s", format->helper->get_filename(
format->helper->format), strerror(errno));
}