mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:14:58 +00:00
LibELF: Refactor how arch-specific dynamic relocation types are handled
We currently expect that the relocation type numbers are unique across all architectures. But RISC-V and x86_64 use the same numbers for different relocation types (R_X86_64_COPY = R_RISCV_JUMP_SLOT = 5). So create a generic reloc type enum which maps to the arch-specific reloc types instead of checking for all arch reloc types individually everywhere.
This commit is contained in:
parent
c216e7439f
commit
f8628f94b8
6 changed files with 98 additions and 23 deletions
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Platform.h>
|
||||
|
||||
#if ARCH(AARCH64)
|
||||
# include <Userland/Libraries/LibELF/Arch/aarch64/GenericDynamicRelocationType.h>
|
||||
#elif ARCH(X86_64)
|
||||
# include <Userland/Libraries/LibELF/Arch/x86_64/GenericDynamicRelocationType.h>
|
||||
#else
|
||||
# error Unknown architecture
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Userland/Libraries/LibELF/ELFABI.h>
|
||||
|
||||
#include <AK/Platform.h>
|
||||
VALIDATE_IS_AARCH64()
|
||||
|
||||
namespace ELF {
|
||||
|
||||
enum class GenericDynamicRelocationType : unsigned {
|
||||
NONE = R_AARCH64_NONE,
|
||||
ABSOLUTE = R_AARCH64_ABS64,
|
||||
COPY = R_AARCH64_COPY,
|
||||
GLOB_DAT = R_AARCH64_GLOB_DAT,
|
||||
JUMP_SLOT = R_AARCH64_JUMP_SLOT,
|
||||
RELATIVE = R_AARCH64_RELATIVE,
|
||||
TLS_DTPMOD = R_AARCH64_TLS_DTPMOD,
|
||||
TLS_DTPREL = R_AARCH64_TLS_DTPREL,
|
||||
TLS_TPREL = R_AARCH64_TLS_TPREL,
|
||||
TLSDESC = R_AARCH64_TLSDESC,
|
||||
IRELATIVE = R_AARCH64_IRELATIVE,
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Userland/Libraries/LibELF/ELFABI.h>
|
||||
|
||||
#include <AK/Platform.h>
|
||||
VALIDATE_IS_X86()
|
||||
|
||||
namespace ELF {
|
||||
|
||||
enum class GenericDynamicRelocationType : unsigned {
|
||||
NONE = R_X86_64_NONE,
|
||||
ABSOLUTE = R_X86_64_64,
|
||||
COPY = R_X86_64_COPY,
|
||||
GLOB_DAT = R_X86_64_GLOB_DAT,
|
||||
JUMP_SLOT = R_X86_64_JUMP_SLOT,
|
||||
RELATIVE = R_X86_64_RELATIVE,
|
||||
TLS_DTPMOD = R_X86_64_DTPMOD64,
|
||||
TLS_DTPREL = R_X86_64_DTPOFF64,
|
||||
TLS_TPREL = R_X86_64_TPOFF64,
|
||||
TLSDESC = R_X86_64_TLSDESC,
|
||||
IRELATIVE = R_X86_64_IRELATIVE,
|
||||
};
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include <AK/Optional.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||
#include <LibELF/DynamicLinker.h>
|
||||
#include <LibELF/DynamicLoader.h>
|
||||
#include <LibELF/Hashes.h>
|
||||
|
@ -228,17 +229,17 @@ void DynamicLoader::do_main_relocations()
|
|||
|
||||
// If the object is position-independent, the pointer to the PLT trampoline needs to be relocated.
|
||||
auto fixup_trampoline_pointer = [&](DynamicObject::Relocation const& relocation) {
|
||||
VERIFY(relocation.type() == R_X86_64_JUMP_SLOT || relocation.type() == R_AARCH64_JUMP_SLOT);
|
||||
VERIFY(static_cast<GenericDynamicRelocationType>(relocation.type()) == GenericDynamicRelocationType::JUMP_SLOT);
|
||||
if (image().is_dynamic())
|
||||
*((FlatPtr*)relocation.address().as_ptr()) += m_dynamic_object->base_address().get();
|
||||
};
|
||||
|
||||
m_dynamic_object->plt_relocation_section().for_each_relocation([&](DynamicObject::Relocation const& relocation) {
|
||||
if (relocation.type() == R_X86_64_IRELATIVE || relocation.type() == R_AARCH64_IRELATIVE) {
|
||||
if (static_cast<GenericDynamicRelocationType>(relocation.type()) == GenericDynamicRelocationType::IRELATIVE) {
|
||||
m_direct_ifunc_relocations.append(relocation);
|
||||
return;
|
||||
}
|
||||
if (relocation.type() == R_X86_64_TLSDESC || relocation.type() == R_AARCH64_TLSDESC) {
|
||||
if (static_cast<GenericDynamicRelocationType>(relocation.type()) == GenericDynamicRelocationType::TLSDESC) {
|
||||
// GNU ld for some reason puts TLSDESC relocations into .rela.plt
|
||||
// https://sourceware.org/bugzilla/show_bug.cgi?id=28387
|
||||
|
||||
|
@ -574,14 +575,14 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
return ResolvedTLSSymbol { *res.value().dynamic_object, res.value().value };
|
||||
};
|
||||
|
||||
switch (relocation.type()) {
|
||||
using enum GenericDynamicRelocationType;
|
||||
switch (static_cast<GenericDynamicRelocationType>(relocation.type())) {
|
||||
|
||||
case R_X86_64_NONE:
|
||||
case NONE:
|
||||
// Apparently most loaders will just skip these?
|
||||
// Seems if the 'link editor' generates one something is funky with your code
|
||||
break;
|
||||
case R_AARCH64_ABS64:
|
||||
case R_X86_64_64: {
|
||||
case ABSOLUTE: {
|
||||
auto symbol = relocation.symbol();
|
||||
auto res = lookup_symbol(symbol);
|
||||
if (!res.has_value()) {
|
||||
|
@ -602,8 +603,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
*patch_ptr = call_ifunc_resolver(VirtualAddress { *patch_ptr }).get();
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_GLOB_DAT:
|
||||
case R_X86_64_GLOB_DAT: {
|
||||
case GLOB_DAT: {
|
||||
auto symbol = relocation.symbol();
|
||||
auto res = lookup_symbol(symbol);
|
||||
VirtualAddress symbol_location;
|
||||
|
@ -633,8 +633,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
*patch_ptr = symbol_location.get();
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_RELATIVE:
|
||||
case R_X86_64_RELATIVE: {
|
||||
case RELATIVE: {
|
||||
if (!image().is_dynamic())
|
||||
break;
|
||||
// FIXME: According to the spec, R_386_relative ones must be done first.
|
||||
|
@ -646,8 +645,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
*patch_ptr += m_dynamic_object->base_address().get();
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_TLS_TPREL:
|
||||
case R_X86_64_TPOFF64: {
|
||||
case TLS_TPREL: {
|
||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||
if (!maybe_resolution.has_value())
|
||||
break;
|
||||
|
@ -660,7 +658,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
VERIFY(static_cast<ssize_t>(*patch_ptr) < 0);
|
||||
break;
|
||||
}
|
||||
case R_X86_64_DTPMOD64: {
|
||||
case TLS_DTPMOD: {
|
||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||
if (!maybe_resolution.has_value())
|
||||
break;
|
||||
|
@ -670,7 +668,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
*patch_ptr = maybe_resolution->dynamic_object.tls_offset().value();
|
||||
break;
|
||||
}
|
||||
case R_X86_64_DTPOFF64: {
|
||||
case TLS_DTPREL: {
|
||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||
if (!maybe_resolution.has_value())
|
||||
break;
|
||||
|
@ -680,7 +678,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
break;
|
||||
}
|
||||
#ifdef HAS_TLSDESC_SUPPORT
|
||||
case R_AARCH64_TLSDESC: {
|
||||
case TLSDESC: {
|
||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||
if (!maybe_resolution.has_value())
|
||||
break;
|
||||
|
@ -693,8 +691,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
case R_AARCH64_IRELATIVE:
|
||||
case R_X86_64_IRELATIVE: {
|
||||
case IRELATIVE: {
|
||||
if (should_call_ifunc_resolver == ShouldCallIfuncResolver::No)
|
||||
return RelocationResult::CallIfuncResolver;
|
||||
VirtualAddress resolver;
|
||||
|
@ -711,8 +708,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
*patch_ptr = call_ifunc_resolver(resolver).get();
|
||||
break;
|
||||
}
|
||||
case R_AARCH64_JUMP_SLOT:
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
case JUMP_SLOT:
|
||||
VERIFY_NOT_REACHED(); // PLT relocations are handled by do_plt_relocation.
|
||||
default:
|
||||
// Raise the alarm! Someone needs to implement this relocation type
|
||||
|
@ -724,7 +720,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
|||
|
||||
DynamicLoader::RelocationResult DynamicLoader::do_plt_relocation(DynamicObject::Relocation const& relocation, ShouldCallIfuncResolver should_call_ifunc_resolver)
|
||||
{
|
||||
VERIFY(relocation.type() == R_X86_64_JUMP_SLOT || relocation.type() == R_AARCH64_JUMP_SLOT);
|
||||
VERIFY(static_cast<GenericDynamicRelocationType>(relocation.type()) == GenericDynamicRelocationType::JUMP_SLOT);
|
||||
auto symbol = relocation.symbol();
|
||||
auto* relocation_address = (FlatPtr*)relocation.address().as_ptr();
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <AK/Concepts.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <Kernel/Memory/VirtualAddress.h>
|
||||
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||
#include <LibELF/ELFABI.h>
|
||||
#include <link.h>
|
||||
|
||||
|
@ -402,7 +403,7 @@ inline void DynamicObject::RelocationSection::for_each_relocation(F func) const
|
|||
{
|
||||
for (unsigned i = 0; i < relocation_count(); ++i) {
|
||||
auto const reloc = relocation(i);
|
||||
if (reloc.type() == 0)
|
||||
if (static_cast<GenericDynamicRelocationType>(reloc.type()) == GenericDynamicRelocationType::NONE)
|
||||
continue;
|
||||
if (func(reloc) == IterationDecision::Break)
|
||||
break;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||
#include <LibELF/ELFABI.h>
|
||||
#include <LibELF/Relocation.h>
|
||||
|
||||
|
@ -59,7 +60,7 @@ bool perform_relative_relocations(FlatPtr base_address)
|
|||
for (unsigned i = 0; i < relocation_count; ++i) {
|
||||
size_t offset_in_section = i * relocation_entry_size;
|
||||
auto* relocation = (Elf_Rela*)(relocation_section_addr + offset_in_section);
|
||||
VERIFY(ELF64_R_TYPE(relocation->r_info) == R_X86_64_RELATIVE || ELF64_R_TYPE(relocation->r_info) == R_AARCH64_RELATIVE);
|
||||
VERIFY(static_cast<GenericDynamicRelocationType>(ELF64_R_TYPE(relocation->r_info)) == GenericDynamicRelocationType::RELATIVE);
|
||||
auto* patch_address = (FlatPtr*)(base_address + relocation->r_offset);
|
||||
FlatPtr relocated_address;
|
||||
if (use_addend) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue