Blame src/meta/pe_get_symbol_name.c

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
#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