diff --git a/src/asm.rs b/src/asm.rs index 08272c7..4c51432 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -105,21 +105,9 @@ pub fn find_items(lines: &[Statement]) -> BTreeMap> { *name_entry += 1; } } - } else if let ( - Some(Statement::Directive(Directive::SymIsFun(sym))), - Statement::Directive(Directive::SetValue(name, _val)), - ) = (ix.checked_sub(1).and_then(|prev| lines.get(prev)), line) - { - // merged function are defined (at least on Linux) as a sequence of 3 - // commands: - // .globl _ZN13sample_merged3two17h0afab563317f9d7bE - // .type _ZN13sample_merged3two17h0afab563317f9d7bE,@function - // .set _ZN13sample_merged3two17h0afab563317f9d7bE, _ZN13sample_merged12one_plus_one17h408b56cb936d6f10E - // - // check above looks for `.type..@function` followed by `.set ...` - + } else if let Some((name, range)) = merged_function(lines, ix) { assert_eq!(item, None); - assert_eq!(sym, name); + let sym = name; if let Some(dem) = demangle::demangled(sym) { let hashed = format!("{dem:?}"); @@ -131,10 +119,10 @@ pub fn find_items(lines: &[Statement]) -> BTreeMap> { name, hashed, index: *name_entry, - len: ix, - non_blank_len: 3, + len: range.len(), + non_blank_len: range.len(), }, - ix - 2..ix + 1, + range, ); *name_entry += 1; } @@ -143,6 +131,43 @@ pub fn find_items(lines: &[Statement]) -> BTreeMap> { res } +/// CHeck if ix is a merged function. +/// +/// merged function are defined (at least on Linux) as a sequence of 3 +/// commands: +/// .globl _ZN13sample_merged3two17h0afab563317f9d7bE +/// .type _ZN13sample_merged3two17h0afab563317f9d7bE,@function +/// .set _ZN13sample_merged3two17h0afab563317f9d7bE, _ZN13sample_merged12one_plus_one17h408b56cb936d6f10E +/// +/// check above looks for `.type..@function` followed by `.set ...` +/// +/// except if we are on mac, where .type is absent: +/// .globl _ZN13sample_merged3two17h0afab563317f9d7bE +/// .set _ZN13sample_merged3two17h0afab563317f9d7bE, _ZN13sample_merged12one_plus_one17h408b56cb936d6f10E +/// +/// So... We have to check both +fn merged_function<'a>(lines: &'a [Statement<'a>], ix: usize) -> Option<(&'a str, Range)> { + let Statement::Directive(Directive::SetValue(name, _val)) = lines.get(ix)? else { + return None; + }; + + if let Some(Statement::Directive(Directive::SymIsFun(sym))) = lines.get(ix.checked_sub(1)?) { + assert_eq!(sym, name); + Some((name, ix - 2..ix + 1)) + } else if lines + .get(ix.checked_sub(2)?) + .map_or(false, |l| l.is_global()) + { + Some((name, ix - 1..ix + 1)) + } else { + None + } + + //if let Some(Statement::Directive(Directive::SymIsFun(sym))), + // Statement::Directive(Directive::SetValue(name, _val)), + // ) = (ix.checked_sub(1).and_then(|prev| lines.get(prev)), line) +} + /// Handles the non-mangled labels found in the given lines of ASM statements. /// /// Returns item if the label is a valid function item, otherwise returns None.