Fixes for switch analysis

- When finalizing a block, restart analysis at
  the first block
- Check for default case in jump table entries
This commit is contained in:
Luke Street 2024-04-03 00:11:58 -06:00
parent 9249fa67b8
commit e9a9ed0453
2 changed files with 11 additions and 3 deletions

View File

@ -248,8 +248,12 @@ impl AnalyzerState {
} }
if self.functions.iter().any(|(_, i)| i.is_unfinalized()) { if self.functions.iter().any(|(_, i)| i.is_unfinalized()) {
log::error!("Failed to finalize functions:"); log::error!("Failed to finalize functions:");
for (addr, _) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) { for (addr, info) in self.functions.iter().filter(|(_, i)| i.is_unfinalized()) {
log::error!(" {:#010X}", addr); log::error!(
" {:#010X}: blocks [{:?}]",
addr,
info.slices.as_ref().unwrap().possible_blocks.keys()
);
} }
bail!("Failed to finalize functions"); bail!("Failed to finalize functions");
} }
@ -298,11 +302,15 @@ impl AnalyzerState {
&self.functions, &self.functions,
Some(vm), Some(vm),
)?; )?;
// Start at the beginning of the function again
current = SectionAddress::new(addr.section, 0);
} }
TailCallResult::Is => { TailCallResult::Is => {
log::trace!("Finalized tail call @ {:#010X}", block); log::trace!("Finalized tail call @ {:#010X}", block);
slices.possible_blocks.remove(&block); slices.possible_blocks.remove(&block);
slices.function_references.insert(block); slices.function_references.insert(block);
// Start at the beginning of the function again
current = SectionAddress::new(addr.section, 0);
} }
TailCallResult::Possible => { TailCallResult::Possible => {
if finalize { if finalize {

View File

@ -328,7 +328,7 @@ impl FunctionSlices {
function_end.or_else(|| self.end()), function_end.or_else(|| self.end()),
)?; )?;
log::debug!("-> size {}: {:?}", size, entries); log::debug!("-> size {}: {:?}", size, entries);
if entries.contains(&next_address) if (entries.contains(&next_address) || self.blocks.contains_key(&next_address))
&& !entries.iter().any(|&addr| { && !entries.iter().any(|&addr| {
self.is_known_function(known_functions, addr) self.is_known_function(known_functions, addr)
.is_some_and(|fn_addr| fn_addr != function_start) .is_some_and(|fn_addr| fn_addr != function_start)