use std::{io, mem::offset_of};
use object::{pe::ImportObjectHeader, xcoff, Object, ObjectSymbol};
use crate::coff_import_file;
fn is_archive_symbol(sym: &object::read::Symbol<'_, '_>) -> bool {
if sym.kind() == object::SymbolKind::File || sym.kind() == object::SymbolKind::Section {
return false;
}
if !sym.is_global() {
return false;
}
if sym.is_undefined() {
return false;
}
true
}
pub fn get_native_object_symbols(
buf: &[u8],
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
) -> io::Result<bool> {
match object::File::parse(buf) {
Ok(file) => {
for sym in file.symbols() {
if !is_archive_symbol(&sym) {
continue;
}
f(sym.name_bytes().expect("FIXME"))?;
}
Ok(true)
}
Err(_) => {
let mut offset = 0;
if ImportObjectHeader::parse(buf, &mut offset).is_ok() {
coff_import_file::get_short_import_symbol(buf, f).or(Ok(false))
} else {
Ok(false)
}
}
}
}
pub fn is_ec_object(obj: &[u8]) -> bool {
match object::FileKind::parse(obj) {
Ok(object::FileKind::Coff) => {
u16::from_le_bytes([obj[0], obj[1]]) != object::pe::IMAGE_FILE_MACHINE_ARM64
}
Ok(object::FileKind::CoffImport) => {
u16::from_le_bytes([obj[6], obj[7]]) != object::pe::IMAGE_FILE_MACHINE_ARM64
}
_ => false,
}
}
pub fn is_64_bit_symbolic_file(obj: &[u8]) -> bool {
object::FileKind::parse(obj).is_ok_and(|kind| match kind {
object::FileKind::Elf64
| object::FileKind::MachO64
| object::FileKind::Pe64
| object::FileKind::Xcoff64
| object::FileKind::MachOFat64 => true,
object::FileKind::Elf32
| object::FileKind::MachO32
| object::FileKind::Pe32
| object::FileKind::Xcoff32
| object::FileKind::MachOFat32
| object::FileKind::Coff
| object::FileKind::CoffBig
| object::FileKind::CoffImport => false,
_ => panic!("Unexpected file kind"),
})
}
const LOG2_OF_AIXPAGE_SIZE: u32 = 12;
const MIN_BIG_ARCHIVE_MEM_DATA_ALIGN: u32 = 2;
fn get_aux_max_alignment<AuxiliaryHeader: object::read::xcoff::AuxHeader>(
aux_header_size: u16,
aux_header: Option<&AuxiliaryHeader>,
log_2_of_max_align: u32,
offset_of_modtype: u16,
) -> u32 {
let Some(aux_header) = aux_header else {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
};
if aux_header_size < offset_of_modtype {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
}
if aux_header.o_snloader() == 0 {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
}
let log_2_of_align = u32::from(std::cmp::max(
aux_header.o_algntext(),
aux_header.o_algndata(),
));
1 << (if log_2_of_align > LOG2_OF_AIXPAGE_SIZE {
log_2_of_max_align
} else {
log_2_of_align
})
}
pub fn get_member_alignment(obj: &[u8]) -> u32 {
use object::read::xcoff::FileHeader;
match object::FileKind::parse(obj) {
Ok(object::FileKind::Xcoff64) => {
let mut offset = 0;
let Ok(header) = xcoff::FileHeader64::parse(obj, &mut offset) else {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
};
let Ok(aux_header) = header.aux_header(obj, &mut offset) else {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
};
get_aux_max_alignment(
header.f_opthdr(),
aux_header,
LOG2_OF_AIXPAGE_SIZE,
offset_of!(object::xcoff::AuxHeader64, o_modtype)
.try_into()
.unwrap(),
)
}
Ok(object::FileKind::Xcoff32) => {
let mut offset = 0;
let Ok(header) = object::xcoff::FileHeader32::parse(obj, &mut offset) else {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
};
let Ok(aux_header) = header.aux_header(obj, &mut offset) else {
return MIN_BIG_ARCHIVE_MEM_DATA_ALIGN;
};
get_aux_max_alignment(
header.f_opthdr(),
aux_header,
2,
offset_of!(object::xcoff::AuxHeader32, o_modtype)
.try_into()
.unwrap(),
)
}
_ => MIN_BIG_ARCHIVE_MEM_DATA_ALIGN,
}
}