Tracking some function calls

This commit is contained in:
Pierre Pronchery 2011-09-06 22:12:55 +00:00
parent 1ed2fb51a1
commit 8cae299570

View File

@ -29,6 +29,21 @@
/* private */
/* types */
#pragma pack(1)
struct pe_export_directory
{
uint32_t flags;
uint32_t time;
uint16_t major;
uint16_t minor;
uint32_t name;
uint32_t base;
uint32_t functions_cnt;
uint32_t names_cnt;
uint32_t functions_addr;
uint32_t names_addr;
uint32_t ordinals_addr;
};
struct pe_header
{
uint16_t machine;
@ -228,7 +243,6 @@ FormatPlugin format_plugin =
static int _pe_init(FormatPlugin * format, char const * arch)
{
FormatPluginHelper * helper = format->helper;
char const ps[4] = { 'P', 'E', '\0', '\0' };
int machine;
struct pe_msdos pm;
struct pe_header ph;
@ -244,7 +258,9 @@ static int _pe_init(FormatPlugin * format, char const * arch)
if(helper->write(helper->format, &pm, sizeof(pm)) != sizeof(pm))
return -1;
/* output the PE signature */
if(helper->write(helper->format, &ps, sizeof(ps)) != sizeof(ps))
if(helper->write(helper->format, _pe_header_signature,
sizeof(_pe_header_signature))
!= sizeof(_pe_header_signature))
return -1;
/* output the PE header */
memset(&ph, 0, sizeof(ph));
@ -279,12 +295,18 @@ static char const * _pe_detect(FormatPlugin * format)
/* pe_decode */
static int _decode_data(FormatPlugin * format, uint32_t vaddr, uint32_t base,
struct pe_image_header_data * pid, size_t i);
static int _decode_data_export_directory(FormatPlugin * format, uint32_t vaddr,
uint32_t base, struct pe_image_header_data * pid);
static int _decode_error(FormatPlugin * format);
static char * _decode_string(FormatPlugin * format, off_t offset);
static int _pe_decode(FormatPlugin * format, int raw)
{
FormatPluginHelper * helper = format->helper;
struct pe_msdos pm;
char buf[sizeof(_pe_header_signature)];
struct pe_header ph;
size_t i;
size_t cnt;
@ -304,11 +326,14 @@ static int _pe_decode(FormatPlugin * format, int raw)
return -1;
if(helper->read(helper->format, &pm, sizeof(pm)) != sizeof(pm))
return -1;
/* FIXME check the PE signature */
/* read the PE header */
pm.offset = _htol16(pm.offset) + 4;
/* check the PE signature */
if(helper->seek(helper->format, pm.offset, SEEK_SET) != pm.offset)
return -1;
if(helper->read(helper->format, &buf, sizeof(buf)) != sizeof(buf))
return -1;
if(memcmp(buf, _pe_header_signature, sizeof(buf)) != 0)
return -1;
/* read the PE header */
if(helper->read(helper->format, &ph, sizeof(ph)) != sizeof(ph))
return _decode_error(format);
ph.section_cnt = _htol16(ph.section_cnt);
@ -326,6 +351,7 @@ static int _pe_decode(FormatPlugin * format, int raw)
}
pih = (struct pe_image_header *)p;
pih->signature = _htol16(pih->signature);
pih->code_base = _htol32(pih->code_base);
/* read any additional part of the optional header */
cnt = 0;
if(pih->signature == PE_IMAGE_HEADER_PE32
@ -355,21 +381,13 @@ static int _pe_decode(FormatPlugin * format, int raw)
/* read the data directories */
for(i = 0; pid != NULL && (char *)(&pid[i + 1]) < p
+ ph.opthdr_size && i < cnt; i++)
{
pid[i].vaddr = _htol32(pid[i].vaddr);
pid[i].size = _htol32(pid[i].size);
/* FIXME really implement */
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() pid[%lu] 0x%08x, 0x%08x\n",
__func__, i, pid[i].vaddr, pid[i].size);
#endif
}
if(_decode_data(format, base, pih->code_base, &pid[i],
i) != 0)
break; /* XXX report error */
}
else if(ph.opthdr_size != 0 && helper->seek(helper->format,
ph.opthdr_size, SEEK_CUR) != ph.opthdr_size)
return _decode_error(format);
/* read and decode each section */
offset = pm.offset + sizeof(ph) + ph.opthdr_size;
offset = pm.offset + sizeof(_pe_header_signature) + sizeof(ph)
+ ph.opthdr_size;
if(ph.opthdr_size != 0 && helper->seek(helper->format, offset, SEEK_SET)
!= offset)
return _decode_error(format);
@ -414,18 +432,127 @@ static int _pe_decode(FormatPlugin * format, int raw)
/* FIXME implement */
}
}
/* read symbols */
/* FIXME implement */
free(p);
return 0;
}
static int _decode_data(FormatPlugin * format, uint32_t vaddr, uint32_t base,
struct pe_image_header_data * pid, size_t i)
{
pid->vaddr = _htol32(pid->vaddr);
pid->size = _htol32(pid->size);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() pid[%lu] 0x%08x, 0x%08x\n", __func__, i,
pid->vaddr, pid->size);
#endif
switch(i)
{
case 0:
return _decode_data_export_directory(format, vaddr,
base, pid);
default:
/* FIXME implement the rest */
break;
}
return 0;
}
static int _decode_data_export_directory(FormatPlugin * format, uint32_t vaddr,
uint32_t base, struct pe_image_header_data * pid)
{
FormatPluginHelper * helper = format->helper;
struct pe_export_directory ped;
size_t j;
uint32_t f;
uint32_t n;
char * p;
if(base > pid->vaddr || helper->seek(helper->format, pid->vaddr - base,
SEEK_SET) < 0
|| helper->read(helper->format, &ped, sizeof(ped))
!= sizeof(ped))
return -1;
ped.major = _htol16(ped.major);
ped.minor = _htol16(ped.minor);
ped.name = _htol32(ped.name);
ped.base = _htol32(ped.base);
ped.functions_cnt = _htol32(ped.functions_cnt);
ped.names_cnt = _htol32(ped.names_cnt);
ped.functions_addr = _htol32(ped.functions_addr);
ped.names_addr = _htol32(ped.names_addr);
ped.ordinals_addr = _htol32(ped.ordinals_addr);
ped.time = _htol32(ped.time);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() M:0x%04x m:0x%04x n:0x%08x f:0x%08x@0x%08x"
" n:0x%0x8@0x%08x 0x%08x t:0x%08x\n", __func__,
ped.major, ped.minor, ped.name, ped.functions_cnt,
ped.functions_addr, ped.names_cnt, ped.names_addr,
ped.base, ped.time);
#endif
for(j = 0; j < ped.functions_cnt && j < ped.names_cnt; j++)
{
if(helper->seek(helper->format, ped.functions_addr - base
+ j * sizeof(f), SEEK_SET) < 0)
return -1;
if(helper->read(helper->format, &f, sizeof(f)) != sizeof(f))
return -1;
if(helper->seek(helper->format, ped.names_addr - base
+ j * sizeof(n), SEEK_SET) < 0)
return -1;
if(helper->read(helper->format, &n, sizeof(n)) != sizeof(n))
return -1;
if((p = _decode_string(format, n - base)) == NULL)
continue;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() 0x%08x@0x%08x \"%s\"\n", __func__,
n - base, f + vaddr, p);
#endif
/* XXX report errors */
helper->set_function(helper->format, f + vaddr, p, f, -1);
free(p);
}
return 0;
}
static int _decode_error(FormatPlugin * format)
{
return -error_set_code(1, "%s: %s", format->helper->get_filename(
format->helper->format), strerror(errno));
}
static char * _decode_string(FormatPlugin * format, off_t offset)
{
FormatPluginHelper * helper = format->helper;
char * ret = NULL;
char * p;
size_t len = 0;
ssize_t s;
size_t i;
const int inc = 32;
if(helper->seek(helper->format, offset, SEEK_SET) != offset)
return NULL;
for(;;)
{
if((p = realloc(ret, len + inc)) == NULL)
{
free(ret);
return NULL;
}
ret = p;
if((s = helper->read(helper->format, &ret[len], inc)) < 0)
{
free(ret);
return NULL;
}
for(i = len; i < len + inc; i++)
if(ret[i] == '\0')
return ret;
len += s;
}
return ret;
}
/* accessors */
/* pe_get_arch */