Skip to content
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
if: ${{ matrix.test-qemu }}
- run: apt-get update && apt-get -y install gcc g++ clang clang-format lld curl bubblewrap
if: ${{ contains(matrix.container, 'ubuntu') }}
- run: apt-get update && apt-get -y install qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-riscv64-linux-gnu g++-riscv64-linux-gnu gcc-loongarch64-linux-gnu g++-loongarch64-linux-gnu binutils-aarch64-linux-gnu binutils-riscv64-linux-gnu binutils-loongarch64-linux-gnu
- run: apt-get update && apt-get -y install qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-riscv64-linux-gnu g++-riscv64-linux-gnu gcc-loongarch64-linux-gnu g++-loongarch64-linux-gnu gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu binutils-aarch64-linux-gnu binutils-riscv64-linux-gnu binutils-loongarch64-linux-gnu binutils-powerpc64le-linux-gnu
if: ${{ matrix.test-qemu }}
- run: zypper refresh && zypper in -y gcc gcc-c++ glibc-devel-static clang lld curl rustup bubblewrap
if: ${{ contains(matrix.container, 'opensuse') }}
Expand All @@ -79,7 +79,7 @@ jobs:
- uses: dtolnay/rust-toolchain@nightly
id: rust-toolchain
with:
targets: x86_64-unknown-linux-gnu,x86_64-unknown-linux-musl,aarch64-unknown-linux-gnu,aarch64-unknown-linux-musl,riscv64gc-unknown-linux-gnu,riscv64gc-unknown-linux-musl,loongarch64-unknown-linux-gnu,loongarch64-unknown-linux-musl
targets: x86_64-unknown-linux-gnu,x86_64-unknown-linux-musl,aarch64-unknown-linux-gnu,aarch64-unknown-linux-musl,riscv64gc-unknown-linux-gnu,riscv64gc-unknown-linux-musl,loongarch64-unknown-linux-gnu,loongarch64-unknown-linux-musl,powerpc64le-unknown-linux-gnu
components: rustc-codegen-cranelift-preview
- uses: wild-linker/action@latest
with:
Expand Down
6 changes: 5 additions & 1 deletion libwild/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ pub(crate) mod perf;
not(target_os = "linux"),
all(
target_os = "linux",
any(target_arch = "riscv64", target_arch = "loongarch64")
any(
target_arch = "riscv64",
target_arch = "loongarch64",
target_arch = "powerpc64"
)
)
))]
#[path = "perf_unsupported.rs"]
Expand Down
2 changes: 2 additions & 0 deletions linker-diff/src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) enum ArchKind {
Aarch64,
RiscV64,
LoongArch64,
Ppc64,
}

/// Provides architecture-specific functionality needed by linker-diff.
Expand Down Expand Up @@ -283,6 +284,7 @@ impl ArchKind {
object::elf::EM_AARCH64 => Ok(ArchKind::Aarch64),
object::elf::EM_RISCV => Ok(ArchKind::RiscV64),
object::elf::EM_LOONGARCH => Ok(ArchKind::LoongArch64),
object::elf::EM_PPC64 => Ok(ArchKind::Ppc64),
other => bail!("Unsupported ELF architecture {other}",),
}
}
Expand Down
5 changes: 5 additions & 0 deletions linker-diff/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mod gnu_hash;
mod header_diff;
mod init_order;
mod loongarch64;
mod ppc64;
mod riscv64;
mod riscv_attributes;
pub(crate) mod section_map;
Expand Down Expand Up @@ -324,6 +325,7 @@ impl Config {
.map(ToOwned::to_owned),
),
ArchKind::X86_64 => {}
ArchKind::Ppc64 => {}
ArchKind::LoongArch64 => self.ignore.extend(
[
"section.sdata",
Expand Down Expand Up @@ -708,6 +710,9 @@ impl Report {
ArchKind::LoongArch64 => {
self.report_arch_specific_diffs::<crate::loongarch64::LoongArch64>(objects);
}
ArchKind::Ppc64 => {
self.report_arch_specific_diffs::<crate::ppc64::Ppc64>(objects);
}
}
}

Expand Down
150 changes: 150 additions & 0 deletions linker-diff/src/ppc64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use crate::ArchKind;
use crate::arch::Arch;
use crate::arch::Instruction;
use crate::arch::Relaxation;
use crate::arch::RelaxationByteRange;
use crate::asm_diff::BasicValueKind;
use crate::utils::decode_insn_with_objdump;
use linker_utils::elf::DynamicRelocationKind;
use linker_utils::elf::RelocationKindInfo;
use linker_utils::elf::ppc64_rel_type_to_string;
use linker_utils::ppc64::RelaxationKind;
use linker_utils::relaxation::RelocationModifier;
use std::fmt::Display;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) struct Ppc64;

