summaryrefslogtreecommitdiffhomepage
path: root/src/logic
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic')
-rw-r--r--src/logic/pe_image_meta_data.c151
1 files changed, 124 insertions, 27 deletions
diff --git a/src/logic/pe_image_meta_data.c b/src/logic/pe_image_meta_data.c
index b2255d7..9914350 100644
--- a/src/logic/pe_image_meta_data.c
+++ b/src/logic/pe_image_meta_data.c
@@ -15,6 +15,7 @@
#include <perk/perk.h>
#include <perk/perk_consts.h>
#include <perk/perk_structs.h>
+#include "perk_endian_impl.h"
#include "perk_reader_impl.h"
#include "perk_errinfo_impl.h"
@@ -28,6 +29,7 @@ static int pe_free_image_meta_impl(struct pe_image_meta * meta, int ret)
free(meta->m_symvec_crc32);
free(meta->m_symvec_crc64);
+ free(meta->m_symvec_symidx);
free(meta->m_idata);
free(meta->m_symtbl);
@@ -61,7 +63,9 @@ static int pe_symrec_crc64_compare(const void * a, const void * b)
return eqor * (syma->cs_crc64 > symb->cs_crc64 ? (1) : (-1));
}
-static int pe_get_named_section_index(const struct pe_image_meta * m, const char * name)
+static int pe_get_named_section_index(
+ const struct pe_image_meta * m,
+ const char * name)
{
int i; for (i=0; i<m->m_coff.cfh_num_of_sections; i++)
if (!(strcmp(name,m->m_sectbl[i].sh_name)))
@@ -70,12 +74,16 @@ static int pe_get_named_section_index(const struct pe_image_meta * m, const char
return -1;
}
-int pe_meta_get_named_section_index(const struct pe_image_meta * m, const char * name)
+int pe_meta_get_named_section_index(
+ const struct pe_image_meta * m,
+ const char * name)
{
return pe_get_named_section_index(m,name);
}
-static int pe_get_block_section_index(const struct pe_image_meta * m, const struct pe_block * block)
+static int pe_get_block_section_index(
+ const struct pe_image_meta * m,
+ const struct pe_block * block)
{
int i;
uint32_t low,high;
@@ -87,21 +95,28 @@ static int pe_get_block_section_index(const struct pe_image_meta * m, const stru
low = m->m_sectbl[i].sh_virtual_addr;
high = low + m->m_sectbl[i].sh_virtual_size;
- if ((block->dh_rva >= low) && (block->dh_rva + block->dh_size <= high))
- return i;
+ if (block->dh_rva >= low)
+ if (block->dh_rva + block->dh_size <= high)
+ return i;
}
return -1;
}
-int pe_meta_get_block_section_index(const struct pe_image_meta * m, const struct pe_block * block)
+int pe_meta_get_block_section_index(
+ const struct pe_image_meta * m,
+ const struct pe_block * block)
{
return pe_get_block_section_index(m,block);
}
-int pe_meta_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, uint32_t * roffset)
+int pe_meta_get_roffset_from_rva(
+ const struct pe_image_meta * m,
+ uint32_t rva,
+ uint32_t * roffset)
{
- int i;
+ int i;
+ uint32_t offset;
uint32_t low,high;
for (i=0; i<m->m_coff.cfh_num_of_sections; i++) {
@@ -109,7 +124,11 @@ int pe_meta_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, u
high = low + m->m_sectbl[i].sh_virtual_size;
if ((rva >= low) && (rva < high)) {
- *roffset = (rva - low) + m->m_sectbl[i].sh_ptr_to_raw_data;
+ offset = m->m_sectbl[i].sh_ptr_to_raw_data;
+ offset += rva - low;
+
+ *roffset = offset;
+
return 0;
}
}
@@ -117,9 +136,12 @@ int pe_meta_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, u
return -1;
}
-int pe_meta_get_rva_from_roffset(const struct pe_image_meta * m, uint32_t roffset, uint32_t * rva)
+int pe_meta_get_rva_from_roffset(
+ const struct pe_image_meta * m,
+ uint32_t roffset,
+ uint32_t * rva)
{
- int i;
+ int i;
uint32_t low,high,ref;
for (i=0, ref=~0; i<m->m_coff.cfh_num_of_sections; i++) {
@@ -127,8 +149,13 @@ int pe_meta_get_rva_from_roffset(const struct pe_image_meta * m, uint32_t roffse
high = low + m->m_sectbl[i].sh_virtual_size;
if ((roffset >= low) && (roffset < high)) {
- *rva = (roffset - low) + m->m_sectbl[i].sh_virtual_addr;
+ roffset -= low;
+ roffset += m->m_sectbl[i].sh_virtual_addr;
+
+ *rva = roffset;
+
return 0;
+
} else if (ref > low) {
ref = low;
}
@@ -147,19 +174,24 @@ static int pe_get_expsym_by_name(
const char * name,
struct pe_expsym * expsym)
{
- uint32_t offset;
- uint32_t * symrva;
- const char * sym;
- unsigned i;
+ uint32_t offset;
+ const unsigned char * ptrtbl;
+ const char * sym;
+ unsigned i;
if (m->r_obj || !m->h_edata)
return -1;
- offset = m->h_edata->sh_virtual_addr - m->h_edata->sh_ptr_to_raw_data;
- symrva = (uint32_t *)((uintptr_t)m->r_image.map_addr + (m->m_edata.eh_name_ptr_rva - offset));
+ offset = m->h_edata->sh_virtual_addr;
+ offset -= m->h_edata->sh_ptr_to_raw_data;
+
+ ptrtbl = m->r_image.map_addr;
+ ptrtbl += m->m_edata.eh_name_ptr_rva;
+ ptrtbl -= offset;
for (i=0; i<m->m_edata.eh_num_of_name_ptrs; i++) {
- sym = (const char *)m->r_image.map_addr + symrva[i] - offset;
+ sym = m->r_image.map_addr;
+ sym += pe_read_long(ptrtbl) - offset;
if (!(strcmp(sym,name))) {
if (expsym) {
@@ -171,6 +203,8 @@ static int pe_get_expsym_by_name(
return 0;
}
+
+ ptrtbl += sizeof(uint32_t);
}
return -1;
@@ -189,9 +223,9 @@ static int pe_get_expsym_by_index(
unsigned index,
struct pe_expsym * expsym)
{
- uint32_t offset;
- uint32_t * symrva;
- uintptr_t symaddr;
+ uint32_t offset;
+ const unsigned char * symptr;
+ const char * sym;
if (m->r_obj)
return -1;
@@ -200,11 +234,17 @@ static int pe_get_expsym_by_index(
return -1;
if (expsym) {
- offset = m->h_edata->sh_virtual_addr - m->h_edata->sh_ptr_to_raw_data;
- symrva = (uint32_t *)((uintptr_t)m->r_image.map_addr + (m->m_edata.eh_name_ptr_rva - offset));
- symaddr = (uintptr_t)m->r_image.map_addr + symrva[index] - offset;
+ offset = m->h_edata->sh_virtual_addr;
+ offset -= m->h_edata->sh_ptr_to_raw_data;
- expsym->s_name = (const char *)symaddr;
+ symptr = m->r_image.map_addr;
+ symptr += m->m_edata.eh_name_ptr_rva - offset;
+ symptr += index * sizeof(uint32_t);
+
+ sym = m->r_image.map_addr;
+ sym += pe_read_long(symptr) - offset;
+
+ expsym->s_name = sym;
expsym->s_eaddr = 0;
expsym->s_maddr = 0;
expsym->s_roffset = 0;
@@ -364,6 +404,7 @@ int pe_meta_get_image_meta(
void * addr;
char * base;
const unsigned char * mark;
+ const unsigned char * cap;
uint64_t vaddr;
struct pe_image_meta * m;
@@ -404,11 +445,17 @@ int pe_meta_get_image_meta(
}
- if ((nrecs = m->m_coff.cfh_size_of_sym_tbl/sizeof(struct pe_raw_coff_symbol)))
+ if ((nrecs = m->m_coff.cfh_size_of_sym_tbl/sizeof(struct pe_raw_coff_symbol))) {
if (!(m->m_symtbl = calloc(nrecs+1,sizeof(struct pe_meta_coff_symbol))))
return PERK_SYSTEM_ERROR(dctx);
+ if (!(m->m_symvec_symidx = calloc(nrecs,sizeof(struct pe_meta_coff_symbol *))))
+ return PERK_SYSTEM_ERROR(dctx);
+ }
+
for (i=0,symrec=m->m_symtbl; i<nrecs; i++,symrec++) {
+ m->m_symvec_symidx[i] = symrec;
+
pe_read_coff_symbol(
&m->r_symtbl[i],symrec,
&m->m_coff,base);
@@ -476,6 +523,56 @@ int pe_meta_get_image_meta(
m->m_sectbl[i].sh_name = base + m->m_coff.cfh_ptr_to_str_tbl + l;
}
+ /* .relocs */
+ struct pe_raw_base_reloc_block * r;
+ struct pe_block b;
+
+ i = pe_get_named_section_index(m,".reloc");
+ s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_base_reloc_tbl);
+
+ if ((i >= 0) && (i != s))
+ return pe_free_image_meta_impl(
+ m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED));
+
+
+ if (s >= 0) {
+ mark = image->map_addr;
+ mark += m->m_sectbl[s].sh_ptr_to_raw_data;
+ mark += m->m_opt.oh_dirs.coh_base_reloc_tbl.dh_rva;
+ mark -= m->m_sectbl[s].sh_virtual_addr;
+ cap = &mark[m->m_sectbl[s].sh_virtual_size];
+
+ } else if (i >= 0) {
+ mark = image->map_addr;
+ mark += m->m_sectbl[i].sh_ptr_to_raw_data;
+ cap = &mark[m->m_sectbl[s].sh_virtual_size];
+
+ } else {
+ mark = 0;
+ cap = 0;
+ }
+
+
+
+ for (; mark < cap; ) {
+ r = (struct pe_raw_base_reloc_block *)mark;
+
+ b.dh_rva = pe_read_long(r->blk_rva);
+ b.dh_size = pe_read_long(r->blk_size);
+
+ if (b.dh_size <= offsetof(struct pe_raw_base_reloc_block,blk_data))
+ return pe_free_image_meta_impl(
+ m,PERK_CUSTOM_ERROR(
+ dctx,
+ PERK_ERR_IMAGE_MALFORMED));
+
+ mark += b.dh_size;
+ b.dh_size -= offsetof(struct pe_raw_base_reloc_block,blk_data);
+
+ m->m_stats.t_nrelocs += b.dh_size / sizeof(uint16_t);
+ m->m_stats.t_nrelblks++;
+ }
+
/* .edata */
i = pe_get_named_section_index(m,".edata");
s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_export_tbl);