///|
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, }
}