1use crate::common::{
2 DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsBase, DebugStrOffsetsIndex, DwarfFileType,
3 Encoding, SectionId,
4};
5use crate::endianity::Endianity;
6use crate::read::{EndianSlice, Reader, ReaderOffset, Result, Section};
7use crate::Format;
8
9#[derive(Debug, Default, Clone, Copy)]
12pub struct DebugStr<R> {
13 debug_str_section: R,
14}
15
16impl<'input, Endian> DebugStr<EndianSlice<'input, Endian>>
17where
18 Endian: Endianity,
19{
20 pub fn new(debug_str_section: &'input [u8], endian: Endian) -> Self {
35 Self::from(EndianSlice::new(debug_str_section, endian))
36 }
37}
38
39impl<R: Reader> DebugStr<R> {
40 pub fn get_str(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
53 let input = &mut self.debug_str_section.clone();
54 input.skip(offset.0)?;
55 input.read_null_terminated_slice()
56 }
57}
58
59impl<T> DebugStr<T> {
60 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr<R>
66 where
67 F: FnMut(&'a T) -> R,
68 {
69 borrow(&self.debug_str_section).into()
70 }
71}
72
73impl<R> Section<R> for DebugStr<R> {
74 fn id() -> SectionId {
75 SectionId::DebugStr
76 }
77
78 fn reader(&self) -> &R {
79 &self.debug_str_section
80 }
81}
82
83impl<R> From<R> for DebugStr<R> {
84 fn from(debug_str_section: R) -> Self {
85 DebugStr { debug_str_section }
86 }
87}
88
89#[derive(Debug, Default, Clone, Copy)]
91pub struct DebugStrOffsets<R> {
92 section: R,
93}
94
95impl<R: Reader> DebugStrOffsets<R> {
96 pub fn get_str_offset(
113 &self,
114 format: Format,
115 base: DebugStrOffsetsBase<R::Offset>,
116 index: DebugStrOffsetsIndex<R::Offset>,
117 ) -> Result<DebugStrOffset<R::Offset>> {
118 let input = &mut self.section.clone();
119 input.skip(base.0)?;
120 input.skip(R::Offset::from_u64(
121 index.0.into_u64() * u64::from(format.word_size()),
122 )?)?;
123 input.read_offset(format).map(DebugStrOffset)
124 }
125}
126
127impl<T> DebugStrOffsets<T> {
128 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets<R>
134 where
135 F: FnMut(&'a T) -> R,
136 {
137 borrow(&self.section).into()
138 }
139}
140
141impl<R> Section<R> for DebugStrOffsets<R> {
142 fn id() -> SectionId {
143 SectionId::DebugStrOffsets
144 }
145
146 fn reader(&self) -> &R {
147 &self.section
148 }
149}
150
151impl<R> From<R> for DebugStrOffsets<R> {
152 fn from(section: R) -> Self {
153 DebugStrOffsets { section }
154 }
155}
156
157impl<Offset> DebugStrOffsetsBase<Offset>
158where
159 Offset: ReaderOffset,
160{
161 pub fn default_for_encoding_and_file(
164 encoding: Encoding,
165 file_type: DwarfFileType,
166 ) -> DebugStrOffsetsBase<Offset> {
167 if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
168 DebugStrOffsetsBase(Offset::from_u8(
173 encoding.format.initial_length_size() + 2 + 2,
174 ))
175 } else {
176 DebugStrOffsetsBase(Offset::from_u8(0))
177 }
178 }
179}
180
181#[derive(Debug, Default, Clone, Copy)]
184pub struct DebugLineStr<R> {
185 section: R,
186}
187
188impl<'input, Endian> DebugLineStr<EndianSlice<'input, Endian>>
189where
190 Endian: Endianity,
191{
192 pub fn new(debug_line_str_section: &'input [u8], endian: Endian) -> Self {
207 Self::from(EndianSlice::new(debug_line_str_section, endian))
208 }
209}
210
211impl<R: Reader> DebugLineStr<R> {
212 pub fn get_str(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
214 let input = &mut self.section.clone();
215 input.skip(offset.0)?;
216 input.read_null_terminated_slice()
217 }
218}
219
220impl<T> DebugLineStr<T> {
221 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr<R>
227 where
228 F: FnMut(&'a T) -> R,
229 {
230 borrow(&self.section).into()
231 }
232}
233
234impl<R> Section<R> for DebugLineStr<R> {
235 fn id() -> SectionId {
236 SectionId::DebugLineStr
237 }
238
239 fn reader(&self) -> &R {
240 &self.section
241 }
242}
243
244impl<R> From<R> for DebugLineStr<R> {
245 fn from(section: R) -> Self {
246 DebugLineStr { section }
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253 use crate::test_util::GimliSectionMethods;
254 use crate::LittleEndian;
255 use test_assembler::{Endian, Label, LabelMaker, Section};
256
257 #[test]
258 fn test_get_str_offset() {
259 for format in [Format::Dwarf32, Format::Dwarf64] {
260 let zero = Label::new();
261 let length = Label::new();
262 let start = Label::new();
263 let first = Label::new();
264 let end = Label::new();
265 let mut section = Section::with_endian(Endian::Little)
266 .mark(&zero)
267 .initial_length(format, &length, &start)
268 .D16(5)
269 .D16(0)
270 .mark(&first);
271 for i in 0..20 {
272 section = section.word(format.word_size(), 1000 + i);
273 }
274 section = section.mark(&end);
275 length.set_const((&end - &start) as u64);
276
277 let section = section.get_contents().unwrap();
278 let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(§ion, LittleEndian));
279 let base = DebugStrOffsetsBase((&first - &zero) as usize);
280
281 assert_eq!(
282 debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(0)),
283 Ok(DebugStrOffset(1000))
284 );
285 assert_eq!(
286 debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(19)),
287 Ok(DebugStrOffset(1019))
288 );
289 }
290 }
291}