impl Arch for Ppc64 {
type RType = RType;
type RelaxationKind = RelaxationKind;
type RawInstruction = Option<String>;

const MAX_RELAX_MODIFY_BEFORE: u64 = 0;
const MAX_RELAX_MODIFY_AFTER: u64 = 0;

fn possible_relaxations_do(
_r_type: Self::RType,
_section_kind: object::SectionKind,
_cb: impl FnMut(Relaxation<Self>),
) {
// No relaxations are implemented for ppc64 yet.
}

fn relaxation_byte_range(_relaxation: Relaxation<Self>) -> RelaxationByteRange {
RelaxationByteRange {
offset_shift: 0,
num_bytes: 4,
}
}

fn apply_relaxation(
relaxation_kind: Self::RelaxationKind,
section_bytes: &mut [u8],
offset_in_section: &mut u64,
addend: &mut i64,
) {
relaxation_kind.apply(section_bytes, offset_in_section, addend);
}

fn next_relocation_modifier(relaxation_kind: Self::RelaxationKind) -> RelocationModifier {
relaxation_kind.next_modifier()
}

fn instruction_to_string(instruction: &Instruction<Self>) -> String {
instruction.raw_instruction.clone().unwrap_or_default()
}

fn decode_instructions_in_range(
section_bytes: &[u8],
section_address: u64,
_function_offset_in_section: u64,
range: std::ops::Range<u64>,
) -> Vec<Instruction<'_, Self>> {
// ppc64 instructions are a fixed 4 bytes, so we can start decoding at the (aligned) start
// of the range.
let mut offset = range.start & !3;
let mut instructions = Vec::new();
while offset < range.end {
if offset as usize + 4 > section_bytes.len() {
break;
}
let bytes = &section_bytes[offset as usize..offset as usize + 4];
let address = section_address + offset;
let raw_instruction = decode_insn_with_objdump(bytes, address, ArchKind::Ppc64).ok();
instructions.push(Instruction {
raw_instruction,
address,
bytes,
});
offset += 4;
}
instructions
}

fn decode_plt_entry(
_plt_entry: &[u8],
_plt_base: u64,
_plt_offset: u64,
) -> Option<crate::arch::PltEntry> {
// PLT generation isn't implemented for ppc64 yet.
None
}

fn should_chain_relocations(_chain_prefix: &[Self::RType]) -> bool {
false
}

fn get_relocation_base_mask(_relocation_info: &RelocationKindInfo) -> u64 {
u64::MAX
}

fn relocation_to_pc_offset(_relocation_info: &RelocationKindInfo) -> u64 {
0
}

fn is_complete_chain(_chain: impl Iterator<Item = Self::RType>) -> bool {
true
}

fn get_basic_value_for_tp_offset() -> BasicValueKind {
BasicValueKind::TlsOffset
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct RType(u32);

impl crate::arch::RType for RType {
fn from_raw(raw: u32) -> Self {
RType(raw)
}

fn from_dynamic_relocation_kind(kind: DynamicRelocationKind) -> Self {
Self::from_raw(kind.ppc64_r_type())
}

fn opt_relocation_info(self) -> Option<RelocationKindInfo> {
linker_utils::ppc64::relocation_type_from_raw(self.0)
}

fn dynamic_relocation_kind(self) -> Option<DynamicRelocationKind> {
DynamicRelocationKind::from_ppc64_r_type(self.0)
}
}

impl Display for RType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&ppc64_rel_type_to_string(self.0), f)
}
}

impl crate::arch::RelaxationKind for RelaxationKind {
fn is_no_op(self) -> bool {
matches!(self, RelaxationKind::NoOp)
}

fn is_replace_with_no_op(self) -> bool {
false
}
}
8 changes: 8 additions & 0 deletions linker-diff/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ pub fn decode_insn_with_objdump(insn: &[u8], address: u64, arch: ArchKind) -> Re
ArchKind::RiscV64 => ("riscv:rv64", ["riscv64-linux-gnu-objdump", "objdump"]),
ArchKind::X86_64 => todo!(), // x86_64 objdump is not used in linker-diff currently
ArchKind::LoongArch64 => ("Loongarch64", ["loongarch64-linux-gnu-objdump", "objdump"]),
ArchKind::Ppc64 => (
"powerpc:common64",
["powerpc64le-linux-gnu-objdump", "objdump"],
),
};

let objdump = objdump_bin_candidates
Expand All @@ -28,6 +32,10 @@ pub fn decode_insn_with_objdump(insn: &[u8], address: u64, arch: ArchKind) -> Re
let command = Command::new(objdump)
.arg("-b")
.arg("binary")
// Every target we support is little-endian. Be explicit, since some machines (e.g. the
// generic `powerpc:common64`) default to big-endian and would otherwise disassemble the
// raw bytes as garbage on a big-endian-defaulting host.
.arg("--endian=little")
.arg(format!("--adjust-vma=0x{address:x}"))
.arg("-m")
.arg(objdump_arch)
Expand Down
17 changes: 17 additions & 0 deletions linker-utils/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,23 @@ impl DynamicRelocationKind {
DynamicRelocationKind::JumpSlot => object::elf::R_PPC64_JMP_SLOT,
}
}

#[must_use]
pub fn from_ppc64_r_type(r_type: u32) -> Option<Self> {
let kind = match r_type {
object::elf::R_PPC64_COPY => DynamicRelocationKind::Copy,
object::elf::R_PPC64_IRELATIVE => DynamicRelocationKind::Irelative,
object::elf::R_PPC64_DTPMOD64 => DynamicRelocationKind::DtpMod,
object::elf::R_PPC64_DTPREL64 => DynamicRelocationKind::DtpOff,
object::elf::R_PPC64_TPREL64 => DynamicRelocationKind::TpOff,
object::elf::R_PPC64_RELATIVE => DynamicRelocationKind::Relative,
object::elf::R_PPC64_ADDR64 => DynamicRelocationKind::Absolute,
object::elf::R_PPC64_GLOB_DAT => DynamicRelocationKind::GotEntry,
object::elf::R_PPC64_JMP_SLOT => DynamicRelocationKind::JumpSlot,
_ => return None,
};
Some(kind)
}
}

#[derive(Clone, Debug, Copy, PartialEq, Eq)]
Expand Down
4 changes: 4 additions & 0 deletions wild/tests/external_tests/mold_skip_tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ tests = [
"arch-loongarch64-relax-tlsdesc.sh",
]

[skipped_groups.arch_ppc64le]
reason = "ppc64le specific tests"
tests = ["arch-ppc64le-save-restore-gprs.sh"]

[skipped_groups.tls]
reason = "Related to TLS"
tests = ["tls-common.sh", "tls-le-error.sh"]
Expand Down
Loading
Loading