Skip to content

Commit af8595e

Browse files
committed
Improve extab handling with interleaved extabindex
Fixes #108
1 parent 2b39879 commit af8595e

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

src/util/split.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,67 @@ fn split_extabindex(obj: &mut ObjInfo, start: SectionAddress) -> Result<()> {
293293
}
294294
}
295295

296+
// Pass 3: Merge groups with overlapping extabindex ranges.
297+
// After absorption, two groups may have interleaved extabindex entries,
298+
// producing overlapping covering splits. Merge such groups.
299+
if num_groups > 1 {
300+
// Compute extabindex range [eti_min, eti_max] for each group.
301+
let mut group_eti_ranges: Vec<Option<(u32, u32)>> = vec![None; num_groups];
302+
for (i, &g) in group_ids.iter().enumerate() {
303+
let addr = entries[i].eti_address.address;
304+
match &mut group_eti_ranges[g] {
305+
Some((min, max)) => {
306+
*min = (*min).min(addr);
307+
*max = (*max).max(addr);
308+
}
309+
None => {
310+
group_eti_ranges[g] = Some((addr, addr));
311+
}
312+
}
313+
}
314+
315+
// Sort groups by eti_min and merge overlapping ones.
316+
// Build a list of (eti_min, eti_end, group_id) for non-empty groups.
317+
let mut sorted_groups: Vec<(u32, u32, usize)> = group_eti_ranges
318+
.iter()
319+
.enumerate()
320+
.filter_map(|(g, range)| range.map(|(min, max)| (min, max + 12, g)))
321+
.collect();
322+
sorted_groups.sort_by_key(|&(min, _, _)| min);
323+
324+
let mut merged = true;
325+
while merged {
326+
merged = false;
327+
for i in 0..sorted_groups.len().saturating_sub(1) {
328+
let (_, end_a, ga) = sorted_groups[i];
329+
let (start_b, end_b, gb) = sorted_groups[i + 1];
330+
if start_b < end_a && ga != gb {
331+
// Overlapping ranges: merge gb into ga.
332+
let merge_into = ga.min(gb);
333+
let merge_from = ga.max(gb);
334+
for gid in group_ids.iter_mut() {
335+
if *gid == merge_from {
336+
*gid = merge_into;
337+
}
338+
}
339+
// Update the range for the merged group.
340+
sorted_groups[i].1 = end_a.max(end_b);
341+
sorted_groups[i].2 = merge_into;
342+
sorted_groups.remove(i + 1);
343+
merged = true;
344+
log::debug!(
345+
"Merged overlapping groups {} and {} (extabindex range {:#010X}-{:#010X})",
346+
merge_from,
347+
merge_into,
348+
sorted_groups[i].0,
349+
sorted_groups[i].1,
350+
);
351+
break;
352+
}
353+
}
354+
}
355+
}
356+
296357
// Build group ranges: collect entry indices per group, in iteration order.
297358
let mut group_entries: Vec<Vec<usize>> = vec![Vec::new(); num_groups];
298359
for (i, &g) in group_ids.iter().enumerate() {

0 commit comments

Comments
 (0)