mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 15:28:11 +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/Optional.h>
|
||||||
#include <AK/QuickSort.h>
|
#include <AK/QuickSort.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||||
#include <LibELF/DynamicLinker.h>
|
#include <LibELF/DynamicLinker.h>
|
||||||
#include <LibELF/DynamicLoader.h>
|
#include <LibELF/DynamicLoader.h>
|
||||||
#include <LibELF/Hashes.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.
|
// If the object is position-independent, the pointer to the PLT trampoline needs to be relocated.
|
||||||
auto fixup_trampoline_pointer = [&](DynamicObject::Relocation const& relocation) {
|
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())
|
if (image().is_dynamic())
|
||||||
*((FlatPtr*)relocation.address().as_ptr()) += m_dynamic_object->base_address().get();
|
*((FlatPtr*)relocation.address().as_ptr()) += m_dynamic_object->base_address().get();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_dynamic_object->plt_relocation_section().for_each_relocation([&](DynamicObject::Relocation const& relocation) {
|
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);
|
m_direct_ifunc_relocations.append(relocation);
|
||||||
return;
|
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
|
// GNU ld for some reason puts TLSDESC relocations into .rela.plt
|
||||||
// https://sourceware.org/bugzilla/show_bug.cgi?id=28387
|
// 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 };
|
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?
|
// Apparently most loaders will just skip these?
|
||||||
// Seems if the 'link editor' generates one something is funky with your code
|
// Seems if the 'link editor' generates one something is funky with your code
|
||||||
break;
|
break;
|
||||||
case R_AARCH64_ABS64:
|
case ABSOLUTE: {
|
||||||
case R_X86_64_64: {
|
|
||||||
auto symbol = relocation.symbol();
|
auto symbol = relocation.symbol();
|
||||||
auto res = lookup_symbol(symbol);
|
auto res = lookup_symbol(symbol);
|
||||||
if (!res.has_value()) {
|
if (!res.has_value()) {
|
||||||
|
@ -602,8 +603,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
*patch_ptr = call_ifunc_resolver(VirtualAddress { *patch_ptr }).get();
|
*patch_ptr = call_ifunc_resolver(VirtualAddress { *patch_ptr }).get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_AARCH64_GLOB_DAT:
|
case GLOB_DAT: {
|
||||||
case R_X86_64_GLOB_DAT: {
|
|
||||||
auto symbol = relocation.symbol();
|
auto symbol = relocation.symbol();
|
||||||
auto res = lookup_symbol(symbol);
|
auto res = lookup_symbol(symbol);
|
||||||
VirtualAddress symbol_location;
|
VirtualAddress symbol_location;
|
||||||
|
@ -633,8 +633,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
*patch_ptr = symbol_location.get();
|
*patch_ptr = symbol_location.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_AARCH64_RELATIVE:
|
case RELATIVE: {
|
||||||
case R_X86_64_RELATIVE: {
|
|
||||||
if (!image().is_dynamic())
|
if (!image().is_dynamic())
|
||||||
break;
|
break;
|
||||||
// FIXME: According to the spec, R_386_relative ones must be done first.
|
// 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();
|
*patch_ptr += m_dynamic_object->base_address().get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_AARCH64_TLS_TPREL:
|
case TLS_TPREL: {
|
||||||
case R_X86_64_TPOFF64: {
|
|
||||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||||
if (!maybe_resolution.has_value())
|
if (!maybe_resolution.has_value())
|
||||||
break;
|
break;
|
||||||
|
@ -660,7 +658,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
VERIFY(static_cast<ssize_t>(*patch_ptr) < 0);
|
VERIFY(static_cast<ssize_t>(*patch_ptr) < 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_X86_64_DTPMOD64: {
|
case TLS_DTPMOD: {
|
||||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||||
if (!maybe_resolution.has_value())
|
if (!maybe_resolution.has_value())
|
||||||
break;
|
break;
|
||||||
|
@ -670,7 +668,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
*patch_ptr = maybe_resolution->dynamic_object.tls_offset().value();
|
*patch_ptr = maybe_resolution->dynamic_object.tls_offset().value();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_X86_64_DTPOFF64: {
|
case TLS_DTPREL: {
|
||||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||||
if (!maybe_resolution.has_value())
|
if (!maybe_resolution.has_value())
|
||||||
break;
|
break;
|
||||||
|
@ -680,7 +678,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef HAS_TLSDESC_SUPPORT
|
#ifdef HAS_TLSDESC_SUPPORT
|
||||||
case R_AARCH64_TLSDESC: {
|
case TLSDESC: {
|
||||||
auto maybe_resolution = resolve_tls_symbol(relocation);
|
auto maybe_resolution = resolve_tls_symbol(relocation);
|
||||||
if (!maybe_resolution.has_value())
|
if (!maybe_resolution.has_value())
|
||||||
break;
|
break;
|
||||||
|
@ -693,8 +691,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case R_AARCH64_IRELATIVE:
|
case IRELATIVE: {
|
||||||
case R_X86_64_IRELATIVE: {
|
|
||||||
if (should_call_ifunc_resolver == ShouldCallIfuncResolver::No)
|
if (should_call_ifunc_resolver == ShouldCallIfuncResolver::No)
|
||||||
return RelocationResult::CallIfuncResolver;
|
return RelocationResult::CallIfuncResolver;
|
||||||
VirtualAddress resolver;
|
VirtualAddress resolver;
|
||||||
|
@ -711,8 +708,7 @@ DynamicLoader::RelocationResult DynamicLoader::do_direct_relocation(DynamicObjec
|
||||||
*patch_ptr = call_ifunc_resolver(resolver).get();
|
*patch_ptr = call_ifunc_resolver(resolver).get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_AARCH64_JUMP_SLOT:
|
case JUMP_SLOT:
|
||||||
case R_X86_64_JUMP_SLOT:
|
|
||||||
VERIFY_NOT_REACHED(); // PLT relocations are handled by do_plt_relocation.
|
VERIFY_NOT_REACHED(); // PLT relocations are handled by do_plt_relocation.
|
||||||
default:
|
default:
|
||||||
// Raise the alarm! Someone needs to implement this relocation type
|
// 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)
|
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 symbol = relocation.symbol();
|
||||||
auto* relocation_address = (FlatPtr*)relocation.address().as_ptr();
|
auto* relocation_address = (FlatPtr*)relocation.address().as_ptr();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <AK/Concepts.h>
|
#include <AK/Concepts.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <Kernel/Memory/VirtualAddress.h>
|
#include <Kernel/Memory/VirtualAddress.h>
|
||||||
|
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||||
#include <LibELF/ELFABI.h>
|
#include <LibELF/ELFABI.h>
|
||||||
#include <link.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) {
|
for (unsigned i = 0; i < relocation_count(); ++i) {
|
||||||
auto const reloc = relocation(i);
|
auto const reloc = relocation(i);
|
||||||
if (reloc.type() == 0)
|
if (static_cast<GenericDynamicRelocationType>(reloc.type()) == GenericDynamicRelocationType::NONE)
|
||||||
continue;
|
continue;
|
||||||
if (func(reloc) == IterationDecision::Break)
|
if (func(reloc) == IterationDecision::Break)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibELF/Arch/GenericDynamicRelocationType.h>
|
||||||
#include <LibELF/ELFABI.h>
|
#include <LibELF/ELFABI.h>
|
||||||
#include <LibELF/Relocation.h>
|
#include <LibELF/Relocation.h>
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ bool perform_relative_relocations(FlatPtr base_address)
|
||||||
for (unsigned i = 0; i < relocation_count; ++i) {
|
for (unsigned i = 0; i < relocation_count; ++i) {
|
||||||
size_t offset_in_section = i * relocation_entry_size;
|
size_t offset_in_section = i * relocation_entry_size;
|
||||||
auto* relocation = (Elf_Rela*)(relocation_section_addr + offset_in_section);
|
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);
|
auto* patch_address = (FlatPtr*)(base_address + relocation->r_offset);
|
||||||
FlatPtr relocated_address;
|
FlatPtr relocated_address;
|
||||||
if (use_addend) {
|
if (use_addend) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue