Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split TlsLdToLocalExec relaxation into two #279

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions libwild/src/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
33 changes: 17 additions & 16 deletions linker-utils/src/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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 => {}
Expand Down