summaryrefslogtreecommitdiff
path: root/src/reader
diff options
context:
space:
mode:
Diffstat (limited to 'src/reader')
-rw-r--r--src/reader/pe_read_coff_header.c37
-rw-r--r--src/reader/pe_read_dos_header.c52
-rw-r--r--src/reader/pe_read_export_header.c32
-rw-r--r--src/reader/pe_read_import_header.c46
-rw-r--r--src/reader/pe_read_optional_header.c139
-rw-r--r--src/reader/pe_read_section_header.c37
6 files changed, 343 insertions, 0 deletions
diff --git a/src/reader/pe_read_coff_header.c b/src/reader/pe_read_coff_header.c
new file mode 100644
index 0000000..e7bdf8a
--- /dev/null
+++ b/src/reader/pe_read_coff_header.c
@@ -0,0 +1,37 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_coff_header(const struct pe_coff_file_hdr * p, struct pe_meta_coff_file_hdr * m)
+{
+ if ((p->signature[0] != 'P') || (p->signature[1] != 'E')
+ || *(uint16_t *)&p->signature[2])
+ return PERK_BAD_COFF_HEADER;
+
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(m,p,sizeof(*p));
+
+ #else
+
+ m->signature[0] = p->signature[0];
+ m->signature[1] = p->signature[1];
+ m->signature[2] = p->signature[2];
+ m->signature[3] = p->signature[3];
+
+ m->machine = pe_read_short(p->machine);
+ m->num_of_sections = pe_read_short(p->num_of_sections);
+
+ m->time_date_stamp = pe_read_long(p->time_date_stamp);
+ m->ptr_to_sym_tbl = pe_read_long(p->ptr_to_sym_tbl);
+ m->num_of_syms = pe_read_long(p->num_of_syms);
+
+ m->size_of_opt_hdr = pe_read_short(p->size_of_opt_hdr);
+ m->characteristics = pe_read_short(p->characteristics);
+
+ #endif
+
+ return 0;
+};
diff --git a/src/reader/pe_read_dos_header.c b/src/reader/pe_read_dos_header.c
new file mode 100644
index 0000000..75b7d31
--- /dev/null
+++ b/src/reader/pe_read_dos_header.c
@@ -0,0 +1,52 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_dos_header(const struct pe_image_dos_hdr * p, struct pe_meta_image_dos_hdr * m)
+{
+ int i;
+
+ if ((p->dos_magic[0] != 'M') || (p->dos_magic[1] != 'Z'))
+ return PERK_BAD_DOS_HEADER;
+
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(m,p,sizeof(*p));
+
+ #else
+
+ m->dos_magic[0] = p->dos_magic[0];
+ m->dos_magic[1] = p->dos_magic[1];
+
+ m->dos_cblp = pe_read_short(p->dos_cblp);
+ m->dos_cp = pe_read_short(p->dos_cp);
+ m->dos_crlc = pe_read_short(p->dos_crlc);
+ m->dos_cparhdr = pe_read_short(p->dos_cparhdr);
+ m->dos_minalloc = pe_read_short(p->dos_minalloc);
+ m->dos_maxalloc = pe_read_short(p->dos_maxalloc);
+ m->dos_ss = pe_read_short(p->dos_ss);
+ m->dos_sp = pe_read_short(p->dos_sp);
+ m->dos_csum = pe_read_short(p->dos_csum);
+ m->dos_ip = pe_read_short(p->dos_ip);
+ m->dos_cs = pe_read_short(p->dos_cs);
+ m->dos_lfarlc = pe_read_short(p->dos_lfarlc);
+ m->dos_ovno = pe_read_short(p->dos_ovno);
+
+
+ for (i=0; i<4; i++)
+ m->dos_res[i] = pe_read_short(&p->dos_res[2*i]);
+
+ m->dos_oemid = pe_read_short(p->dos_oemid);
+ m->dos_oeminfo = pe_read_short(p->dos_oeminfo);
+
+ for (i=0; i<10; i++)
+ m->dos_res2[i] = pe_read_short(&p->dos_res2[2*i]);
+
+ m->dos_lfanew = pe_read_long(p->dos_lfanew);
+
+ #endif
+
+ return 0;
+};
diff --git a/src/reader/pe_read_export_header.c b/src/reader/pe_read_export_header.c
new file mode 100644
index 0000000..6a959c9
--- /dev/null
+++ b/src/reader/pe_read_export_header.c
@@ -0,0 +1,32 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_export_header(const struct pe_export_hdr * p, struct pe_meta_export_hdr * m)
+{
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(m,p,sizeof(*p));
+
+ #else
+
+ m->export_flags = pe_read_long(p->export_flags);
+ m->time_date_stamp = pe_read_long(p->time_date_stamp);
+
+ m->major_ver = pe_read_short(p->major_ver);
+ m->minor_ver = pe_read_short(p->minor_ver);
+
+ m->name_rva = pe_read_long(p->name_rva);
+ m->ordinal_base = pe_read_long(p->ordinal_base);
+ m->addr_tbl_entries = pe_read_long(p->addr_tbl_entries);
+ m->num_of_name_ptrs = pe_read_long(p->num_of_name_ptrs);
+ m->export_addr_tbl_rva = pe_read_long(p->export_addr_tbl_rva);
+ m->name_ptr_rva = pe_read_long(p->name_ptr_rva);
+ m->ordinal_tbl_rva = pe_read_long(p->ordinal_tbl_rva);
+
+ #endif
+
+ return 0;
+};
diff --git a/src/reader/pe_read_import_header.c b/src/reader/pe_read_import_header.c
new file mode 100644
index 0000000..7d71143
--- /dev/null
+++ b/src/reader/pe_read_import_header.c
@@ -0,0 +1,46 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_import_header(const struct pe_import_hdr * p, struct pe_meta_import_hdr * m)
+{
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(m,p,sizeof(*p));
+
+ #else
+
+ m->import_lookup_tbl_rva = pe_read_long(p->import_lookup_tbl_rva);
+ m->time_date_stamp = pe_read_long(p->time_date_stamp);
+ m->forwarder_chain = pe_read_long(p>forwarder_chain);
+ m->name_rva = pe_read_long(p->name_rva);
+ m->import_addr_tbl_rva = pe_read_long(p>import_addr_tbl_rva);
+
+ #endif
+
+ m->name = 0;
+ m->aitems = 0;
+
+ return 0;
+};
+
+int pe_read_import_lookup_item(
+ const struct pe_import_lookup_item * p,
+ struct pe_meta_import_lookup_item * m,
+ uint32_t magic)
+{
+ switch (magic) {
+ case PE_MAGIC_PE32:
+ m->u.import_lookup_entry_64 = pe_read_long(p->u.import_lookup_entry_32);
+ return 0;
+
+ case PE_MAGIC_PE32_PLUS:
+ m->u.import_lookup_entry_64 = pe_read_quad(p->u.import_lookup_entry_64);
+ return 0;
+
+ default:
+ return PERK_BAD_IMAGE_TYPE;
+ }
+};
diff --git a/src/reader/pe_read_optional_header.c b/src/reader/pe_read_optional_header.c
new file mode 100644
index 0000000..701c6a9
--- /dev/null
+++ b/src/reader/pe_read_optional_header.c
@@ -0,0 +1,139 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_optional_header(const union pe_opt_hdr * p, struct pe_meta_opt_hdr * m)
+{
+ struct pe_opt_hdr_std * astd;
+ struct pe_opt_hdr_vers * avers;
+ struct pe_opt_hdr_align * aalign;
+ struct pe_opt_hdr_img * aimg;
+ struct pe_opt_hdr_ldr * aldr;
+ struct pe_opt_hdr_dirs * adirs;
+ size_t sdirs;
+
+ m->std.magic = pe_read_short(p->opt_hdr_32.magic);
+ memset(&m->dirs,0,sizeof(m->dirs));
+
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(&m->std,p,sizeof(struct pe_meta_opt_hdr_std));
+
+ switch (m->std.magic) {
+ case PE_MAGIC_PE32:
+ memcpy(&m->vers,&p->opt_hdr_32.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers));
+ memcpy(&m->align,&p->opt_hdr_32.section_align,sizeof(struct pe_meta_opt_hdr_align));
+ memcpy(&m->img,&p->opt_hdr_32.size_of_image,sizeof(struct pe_meta_opt_hdr_img));
+ memcpy(&m->ldr,&p->opt_hdr_32.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr));
+
+ if (m->ldr.rva_and_sizes > 0x10)
+ return PERK_BAD_IMAGE_TYPE;
+ else
+ memcpy(&m->dirs,&p->opt_hdr_32.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs));
+
+ break;
+
+ case PE_MAGIC_PE32_PLUS:
+ memcpy(&m->vers,&p->opt_hdr_64.major_os_ver,sizeof(struct pe_meta_opt_hdr_vers));
+ memcpy(&m->align,&p->opt_hdr_64.section_align,sizeof(struct pe_meta_opt_hdr_align));
+ memcpy(&m->img,&p->opt_hdr_64.size_of_image,sizeof(struct pe_meta_opt_hdr_img));
+ memcpy(&m->ldr,&p->opt_hdr_64.loader_flags,sizeof(struct pe_meta_opt_hdr_ldr));
+
+ if (m->ldr.rva_and_sizes > 0x10)
+ return PERK_BAD_IMAGE_TYPE;
+ else
+ memcpy(&m->dirs,&p->opt_hdr_64.export_tbl,sizeof(struct pe_meta_opt_hdr_dirs));
+
+ break;
+
+ default:
+ return PERK_BAD_IMAGE_TYPE;
+ };
+
+ #else
+
+ astd = (struct pe_opt_hdr_std *)p;
+
+ switch (m->std.magic) {
+ case PE_MAGIC_PE32:
+ avers = (struct pe_opt_hdr_std *)&p->opt_hdr_32.major_os_ver;
+ aalign = (struct pe_opt_hdr_std *)&p->opt_hdr_32.section_align;
+ aimg = (struct pe_opt_hdr_img *)&p->opt_hdr_32.size_of_image;
+ aldr = (struct pe_opt_hdr_ldr *)&p->opt_hdr_32.loader_flags;
+ adirs = (struct pe_opt_hdr_dirs *)&p->opt_hdr_32.export_tbl;
+ break;
+
+ case PE_MAGIC_PE32_PLUS:
+ avers = (struct pe_opt_hdr_std *)&p->opt_hdr_64.major_os_ver;
+ aalign = (struct pe_opt_hdr_std *)&p->opt_hdr_64.section_align;
+ aimg = (struct pe_opt_hdr_img *)&p->opt_hdr_64.size_of_image;
+ aldr = (struct pe_opt_hdr_ldr *)&p->opt_hdr_64.loader_flags;
+ adirs = (struct pe_opt_hdr_dirs *)&p->opt_hdr_64.export_tbl;
+ break;
+
+ default:
+ return PERK_BAD_IMAGE_TYPE;
+ }
+
+ /* std */
+ m->std.major_linker_ver = astd->major_linker_ver;
+ m->std.minor_linker_ver = astd->minor_linker_ver;
+
+ m->std.size_of_code = pe_read_long(astd->size_of_code);
+ m->std.size_of_initialized_data = pe_read_long(astd->size_of_initialized_data);
+ m->std.size_of_uninitialized_data = pe_read_long(astd->size_of_uninitialized_data);
+ m->std.entry_point = pe_read_long(astd->entry_point);
+ m->std.base_of_code = pe_read_long(astd->base_of_code);
+
+ /* vers */
+ m->vers.major_os_ver = pe_read_short(avers->major_os_ver);
+ m->vers.minor_os_ver = pe_read_short(avers->minor_os_ver);
+ m->vers.major_image_ver = pe_read_short(avers->major_image_ver);
+ m->vers.minor_image_ver = pe_read_short(avers->minor_image_ver);
+ m->vers.major_subsys_ver = pe_read_short(avers->major_subsys_ver);
+ m->vers.minor_subsys_ver = pe_read_short(avers->minor_subsys_ver);
+
+ m->vers.win32_ver = pe_read_long(avers->win32_ver);
+
+ /* align */
+ m->align.section_align = pe_read_long(aalign->section_align);
+ m->align.file_align = pe_read_long(aalign->file_align);
+
+ /* img */
+ m->img.size_of_image = pe_read_long(aimg->size_of_image);
+ m->img.size_of_headers = pe_read_long(aimg->size_of_headers);
+ m->img.checksum = pe_read_long(aimg->checksum);
+
+ m->img.subsystem = pe_read_short(aimg->subsystem);
+ m->img.dll_characteristics = pe_read_short(aimg->dll_characteristics);
+
+ /* ldr */
+ m->ldr.loader_flags = pe_read_long(aldr->loader_flags);
+ m->ldr.rva_and_sizes = pe_read_long(aldr->rva_and_sizes);
+
+ #endif
+
+ switch (m->std.magic) {
+ case PE_MAGIC_PE32:
+ m->mem.base_of_data = pe_read_long(p->opt_hdr_32.base_of_data);
+ m->mem.image_base = pe_read_long(p->opt_hdr_32.image_base);
+ m->mem.size_of_stack_reserve = pe_read_long(p->opt_hdr_32.size_of_stack_reserve);
+ m->mem.size_of_stack_commit = pe_read_long(p->opt_hdr_32.size_of_stack_commit);
+ m->mem.size_of_heap_reserve = pe_read_long(p->opt_hdr_32.size_of_heap_reserve);
+ m->mem.size_of_heap_commit = pe_read_long(p->opt_hdr_32.size_of_heap_commit);
+ break;
+
+ case PE_MAGIC_PE32_PLUS:
+ m->mem.base_of_data = (uint64_t)-1;
+ m->mem.image_base = pe_read_quad(p->opt_hdr_64.image_base);
+ m->mem.size_of_stack_reserve = pe_read_quad(p->opt_hdr_64.size_of_stack_reserve);
+ m->mem.size_of_stack_commit = pe_read_quad(p->opt_hdr_64.size_of_stack_commit);
+ m->mem.size_of_heap_reserve = pe_read_quad(p->opt_hdr_64.size_of_heap_reserve);
+ m->mem.size_of_heap_commit = pe_read_quad(p->opt_hdr_64.size_of_heap_commit);
+ break;
+ };
+
+ return 0;
+};
diff --git a/src/reader/pe_read_section_header.c b/src/reader/pe_read_section_header.c
new file mode 100644
index 0000000..1a37f63
--- /dev/null
+++ b/src/reader/pe_read_section_header.c
@@ -0,0 +1,37 @@
+#include <endian.h>
+#include <string.h>
+
+#include <perk/perk.h>
+#include "perk_impl.h"
+
+int pe_read_section_header(const struct pe_sec_hdr * p, struct pe_meta_sec_hdr * m)
+{
+ /* name: meta struct conveniently contains null termination */
+ memset(m,0,sizeof(m->name));
+ memcpy(m,p,sizeof(p->name));
+
+ /* todo: long name support */
+ m->long_name = 0;
+
+ #if (BYTE_ORDER == LITTLE_ENDIAN)
+
+ memcpy(&m->virtual_size,&p->virtual_size,sizeof(*p)-sizeof(p->name));
+
+ #else
+
+ m->virtual_size = pe_read_long(p->virtual_size);
+ m->virtual_addr = pe_read_long(p->virtual_addr);
+ m->size_of_raw_data = pe_read_long(p->size_of_raw_data);
+ m->ptr_to_raw_data = pe_read_long(p->ptr_to_raw_data);
+ m->ptr_to_relocs = pe_read_long(p->ptr_to_relocs);
+ m->ptr_to_line_nums = pe_read_long(p->ptr_to_linu_nums);
+
+ m->num_of_relocs = pe_read_short(p->num_of_relocs);
+ m->num_of_line_nums = pe_read_short(p->num_of_line_nums);
+
+ m->characteristics = pe_read_long(p->characteristics);
+
+ #endif
+
+ return 0;
+};