Coverage Report

Created: 2025-07-18 06:13

/src/gimli/src/read/relocate.rs
Line
Count
Source (jump to first uncovered line)
1
#[cfg(feature = "read")]
2
use alloc::borrow::Cow;
3
use core::fmt::Debug;
4
5
use crate::common::Format;
6
use crate::read::{Reader, ReaderOffset, ReaderOffsetId, Result};
7
8
/// Trait for relocating addresses and offsets while reading a section.
9
pub trait Relocate<T: ReaderOffset = usize> {
10
    /// Relocate an address which was read from the given section offset.
11
    fn relocate_address(&self, offset: T, value: u64) -> Result<u64>;
12
13
    /// Relocate a value which was read from the given section offset.
14
    fn relocate_offset(&self, offset: T, value: T) -> Result<T>;
15
}
16
17
/// A `Reader` which applies relocations to addresses and offsets.
18
///
19
/// This is useful for reading sections which contain relocations,
20
/// such as those in a relocatable object file.
21
/// It is generally not used for reading sections in an executable file.
22
#[derive(Debug, Clone)]
23
pub struct RelocateReader<R: Reader<Offset = usize>, T: Relocate<R::Offset>> {
24
    section: R,
25
    reader: R,
26
    relocate: T,
27
}
28
29
impl<R, T> RelocateReader<R, T>
30
where
31
    R: Reader<Offset = usize>,
32
    T: Relocate<R::Offset>,
33
{
34
    /// Create a new `RelocateReader` which applies relocations to the given section reader.
35
0
    pub fn new(section: R, relocate: T) -> Self {
36
0
        let reader = section.clone();
37
0
        Self {
38
0
            section,
39
0
            reader,
40
0
            relocate,
41
0
        }
42
0
    }
43
}
44
45
impl<R, T> Reader for RelocateReader<R, T>
46
where
47
    R: Reader<Offset = usize>,
48
    T: Relocate<R::Offset> + Debug + Clone,
49
{
50
    type Endian = R::Endian;
51
    type Offset = R::Offset;
52
53
0
    fn read_address(&mut self, address_size: u8) -> Result<u64> {
54
0
        let offset = self.reader.offset_from(&self.section);
55
0
        let value = self.reader.read_address(address_size)?;
56
0
        self.relocate.relocate_address(offset, value)
57
0
    }
58
59
0
    fn read_offset(&mut self, format: Format) -> Result<R::Offset> {
60
0
        let offset = self.reader.offset_from(&self.section);
61
0
        let value = self.reader.read_offset(format)?;
62
0
        self.relocate.relocate_offset(offset, value)
63
0
    }
64
65
0
    fn read_sized_offset(&mut self, size: u8) -> Result<R::Offset> {
66
0
        let offset = self.reader.offset_from(&self.section);
67
0
        let value = self.reader.read_sized_offset(size)?;
68
0
        self.relocate.relocate_offset(offset, value)
69
0
    }
70
71
    #[inline]
72
0
    fn split(&mut self, len: Self::Offset) -> Result<Self> {
73
0
        let mut other = self.clone();
74
0
        other.reader.truncate(len)?;
75
0
        self.reader.skip(len)?;
76
0
        Ok(other)
77
0
    }
78
79
    // All remaining methods simply delegate to `self.reader`.
80
81
    #[inline]
82
0
    fn endian(&self) -> Self::Endian {
83
0
        self.reader.endian()
84
0
    }
85
86
    #[inline]
87
0
    fn len(&self) -> Self::Offset {
88
0
        self.reader.len()
89
0
    }
90
91
    #[inline]
92
0
    fn empty(&mut self) {
93
0
        self.reader.empty()
94
0
    }
95
96
    #[inline]
97
0
    fn truncate(&mut self, len: Self::Offset) -> Result<()> {
98
0
        self.reader.truncate(len)
99
0
    }
100
101
    #[inline]
102
0
    fn offset_from(&self, base: &Self) -> Self::Offset {
103
0
        self.reader.offset_from(&base.reader)
104
0
    }
105
106
    #[inline]
107
0
    fn offset_id(&self) -> ReaderOffsetId {
108
0
        self.reader.offset_id()
109
0
    }
110
111
    #[inline]
112
0
    fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
113
0
        self.reader.lookup_offset_id(id)
114
0
    }
115
116
    #[inline]
117
0
    fn find(&self, byte: u8) -> Result<Self::Offset> {
118
0
        self.reader.find(byte)
119
0
    }
120
121
    #[inline]
122
0
    fn skip(&mut self, len: Self::Offset) -> Result<()> {
123
0
        self.reader.skip(len)
124
0
    }
125
126
    #[cfg(not(feature = "read"))]
127
    fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
128
        super::reader::seal_if_no_alloc::Sealed
129
    }
130
131
    #[cfg(feature = "read")]
132
    #[inline]
133
0
    fn to_slice(&self) -> Result<Cow<'_, [u8]>> {
134
0
        self.reader.to_slice()
135
0
    }
136
137
    #[cfg(feature = "read")]
138
    #[inline]
139
0
    fn to_string(&self) -> Result<Cow<'_, str>> {
140
0
        self.reader.to_string()
141
0
    }
142
143
    #[cfg(feature = "read")]
144
    #[inline]
145
0
    fn to_string_lossy(&self) -> Result<Cow<'_, str>> {
146
0
        self.reader.to_string_lossy()
147
0
    }
148
149
    #[inline]
150
0
    fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
151
0
        self.reader.read_slice(buf)
152
0
    }
153
}