Skip to content

Commit f49dfeb

Browse files
authored
read: handle tombstones in .debug_aranges (gimli-rs#743)
1 parent dd3c98c commit f49dfeb

File tree

2 files changed

+203
-18
lines changed

2 files changed

+203
-18
lines changed

crates/examples/src/bin/dwarfdump.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,9 +2217,13 @@ fn dump_aranges<R: Reader, W: Write>(
22172217
header.encoding().address_size,
22182218
)?;
22192219
let mut aranges = header.entries();
2220-
while let Some(arange) = aranges.next()? {
2221-
let range = arange.range();
2222-
writeln!(w, "[{:#x}, {:#x})", range.begin, range.end)?;
2220+
while let Some(raw) = aranges.next_raw()? {
2221+
if let Some(arange) = aranges.convert_raw(raw.clone())? {
2222+
let range = arange.range();
2223+
writeln!(w, "[{:#x}, {:#x})", range.begin, range.end)?;
2224+
} else {
2225+
writeln!(w, "[{:#x}, {:#x}) (ignored)", raw.address(), raw.length())?;
2226+
}
22232227
}
22242228
}
22252229
Ok(())

src/read/aranges.rs

Lines changed: 196 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,24 @@ impl<R: Reader> ArangeEntryIter<R> {
249249
/// yielded. If an error occurs while parsing the next arange, then this error
250250
/// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
251251
pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
252+
loop {
253+
let raw_entry = match self.next_raw()? {
254+
Some(entry) => entry,
255+
None => return Ok(None),
256+
};
257+
258+
let entry = self.convert_raw(raw_entry)?;
259+
if entry.is_some() {
260+
return Ok(entry);
261+
}
262+
}
263+
}
264+
265+
/// Advance the iterator and return the next arange without validating it.
266+
///
267+
/// The returned entry will have `range.end` set to 0.
268+
/// This will return tombstone entries as well.
269+
pub fn next_raw(&mut self) -> Result<Option<ArangeEntry>> {
252270
if self.input.is_empty() {
253271
return Ok(None);
254272
}
@@ -265,6 +283,23 @@ impl<R: Reader> ArangeEntryIter<R> {
265283
}
266284
}
267285
}
286+
287+
/// Convert a raw range into a range.
288+
///
289+
/// The raw range should have been obtained from `next_raw`.
290+
#[doc(hidden)]
291+
pub fn convert_raw(&self, mut entry: ArangeEntry) -> Result<Option<ArangeEntry>> {
292+
// Skip tombstone entries.
293+
let address_size = self.encoding.address_size;
294+
let tombstone_address = !0 >> (64 - self.encoding.address_size * 8);
295+
if entry.range.begin == tombstone_address {
296+
return Ok(None);
297+
}
298+
299+
// Calculate end now so that we can handle overflow.
300+
entry.range.end = entry.range.begin.add_sized(entry.length, address_size)?;
301+
Ok(Some(entry))
302+
}
268303
}
269304

