Skip to content

Commit

Permalink
Delete support for segment selectors
Browse files Browse the repository at this point in the history
segment selectors are deprecated in DWARF6, and we already don't
properly support them in some other sections.
https://dwarfstd.org/issues/220427.1.html

This will simplify adding support for different address types.
  • Loading branch information
philipc committed Jul 4, 2024
1 parent 345d60f commit 72ac45f
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 249 deletions.
13 changes: 2 additions & 11 deletions crates/examples/src/bin/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2162,25 +2162,16 @@ fn dump_aranges<R: Reader, W: Write>(
while let Some(header) = headers.next()? {
writeln!(
w,
"Address Range Header: length = 0x{:08x}, version = 0x{:04x}, cu_offset = 0x{:08x}, addr_size = 0x{:02x}, seg_size = 0x{:02x}",
"Address Range Header: length = 0x{:08x}, version = 0x{:04x}, cu_offset = 0x{:08x}, addr_size = 0x{:02x}",
header.length(),
header.encoding().version,
header.debug_info_offset().0,
header.encoding().address_size,
header.segment_size(),
)?;
let mut aranges = header.entries();
while let Some(arange) = aranges.next()? {
let range = arange.range();
if let Some(segment) = arange.segment() {
writeln!(
w,
"[0x{:016x}, 0x{:016x}) segment 0x{:x}",
range.begin, range.end, segment
)?;
} else {
writeln!(w, "[0x{:016x}, 0x{:016x})", range.begin, range.end)?;
}
writeln!(w, "[0x{:016x}, 0x{:016x})", range.begin, range.end)?;
}
}
Ok(())
Expand Down
2 changes: 0 additions & 2 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ pub struct Encoding {
/// The size of an address.
pub address_size: u8,

// The size of a segment selector.
// TODO: pub segment_size: u8,
/// Whether the DWARF format is 32- or 64-bit.
pub format: Format,

Expand Down
118 changes: 20 additions & 98 deletions src/read/aranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ where
encoding: Encoding,
length: Offset,
debug_info_offset: DebugInfoOffset<Offset>,
segment_size: u8,
entries: R,
}

Expand All @@ -160,16 +159,17 @@ where
let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
let address_size = rest.read_u8()?;
let segment_size = rest.read_u8()?;
if segment_size != 0 {
return Err(Error::UnsupportedSegmentSize);
}

// unit_length + version + offset + address_size + segment_size
let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;

// The first tuple following the header in each set begins at an offset that is
// a multiple of the size of a single tuple (that is, the size of a segment selector
// plus twice the size of an address).
// a multiple of the size of a single tuple (that is, twice the size of an address).
let tuple_length = address_size
.checked_mul(2)
.and_then(|x| x.checked_add(segment_size))
.ok_or(Error::InvalidAddressRange)?;
if tuple_length == 0 {
return Err(Error::InvalidAddressRange);
Expand All @@ -185,14 +185,12 @@ where
format,
version,
address_size,
// TODO: segment_size
};
Ok(ArangeHeader {
offset,
encoding,
length,
debug_info_offset,
segment_size,
entries: rest,
})
}
Expand All @@ -215,12 +213,6 @@ where
self.encoding
}

/// Return the segment size for this set of entries.
#[inline]
pub fn segment_size(&self) -> u8 {
self.segment_size
}

/// Return the offset into the .debug_info section for this set of arange entries.
#[inline]
pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
Expand All @@ -233,7 +225,6 @@ where
ArangeEntryIter {
input: self.entries.clone(),
encoding: self.encoding,
segment_size: self.segment_size,
}
}
}
Expand All @@ -246,7 +237,6 @@ where
pub struct ArangeEntryIter<R: Reader> {
input: R,
encoding: Encoding,
segment_size: u8,
}

