From 57ddbe03f41c4fc4686f92734b2aa3a56392815a Mon Sep 17 00:00:00 2001 From: midipix Date: Fri, 30 May 2025 23:17:35 +0000 Subject: library api: _meta_ (object and image meta data) namespace overhaul. --- src/driver/pe_unit_ctx.c | 4 +- src/logic/pe_get_image_meta.c | 555 ---------------------------------- src/logic/pe_image_meta_data.c | 555 ++++++++++++++++++++++++++++++++++ src/output/pe_output_mdso_libraries.c | 14 +- 4 files changed, 564 insertions(+), 564 deletions(-) delete mode 100644 src/logic/pe_get_image_meta.c create mode 100644 src/logic/pe_image_meta_data.c (limited to 'src') diff --git a/src/driver/pe_unit_ctx.c b/src/driver/pe_unit_ctx.c index 48afa81..8a88884 100644 --- a/src/driver/pe_unit_ctx.c +++ b/src/driver/pe_unit_ctx.c @@ -17,7 +17,7 @@ static int pe_lib_free_unit_ctx_impl(struct pe_unit_ctx_impl * ctx, int ret) { if (ctx) { - pe_free_image_meta(ctx->meta); + pe_meta_free_image_meta(ctx->meta); pe_unmap_raw_image(&ctx->map); free(ctx); } @@ -51,7 +51,7 @@ int pe_lib_get_unit_ctx( return pe_lib_free_unit_ctx_impl(ctx, PERK_NESTED_ERROR(dctx)); - if (pe_get_image_meta(dctx,&ctx->map,&ctx->meta)) + if (pe_meta_get_image_meta(dctx,&ctx->map,&ctx->meta)) return pe_lib_free_unit_ctx_impl(ctx, PERK_NESTED_ERROR(dctx)); diff --git a/src/logic/pe_get_image_meta.c b/src/logic/pe_get_image_meta.c deleted file mode 100644 index daf6939..0000000 --- a/src/logic/pe_get_image_meta.c +++ /dev/null @@ -1,555 +0,0 @@ -/***************************************************************/ -/* perk: PE Resource Kit */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ -/* Released under GPLv2 and GPLv3; see COPYING.PERK. */ -/***************************************************************/ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include "perk_reader_impl.h" -#include "perk_errinfo_impl.h" - -static int pe_free_image_meta_impl(struct pe_image_meta * meta, int ret) -{ - int i; - - if (meta) { - for (i=0; im_stats.t_nimplibs; i++) - free(meta->m_idata[i].ih_items); - - free(meta->m_idata); - free(meta->m_sectbl); - free(meta); - } - - return ret; -} - -void pe_free_image_meta(struct pe_image_meta * meta) -{ - pe_free_image_meta_impl(meta,0); -} - -int pe_get_named_section_index(const struct pe_image_meta * m, const char * name) -{ - int i; for (i=0; im_coff.cfh_num_of_sections; i++) - if (!(strcmp(name,m->m_sectbl[i].sh_name))) - return i; - - return -1; -} - -int pe_get_block_section_index(const struct pe_image_meta * m, const struct pe_block * block) -{ - int i; - uint32_t low,high; - - if (m->r_obj) - return -1; - - for (i=0; im_coff.cfh_num_of_sections; i++) { - 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; - } - - return -1; -} - -int pe_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, uint32_t * roffset) -{ - int i; - uint32_t low,high; - - for (i=0; im_coff.cfh_num_of_sections; i++) { - low = m->m_sectbl[i].sh_virtual_addr; - 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; - return 0; - } - } - - return -1; -} - -int pe_get_rva_from_roffset(const struct pe_image_meta * m, uint32_t roffset, uint32_t * rva) -{ - int i; - uint32_t low,high,ref; - - for (i=0, ref=~0; im_coff.cfh_num_of_sections; i++) { - low = m->m_sectbl[i].sh_ptr_to_raw_data; - high = low + m->m_sectbl[i].sh_virtual_size; - - if ((roffset >= low) && (roffset < high)) { - *rva = (roffset - low) + m->m_sectbl[i].sh_virtual_addr; - return 0; - } else if (ref > low) { - ref = low; - } - } - - if (roffset < ref) { - *rva = roffset; - return 0; - } - - return -1; -} - -int pe_get_expsym_by_name( - const struct pe_image_meta * m, - const char * name, - struct pe_expsym * expsym) -{ - uint32_t offset; - uint32_t * symrva; - 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)); - - for (i=0; im_edata.eh_num_of_name_ptrs; i++) { - sym = (const char *)m->r_image.map_addr + symrva[i] - offset; - - if (!(strcmp(sym,name))) { - if (expsym) { - expsym->s_name = sym; - expsym->s_eaddr = 0; - expsym->s_maddr = 0; - expsym->s_roffset = 0; - } - - return 0; - } - } - - return -1; -} - -int pe_get_expsym_by_index( - const struct pe_image_meta * m, - unsigned index, - struct pe_expsym * expsym) -{ - uint32_t offset; - uint32_t * symrva; - uintptr_t symaddr; - - if (m->r_obj) - return -1; - - if (index >= m->m_edata.eh_num_of_name_ptrs) - 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; - - expsym->s_name = (const char *)symaddr; - expsym->s_eaddr = 0; - expsym->s_maddr = 0; - expsym->s_roffset = 0; - } - - return 0; -} - -static void pe_detect_image_abi(struct pe_image_meta * m) -{ - int abi; - - if (m->r_obj) { - switch (m->m_coff.cfh_machine) { - case PE_IMAGE_FILE_MACHINE_I386: - abi = PE_ABI_PE32; - break; - - case PE_IMAGE_FILE_MACHINE_IA64: - case PE_IMAGE_FILE_MACHINE_AMD64: - abi = PE_ABI_PE64; - break; - - default: - abi = PE_ABI_UNSUPPORTED; - break; - } - } else { - switch (m->m_opt.oh_std.coh_magic) { - case PE_MAGIC_PE32: - abi = PE_ABI_PE32; - break; - - case PE_MAGIC_PE32_PLUS: - abi = PE_ABI_PE64; - break; - - default: - abi = PE_ABI_UNSUPPORTED; - break; - } - } - - m->m_abi = abi; -} - -static void pe_detect_image_subtype(struct pe_image_meta * m) -{ - int subtype; - - if (m->r_obj) - subtype = PE_SUBTYPE_OBJ; - - else if (m->m_coff.cfh_characteristics & PE_IMAGE_FILE_DLL) - subtype = PE_SUBTYPE_DLL; - - else - subtype = PE_SUBTYPE_EXE; - - m->m_subtype = subtype; -} - -static bool pe_image_is_psxscl(const struct pe_image_meta * m) -{ - return (!m->m_stats.t_nimplibs - && !pe_get_expsym_by_name(m,"__psx_init",0)); -} - -static bool pe_image_is_cygwin(const struct pe_image_meta * m) -{ - int i; - - for (i=0; im_stats.t_nimplibs; i++) - if (!(strcmp(m->m_idata[i].ih_name,"cygwin1.dll"))) - return true; - - return false; -} - -static bool pe_image_is_msys(const struct pe_image_meta * m) -{ - int i; - - for (i=0; im_stats.t_nimplibs; i++) - if (!(strcmp(m->m_idata[i].ih_name,"msys-2.0.dll"))) - return true; - - return false; -} - -static bool pe_image_is_mingw(const struct pe_image_meta * m) -{ - return ((pe_get_named_section_index(m,".CRT") >= 0) - && (pe_get_named_section_index(m,".bss") >= 0) - && (pe_get_named_section_index(m,".tls") >= 0)); -} - -static void pe_detect_image_framework(struct pe_image_meta * m) -{ - int framework; - - if (pe_get_named_section_index(m,".midipix") >= 0) - framework = PE_FRAMEWORK_MIDIPIX; - - else if (pe_get_named_section_index(m,".freestd") >= 0) - framework = PE_FRAMEWORK_FREESTD; - - else if (pe_get_named_section_index(m,".cygheap") >= 0) - framework = PE_FRAMEWORK_CYGONE; - - else if (pe_image_is_psxscl(m)) - framework = PE_FRAMEWORK_PSXSCL; - - else if (pe_image_is_cygwin(m)) - framework = PE_FRAMEWORK_CYGWIN; - - else if (pe_image_is_msys(m)) - framework = PE_FRAMEWORK_MSYS; - - else if (pe_image_is_mingw(m)) - framework = PE_FRAMEWORK_MINGW; - - else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_POSIX_CUI) - framework = PE_FRAMEWORK_SUACON; - - else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_CUI) - framework = PE_FRAMEWORK_WINCON; - - else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_GUI) - framework = PE_FRAMEWORK_WIN32; - - else - framework = PE_FRAMEWORK_UNKNOWN; - - m->m_framework = framework; -} - -int pe_get_image_meta( - const struct pe_driver_ctx * dctx, - const struct pe_raw_image * image, - struct pe_image_meta ** meta) -{ - int ret; - int i,s; - long l; - unsigned j; - const unsigned char * mark; - struct pe_image_meta * m; - char * base; - uint64_t vaddr; - - base = image->map_addr; - - if (!(m = calloc(1,sizeof(*m)))) - return PERK_SYSTEM_ERROR(dctx); - - m->r_obj = (struct pe_raw_coff_object_hdr *)base; - - if (pe_read_object_header(m->r_obj,&m->m_coff)) { - m->r_obj = 0; - m->r_dos = (struct pe_raw_image_dos_hdr *)base; - - if ((ret = (pe_read_dos_header(m->r_dos,&m->m_dos)))) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,ret)); - - m->r_coff = (struct pe_raw_coff_image_hdr *)(base + m->m_dos.dos_lfanew); - - if ((ret = (pe_read_coff_header(m->r_coff,&m->m_coff)))) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,ret)); - } - - mark = (const unsigned char *)base + m->m_coff.cfh_ptr_to_sym_tbl; - mark += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol); - - if (m->m_coff.cfh_ptr_to_sym_tbl) { - m->m_coff.cfh_ptr_to_str_tbl = m->m_coff.cfh_ptr_to_sym_tbl; - m->m_coff.cfh_ptr_to_str_tbl += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol); - m->m_coff.cfh_size_of_str_tbl = pe_read_long(mark); - } - - if (m->r_dos) { - mark = &m->r_coff->cfh_signature[0]; - m->r_opt = (union pe_raw_opt_hdr *)(mark + sizeof(*m->r_coff)); - - if ((ret = (pe_read_optional_header(m->r_opt,&m->m_opt)))) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,ret)); - - mark = &m->r_opt->opt_hdr_32.coh_magic[0]; - m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + m->m_coff.cfh_size_of_opt_hdr); - } else { - mark = &m->r_obj->cfh_machine[0]; - m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + sizeof(*m->r_obj)); - } - - if (!(m->m_sectbl = calloc(m->m_coff.cfh_num_of_sections,sizeof(*(m->m_sectbl))))) - return pe_free_image_meta_impl( - m,PERK_SYSTEM_ERROR(dctx)); - - for (i=0; im_coff.cfh_num_of_sections; i++) { - pe_read_section_header(&m->r_sectbl[i],&m->m_sectbl[i]); - - if (m->m_sectbl[i].sh_name[0] == '/') - if ((l = strtol(&m->m_sectbl[i].sh_name[1],0,10)) > 0) - if (l < m->m_coff.cfh_size_of_str_tbl) - m->m_sectbl[i].sh_long_name = base + m->m_coff.cfh_ptr_to_str_tbl + l; - } - - /* .edata */ - i = pe_get_named_section_index(m,".edata"); - s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_export_tbl); - - if ((i >= 0) && (i != s)) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED)); - - if (s >= 0) { - m->h_edata = &m->m_sectbl[s]; - m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data - + m->m_opt.oh_dirs.coh_export_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr); - m->m_edata.eh_virtual_addr = m->m_opt.oh_dirs.coh_export_tbl.dh_rva; - } else if (i >= 0) { - m->h_edata = &m->m_sectbl[i]; - m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data); - m->m_edata.eh_virtual_addr = m->m_sectbl[i].sh_virtual_addr; - } - - if (m->r_edata) { - pe_read_export_header(m->r_edata,&m->m_edata); - m->m_stats.t_nexpsyms = m->m_edata.eh_num_of_name_ptrs; - } - - /* .idata */ - struct pe_raw_import_hdr * pidata; - unsigned char * pitem; - size_t psize; - - i = pe_get_named_section_index(m,".idata"); - s = pe_get_block_section_index(m,&m->m_opt.oh_dirs.coh_import_tbl); - - if ((i >= 0) && (i != s)) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED)); - - if (s >= 0) { - m->h_idata = &m->m_sectbl[s]; - m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data - + m->m_opt.oh_dirs.coh_import_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr); - vaddr = m->m_opt.oh_dirs.coh_import_tbl.dh_rva; - } else if (i >= 0) { - m->h_idata = &m->m_sectbl[i]; - m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data); - vaddr = m->m_sectbl[i].sh_virtual_addr; - } - - if (m->r_idata) { - /* num of implibs */ - for (pidata=m->r_idata; pe_read_long(pidata->ih_name_rva); pidata++) - m->m_stats.t_nimplibs++; - - /* import headers */ - if (!(m->m_idata = calloc(m->m_stats.t_nimplibs,sizeof(*m->m_idata)))) - return pe_free_image_meta_impl( - m,PERK_SYSTEM_ERROR(dctx)); - - for (i=0; im_stats.t_nimplibs; i++) { - m->m_idata[i].ih_virtual_addr = vaddr + (i * sizeof(*m->r_idata)); - pe_read_import_header(&m->r_idata[i],&m->m_idata[i]); - - m->m_idata[i].ih_name = base + m->h_idata->sh_ptr_to_raw_data - + m->m_idata[i].ih_name_rva - - m->h_idata->sh_virtual_addr; - - if (m->m_idata[i].ih_import_lookup_tbl_rva) - m->m_idata[i].ih_aitems = (union pe_raw_import_lookup *)(base + m->h_idata->sh_ptr_to_raw_data - + m->m_idata[i].ih_import_lookup_tbl_rva - - m->h_idata->sh_virtual_addr); - - /* items */ - if (m->m_idata[i].ih_import_lookup_tbl_rva) { - if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32) { - pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_32; - - for (; pe_read_long(pitem); m->m_idata[i].ih_count++) - pitem += sizeof(uint32_t); - } else if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) { - pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_64; - - for (; pe_read_quad(pitem); m->m_idata[i].ih_count++) - pitem += sizeof(uint64_t); - } else { - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR( - dctx,PERK_ERR_UNSUPPORTED_ABI)); - } - - if (!(m->m_idata[i].ih_items = calloc(m->m_idata[i].ih_count,sizeof(*(m->m_idata[i].ih_items))))) - return pe_free_image_meta_impl( - m,PERK_SYSTEM_ERROR(dctx)); - } - - switch (m->m_opt.oh_std.coh_magic) { - case PE_MAGIC_PE32: - pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_32; - psize = sizeof(uint32_t); - break; - - case PE_MAGIC_PE32_PLUS: - pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_64; - psize = sizeof(uint64_t); - break; - } - - for (j=0; jm_idata[i].ih_count; j++) { - if ((ret = pe_read_import_lookup( - pitem + j*psize, - &(m->m_idata[i].ih_items[j]), - m->m_opt.oh_std.coh_magic))) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR(dctx,ret)); - - if (!m->m_idata[i].ih_items[j].ii_flag) { - struct pe_raw_hint_name_entry * pentry = - (struct pe_raw_hint_name_entry *)(base + m->h_idata->sh_ptr_to_raw_data - + m->m_idata[i].ih_items[j].ii_hint_name_tbl_rva - m->h_idata->sh_virtual_addr); - - m->m_idata[i].ih_items[j].ii_hint = pe_read_short(pentry->ii_hint); - m->m_idata[i].ih_items[j].ii_name = (char *)pentry->ii_name; - } - } - } - } - - /* .dsometa */ - if ((i = pe_get_named_section_index(m,MDSO_META_SECTION)) >= 0) { - m->h_dsometa = &m->m_sectbl[i]; - m->r_dsometa = base + m->m_sectbl[i].sh_ptr_to_raw_data; - - m->m_stats.t_ndsolibs = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) - ? m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m64) - : m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m32); - } - - /* .dsosyms */ - if ((i = pe_get_named_section_index(m,MDSO_SYMS_SECTION)) >= 0) { - m->h_dsosyms = &m->m_sectbl[i]; - m->r_dsosyms = base + m->m_sectbl[i].sh_ptr_to_raw_data; - - m->m_stats.t_ndsosyms = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) - ? m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m64) - : m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m32); - } - - /* .dsostrs */ - if ((i = pe_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0) { - m->h_dsostrs = &m->m_sectbl[i]; - m->r_dsostrs = base + m->m_sectbl[i].sh_ptr_to_raw_data; - } - - /* .dsodata */ - if ((i = pe_get_named_section_index(m,MDSO_DATA_SECTION)) >= 0) { - m->h_dsodata = &m->m_sectbl[i]; - m->r_dsodata = base + m->m_sectbl[i].sh_ptr_to_raw_data; - } - - /* image */ - m->r_image.map_addr = image->map_addr; - m->r_image.map_size = image->map_size; - - /* info */ - pe_detect_image_abi(m); - pe_detect_image_subtype(m); - pe_detect_image_framework(m); - - /* mdso abi */ - if (m->h_dsometa || m->h_dsosyms) - if (m->m_abi == PE_ABI_UNSUPPORTED) - return pe_free_image_meta_impl( - m,PERK_CUSTOM_ERROR( - dctx,PERK_ERR_UNSUPPORTED_ABI)); - - - /* all done */ - *meta = m; - return 0; -} diff --git a/src/logic/pe_image_meta_data.c b/src/logic/pe_image_meta_data.c new file mode 100644 index 0000000..37d524f --- /dev/null +++ b/src/logic/pe_image_meta_data.c @@ -0,0 +1,555 @@ +/***************************************************************/ +/* perk: PE Resource Kit */ +/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.PERK. */ +/***************************************************************/ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include "perk_reader_impl.h" +#include "perk_errinfo_impl.h" + +static int pe_free_image_meta_impl(struct pe_image_meta * meta, int ret) +{ + int i; + + if (meta) { + for (i=0; im_stats.t_nimplibs; i++) + free(meta->m_idata[i].ih_items); + + free(meta->m_idata); + free(meta->m_sectbl); + free(meta); + } + + return ret; +} + +void pe_meta_free_image_meta(struct pe_image_meta * meta) +{ + pe_free_image_meta_impl(meta,0); +} + +int pe_meta_get_named_section_index(const struct pe_image_meta * m, const char * name) +{ + int i; for (i=0; im_coff.cfh_num_of_sections; i++) + if (!(strcmp(name,m->m_sectbl[i].sh_name))) + return i; + + return -1; +} + +int pe_meta_get_block_section_index(const struct pe_image_meta * m, const struct pe_block * block) +{ + int i; + uint32_t low,high; + + if (m->r_obj) + return -1; + + for (i=0; im_coff.cfh_num_of_sections; i++) { + 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; + } + + return -1; +} + +int pe_meta_get_roffset_from_rva(const struct pe_image_meta * m, uint32_t rva, uint32_t * roffset) +{ + int i; + uint32_t low,high; + + for (i=0; im_coff.cfh_num_of_sections; i++) { + low = m->m_sectbl[i].sh_virtual_addr; + 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; + return 0; + } + } + + return -1; +} + +int pe_meta_get_rva_from_roffset(const struct pe_image_meta * m, uint32_t roffset, uint32_t * rva) +{ + int i; + uint32_t low,high,ref; + + for (i=0, ref=~0; im_coff.cfh_num_of_sections; i++) { + low = m->m_sectbl[i].sh_ptr_to_raw_data; + high = low + m->m_sectbl[i].sh_virtual_size; + + if ((roffset >= low) && (roffset < high)) { + *rva = (roffset - low) + m->m_sectbl[i].sh_virtual_addr; + return 0; + } else if (ref > low) { + ref = low; + } + } + + if (roffset < ref) { + *rva = roffset; + return 0; + } + + return -1; +} + +int pe_meta_get_expsym_by_name( + const struct pe_image_meta * m, + const char * name, + struct pe_expsym * expsym) +{ + uint32_t offset; + uint32_t * symrva; + 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)); + + for (i=0; im_edata.eh_num_of_name_ptrs; i++) { + sym = (const char *)m->r_image.map_addr + symrva[i] - offset; + + if (!(strcmp(sym,name))) { + if (expsym) { + expsym->s_name = sym; + expsym->s_eaddr = 0; + expsym->s_maddr = 0; + expsym->s_roffset = 0; + } + + return 0; + } + } + + return -1; +} + +int pe_meta_get_expsym_by_index( + const struct pe_image_meta * m, + unsigned index, + struct pe_expsym * expsym) +{ + uint32_t offset; + uint32_t * symrva; + uintptr_t symaddr; + + if (m->r_obj) + return -1; + + if (index >= m->m_edata.eh_num_of_name_ptrs) + 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; + + expsym->s_name = (const char *)symaddr; + expsym->s_eaddr = 0; + expsym->s_maddr = 0; + expsym->s_roffset = 0; + } + + return 0; +} + +static void pe_detect_image_abi(struct pe_image_meta * m) +{ + int abi; + + if (m->r_obj) { + switch (m->m_coff.cfh_machine) { + case PE_IMAGE_FILE_MACHINE_I386: + abi = PE_ABI_PE32; + break; + + case PE_IMAGE_FILE_MACHINE_IA64: + case PE_IMAGE_FILE_MACHINE_AMD64: + abi = PE_ABI_PE64; + break; + + default: + abi = PE_ABI_UNSUPPORTED; + break; + } + } else { + switch (m->m_opt.oh_std.coh_magic) { + case PE_MAGIC_PE32: + abi = PE_ABI_PE32; + break; + + case PE_MAGIC_PE32_PLUS: + abi = PE_ABI_PE64; + break; + + default: + abi = PE_ABI_UNSUPPORTED; + break; + } + } + + m->m_abi = abi; +} + +static void pe_detect_image_subtype(struct pe_image_meta * m) +{ + int subtype; + + if (m->r_obj) + subtype = PE_SUBTYPE_OBJ; + + else if (m->m_coff.cfh_characteristics & PE_IMAGE_FILE_DLL) + subtype = PE_SUBTYPE_DLL; + + else + subtype = PE_SUBTYPE_EXE; + + m->m_subtype = subtype; +} + +static bool pe_image_is_psxscl(const struct pe_image_meta * m) +{ + return (!m->m_stats.t_nimplibs + && !pe_meta_get_expsym_by_name(m,"__psx_init",0)); +} + +static bool pe_image_is_cygwin(const struct pe_image_meta * m) +{ + int i; + + for (i=0; im_stats.t_nimplibs; i++) + if (!(strcmp(m->m_idata[i].ih_name,"cygwin1.dll"))) + return true; + + return false; +} + +static bool pe_image_is_msys(const struct pe_image_meta * m) +{ + int i; + + for (i=0; im_stats.t_nimplibs; i++) + if (!(strcmp(m->m_idata[i].ih_name,"msys-2.0.dll"))) + return true; + + return false; +} + +static bool pe_image_is_mingw(const struct pe_image_meta * m) +{ + return ((pe_meta_get_named_section_index(m,".CRT") >= 0) + && (pe_meta_get_named_section_index(m,".bss") >= 0) + && (pe_meta_get_named_section_index(m,".tls") >= 0)); +} + +static void pe_detect_image_framework(struct pe_image_meta * m) +{ + int framework; + + if (pe_meta_get_named_section_index(m,".midipix") >= 0) + framework = PE_FRAMEWORK_MIDIPIX; + + else if (pe_meta_get_named_section_index(m,".freestd") >= 0) + framework = PE_FRAMEWORK_FREESTD; + + else if (pe_meta_get_named_section_index(m,".cygheap") >= 0) + framework = PE_FRAMEWORK_CYGONE; + + else if (pe_image_is_psxscl(m)) + framework = PE_FRAMEWORK_PSXSCL; + + else if (pe_image_is_cygwin(m)) + framework = PE_FRAMEWORK_CYGWIN; + + else if (pe_image_is_msys(m)) + framework = PE_FRAMEWORK_MSYS; + + else if (pe_image_is_mingw(m)) + framework = PE_FRAMEWORK_MINGW; + + else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_POSIX_CUI) + framework = PE_FRAMEWORK_SUACON; + + else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_CUI) + framework = PE_FRAMEWORK_WINCON; + + else if (m->m_opt.oh_img.coh_subsystem == PE_IMAGE_SUBSYSTEM_WINDOWS_GUI) + framework = PE_FRAMEWORK_WIN32; + + else + framework = PE_FRAMEWORK_UNKNOWN; + + m->m_framework = framework; +} + +int pe_meta_get_image_meta( + const struct pe_driver_ctx * dctx, + const struct pe_raw_image * image, + struct pe_image_meta ** meta) +{ + int ret; + int i,s; + long l; + unsigned j; + const unsigned char * mark; + struct pe_image_meta * m; + char * base; + uint64_t vaddr; + + base = image->map_addr; + + if (!(m = calloc(1,sizeof(*m)))) + return PERK_SYSTEM_ERROR(dctx); + + m->r_obj = (struct pe_raw_coff_object_hdr *)base; + + if (pe_read_object_header(m->r_obj,&m->m_coff)) { + m->r_obj = 0; + m->r_dos = (struct pe_raw_image_dos_hdr *)base; + + if ((ret = (pe_read_dos_header(m->r_dos,&m->m_dos)))) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,ret)); + + m->r_coff = (struct pe_raw_coff_image_hdr *)(base + m->m_dos.dos_lfanew); + + if ((ret = (pe_read_coff_header(m->r_coff,&m->m_coff)))) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,ret)); + } + + mark = (const unsigned char *)base + m->m_coff.cfh_ptr_to_sym_tbl; + mark += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol); + + if (m->m_coff.cfh_ptr_to_sym_tbl) { + m->m_coff.cfh_ptr_to_str_tbl = m->m_coff.cfh_ptr_to_sym_tbl; + m->m_coff.cfh_ptr_to_str_tbl += m->m_coff.cfh_num_of_syms * sizeof(struct pe_raw_coff_symbol); + m->m_coff.cfh_size_of_str_tbl = pe_read_long(mark); + } + + if (m->r_dos) { + mark = &m->r_coff->cfh_signature[0]; + m->r_opt = (union pe_raw_opt_hdr *)(mark + sizeof(*m->r_coff)); + + if ((ret = (pe_read_optional_header(m->r_opt,&m->m_opt)))) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,ret)); + + mark = &m->r_opt->opt_hdr_32.coh_magic[0]; + m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + m->m_coff.cfh_size_of_opt_hdr); + } else { + mark = &m->r_obj->cfh_machine[0]; + m->r_sectbl = (struct pe_raw_sec_hdr *)(mark + sizeof(*m->r_obj)); + } + + if (!(m->m_sectbl = calloc(m->m_coff.cfh_num_of_sections,sizeof(*(m->m_sectbl))))) + return pe_free_image_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + for (i=0; im_coff.cfh_num_of_sections; i++) { + pe_read_section_header(&m->r_sectbl[i],&m->m_sectbl[i]); + + if (m->m_sectbl[i].sh_name[0] == '/') + if ((l = strtol(&m->m_sectbl[i].sh_name[1],0,10)) > 0) + if (l < m->m_coff.cfh_size_of_str_tbl) + m->m_sectbl[i].sh_long_name = base + m->m_coff.cfh_ptr_to_str_tbl + l; + } + + /* .edata */ + i = pe_meta_get_named_section_index(m,".edata"); + s = pe_meta_get_block_section_index(m,&m->m_opt.oh_dirs.coh_export_tbl); + + if ((i >= 0) && (i != s)) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED)); + + if (s >= 0) { + m->h_edata = &m->m_sectbl[s]; + m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data + + m->m_opt.oh_dirs.coh_export_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr); + m->m_edata.eh_virtual_addr = m->m_opt.oh_dirs.coh_export_tbl.dh_rva; + } else if (i >= 0) { + m->h_edata = &m->m_sectbl[i]; + m->r_edata = (struct pe_raw_export_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data); + m->m_edata.eh_virtual_addr = m->m_sectbl[i].sh_virtual_addr; + } + + if (m->r_edata) { + pe_read_export_header(m->r_edata,&m->m_edata); + m->m_stats.t_nexpsyms = m->m_edata.eh_num_of_name_ptrs; + } + + /* .idata */ + struct pe_raw_import_hdr * pidata; + unsigned char * pitem; + size_t psize; + + i = pe_meta_get_named_section_index(m,".idata"); + s = pe_meta_get_block_section_index(m,&m->m_opt.oh_dirs.coh_import_tbl); + + if ((i >= 0) && (i != s)) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,PERK_ERR_IMAGE_MALFORMED)); + + if (s >= 0) { + m->h_idata = &m->m_sectbl[s]; + m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[s].sh_ptr_to_raw_data + + m->m_opt.oh_dirs.coh_import_tbl.dh_rva - m->m_sectbl[s].sh_virtual_addr); + vaddr = m->m_opt.oh_dirs.coh_import_tbl.dh_rva; + } else if (i >= 0) { + m->h_idata = &m->m_sectbl[i]; + m->r_idata = (struct pe_raw_import_hdr *)(base + m->m_sectbl[i].sh_ptr_to_raw_data); + vaddr = m->m_sectbl[i].sh_virtual_addr; + } + + if (m->r_idata) { + /* num of implibs */ + for (pidata=m->r_idata; pe_read_long(pidata->ih_name_rva); pidata++) + m->m_stats.t_nimplibs++; + + /* import headers */ + if (!(m->m_idata = calloc(m->m_stats.t_nimplibs,sizeof(*m->m_idata)))) + return pe_free_image_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + for (i=0; im_stats.t_nimplibs; i++) { + m->m_idata[i].ih_virtual_addr = vaddr + (i * sizeof(*m->r_idata)); + pe_read_import_header(&m->r_idata[i],&m->m_idata[i]); + + m->m_idata[i].ih_name = base + m->h_idata->sh_ptr_to_raw_data + + m->m_idata[i].ih_name_rva + - m->h_idata->sh_virtual_addr; + + if (m->m_idata[i].ih_import_lookup_tbl_rva) + m->m_idata[i].ih_aitems = (union pe_raw_import_lookup *)(base + m->h_idata->sh_ptr_to_raw_data + + m->m_idata[i].ih_import_lookup_tbl_rva + - m->h_idata->sh_virtual_addr); + + /* items */ + if (m->m_idata[i].ih_import_lookup_tbl_rva) { + if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32) { + pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_32; + + for (; pe_read_long(pitem); m->m_idata[i].ih_count++) + pitem += sizeof(uint32_t); + } else if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) { + pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_64; + + for (; pe_read_quad(pitem); m->m_idata[i].ih_count++) + pitem += sizeof(uint64_t); + } else { + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx,PERK_ERR_UNSUPPORTED_ABI)); + } + + if (!(m->m_idata[i].ih_items = calloc(m->m_idata[i].ih_count,sizeof(*(m->m_idata[i].ih_items))))) + return pe_free_image_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + } + + switch (m->m_opt.oh_std.coh_magic) { + case PE_MAGIC_PE32: + pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_32; + psize = sizeof(uint32_t); + break; + + case PE_MAGIC_PE32_PLUS: + pitem = m->m_idata[i].ih_aitems->ii_import_lookup_entry_64; + psize = sizeof(uint64_t); + break; + } + + for (j=0; jm_idata[i].ih_count; j++) { + if ((ret = pe_read_import_lookup( + pitem + j*psize, + &(m->m_idata[i].ih_items[j]), + m->m_opt.oh_std.coh_magic))) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR(dctx,ret)); + + if (!m->m_idata[i].ih_items[j].ii_flag) { + struct pe_raw_hint_name_entry * pentry = + (struct pe_raw_hint_name_entry *)(base + m->h_idata->sh_ptr_to_raw_data + + m->m_idata[i].ih_items[j].ii_hint_name_tbl_rva - m->h_idata->sh_virtual_addr); + + m->m_idata[i].ih_items[j].ii_hint = pe_read_short(pentry->ii_hint); + m->m_idata[i].ih_items[j].ii_name = (char *)pentry->ii_name; + } + } + } + } + + /* .dsometa */ + if ((i = pe_meta_get_named_section_index(m,MDSO_META_SECTION)) >= 0) { + m->h_dsometa = &m->m_sectbl[i]; + m->r_dsometa = base + m->m_sectbl[i].sh_ptr_to_raw_data; + + m->m_stats.t_ndsolibs = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) + ? m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m64) + : m->h_dsometa->sh_virtual_size / sizeof(struct mdso_raw_meta_record_m32); + } + + /* .dsosyms */ + if ((i = pe_meta_get_named_section_index(m,MDSO_SYMS_SECTION)) >= 0) { + m->h_dsosyms = &m->m_sectbl[i]; + m->r_dsosyms = base + m->m_sectbl[i].sh_ptr_to_raw_data; + + m->m_stats.t_ndsosyms = (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) + ? m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m64) + : m->h_dsosyms->sh_virtual_size / sizeof(struct mdso_raw_sym_entry_m32); + } + + /* .dsostrs */ + if ((i = pe_meta_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0) { + m->h_dsostrs = &m->m_sectbl[i]; + m->r_dsostrs = base + m->m_sectbl[i].sh_ptr_to_raw_data; + } + + /* .dsodata */ + if ((i = pe_meta_get_named_section_index(m,MDSO_DATA_SECTION)) >= 0) { + m->h_dsodata = &m->m_sectbl[i]; + m->r_dsodata = base + m->m_sectbl[i].sh_ptr_to_raw_data; + } + + /* image */ + m->r_image.map_addr = image->map_addr; + m->r_image.map_size = image->map_size; + + /* info */ + pe_detect_image_abi(m); + pe_detect_image_subtype(m); + pe_detect_image_framework(m); + + /* mdso abi */ + if (m->h_dsometa || m->h_dsosyms) + if (m->m_abi == PE_ABI_UNSUPPORTED) + return pe_free_image_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx,PERK_ERR_UNSUPPORTED_ABI)); + + + /* all done */ + *meta = m; + return 0; +} diff --git a/src/output/pe_output_mdso_libraries.c b/src/output/pe_output_mdso_libraries.c index c668564..049cd4e 100644 --- a/src/output/pe_output_mdso_libraries.c +++ b/src/output/pe_output_mdso_libraries.c @@ -92,7 +92,7 @@ static char * dsolib_name(const struct pe_image_meta * m, int i) rva = va - m->m_opt.oh_mem.coh_image_base; } - if (pe_get_roffset_from_rva(m,(uint32_t)rva,&roffset) < 0) + if (pe_meta_get_roffset_from_rva(m,(uint32_t)rva,&roffset) < 0) return 0; return (addr = m->r_image.map_addr) + roffset; @@ -117,14 +117,14 @@ static unsigned char * dsosym_meta(const struct pe_image_meta * m, int j) rva = va; } - if ((idx = pe_get_named_section_index(m,MDSO_META_SECTION)) >= 0) - if (idx != pe_get_block_section_index(m,&(struct pe_block){rva,0})) + if ((idx = pe_meta_get_named_section_index(m,MDSO_META_SECTION)) >= 0) + if (idx != pe_meta_get_block_section_index(m,&(struct pe_block){rva,0})) return (unsigned char *)(-1); if (va > rva) return 0; - if (pe_get_roffset_from_rva(m,rva,&roffset) < 0) + if (pe_meta_get_roffset_from_rva(m,rva,&roffset) < 0) return 0; return (unsigned char *)m->r_image.map_addr + roffset; @@ -150,14 +150,14 @@ static char * dsosym_string(const struct pe_image_meta * m, int j) rva = va; } - if ((idx = pe_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0) - if (idx != pe_get_block_section_index(m,&(struct pe_block){rva,0})) + if ((idx = pe_meta_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0) + if (idx != pe_meta_get_block_section_index(m,&(struct pe_block){rva,0})) return (char *)(-2); if (va > rva) return 0; - if (pe_get_roffset_from_rva(m,rva,&roffset) < 0) + if (pe_meta_get_roffset_from_rva(m,rva,&roffset) < 0) return 0; return (addr = m->r_image.map_addr) + roffset; -- cgit v1.2.3