Skip to content

Commit

Permalink
Don't rely on architecture information to get the type of the PLT table
Browse files Browse the repository at this point in the history
The PLT/Jump table can have different entry types depending on the phase
of the moon, the position of the planets, the current weather and other
unpredictable stuff. Normally x86_64 uses RELA entries, and x86 uses REL
entries. But sometimes it doesn't happen, so we need to check the
DT_PLTREL tag to see which one we should use at runtime.

This method is more reliable than assuming that 64 bits means RELA and
32 bits mean REL.
  • Loading branch information
pablogsal committed Apr 12, 2022
1 parent 8cd4ec0 commit 769ad88
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
31 changes: 29 additions & 2 deletions src/memray/_memray/elf_shenanigans.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ overwrite_elf_table(
#undef FOR_EACH_HOOKED_FUNCTION
}

static Sxword
get_jump_table_type(const Dyn* dynamic_section)
{
// The PLT/Jump table can have different entry types depending on the
// phase of the moon, the position of the planets, the current weather
// and other unpredictable stuff. Normally x86_64 uses RELA entries,
// and x86 uses REL entries. But sometimes it doesn't happen, so we need
// to check the DT_PLTREL tag to see which one we should use at runtime.
for (; dynamic_section->d_tag != DT_NULL; ++dynamic_section) {
if (dynamic_section->d_tag != DT_PLTREL) {
continue;
}
return dynamic_section->d_un.d_val;
}
return 0;
}

static void
patch_symbols(const Dyn* dyn_info_struct, const Addr base, bool restore_original) noexcept
{
Expand Down Expand Up @@ -119,8 +136,18 @@ patch_symbols(const Dyn* dyn_info_struct, const Addr base, bool restore_original
overwrite_elf_table(relas_relocations_table, symbols, base, restore_original);

LOG(DEBUG) << "Patching symbols with JMPRELS relocation type";
JmprelTable jmprels_relocations_table(dyn_info_struct);
overwrite_elf_table(jmprels_relocations_table, symbols, base, restore_original);
switch (get_jump_table_type(dyn_info_struct)) {
case DT_REL: {
JmpRelTable jmp_relocations_table(dyn_info_struct);
overwrite_elf_table(jmp_relocations_table, symbols, base, restore_original);
} break;
case DT_RELA: {
JmpRelaTable jmp_relocations_table(dyn_info_struct);
overwrite_elf_table(jmp_relocations_table, symbols, base, restore_original);
} break;
default:
LOG(ERROR) << "Unknown JMPRELS relocation table type";
}
}

static int
Expand Down
7 changes: 3 additions & 4 deletions src/memray/_memray/elf_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
# define ELF_ST_BIND ELF64_ST_BIND
# endif
# define ELFCLASS_BITS 64
# define Elf_Rela ElfW(Rela)
typedef uint64_t bloom_el_t;
#else
# define ELF_R_SYM ELF32_R_SYM
Expand All @@ -25,7 +24,6 @@ typedef uint64_t bloom_el_t;
# endif
# define ELFCLASS_BITS 32
typedef uint32_t bloom_el_t;
# define Elf_Rela ElfW(Rel)
#endif

/* Utility classes and definitons */
Expand Down Expand Up @@ -70,8 +68,9 @@ struct DynamicInfoTable
};

using RelTable = DynamicInfoTable<Rel, DT_REL, DT_RELSZ>;
using RelaTable = DynamicInfoTable<Elf_Rela, DT_RELA, DT_RELASZ>;
using JmprelTable = DynamicInfoTable<Elf_Rela, DT_JMPREL, DT_PLTRELSZ>;
using RelaTable = DynamicInfoTable<Rela, DT_RELA, DT_RELASZ>;
using JmpRelTable = DynamicInfoTable<Rel, DT_JMPREL, DT_PLTRELSZ>;
using JmpRelaTable = DynamicInfoTable<Rela, DT_JMPREL, DT_PLTRELSZ>;

struct SymbolTable
{
Expand Down

0 comments on commit 769ad88

Please sign in to comment.