Blame src/meta/pe_get_symbol_name.c

feffc7
/*****************************************************************************/
feffc7
/*  pemagination: a (virtual) tour into portable bits and executable bytes   */
740419
/*  Copyright (C) 2013--2020  Z. Gilboa                                      */
feffc7
/*  Released under GPLv2 and GPLv3; see COPYING.PEMAGINE.                    */
feffc7
/*****************************************************************************/
feffc7
feffc7
#include <psxtypes/psxtypes.h>
feffc7
#include <pemagine/pemagine.h>
feffc7
22d157
feffc7
struct pe_symbol_name_ctx {
feffc7
	const void *	addr;
feffc7
	char *		name;
feffc7
};
feffc7
feffc7
static int pe_enum_exports_callback(
feffc7
	const void *			base,
149cda
	struct pe_raw_export_hdr *	exp_hdr,
feffc7
	struct pe_export_sym *		sym,
feffc7
	enum pe_callback_reason		reason,
feffc7
	void *				context);
feffc7
034d8a
#if (__SIZEOF_POINTER__ == 4)
feffc7
static char * pe_get_imported_symbol_info_32(
feffc7
	const void *			sym_addr,
feffc7
	struct pe_ldr_tbl_entry **	ldr_tbl_entry);
feffc7
#endif
feffc7
034d8a
#if (__SIZEOF_POINTER__ == 8)
feffc7
static char * pe_get_imported_symbol_info_64(
feffc7
	const void *			sym_addr,
feffc7
	struct pe_ldr_tbl_entry **	ldr_tbl_entry);
feffc7
#endif
feffc7
22d157
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
char * pe_get_import_symbol_info(
feffc7
	const void *			sym_addr,
feffc7
	struct pe_ldr_tbl_entry **	ldr_tbl_entry)
feffc7
{
034d8a
	#if (__SIZEOF_POINTER__ == 4)
feffc7
		return pe_get_imported_symbol_info_32(
feffc7
			sym_addr,
feffc7
			ldr_tbl_entry);
034d8a
	#elif (__SIZEOF_POINTER__ == 8)
feffc7
		return pe_get_imported_symbol_info_64(
feffc7
			sym_addr,
feffc7
			ldr_tbl_entry);
feffc7
	#endif
feffc7
}
feffc7
feffc7
static int pe_enum_exports_callback(
feffc7
	const void *			base,
149cda
	struct pe_raw_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
90e9fb
	(void)base;
90e9fb
	(void)exp_hdr;
90e9fb
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
034d8a
#if (__SIZEOF_POINTER__ == 4)
feffc7
static char * pe_get_imported_symbol_info_32(
feffc7
	const void *			sym_addr,
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
	sym = (struct symbol *)sym_addr;
feffc7
18fa18
	if ((sym->call == 0xff) && (sym->ds == 0x25))
18fa18
		if ((sym_redirected_addr = (uint32_t ***)sym->sym_addr))
18fa18
			if ((mod_info = pe_get_symbol_module_info(
18fa18
					**sym_redirected_addr)))
18fa18
				if ((mod_base = mod_info->dll_base))
18fa18
					fn_name = pe_get_symbol_name(
18fa18
						mod_base,
18fa18
						**sym_redirected_addr);
feffc7
	if (fn_name && ldr_tbl_entry)
feffc7
		*ldr_tbl_entry = mod_info;
feffc7
feffc7
	return fn_name;
feffc7
}
feffc7
#endif
feffc7
feffc7
034d8a
#if (__SIZEOF_POINTER__ == 8)
feffc7
static char * pe_get_imported_symbol_info_64(
feffc7
	const void *			sym_addr,
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;
ae151a
	mod_info = 0;
feffc7
	sym = (struct symbol *)sym_addr;
feffc7
feffc7
	if ((sym->call == 0xff) && (sym->ds == 0x25)) {
92222c
		if ((sym_offset = (uint32_t *)sym->sym_addr)) {
92222c
			offset   = *sym_offset;
92222c
			sym_addr = *(void **)(offset + (uintptr_t)(++sym_offset));
92222c
		} else
92222c
			sym_addr = 0;
92222c
92222c
		if (sym_addr && (mod_info = pe_get_symbol_module_info(sym_addr)))
92222c
			if ((mod_base = mod_info->dll_base))
92222c
				fn_name = pe_get_symbol_name(
92222c
					mod_base,
92222c
					sym_addr);
feffc7
	}
feffc7
92222c
	if (fn_name && ldr_tbl_entry)
92222c
		*ldr_tbl_entry = mod_info;
feffc7
feffc7
	return fn_name;
feffc7
}
feffc7
#endif