summaryrefslogtreecommitdiffhomepage
path: root/src/exports
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-11-23 01:56:25 +0000
committermidipix <writeonce@midipix.org>2017-11-22 21:14:26 -0500
commit3a98444aaf3f7c041228ddd1f29644b2ea56eb3b (patch)
tree95e2ecb60ed26982260fd80faaa9b003ec4ad4d3 /src/exports
parentdf8ec546a7ee587892063695f0a5942add2678a9 (diff)
downloadpemagine-3a98444aaf3f7c041228ddd1f29644b2ea56eb3b.tar.bz2
pemagine-3a98444aaf3f7c041228ddd1f29644b2ea56eb3b.tar.xz
pe_get_export_symbol_info(): integrated pe_resolve_forwarder_rva().
Diffstat (limited to 'src/exports')
-rw-r--r--src/exports/pe_get_export_symbol_info.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/src/exports/pe_get_export_symbol_info.c b/src/exports/pe_get_export_symbol_info.c
index c933cee..d0cef88 100644
--- a/src/exports/pe_get_export_symbol_info.c
+++ b/src/exports/pe_get_export_symbol_info.c
@@ -15,6 +15,47 @@ static __inline__ int pe_addr_within_bounds(void * addr, void * bottom, void * t
return (((uintptr_t)addr >= (uintptr_t)bottom) && ((uintptr_t)addr < (uintptr_t)top));
}
+static void * pe_resolve_forwarder_rva(char * forwarder)
+{
+ uint16_t soname[512];
+ uint16_t * wch;
+ char * mark;
+ char * dot;
+ void * base;
+
+ for (mark=forwarder; *mark; mark++)
+ (void)0;
+
+ if (mark - forwarder + 5 > 512)
+ return 0;
+
+ for (dot=&mark[-1]; dot>forwarder && *dot!='.'; dot--)
+ (void)0;
+
+ if (*dot != '.')
+ return 0;
+
+ mark = forwarder;
+ wch = soname;
+
+ for (; mark<dot && (unsigned)*mark<0x80; )
+ *wch++ = *mark++;
+
+ if (mark < dot)
+ return 0;
+
+ *wch++ = '.';
+ *wch++ = 'd';
+ *wch++ = 'l';
+ *wch++ = 'l';
+ *wch++ = 0;
+
+ if (!(base = pe_get_module_handle(soname)))
+ return 0;
+
+ return pe_get_procedure_address(base,++dot);
+}
+
int pe_get_export_symbol_info(
const void * base,
const char * name,
@@ -83,11 +124,12 @@ int pe_get_export_symbol_info(
addr_offset = (uintptr_t *)pe_va_from_rva(base,*rva_offset);
if (pe_addr_within_bounds(addr_offset,exp_hdr,sec_addr_cap)) {
+ sym->forwarder_rva = addr_offset;
+ sym->addr = pe_resolve_forwarder_rva((char *)addr_offset);
+ } else {
sym->forwarder_rva = 0;
sym->addr = addr_offset;
- } else
- /* todo: resolve forwarder address */
- sym->addr = addr_offset;
+ }
return 0;
}
@@ -120,9 +162,8 @@ int pe_get_export_symbol_info(
addr_offset = (uintptr_t *)pe_va_from_rva(base,*rva_offset);
if (pe_addr_within_bounds(addr_offset,exp_hdr,sec_addr_cap)) {
- /* todo: resolve forwarder address */
- sym->forwarder_rva = 0;
- sym->addr = 0;
+ sym->forwarder_rva = addr_offset;
+ sym->addr = pe_resolve_forwarder_rva((char *)addr_offset);
} else {
sym->forwarder_rva = 0;
sym->addr = addr_offset;