From 3fb15bd9b50ce54cb990cc75b80624c3b47b026a Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Sat, 4 Jan 2025 15:50:29 +1100 Subject: [PATCH] Split TlsLdToLocalExec relaxation into two This makes it so that we know based on the relaxation what range of bytes it might operate on, which will make changes to linker-diff easier. --- libwild/src/x86_64.rs | 8 ++++++++ linker-utils/src/x86_64.rs | 33 +++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libwild/src/x86_64.rs b/libwild/src/x86_64.rs index 3691588..e80ed23 100644 --- a/libwild/src/x86_64.rs +++ b/libwild/src/x86_64.rs @@ -254,6 +254,14 @@ impl crate::arch::Relaxation for Relaxation { } object::elf::R_X86_64_TLSLD if output_kind.is_executable() => { if section_bytes.get(offset - 3..offset)? == [0x48, 0x8d, 0x3d] { + if section_bytes.get(offset + 4..offset + 6) == Some(&[0x48, 0xb8]) { + // The previous instruction was 64 bit, so we use a slightly different + // relaxation with extra padding. + return create( + RelaxationKind::TlsLdToLocalExec64, + object::elf::R_X86_64_NONE, + ); + } return create(RelaxationKind::TlsLdToLocalExec, object::elf::R_X86_64_NONE); } } diff --git a/linker-utils/src/x86_64.rs b/linker-utils/src/x86_64.rs index d453a6b..1dccc84 100644 --- a/linker-utils/src/x86_64.rs +++ b/linker-utils/src/x86_64.rs @@ -36,6 +36,10 @@ pub enum RelaxationKind { /// Transform local dynamic (LD) into local exec. TlsLdToLocalExec, + /// Transform local dynamic (LD) into local exec with extra padding because the previous + /// instruction was 64 bit. + TlsLdToLocalExec64, + /// Transform general dynamic (GD) into initial exec TlsGdToInitialExec, } @@ -119,22 +123,19 @@ impl RelaxationKind { *next_modifier = RelocationModifier::SkipNextRelocation; } RelaxationKind::TlsLdToLocalExec => { - // Transforms to: `mov %fs:0x0,%rax` with some amount of padding depending on - // whether the subsequent instruction is 64 bit (first) or 32 bit (second). - if section_bytes.get(offset + 4..offset + 6) == Some(&[0x48, 0xb8]) { - section_bytes[offset - 3..offset + 19].copy_from_slice(&[ - // nopw (%rax,%rax) - 0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, - // mov %fs:0,%rax - 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, - ]); - *offset_in_section += 15; - } else { - section_bytes[offset - 3..offset + 9].copy_from_slice(&[ - 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, - ]); - *offset_in_section += 5; - } + section_bytes[offset - 3..offset + 9] + .copy_from_slice(&[0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0]); + *offset_in_section += 5; + *next_modifier = RelocationModifier::SkipNextRelocation; + } + RelaxationKind::TlsLdToLocalExec64 => { + section_bytes[offset - 3..offset + 19].copy_from_slice(&[ + // nopw (%rax,%rax) + 0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, + // mov %fs:0,%rax + 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, + ]); + *offset_in_section += 15; *next_modifier = RelocationModifier::SkipNextRelocation; } RelaxationKind::NoOp => {}