///|
fn link_binding(binding : @elf.SymbolBinding) -> LinkBinding {
match binding {
@elf.SymbolBinding::Local => Local
@elf.SymbolBinding::Global => Global
@elf.SymbolBinding::Weak => Weak
@elf.SymbolBinding::Unknown(value) => Other(value.to_uint())
}
}
///|
fn link_symbol_type(kind : @elf.SymbolType) -> LinkSymbolType {
match kind {
@elf.SymbolType::NoType => NoType
@elf.SymbolType::Object => Object
@elf.SymbolType::Func => Func
@elf.SymbolType::Section => Section
@elf.SymbolType::File => File
@elf.SymbolType::Common => Common
@elf.SymbolType::Tls => Tls
@elf.SymbolType::Unknown(value) => Other(value.to_uint())
}
}
///|
fn section_type_code(kind : @elf.SectionType) -> UInt32 {
match kind {
@elf.SectionType::Null => 0
@elf.SectionType::ProgBits => 1
@elf.SectionType::SymTab => 2
@elf.SectionType::StrTab => 3
@elf.SectionType::Rela => 4
@elf.SectionType::Hash => 5
@elf.SectionType::Dynamic => 6
@elf.SectionType::Note => 7
@elf.SectionType::NoBits => 8
@elf.SectionType::Rel => 9
@elf.SectionType::ShLib => 10
@elf.SectionType::DynSym => 11
@elf.SectionType::InitArray => 14
@elf.SectionType::FiniArray => 15
@elf.SectionType::PreInitArray => 16
@elf.SectionType::Group => 17
@elf.SectionType::SymTabShNdx => 18
@elf.SectionType::UserLow(value) => value
}
}
///|
/// Parse one ELF64 relocatable object and normalize it for linking.
///
/// ELF decoding is delegated to `wuhaiting321/dwarfscope/src/elf`; this
/// package owns only the linker-facing validation and symbol/relocation model.
pub fn parse_object(name : String, bytes : Bytes) -> LinkInput raise LinkError {
let file = @elf.parse_elf(bytes) catch {
_ => raise InvalidElf("ELF parser rejected the input")
}
if file.header.class != @elf.ElfClass::Class64 {
raise UnsupportedClass
}
if file.header.elf_type != 1U {
raise UnsupportedObjectType(file.header.elf_type)
}
let machine = match file.header.machine {
@elf.ElfMachine::X86_64 => X86_64
@elf.ElfMachine::AArch64 => AArch64
_ => raise UnsupportedMachine
}
let sections : Array[LinkSection] = []
for section in file.sections {
sections.push({
index: section.index.reinterpret_as_uint(),
name: section.name,
kind: section_type_code(section.sec_type),
flags: section.flags,
address: section.addr,
size: section.size,
alignment: section.addralign,
entry_size: section.entsize,
})
}
let symbols : Array[LinkSymbol] = []
for index in 0.. raise InvalidRelocation(section.name)
}
for entry in entries {
if entry.sym_idx >= file.symbols.length().reinterpret_as_uint() {
raise InvalidRelocation(section.name)
}
relocations.push({
target_section: section.info,
offset: entry.offset,
symbol_index: entry.sym_idx,
kind: entry.type_code,
addend: entry.addend,
has_addend: is_rela,
})
}
}
}
if !relocations.is_empty() && symbols.is_empty() {
raise MissingSymbolTable
}
{ name, machine, sections, symbols, relocations, }
}