|
|
feffc7 |
/*****************************************************************************/
|
|
|
feffc7 |
/* pemagination: a (virtual) tour into portable bits and executable bytes */
|
|
|
feffc7 |
/* Copyright (C) 2013,2014,2015 Z. Gilboa */
|
|
|
feffc7 |
/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
|
|
|
feffc7 |
/*****************************************************************************/
|
|
|
feffc7 |
|
|
|
feffc7 |
#include <psxtypes/psxtypes.h>
|
|
|
feffc7 |
#include <pemagine/pemagine.h>
|
|
|
feffc7 |
|
|
|
feffc7 |
/* private args structure */
|
|
|
feffc7 |
struct pe_symbol_name_ctx {
|
|
|
feffc7 |
const void * addr;
|
|
|
feffc7 |
char * name;
|
|
|
feffc7 |
};
|
|
|
feffc7 |
|
|
|
feffc7 |
/* private forward declarations */
|
|
|
feffc7 |
static int pe_enum_exports_callback(
|
|
|
feffc7 |
const void * base,
|
|
|
feffc7 |
struct pe_export_hdr * exp_hdr,
|
|
|
feffc7 |
struct pe_export_sym * sym,
|
|
|
feffc7 |
enum pe_callback_reason reason,
|
|
|
feffc7 |
void * context);
|
|
|
feffc7 |
|
|
|
feffc7 |
#if defined (__NT32)
|
|
|
feffc7 |
static char * pe_get_imported_symbol_info_32(
|
|
|
feffc7 |
const void * sym_addr,
|
|
|
feffc7 |
void ** sym_image_addr,
|
|
|
feffc7 |
char ** sym_name,
|
|
|
feffc7 |
struct pe_ldr_tbl_entry ** ldr_tbl_entry);
|
|
|
feffc7 |
#endif
|
|
|
feffc7 |
|
|
|
feffc7 |
#if defined (__NT64)
|
|
|
feffc7 |
static char * pe_get_imported_symbol_info_64(
|
|
|
feffc7 |
const void * sym_addr,
|
|
|
feffc7 |
void ** sym_image_addr,
|
|
|
feffc7 |
char ** sym_name,
|
|
|
feffc7 |
struct pe_ldr_tbl_entry ** ldr_tbl_entry);
|
|
|
feffc7 |
;
|
|
|
feffc7 |
#endif
|
|
|
feffc7 |
|
|
|
feffc7 |
pe_api
|
|
|
feffc7 |
char * pe_get_symbol_name(const void * base, const void * sym_addr)
|
|
|
feffc7 |
{
|
|
|
feffc7 |
struct pe_export_sym exp_item;
|
|
|
feffc7 |
struct pe_symbol_name_ctx ctx;
|
|
|
feffc7 |
|
|
|
feffc7 |
ctx.name = 0;
|
|
|
feffc7 |
ctx.addr = sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
pe_enum_image_exports(
|
|
|
feffc7 |
base,
|
|
|
feffc7 |
pe_enum_exports_callback,
|
|
|
feffc7 |
&exp_item,
|
|
|
feffc7 |
&ctx;;
|
|
|
feffc7 |
|
|
|
feffc7 |
return ctx.name;
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
|
|
|
feffc7 |
pe_api
|
|
|
feffc7 |
char * pe_get_import_symbol_info(
|
|
|
feffc7 |
const void * sym_addr,
|
|
|
feffc7 |
void ** sym_image_addr,
|
|
|
feffc7 |
char ** sym_name,
|
|
|
feffc7 |
struct pe_ldr_tbl_entry ** ldr_tbl_entry)
|
|
|
feffc7 |
{
|
|
|
feffc7 |
#if defined(__NT32)
|
|
|
feffc7 |
return pe_get_imported_symbol_info_32(
|
|
|
feffc7 |
sym_addr,
|
|
|
feffc7 |
sym_image_addr,
|
|
|
feffc7 |
sym_name,
|
|
|
feffc7 |
ldr_tbl_entry);
|
|
|
feffc7 |
#elif defined (__NT64)
|
|
|
feffc7 |
return pe_get_imported_symbol_info_64(
|
|
|
feffc7 |
sym_addr,
|
|
|
feffc7 |
sym_image_addr,
|
|
|
feffc7 |
sym_name,
|
|
|
feffc7 |
ldr_tbl_entry);
|
|
|
feffc7 |
#endif
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
static int pe_enum_exports_callback(
|
|
|
feffc7 |
const void * base,
|
|
|
feffc7 |
struct pe_export_hdr * exp_hdr,
|
|
|
feffc7 |
struct pe_export_sym * sym,
|
|
|
feffc7 |
enum pe_callback_reason reason,
|
|
|
feffc7 |
void * context)
|
|
|
feffc7 |
{
|
|
|
feffc7 |
struct pe_symbol_name_ctx * ctx;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (reason != PE_CALLBACK_REASON_ITEM)
|
|
|
feffc7 |
return 1;
|
|
|
feffc7 |
|
|
|
feffc7 |
ctx = (struct pe_symbol_name_ctx *)context;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (sym->addr == ctx->addr) {
|
|
|
feffc7 |
ctx->name = sym->name;
|
|
|
feffc7 |
return 0;
|
|
|
feffc7 |
} else
|
|
|
feffc7 |
return 1;
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
|
|
|
feffc7 |
#ifdef __NT32
|
|
|
feffc7 |
static char * pe_get_imported_symbol_info_32(
|
|
|
feffc7 |
const void * sym_addr,
|
|
|
feffc7 |
void ** sym_image_addr,
|
|
|
feffc7 |
char ** sym_name,
|
|
|
feffc7 |
struct pe_ldr_tbl_entry ** ldr_tbl_entry)
|
|
|
feffc7 |
{
|
|
|
feffc7 |
struct symbol {
|
|
|
feffc7 |
unsigned char call;
|
|
|
feffc7 |
unsigned char ds;
|
|
|
feffc7 |
unsigned char sym_addr[4];
|
|
|
feffc7 |
unsigned char padding[2];
|
|
|
feffc7 |
};
|
|
|
feffc7 |
|
|
|
feffc7 |
char * fn_name;
|
|
|
feffc7 |
struct pe_ldr_tbl_entry * mod_info;
|
|
|
feffc7 |
void * mod_base;
|
|
|
feffc7 |
uint32_t *** sym_redirected_addr;
|
|
|
feffc7 |
struct symbol * sym;
|
|
|
feffc7 |
|
|
|
feffc7 |
fn_name = 0;
|
|
|
feffc7 |
mod_info = 0;
|
|
|
feffc7 |
sym = (struct symbol *)sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
if ((sym->call == 0xff) && (sym->ds == 0x25)) {
|
|
|
feffc7 |
sym_redirected_addr = (uint32_t ***)sym->sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (sym_redirected_addr)
|
|
|
feffc7 |
mod_info = pe_get_symbol_module_info(**sym_redirected_addr);
|
|
|
feffc7 |
|
|
|
feffc7 |
if (mod_info)
|
|
|
feffc7 |
mod_base = mod_info->dll_base;
|
|
|
feffc7 |
else
|
|
|
feffc7 |
mod_base = (void *)0;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (mod_base)
|
|
|
feffc7 |
fn_name = pe_get_symbol_name(
|
|
|
feffc7 |
mod_base,
|
|
|
feffc7 |
**sym_redirected_addr);
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
if (fn_name && ldr_tbl_entry)
|
|
|
feffc7 |
*ldr_tbl_entry = mod_info;
|
|
|
feffc7 |
|
|
|
feffc7 |
return fn_name;
|
|
|
feffc7 |
}
|
|
|
feffc7 |
#endif
|
|
|
feffc7 |
|
|
|
feffc7 |
|
|
|
feffc7 |
#ifdef __NT64
|
|
|
feffc7 |
static char * pe_get_imported_symbol_info_64(
|
|
|
feffc7 |
const void * sym_addr,
|
|
|
feffc7 |
void ** sym_image_addr,
|
|
|
feffc7 |
char ** sym_name,
|
|
|
feffc7 |
struct pe_ldr_tbl_entry ** ldr_tbl_entry)
|
|
|
feffc7 |
{
|
|
|
feffc7 |
struct symbol {
|
|
|
feffc7 |
unsigned char call;
|
|
|
feffc7 |
unsigned char ds;
|
|
|
feffc7 |
unsigned char sym_addr[4];
|
|
|
feffc7 |
unsigned char padding[2];
|
|
|
feffc7 |
};
|
|
|
feffc7 |
|
|
|
feffc7 |
char * fn_name;
|
|
|
feffc7 |
struct pe_ldr_tbl_entry * mod_info;
|
|
|
feffc7 |
void * mod_base;
|
|
|
feffc7 |
uint32_t * sym_offset;
|
|
|
feffc7 |
uint32_t offset;
|
|
|
feffc7 |
struct symbol * sym;
|
|
|
feffc7 |
|
|
|
feffc7 |
fn_name = 0;
|
|
|
feffc7 |
mod_info = 0;
|
|
|
feffc7 |
sym = (struct symbol *)sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
if ((sym->call == 0xff) && (sym->ds == 0x25)) {
|
|
|
feffc7 |
sym_offset = (uint32_t *)sym->sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (sym_offset) {
|
|
|
feffc7 |
offset = *sym_offset;
|
|
|
feffc7 |
sym_addr = *(void **)(offset + (uintptr_t)(++sym_offset));
|
|
|
feffc7 |
mod_info = pe_get_symbol_module_info(sym_addr);
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
if (mod_info)
|
|
|
feffc7 |
mod_base = mod_info->dll_base;
|
|
|
feffc7 |
else
|
|
|
feffc7 |
mod_base = (void *)0;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (mod_base)
|
|
|
feffc7 |
fn_name = pe_get_symbol_name(mod_base,sym_addr);
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
if (fn_name) {
|
|
|
feffc7 |
if (ldr_tbl_entry)
|
|
|
feffc7 |
*ldr_tbl_entry = mod_info;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (sym_image_addr)
|
|
|
feffc7 |
*sym_image_addr = (void *)sym_addr;
|
|
|
feffc7 |
|
|
|
feffc7 |
if (sym_name)
|
|
|
feffc7 |
*sym_name = fn_name;
|
|
|
feffc7 |
}
|
|
|
feffc7 |
|
|
|
feffc7 |
return fn_name;
|
|
|
feffc7 |
}
|
|
|
feffc7 |
#endif
|