impl<R: Reader> ArangeEntryIter<R> {
Expand All @@ -261,7 +251,7 @@ impl<R: Reader> ArangeEntryIter<R> {
return Ok(None);
}

match ArangeEntry::parse(&mut self.input, self.encoding, self.segment_size) {
match ArangeEntry::parse(&mut self.input, self.encoding) {
Ok(Some(entry)) => Ok(Some(entry)),
Ok(None) => {
self.input.empty();
Expand All @@ -288,60 +278,37 @@ impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
/// A single parsed arange.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ArangeEntry {
segment: Option<u64>,
range: Range,
length: u64,
}

impl ArangeEntry {
/// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
fn parse<R: Reader>(
input: &mut R,
encoding: Encoding,
segment_size: u8,
) -> Result<Option<Self>> {
fn parse<R: Reader>(input: &mut R, encoding: Encoding) -> Result<Option<Self>> {
let address_size = encoding.address_size;

let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
let tuple_length = R::Offset::from_u8(2 * address_size);
if tuple_length > input.len() {
input.empty();
return Ok(None);
}

let segment = if segment_size != 0 {
input.read_address(segment_size)?
} else {
0
};
let begin = input.read_address(address_size)?;
let length = input.read_address(address_size)?;
// Calculate end now so that we can handle overflow.
// TODO: handle 32-bit address overflow as well.
let end = begin.checked_add(length).ok_or(Error::AddressOverflow)?;
let range = Range { begin, end };

match (segment, begin, length) {
match (begin, length) {
// This is meant to be a null terminator, but in practice it can occur
// before the end, possibly due to a linker omitting a function and
// leaving an unrelocated entry.
(0, 0, 0) => Self::parse(input, encoding, segment_size),
_ => Ok(Some(ArangeEntry {
segment: if segment_size != 0 {
Some(segment)
} else {
None
},
range: Range { begin, end },
length,
})),
(0, 0) => Self::parse(input, encoding),
_ => Ok(Some(ArangeEntry { range, length })),
}
}

/// Return the segment selector of this arange.
#[inline]
pub fn segment(&self) -> Option<u64> {
self.segment
}

/// Return the beginning address of this arange.
#[inline]
pub fn address(&self) -> u64 {
Expand Down Expand Up @@ -426,20 +393,19 @@ mod tests {
fn test_parse_header_ok() {
#[rustfmt::skip]
let buf = [
// 32-bit length = 32.
0x20, 0x00, 0x00, 0x00,
// 32-bit length = 28 (8 bytes header, 4 bytes padding, 16 bytes tuple data).
0x1c, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x01, 0x02, 0x03, 0x04,
// Address size.
0x08,
// Segment size.
0x04,
// Length to here = 12, tuple length = 20.
0x00,
// Length to here = 12, tuple length = 16.
// Padding to tuple length multiple = 4.
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,

// Dummy arange tuple data.
0x20, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -472,9 +438,8 @@ mod tests {
version: 2,
address_size: 8,
},
length: 0x20,
length: 0x1c,
debug_info_offset: DebugInfoOffset(0x0403_0201),
segment_size: 4,
entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
}
);
Expand All @@ -493,7 +458,7 @@ mod tests {
// Address size.
0xff,
// Segment size.
0xff,
0x00,
// Length to here = 12, tuple length = 20.
// Padding to tuple length multiple = 4.
0x10, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -566,52 +531,13 @@ mod tests {
version: 2,
address_size: 4,
};
let segment_size = 0;
let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: None,
range: Range {
begin: 0x0403_0201,
end: 0x0403_0201 + 0x0807_0605,
},
length: 0x0807_0605,
})
);
}

#[test]
fn test_parse_entry_segment() {
let encoding = Encoding {
format: Format::Dwarf32,
version: 2,
address_size: 4,
};
let segment_size = 8;
#[rustfmt::skip]
let buf = [
// Segment.
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
// Address.
0x01, 0x02, 0x03, 0x04,
// Length.
0x05, 0x06, 0x07, 0x08,
// Next tuple.
0x09
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
let entry = ArangeEntry::parse(rest, encoding).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: Some(0x1817_1615_1413_1211),
range: Range {
begin: 0x0403_0201,
end: 0x0403_0201 + 0x0807_0605,
Expand All @@ -628,7 +554,6 @@ mod tests {
version: 2,
address_size: 4,
};
let segment_size = 0;
#[rustfmt::skip]
let buf = [
// Zero tuple.
Expand All @@ -641,13 +566,11 @@ mod tests {
0x09
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
let entry = ArangeEntry::parse(rest, encoding).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: None,
range: Range {
begin: 0x0403_0201,
end: 0x0403_0201 + 0x0807_0605,
Expand All @@ -664,7 +587,6 @@ mod tests {
version: 2,
address_size: 8,
};
let segment_size = 0;
#[rustfmt::skip]
let buf = [
// Address.
Expand All @@ -675,7 +597,7 @@ mod tests {
0x09
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry = ArangeEntry::parse(rest, encoding, segment_size);
let entry = ArangeEntry::parse(rest, encoding);
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(entry, Err(Error::AddressOverflow));
}
Expand Down
Loading

0 comments on commit 72ac45f

Please sign in to comment.