diff --git a/gum/gumelfmodule.c b/gum/gumelfmodule.c index 6845555ca..ba794d3b1 100644 --- a/gum/gumelfmodule.c +++ b/gum/gumelfmodule.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2023 Ole André Vadla Ravnås + * Copyright (C) 2010-2024 Ole André Vadla Ravnås * Copyright (C) 2019 Jon Wilson * Copyright (C) 2021 Paul Schmidt * @@ -124,6 +124,9 @@ struct _GumElfEnumerateImportsContext { GumFoundImportFunc func; gpointer user_data; + + GHashTable * slots; + guint32 jump_slot_type; }; struct _GumElfEnumerateExportsContext @@ -177,6 +180,10 @@ static gboolean gum_elf_module_emit_relocations (GumElfModule * self, gpointer user_data); static gboolean gum_emit_elf_import (const GumElfSymbolDetails * details, gpointer user_data); +static gboolean gum_try_get_jump_slot_relocation_type_for_machine ( + GumElfMachine machine, guint32 * type); +static gboolean gum_maybe_collect_import_slot_from_relocation ( + const GumElfRelocationDetails * details, gpointer user_data); static gboolean gum_emit_elf_export (const GumElfSymbolDetails * details, gpointer user_data); static void gum_elf_module_parse_symbol (GumElfModule * self, @@ -1397,6 +1404,8 @@ gum_elf_module_emit_relocations (GumElfModule * self, g_assert_not_reached (); } + d.address = gum_elf_module_translate_to_online (self, d.address); + if (sym_index != GUM_STN_UNDEF) { gconstpointer sym_start, sym_end; @@ -1473,7 +1482,17 @@ gum_elf_module_enumerate_imports (GumElfModule * self, ctx.func = func; ctx.user_data = user_data; + ctx.slots = g_hash_table_new (g_str_hash, g_str_equal); + if (gum_try_get_jump_slot_relocation_type_for_machine (self->ehdr.machine, + &ctx.jump_slot_type)) + { + gum_elf_module_enumerate_relocations (self, + gum_maybe_collect_import_slot_from_relocation, &ctx); + } + gum_elf_module_enumerate_dynamic_symbols (self, gum_emit_elf_import, &ctx); + + g_hash_table_unref (ctx.slots); } static gboolean @@ -1494,7 +1513,7 @@ gum_emit_elf_import (const GumElfSymbolDetails * details, d.name = details->name; d.module = NULL; d.address = 0; - d.slot = 0; /* TODO */ + d.slot = GUM_ADDRESS (g_hash_table_lookup (ctx->slots, details->name)); if (!ctx->func (&d, ctx->user_data)) return FALSE; @@ -1503,6 +1522,53 @@ gum_emit_elf_import (const GumElfSymbolDetails * details, return TRUE; } +static gboolean +gum_try_get_jump_slot_relocation_type_for_machine (GumElfMachine machine, + guint32 * type) +{ + switch (machine) + { + case GUM_ELF_MACHINE_386: + *type = GUM_ELF_IA32_JMP_SLOT; + break; + case GUM_ELF_MACHINE_X86_64: + *type = GUM_ELF_X64_JUMP_SLOT; + break; + case GUM_ELF_MACHINE_ARM: + *type = GUM_ELF_ARM_JUMP_SLOT; + break; + case GUM_ELF_MACHINE_AARCH64: + *type = GUM_ELF_ARM64_JUMP_SLOT; + break; + case GUM_ELF_MACHINE_MIPS: + case GUM_ELF_MACHINE_MIPS_RS3_LE: + case GUM_ELF_MACHINE_MIPS_X: + *type = GUM_ELF_MIPS_JUMP_SLOT; + break; + default: + *type = G_MAXUINT32; + return FALSE; + } + + return TRUE; +} + +static gboolean +gum_maybe_collect_import_slot_from_relocation ( + const GumElfRelocationDetails * details, + gpointer user_data) +{ + GumElfEnumerateImportsContext * ctx = user_data; + + if (details->type == ctx->jump_slot_type && details->symbol != NULL) + { + g_hash_table_insert (ctx->slots, (gpointer) details->symbol->name, + GSIZE_TO_POINTER (details->address)); + } + + return TRUE; +} + void gum_elf_module_enumerate_exports (GumElfModule * self, GumFoundExportFunc func, diff --git a/tests/core/process.c b/tests/core/process.c index b46db3bf2..16893ff52 100644 --- a/tests/core/process.c +++ b/tests/core/process.c @@ -733,12 +733,14 @@ TESTCASE (module_import_slot_should_contain_correct_value) unsupported_on_this_os = slot == NULL; if (unsupported_on_this_os) + { + g_print (" "); return; + } - actual_value = - gum_strip_code_address (GPOINTER_TO_SIZE (*slot)); - expected_value = - gum_strip_code_address (gum_module_find_export_by_name (NULL, "malloc")); + actual_value = gum_strip_code_address (GPOINTER_TO_SIZE (*slot)); + expected_value = gum_strip_code_address (gum_module_find_export_by_name ( + gum_process_query_libc_name (), "malloc")); g_assert_cmphex (actual_value, ==, expected_value); }