Fix block label printing in precise-output tests (#5798)

As a follow-up to #5780, disassemble the regions identified by bb_starts, falling back on disassembling the whole buffer. This ensures that instructions like br_table that introduce a lot of constants don't throw off capstone for the remainder of the function.

---------

Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
Trevor Elliott
2023-02-15 18:35:26 -08:00
committed by GitHub
parent f04decc4a1
commit cc073593a4
123 changed files with 1473 additions and 784 deletions

View File

@@ -354,49 +354,57 @@ impl<T: CompilePhase> CompiledCodeBase<T> {
let relocs = self.buffer.relocs();
let traps = self.buffer.traps();
let labels = self.bb_starts.as_slice();
let insns = cs.disasm_all(self.buffer.data(), 0x0).map_err(map_caperr)?;
for i in insns.iter() {
if let Some((n, off)) = labels
.iter()
.copied()
.enumerate()
.find(|(_, val)| *val == i.address() as u32)
{
writeln!(buf, "block{}: ; offset 0x{:x}", n, off)?;
}
// Normalize the block starts to include an initial block of offset 0.
let mut block_starts = Vec::new();
if self.bb_starts.first().copied() != Some(0) {
block_starts.push(0);
}
block_starts.extend_from_slice(&self.bb_starts);
block_starts.push(self.buffer.data().len() as u32);
write!(buf, " ")?;
// Iterate over block regions, to ensure that we always produce block labels
for (n, (&start, &end)) in block_starts
.iter()
.zip(block_starts.iter().skip(1))
.enumerate()
{
writeln!(buf, "block{}: ; offset 0x{:x}", n, start)?;
let op_str = i.op_str().unwrap_or("");
if let Some(s) = i.mnemonic() {
write!(buf, "{}", s)?;
if !op_str.is_empty() {
write!(buf, " ")?;
let buffer = &self.buffer.data()[start as usize..end as usize];
let insns = cs.disasm_all(buffer, start as u64).map_err(map_caperr)?;
for i in insns.iter() {
write!(buf, " ")?;
let op_str = i.op_str().unwrap_or("");
if let Some(s) = i.mnemonic() {
write!(buf, "{}", s)?;
if !op_str.is_empty() {
write!(buf, " ")?;
}
}
write!(buf, "{}", op_str)?;
let end = i.address() + i.bytes().len() as u64;
let contains = |off| i.address() <= off && off < end;
if let Some(reloc) = relocs.iter().find(|reloc| contains(reloc.offset as u64)) {
write!(
buf,
" ; reloc_external {} {} {}",
reloc.kind,
reloc.name.display(params),
reloc.addend,
)?;
}
if let Some(trap) = traps.iter().find(|trap| contains(trap.offset as u64)) {
write!(buf, " ; trap: {}", trap.code)?;
}
writeln!(buf)?;
}
write!(buf, "{}", op_str)?;
let end = i.address() + i.bytes().len() as u64;
let contains = |off| i.address() <= off && off < end;
if let Some(reloc) = relocs.iter().find(|reloc| contains(reloc.offset as u64)) {
write!(
buf,
" ; reloc_external {} {} {}",
reloc.kind,
reloc.name.display(params),
reloc.addend,
)?;
}
if let Some(trap) = traps.iter().find(|trap| contains(trap.offset as u64)) {
write!(buf, " ; trap: {}", trap.code)?;
}
writeln!(buf)?;
}
return Ok(buf);