Skip to content

Commit e927ed7

Browse files
authored
Merge pull request #200 from philipc/arange
Use .debug_aranges
2 parents 1676872 + aebc36f commit e927ed7

1 file changed

Lines changed: 60 additions & 8 deletions

File tree

src/lib.rs

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ impl<R: gimli::Reader> Context<R> {
152152
pub fn from_sections(
153153
debug_abbrev: gimli::DebugAbbrev<R>,
154154
debug_addr: gimli::DebugAddr<R>,
155+
debug_aranges: gimli::DebugAranges<R>,
155156
debug_info: gimli::DebugInfo<R>,
156157
debug_line: gimli::DebugLine<R>,
157158
debug_line_str: gimli::DebugLineStr<R>,
@@ -164,7 +165,7 @@ impl<R: gimli::Reader> Context<R> {
164165
Self::from_dwarf(gimli::Dwarf {
165166
debug_abbrev,
166167
debug_addr,
167-
debug_aranges: default_section.clone().into(),
168+
debug_aranges,
168169
debug_info,
169170
debug_line,
170171
debug_line_str,
@@ -370,6 +371,16 @@ struct ResDwarf<R: gimli::Reader> {
370371

371372
impl<R: gimli::Reader> ResDwarf<R> {
372373
fn parse(sections: Arc<gimli::Dwarf<R>>) -> Result<Self, Error> {
374+
// Find all the references to compilation units in .debug_aranges.
375+
// Note that we always also iterate through all of .debug_info to
376+
// find compilation units, because .debug_aranges may be missing some.
377+
let mut aranges = Vec::new();
378+
let mut headers = sections.debug_aranges.headers();
379+
while let Some(header) = headers.next()? {
380+
aranges.push((header.debug_info_offset(), header.offset()));
381+
}
382+
aranges.sort_by_key(|i| i.0);
383+
373384
let mut unit_ranges = Vec::new();
374385
let mut res_units = Vec::new();
375386
let mut units = sections.units();
@@ -426,13 +437,54 @@ impl<R: gimli::Reader> ResDwarf<R> {
426437
}
427438
}
428439

429-
ranges.for_each_range(&sections, &dw_unit, |range| {
430-
unit_ranges.push(UnitRange {
431-
range,
432-
unit_id,
433-
max_end: 0,
434-
});
435-
})?;
440+
// Find the address ranges for the CU, using in order of preference:
441+
// - DW_AT_ranges
442+
// - .debug_aranges
443+
// - DW_AT_low_pc/DW_AT_high_pc
444+
//
445+
// Using DW_AT_ranges before .debug_aranges is possibly an arbitrary choice,
446+
// but the feeling is that DW_AT_ranges is more likely to be reliable or complete
447+
// if it is present.
448+
//
449+
// .debug_aranges must be used before DW_AT_low_pc/DW_AT_high_pc because
450+
// it has been observed on macOS that DW_AT_ranges was not emitted even for
451+
// discontiguous CUs.
452+
let i = match ranges.ranges_offset {
453+
Some(_) => None,
454+
None => aranges.binary_search_by_key(&offset, |x| x.0).ok(),
455+
};
456+
if let Some(mut i) = i {
457+
// There should be only one set per CU, but in practice multiple
458+
// sets have been observed. This is probably a compiler bug, but
459+
// either way we need to handle it.
460+
while i > 0 && aranges[i - 1].0 == offset {
461+
i -= 1;
462+
}
463+
for (_, aranges_offset) in aranges[i..].iter().take_while(|x| x.0 == offset) {
464+
let aranges_header = sections.debug_aranges.header(*aranges_offset)?;
465+
let mut aranges = aranges_header.entries();
466+
while let Some(arange) = aranges.next()? {
467+
// Ignore unrelocated ranges (e.g. the function was eliminated
468+
// when linking).
469+
// TODO: allow this if there is a section at address zero.
470+
if arange.address() != 0 && arange.length() != 0 {
471+
unit_ranges.push(UnitRange {
472+
range: arange.range(),
473+
unit_id,
474+
max_end: 0,
475+
});
476+
}
477+
}
478+
}
479+
} else {
480+
ranges.for_each_range(&sections, &dw_unit, |range| {
481+
unit_ranges.push(UnitRange {
482+
range,
483+
unit_id,
484+
max_end: 0,
485+
});
486+
})?;
487+
}
436488
}
437489

438490
res_units.push(ResUnit {

0 commit comments

Comments
 (0)