| 231 | } |
| 232 | |
| 233 | fn resolve_branches(ops: &[InstructionRef], rows: &mut [InstructionDiffRow]) { |
| 234 | let mut branch_idx = 0u32; |
| 235 | // Map addresses to indices |
| 236 | let mut addr_map = BTreeMap::<u64, u32>::new(); |
| 237 | for (i, ins_diff) in rows.iter().enumerate() { |
| 238 | if let Some(ins) = ins_diff.ins_ref { |
| 239 | addr_map.insert(ins.address, i as u32); |
| 240 | } |
| 241 | } |
| 242 | // Generate branches |
| 243 | let mut branches = BTreeMap::<u32, InstructionBranchFrom>::new(); |
| 244 | for ((i, ins_diff), ins) in |
| 245 | rows.iter_mut().enumerate().filter(|(_, row)| row.ins_ref.is_some()).zip(ops) |
| 246 | { |
| 247 | if let Some(ins_idx) = ins.branch_dest.and_then(|a| addr_map.get(&a).copied()) { |
| 248 | match branches.entry(ins_idx) { |
| 249 | btree_map::Entry::Vacant(e) => { |
| 250 | ins_diff.branch_to = Some(InstructionBranchTo { ins_idx, branch_idx }); |
| 251 | e.insert(InstructionBranchFrom { ins_idx: vec![i as u32], branch_idx }); |
| 252 | branch_idx += 1; |
| 253 | } |
| 254 | btree_map::Entry::Occupied(e) => { |
| 255 | let branch = e.into_mut(); |
| 256 | ins_diff.branch_to = |
| 257 | Some(InstructionBranchTo { ins_idx, branch_idx: branch.branch_idx }); |
| 258 | branch.ins_idx.push(i as u32); |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | } |
| 263 | // Store branch from |
| 264 | for (i, branch) in branches { |
| 265 | rows[i as usize].branch_from = Some(branch); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | pub(crate) fn address_eq(left: ResolvedRelocation, right: ResolvedRelocation) -> bool { |
| 270 | if right.symbol.size == 0 && left.symbol.size != 0 { |