270305
#[cfg(feature = "fallible-iterator")]
@@ -297,9 +332,7 @@ impl ArangeEntry {
297332

298333
let begin = input.read_address(address_size)?;
299334
let length = input.read_address(address_size)?;
300-
// Calculate end now so that we can handle overflow.
301-
let end = begin.add_sized(length, address_size)?;
302-
let range = Range { begin, end };
335+
let range = Range { begin, end: 0 };
303336

304337
match (begin, length) {
305338
// This is meant to be a null terminator, but in practice it can occur
@@ -533,9 +566,15 @@ mod tests {
533566
address_size: 4,
534567
};
535568
let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
536-
let rest = &mut EndianSlice::new(&buf, LittleEndian);
537-
let entry = ArangeEntry::parse(rest, encoding).expect("should parse entry ok");
538-
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
569+
let mut iter = ArangeEntryIter {
570+
input: EndianSlice::new(&buf, LittleEndian),
571+
encoding,
572+
};
573+
let entry = iter.next().expect("should parse entry ok");
574+
assert_eq!(
575+
iter.input,
576+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
577+
);
539578
assert_eq!(
540579
entry,
541580
Some(ArangeEntry {
@@ -566,9 +605,15 @@ mod tests {
566605
// Next tuple.
567606
0x09
568607
];
569-
let rest = &mut EndianSlice::new(&buf, LittleEndian);
570-
let entry = ArangeEntry::parse(rest, encoding).expect("should parse entry ok");
571-
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
608+
let mut iter = ArangeEntryIter {
609+
input: EndianSlice::new(&buf, LittleEndian),
610+
encoding,
611+
};
612+
let entry = iter.next().expect("should parse entry ok");
613+
assert_eq!(
614+
iter.input,
615+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
616+
);
572617
assert_eq!(
573618
entry,
574619
Some(ArangeEntry {
@@ -597,9 +642,15 @@ mod tests {
597642
// Next tuple.
598643
0x09
599644
];
600-
let rest = &mut EndianSlice::new(&buf, LittleEndian);
601-
let entry = ArangeEntry::parse(rest, encoding);
602-
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
645+
let mut iter = ArangeEntryIter {
646+
input: EndianSlice::new(&buf, LittleEndian),
647+
encoding,
648+
};
649+
let entry = iter.next();
650+
assert_eq!(
651+
iter.input,
652+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
653+
);
603654
assert_eq!(entry, Err(Error::AddressOverflow));
604655
}
605656

@@ -619,9 +670,139 @@ mod tests {
619670
// Next tuple.
620671
0x09
621672
];
622-
let rest = &mut EndianSlice::new(&buf, LittleEndian);
623-
let entry = ArangeEntry::parse(rest, encoding);
624-
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
673+
let mut iter = ArangeEntryIter {
674+
input: EndianSlice::new(&buf, LittleEndian),
675+
encoding,
676+
};
677+
let entry = iter.next();
678+
assert_eq!(
679+
iter.input,
680+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
681+
);
625682
assert_eq!(entry, Err(Error::AddressOverflow));
626683
}
684+
685+
#[test]
686+
fn test_parse_entry_tombstone_32() {
687+
let encoding = Encoding {
688+
format: Format::Dwarf32,
689+
version: 2,
690+
address_size: 4,
691+
};
692+
#[rustfmt::skip]
693+
let buf = [
694+
// Address.
695+
0xff, 0xff, 0xff, 0xff,
696+
// Length.
697+
0x05, 0x06, 0x07, 0x08,
698+
// Address.
699+
0x01, 0x02, 0x03, 0x04,
700+
// Length.
701+
0x05, 0x06, 0x07, 0x08,
702+
// Next tuple.
703+
0x09
704+
];
705+
706+
let mut iter = ArangeEntryIter {
707+
input: EndianSlice::new(&buf, LittleEndian),
708+
encoding,
709+
};
710+
let entry = iter.next_raw().unwrap();
711+
assert_eq!(
712+
iter.input,
713+
EndianSlice::new(&buf[buf.len() - 9..], LittleEndian)
714+
);
715+
assert_eq!(
716+
entry,
717+
Some(ArangeEntry {
718+
range: Range {
719+
begin: 0xffff_ffff,
720+
end: 0,
721+
},
722+
length: 0x0807_0605,
723+
})
724+
);
725+
726+
let mut iter = ArangeEntryIter {
727+
input: EndianSlice::new(&buf, LittleEndian),
728+
encoding,
729+
};
730+
let entry = iter.next().unwrap();
731+
assert_eq!(
732+
iter.input,
733+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
734+
);
735+
assert_eq!(
736+
entry,
737+
Some(ArangeEntry {
738+
range: Range {
739+
begin: 0x0403_0201,
740+
end: 0x0403_0201 + 0x0807_0605,
741+
},
742+
length: 0x0807_0605,
743+
})
744+
);
745+
}
746+
747+
#[test]
748+
fn test_parse_entry_tombstone_64() {
749+
let encoding = Encoding {
750+
format: Format::Dwarf32,
751+
version: 2,
752+
address_size: 8,
753+
};
754+
#[rustfmt::skip]
755+
let buf = [
756+
// Address.
757+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
758+
// Length.
759+
0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
760+
// Address.
761+
0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
762+
// Length.
763+
0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
764+
// Next tuple.
765+
0x09
766+
];
767+
768+
let mut iter = ArangeEntryIter {
769+
input: EndianSlice::new(&buf, LittleEndian),
770+
encoding,
771+
};
772+
let entry = iter.next_raw().unwrap();
773+
assert_eq!(
774+
iter.input,
775+
EndianSlice::new(&buf[buf.len() - 17..], LittleEndian)
776+
);
777+
assert_eq!(
778+
entry,
779+
Some(ArangeEntry {
780+
range: Range {
781+
begin: 0xffff_ffff_ffff_ffff,
782+
end: 0,
783+
},
784+
length: 0x0807_0605,
785+
})
786+
);
787+
788+
let mut iter = ArangeEntryIter {
789+
input: EndianSlice::new(&buf, LittleEndian),
790+
encoding,
791+
};
792+
let entry = iter.next().unwrap();
793+
assert_eq!(
794+
iter.input,
795+
EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
796+
);
797+
assert_eq!(
798+
entry,
799+
Some(ArangeEntry {
800+
range: Range {
801+
begin: 0x0403_0201,
802+
end: 0x0403_0201 + 0x0807_0605,
803+
},
804+
length: 0x0807_0605,
805+
})
806+
);
807+
}
627808
}

0 commit comments

Comments
 (0)