Skip to content

Commit

Permalink
read/line: handle 0 tombstone address during sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Sep 3, 2024
1 parent f49dfeb commit aea8345
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/read/aranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ impl<R: Reader> ArangeEntryIter<R> {
#[doc(hidden)]
pub fn convert_raw(&self, mut entry: ArangeEntry) -> Result<Option<ArangeEntry>> {
// Skip tombstone entries.
// DWARF specifies a tombstone value of -1, but many linkers use 0.
// However, 0 may be a valid address, so the caller must handle that case.
let address_size = self.encoding.address_size;
let tombstone_address = !0 >> (64 - self.encoding.address_size * 8);
if entry.range.begin == tombstone_address {
Expand Down
23 changes: 14 additions & 9 deletions src/read/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,12 +828,16 @@ impl LineRow {
}

LineInstruction::SetAddress(address) => {
// If the address is a tombstone, then skip instructions until the next address.
// DWARF specifies a tombstone value of -1, but many linkers use 0.
// However, 0 may be a valid address, so we only skip that if we have previously
// seen a higher address. Additionally, gold may keep the relocation addend,
// so we treat all lower addresses as tombstones instead of just 0.
// This works because DWARF specifies that addresses are monotonically increasing
// within a sequence; the alternative is to return an error.
let tombstone_address = !0 >> (64 - program.header().encoding.address_size * 8);
self.tombstone = address == tombstone_address;
self.tombstone = address < self.address || address == tombstone_address;
if !self.tombstone {
if address < self.address {
return Err(Error::InvalidAddressRange);
}
self.address = address;
self.op_index.0 = 0;
}
Expand Down Expand Up @@ -2877,13 +2881,14 @@ mod tests {
#[test]
fn test_exec_set_address_backwards() {
let header = make_test_header(EndianSlice::new(&[], LittleEndian));
let mut registers = LineRow::new(&header);
registers.address = 1;
let mut initial_registers = LineRow::new(&header);
initial_registers.address = 1;
let opcode = LineInstruction::SetAddress(0);

let mut program = IncompleteLineProgram { header };
let result = registers.execute(opcode, &mut program);
assert_eq!(result, Err(Error::InvalidAddressRange));
let mut expected_registers = initial_registers;
expected_registers.tombstone = true;

assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
}

#[test]
Expand Down
3 changes: 3 additions & 0 deletions src/read/loclists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,9 @@ impl<R: Reader> LocListIter<R> {
) -> Result<Option<LocationListEntry<R>>> {
let address_size = self.raw.encoding.address_size;
let mask = u64::ones_sized(address_size);
// Skip tombstone entries.
// DWARF specifies a tombstone value of -1 or -2, but many linkers use 0 or 1.
// However, 0/1 may be a valid address, so the caller must handle that case.
let tombstone = if self.raw.encoding.version <= 4 {
mask - 1
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/read/rnglists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,9 @@ impl<R: Reader> RngListIter<R> {
pub fn convert_raw(&mut self, raw_range: RawRngListEntry<R::Offset>) -> Result<Option<Range>> {
let address_size = self.raw.encoding.address_size;
let mask = u64::ones_sized(address_size);
// Skip tombstone entries.
// DWARF specifies a tombstone value of -1 or -2, but many linkers use 0 or 1.
// However, 0/1 may be a valid address, so the caller must handle that case.
let tombstone = if self.raw.encoding.version <= 4 {
mask - 1
} else {
Expand Down

0 comments on commit aea8345

Please sign in to comment.