use object::{Object, ObjectSection, ObjectSymbol};
use target_lexicon::BinaryFormat;
use std::collections::{HashMap, HashSet};
use std::convert::TryInto;
use std::num::TryFromIntError;
use wasmer_types::{CompileError, SourceLoc, entity::PrimaryMap};
use wasmer_compiler::types::{
address_map::{FunctionAddressMap, InstructionAddressMap},
function::{CompiledFunctionFrameInfo, CustomSections, FunctionBody},
relocation::{Relocation, RelocationKind, RelocationTarget},
section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex},
};
use wasmer_vm::libcalls::LibCall;
fn map_tryfromint_err(error: TryFromIntError) -> CompileError {
CompileError::Codegen(format!("int doesn't fit: {error}"))
}
fn map_object_err(error: object::read::Error) -> CompileError {
CompileError::Codegen(format!("error parsing object file: {error}"))
}
#[derive(Debug)]
pub struct CompiledFunction {
pub compiled_function: wasmer_compiler::types::function::CompiledFunction,
pub custom_sections: CustomSections,
pub eh_frame_section_indices: Vec<SectionIndex>,
pub compact_unwind_section_indices: Vec<SectionIndex>,
pub gcc_except_table_section_indices: Vec<SectionIndex>,
pub data_dw_ref_personality_section_indices: Vec<SectionIndex>,
}
impl wasmer_compiler::CompiledFunction for CompiledFunction {}
static LIBCALLS_ELF: phf::Map<&'static str, LibCall> = phf::phf_map! {
"ceilf" => LibCall::CeilF32,
"ceil" => LibCall::CeilF64,
"floorf" => LibCall::FloorF32,
"floor" => LibCall::FloorF64,
"nearbyintf" => LibCall::NearestF32,
"nearbyint" => LibCall::NearestF64,
"truncf" => LibCall::TruncF32,
"trunc" => LibCall::TruncF64,
"__chkstk" => LibCall::Probestack,
"wasmer_vm_f32_ceil" => LibCall::CeilF32,
"wasmer_vm_f64_ceil" => LibCall::CeilF64,
"wasmer_vm_f32_floor" => LibCall::FloorF32,
"wasmer_vm_f64_floor" => LibCall::FloorF64,
"wasmer_vm_f32_nearest" => LibCall::NearestF32,
"wasmer_vm_f64_nearest" => LibCall::NearestF64,
"wasmer_vm_f32_trunc" => LibCall::TruncF32,
"wasmer_vm_f64_trunc" => LibCall::TruncF64,
"wasmer_vm_memory32_size" => LibCall::Memory32Size,
"wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
"wasmer_vm_table_copy" => LibCall::TableCopy,
"wasmer_vm_table_init" => LibCall::TableInit,
"wasmer_vm_table_fill" => LibCall::TableFill,
"wasmer_vm_table_size" => LibCall::TableSize,
"wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
"wasmer_vm_table_get" => LibCall::TableGet,
"wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
"wasmer_vm_table_set" => LibCall::TableSet,
"wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
"wasmer_vm_table_grow" => LibCall::TableGrow,
"wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
"wasmer_vm_func_ref" => LibCall::FuncRef,
"wasmer_vm_elem_drop" => LibCall::ElemDrop,
"wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
"wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
"wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
"wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
"wasmer_vm_memory32_init" => LibCall::Memory32Init,
"wasmer_vm_data_drop" => LibCall::DataDrop,
"wasmer_vm_raise_trap" => LibCall::RaiseTrap,
"wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
"wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
"wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
"wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
"wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
"wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
"wasmer_vm_throw" => LibCall::Throw,
"wasmer_vm_alloc_exception" => LibCall::AllocException,
"wasmer_vm_read_exnref" => LibCall::ReadExnRef,
"wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
"wasmer_eh_personality" => LibCall::EHPersonality,
"wasmer_eh_personality2" => LibCall::EHPersonality2,
"wasmer_vm_dbg_usize" => LibCall::DebugUsize,
"wasmer_vm_dbg_str" => LibCall::DebugStr,
};
static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
"_ceilf" => LibCall::CeilF32,
"_ceil" => LibCall::CeilF64,
"_floorf" => LibCall::FloorF32,
"_floor" => LibCall::FloorF64,
"_nearbyintf" => LibCall::NearestF32,
"_nearbyint" => LibCall::NearestF64,
"_truncf" => LibCall::TruncF32,
"_trunc" => LibCall::TruncF64,
"_wasmer_vm_f32_ceil" => LibCall::CeilF32,
"_wasmer_vm_f64_ceil" => LibCall::CeilF64,
"_wasmer_vm_f32_floor" => LibCall::FloorF32,
"_wasmer_vm_f64_floor" => LibCall::FloorF64,
"_wasmer_vm_f32_nearest" => LibCall::NearestF32,
"_wasmer_vm_f64_nearest" => LibCall::NearestF64,
"_wasmer_vm_f32_trunc" => LibCall::TruncF32,
"_wasmer_vm_f64_trunc" => LibCall::TruncF64,
"_wasmer_vm_memory32_size" => LibCall::Memory32Size,
"_wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
"_wasmer_vm_table_copy" => LibCall::TableCopy,
"_wasmer_vm_table_init" => LibCall::TableInit,
"_wasmer_vm_table_fill" => LibCall::TableFill,
"_wasmer_vm_table_size" => LibCall::TableSize,
"_wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
"_wasmer_vm_table_get" => LibCall::TableGet,
"_wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
"_wasmer_vm_table_set" => LibCall::TableSet,
"_wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
"_wasmer_vm_table_grow" => LibCall::TableGrow,
"_wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
"_wasmer_vm_func_ref" => LibCall::FuncRef,
"_wasmer_vm_elem_drop" => LibCall::ElemDrop,
"_wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
"_wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
"_wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
"_wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
"_wasmer_vm_memory32_init" => LibCall::Memory32Init,
"_wasmer_vm_data_drop" => LibCall::DataDrop,
"_wasmer_vm_raise_trap" => LibCall::RaiseTrap,
"_wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
"_wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
"_wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
"_wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
"_wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
"_wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
"_wasmer_vm_throw" => LibCall::Throw,
"_wasmer_vm_alloc_exception" => LibCall::AllocException,
"_wasmer_vm_read_exnref" => LibCall::ReadExnRef,
"_wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
"___gxx_personality_v0" => LibCall::EHPersonality,
"_wasmer_eh_personality2" => LibCall::EHPersonality2,
"_wasmer_vm_dbg_usize" => LibCall::DebugUsize,
"_wasmer_vm_dbg_str" => LibCall::DebugStr,
};
pub fn load_object_file<F>(
contents: &[u8],
root_section: &str,
root_section_reloc_target: RelocationTarget,
mut symbol_name_to_relocation_target: F,
binary_fmt: BinaryFormat,
) -> Result<CompiledFunction, CompileError>
where
F: FnMut(&str) -> Result<Option<RelocationTarget>, CompileError>,
{
let obj = object::File::parse(contents).map_err(map_object_err)?;
let libcalls = match binary_fmt {
BinaryFormat::Elf => &LIBCALLS_ELF,
BinaryFormat::Macho => &LIBCALLS_MACHO,
_ => {
return Err(CompileError::UnsupportedTarget(format!(
"Unsupported binary format {binary_fmt:?}"
)));
}
};
let mut worklist: Vec<object::read::SectionIndex> = Vec::new();
let mut section_targets: HashMap<object::read::SectionIndex, RelocationTarget> = HashMap::new();
let root_section_index = obj
.section_by_name(root_section)
.ok_or_else(|| CompileError::Codegen(format!("no section named {root_section}")))?
.index();
let mut section_to_custom_section = HashMap::new();
section_targets.insert(root_section_index, root_section_reloc_target);
let mut next_custom_section: u32 = 0;
let mut elf_section_to_target = |elf_section_index: object::read::SectionIndex| {
*section_targets.entry(elf_section_index).or_insert_with(|| {
let next = SectionIndex::from_u32(next_custom_section);
section_to_custom_section.insert(elf_section_index, next);
let target = RelocationTarget::CustomSection(next);
next_custom_section += 1;
target
})
};
let mut relocations: HashMap<object::read::SectionIndex, Vec<Relocation>> = HashMap::new();
worklist.push(root_section_index);
let mut eh_frame_section_indices = vec![];
let mut compact_unwind_section_indices = vec![];
let mut gcc_except_table_section_indices = vec![];
let mut data_dw_ref_personality_section_indices = vec![];
for section in obj.sections() {
let index = section.index();
let Ok(section_name) = section.name() else {
continue;
};
match section_name {
"__eh_frame" | ".eh_frame" => {
worklist.push(index);
eh_frame_section_indices.push(index);
elf_section_to_target(index);
}
"__compact_unwind" => {
worklist.push(index);
compact_unwind_section_indices.push(index);
elf_section_to_target(index);
}
".gcc_except_table" => {
worklist.push(index);
gcc_except_table_section_indices.push(index);
elf_section_to_target(index);
}
".data.DW.ref.wasmer_eh_personality" => {
worklist.push(index);
data_dw_ref_personality_section_indices.push(index);
elf_section_to_target(index);
}
_ => {}
}
}
let mut visited: HashSet<_> = HashSet::from_iter(worklist.iter().copied());
while let Some(section_index) = worklist.pop() {
let sec = obj
.section_by_index(section_index)
.map_err(map_object_err)?;
let relocs = sec.relocations();
for (offset, reloc) in relocs {
let mut addend = reloc.addend();
let target = match reloc.target() {
object::read::RelocationTarget::Symbol(index) => {
let symbol = obj.symbol_by_index(index).map_err(map_object_err)?;
let symbol_name = symbol.name().map_err(map_object_err)?;
if symbol.kind() == object::SymbolKind::Section {
match symbol.section() {
object::SymbolSection::Section(section_index) => {
if section_index == root_section_index {
root_section_reloc_target
} else {
if visited.insert(section_index) {
worklist.push(section_index);
}
elf_section_to_target(section_index)
}
}
_ => {
return Err(CompileError::Codegen(format!(
"relocation targets unknown section {reloc:?}",
)));
}
}
} else if let Some(libcall) = libcalls.get(symbol_name) {
RelocationTarget::LibCall(*libcall)
} else if let Ok(Some(reloc_target)) =
symbol_name_to_relocation_target(symbol_name)
{
reloc_target
} else if let object::SymbolSection::Section(section_index) = symbol.section() {
if matches!(
reloc.flags(),
object::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
r_pcrel: false,
..
} | object::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_POINTER_TO_GOT,
r_pcrel: true,
..
} | object::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
r_pcrel: true,
..
} | object::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_PAGE21,
r_pcrel: true,
..
} | object::RelocationFlags::MachO {
r_type: object::macho::ARM64_RELOC_PAGEOFF12,
r_pcrel: false,
..
}
) {
let symbol_sec = obj
.section_by_index(section_index)
.map_err(map_object_err)?;
addend = addend
.wrapping_add((symbol.address() - symbol_sec.address()) as i64);
} else {
addend = addend.wrapping_add(symbol.address() as i64);
}
if section_index == root_section_index {
root_section_reloc_target
} else {
if visited.insert(section_index) {
worklist.push(section_index);
}
elf_section_to_target(section_index)
}
} else {
return Err(CompileError::Codegen(format!(
"relocation {reloc:?} targets unknown symbol '{symbol:?}'",
)));
}
}
object::read::RelocationTarget::Section(index) => {
if index == root_section_index {
root_section_reloc_target
} else {
if visited.insert(index) {
worklist.push(index);
}
elf_section_to_target(index)
}
}
object::read::RelocationTarget::Absolute => {
return Err(CompileError::Codegen(format!(
"relocation targets absolute address {reloc:?}",
)));
}
t => {
return Err(CompileError::Codegen(format!(
"relocation target is unknown `{t:?}`",
)));
}
};
let kind = match (obj.architecture(), reloc.flags(), reloc.size()) {
(
_,
object::RelocationFlags::Elf {
r_type: object::elf::R_X86_64_64,
},
64,
) => RelocationKind::Abs8,
(
object::Architecture::X86_64,
object::RelocationFlags::Elf {
r_type: object::elf::R_X86_64_PC64,
},
0,
) => RelocationKind::PCRel8,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_CALL26,
},
26,
) => RelocationKind::Arm64Call,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_JUMP26,
},
0,
) => RelocationKind::Arm64Call,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_MOVW_UABS_G0_NC,
},
0,
) => RelocationKind::Arm64Movw0,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_MOVW_UABS_G1_NC,
},
0,
) => RelocationKind::Arm64Movw1,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_MOVW_UABS_G2_NC,
},
0,
) => RelocationKind::Arm64Movw2,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_MOVW_UABS_G3,
},
0,
) => RelocationKind::Arm64Movw3,
(
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_64,
},
64,
) => RelocationKind::Abs8,
(
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_CALL_PLT,
},
0,
) => RelocationKind::RiscvCall,
(
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_PCREL_HI20,
},
0,
) => RelocationKind::RiscvPCRelHi20,
(
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_PCREL_LO12_I,
},
0,
) => RelocationKind::RiscvPCRelLo12I,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_ADD8,
},
0,
) => RelocationKind::Add,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_ADD16,
},
0,
) => RelocationKind::Add2,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_ADD32,
},
0,
) => RelocationKind::Add4,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_ADD64,
},
0,
) => RelocationKind::Add8,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SUB6,
},
0,
) => RelocationKind::Sub6Bits,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SUB8,
},
0,
) => RelocationKind::Sub,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SUB16,
},
0,
) => RelocationKind::Sub2,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SUB32,
},
0,
) => RelocationKind::Sub4,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SUB64,
},
0,
) => RelocationKind::Sub8,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SET6,
},
0,
) => RelocationKind::Abs6Bits,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SET8,
},
0,
) => RelocationKind::Abs,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SET16,
},
0,
) => RelocationKind::Abs2,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_SET32,
},
0,
) => RelocationKind::Abs4,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_32,
},
32,
) => RelocationKind::Abs4,
(
object::Architecture::Riscv64,
object::RelocationFlags::Elf {
r_type: object::elf::R_RISCV_32_PCREL,
},
0,
) => RelocationKind::PCRel4,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_ABS_HI20,
},
0,
) => RelocationKind::LArchAbsHi20,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_ABS_LO12,
},
0,
) => RelocationKind::LArchAbsLo12,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_ABS64_HI12,
},
0,
) => RelocationKind::LArchAbs64Hi12,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_ABS64_LO20,
},
0,
) => RelocationKind::LArchAbs64Lo20,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_CALL36,
},
0,
) => RelocationKind::LArchCall36,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_PCALA_HI20,
},
0,
) => RelocationKind::LArchPCAlaHi20,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_PCALA_LO12,
},
0,
) => RelocationKind::LArchPCAlaLo12,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_PCALA64_HI12,
},
0,
) => RelocationKind::LArchPCAla64Hi12,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_PCALA64_LO20,
},
0,
) => RelocationKind::LArchPCAla64Lo20,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_ADR_PREL_LO21,
},
0,
) => RelocationKind::Aarch64AdrPrelLo21,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_64,
},
64,
) => RelocationKind::Abs8,
(
object::Architecture::LoongArch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_LARCH_32_PCREL,
},
32,
) => RelocationKind::PCRel4,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_ADR_PREL_PG_HI21,
},
0,
) => RelocationKind::Aarch64AdrPrelPgHi21,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_LDST128_ABS_LO12_NC,
},
0,
) => RelocationKind::Aarch64Ldst128AbsLo12Nc,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_ADD_ABS_LO12_NC,
},
0,
) => RelocationKind::Aarch64AddAbsLo12Nc,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_LDST64_ABS_LO12_NC,
},
0,
) => RelocationKind::Aarch64Ldst64AbsLo12Nc,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_PREL64,
},
64,
) => RelocationKind::PCRel8,
(
object::Architecture::Aarch64,
object::RelocationFlags::Elf {
r_type: object::elf::R_AARCH64_ABS64,
},
64,
) => RelocationKind::Abs8,
(
object::Architecture::Aarch64,
object::RelocationFlags::MachO { r_type: value, .. },
_,
) => match value {
object::macho::ARM64_RELOC_UNSIGNED => RelocationKind::MachoArm64RelocUnsigned,
object::macho::ARM64_RELOC_SUBTRACTOR => {
RelocationKind::MachoArm64RelocSubtractor
}
object::macho::ARM64_RELOC_BRANCH26 => RelocationKind::MachoArm64RelocBranch26,
object::macho::ARM64_RELOC_PAGE21 => RelocationKind::MachoArm64RelocPage21,
object::macho::ARM64_RELOC_PAGEOFF12 => {
RelocationKind::MachoArm64RelocPageoff12
}
object::macho::ARM64_RELOC_GOT_LOAD_PAGE21 => {
RelocationKind::MachoArm64RelocGotLoadPage21
}
object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12 => {
RelocationKind::MachoArm64RelocGotLoadPageoff12
}
object::macho::ARM64_RELOC_POINTER_TO_GOT => {
RelocationKind::MachoArm64RelocPointerToGot
}
object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21 => {
RelocationKind::MachoArm64RelocTlvpLoadPage21
}
object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
RelocationKind::MachoArm64RelocTlvpLoadPageoff12
}
object::macho::ARM64_RELOC_ADDEND => RelocationKind::MachoArm64RelocAddend,
_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {reloc:?}",
)));
}
},
(
object::Architecture::X86_64,
object::RelocationFlags::MachO { r_type: value, .. },
_,
) => match value {
object::macho::X86_64_RELOC_UNSIGNED => {
RelocationKind::MachoX86_64RelocUnsigned
}
object::macho::X86_64_RELOC_SIGNED => RelocationKind::MachoX86_64RelocSigned,
object::macho::X86_64_RELOC_BRANCH => RelocationKind::MachoX86_64RelocBranch,
object::macho::X86_64_RELOC_GOT_LOAD => RelocationKind::MachoX86_64RelocGotLoad,
object::macho::X86_64_RELOC_GOT => RelocationKind::MachoX86_64RelocGot,
object::macho::X86_64_RELOC_SUBTRACTOR => {
RelocationKind::MachoX86_64RelocSubtractor
}
object::macho::X86_64_RELOC_SIGNED_1 => RelocationKind::MachoX86_64RelocSigned1,
object::macho::X86_64_RELOC_SIGNED_2 => RelocationKind::MachoX86_64RelocSigned2,
object::macho::X86_64_RELOC_SIGNED_4 => RelocationKind::MachoX86_64RelocSigned4,
object::macho::X86_64_RELOC_TLV => RelocationKind::MachoX86_64RelocTlv,
_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {reloc:?}"
)));
}
},
_ => {
return Err(CompileError::Codegen(format!(
"unknown relocation {reloc:?}",
)));
}
};
relocations
.entry(section_index)
.or_default()
.push(Relocation {
kind,
reloc_target: target,
offset: offset.try_into().map_err(map_tryfromint_err)?,
addend,
});
}
}
let eh_frame_section_indices = eh_frame_section_indices
.iter()
.map(|index| {
section_to_custom_section.get(index).map_or_else(
|| {
Err(CompileError::Codegen(format!(
".eh_frame section with index={index:?} was never loaded",
)))
},
|idx| Ok(*idx),
)
})
.collect::<Result<Vec<SectionIndex>, _>>()?;
let compact_unwind_section_indices = compact_unwind_section_indices
.iter()
.map(|index| {
section_to_custom_section.get(index).map_or_else(
|| {
Err(CompileError::Codegen(format!(
"_compact_unwind section with index={index:?} was never loaded",
)))
},
|idx| Ok(*idx),
)
})
.collect::<Result<Vec<SectionIndex>, _>>()?;
let gcc_except_table_section_indices = gcc_except_table_section_indices
.iter()
.map(|index| {
section_to_custom_section.get(index).map_or_else(
|| {
Err(CompileError::Codegen(format!(
".gcc_except_table section with index={index:?} was never loaded",
)))
},
|idx| Ok(*idx),
)
})
.collect::<Result<Vec<SectionIndex>, _>>()?;
let data_dw_ref_personality_section_indices = data_dw_ref_personality_section_indices
.iter()
.map(|index| {
section_to_custom_section.get(index).map_or_else(
|| {
Err(CompileError::Codegen(format!(
".data.DW.ref.wasmer_eh_personality section with index={index:?} was never loaded",
)))
},
|idx| Ok(*idx),
)
})
.collect::<Result<Vec<SectionIndex>, _>>()?;
let mut custom_sections = section_to_custom_section
.iter()
.map(|(elf_section_index, custom_section_index)| {
let section = obj.section_by_index(*elf_section_index).unwrap();
(
custom_section_index,
CustomSection {
protection: CustomSectionProtection::Read,
alignment: Some(section.align()),
bytes: SectionBody::new_with_vec(section.data().unwrap().to_vec()),
relocations: relocations
.remove_entry(elf_section_index)
.map_or(vec![], |(_, v)| v),
},
)
})
.collect::<Vec<_>>();
custom_sections.sort_unstable_by_key(|a| a.0);
let custom_sections = custom_sections
.into_iter()
.map(|(_, v)| v)
.collect::<PrimaryMap<SectionIndex, _>>();
let function_body = FunctionBody {
body: obj
.section_by_index(root_section_index)
.unwrap()
.data()
.unwrap()
.to_vec(),
unwind_info: None,
};
let address_map = FunctionAddressMap {
instructions: vec![InstructionAddressMap {
srcloc: SourceLoc::default(),
code_offset: 0,
code_len: function_body.body.len(),
}],
start_srcloc: SourceLoc::default(),
end_srcloc: SourceLoc::default(),
body_offset: 0,
body_len: function_body.body.len(),
};
Ok(CompiledFunction {
compiled_function: wasmer_compiler::types::function::CompiledFunction {
body: function_body,
relocations: relocations
.remove_entry(&root_section_index)
.map_or(vec![], |(_, v)| v),
frame_info: CompiledFunctionFrameInfo {
address_map,
traps: vec![],
},
},
custom_sections,
eh_frame_section_indices,
compact_unwind_section_indices,
gcc_except_table_section_indices,
data_dw_ref_personality_section_indices,
})
}