use std::io::{self, Write};
use crate::{
file::pe::SectionTable,
formatting::helpers::data_label_for_rva,
metadata::vtfixup::{
VtFixupContext, COR_VTABLE_64BIT, COR_VTABLE_CALL_MOST_DERIVED, COR_VTABLE_FROM_UNMANAGED,
COR_VTABLE_RETAIN_APPDOMAIN,
},
};
pub(super) fn format_vtfixup_directives(
w: &mut dyn Write,
ctx: &VtFixupContext,
sections: &[SectionTable],
) -> io::Result<()> {
for entry in &ctx.entries {
let (prefix, _) = data_label_for_rva(sections, entry.rva);
let width = if entry.flags & COR_VTABLE_64BIT != 0 {
"int64"
} else {
"int32"
};
write!(w, ".vtfixup [{:>4}] {width}", entry.count)?;
if entry.flags & COR_VTABLE_FROM_UNMANAGED != 0 {
write!(w, " fromunmanaged")?;
}
if entry.flags & COR_VTABLE_RETAIN_APPDOMAIN != 0 {
write!(w, " retainappdomain")?;
}
if entry.flags & COR_VTABLE_CALL_MOST_DERIVED != 0 {
write!(w, " callmostderived")?;
}
writeln!(w, " at {prefix}{:08X}", entry.rva)?;
}
Ok(())
}
pub(super) fn format_method_vtentry_export(
w: &mut dyn Write,
method_token: u32,
ctx: &VtFixupContext,
) -> io::Result<()> {
if let Some(positions) = ctx.vtentry_map.get(&method_token) {
for &(entry, slot) in positions {
writeln!(w, " .vtentry {entry} : {slot}")?;
}
}
if let Some((ordinal, ref name)) = ctx.export_map.get(&method_token) {
match name {
Some(n) => writeln!(w, " .export [{ordinal}] as {n}")?,
None => writeln!(w, " .export [{ordinal}]")?,
}
}
Ok(())
}