2 DebugLineStrOffset
, DebugStrOffset
, DebugStrOffsetsBase
, DebugStrOffsetsIndex
, SectionId
,
4 use crate::endianity
::Endianity
;
5 use crate::read
::{EndianSlice, Reader, ReaderOffset, Result, Section}
;
8 /// The `DebugStr` struct represents the DWARF strings
9 /// found in the `.debug_str` section.
10 #[derive(Debug, Default, Clone, Copy)]
11 pub struct DebugStr
<R
> {
15 impl<'input
, Endian
> DebugStr
<EndianSlice
<'input
, Endian
>>
19 /// Construct a new `DebugStr` instance from the data in the `.debug_str`
22 /// It is the caller's responsibility to read the `.debug_str` section and
23 /// present it as a `&[u8]` slice. That means using some ELF loader on
24 /// Linux, a Mach-O loader on OSX, etc.
27 /// use gimli::{DebugStr, LittleEndian};
29 /// # let buf = [0x00, 0x01, 0x02, 0x03];
30 /// # let read_debug_str_section_somehow = || &buf;
31 /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
33 pub fn new(debug_str_section
: &'input
[u8], endian
: Endian
) -> Self {
34 Self::from(EndianSlice
::new(debug_str_section
, endian
))
38 impl<R
: Reader
> DebugStr
<R
> {
39 /// Lookup a string from the `.debug_str` section by DebugStrOffset.
42 /// use gimli::{DebugStr, DebugStrOffset, LittleEndian};
44 /// # let buf = [0x01, 0x02, 0x00];
45 /// # let offset = DebugStrOffset(0);
46 /// # let read_debug_str_section_somehow = || &buf;
47 /// # let debug_str_offset_somehow = || offset;
48 /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
49 /// println!("Found string {:?}", debug_str.get_str(debug_str_offset_somehow()));
51 pub fn get_str(&self, offset
: DebugStrOffset
<R
::Offset
>) -> Result
<R
> {
52 let input
= &mut self.debug_str_section
.clone();
53 input
.skip(offset
.0)?
;
54 input
.read_null_terminated_slice()
59 /// Create a `DebugStr` section that references the data in `self`.
61 /// This is useful when `R` implements `Reader` but `T` does not.
66 /// # let load_section = || unimplemented!();
67 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
68 /// let owned_section: gimli::DebugStr<Vec<u8>> = load_section();
69 /// // Create a reference to the DWARF section.
70 /// let section = owned_section.borrow(|section| {
71 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
74 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> DebugStr
<R
>
78 borrow(&self.debug_str_section
).into()
82 impl<R
> Section
<R
> for DebugStr
<R
> {
83 fn id() -> SectionId
{
87 fn reader(&self) -> &R
{
88 &self.debug_str_section
92 impl<R
> From
<R
> for DebugStr
<R
> {
93 fn from(debug_str_section
: R
) -> Self {
94 DebugStr { debug_str_section }
98 /// The raw contents of the `.debug_str_offsets` section.
99 #[derive(Debug, Default, Clone, Copy)]
100 pub struct DebugStrOffsets
<R
> {
104 impl<R
: Reader
> DebugStrOffsets
<R
> {
105 // TODO: add an iterator over the sets of entries in the section.
106 // This is not needed for common usage of the section though.
108 /// Returns the `.debug_str` offset at the given `base` and `index`.
110 /// A set of entries in the `.debug_str_offsets` section consists of a header
111 /// followed by a series of string table offsets.
113 /// The `base` must be the `DW_AT_str_offsets_base` value from the compilation unit DIE.
114 /// This is an offset that points to the first entry following the header.
116 /// The `index` is the value of a `DW_FORM_strx` attribute.
118 /// The `format` must be the DWARF format of the compilation unit. This format must
119 /// match the header. However, note that we do not parse the header to validate this,
120 /// since locating the header is unreliable, and the GNU extensions do not emit it.
121 pub fn get_str_offset(
124 base
: DebugStrOffsetsBase
<R
::Offset
>,
125 index
: DebugStrOffsetsIndex
<R
::Offset
>,
126 ) -> Result
<DebugStrOffset
<R
::Offset
>> {
127 let input
= &mut self.section
.clone();
129 input
.skip(R
::Offset
::from_u64(
130 index
.0.into_u
64() * u64::from(format
.word_size()),
132 input
.read_offset(format
).map(DebugStrOffset
)
136 impl<T
> DebugStrOffsets
<T
> {
137 /// Create a `DebugStrOffsets` section that references the data in `self`.
139 /// This is useful when `R` implements `Reader` but `T` does not.
144 /// # let load_section = || unimplemented!();
145 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
146 /// let owned_section: gimli::DebugStrOffsets<Vec<u8>> = load_section();
147 /// // Create a reference to the DWARF section.
148 /// let section = owned_section.borrow(|section| {
149 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
152 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> DebugStrOffsets
<R
>
154 F
: FnMut(&'a T
) -> R
,
156 borrow(&self.section
).into()
160 impl<R
> Section
<R
> for DebugStrOffsets
<R
> {
161 fn id() -> SectionId
{
162 SectionId
::DebugStrOffsets
165 fn reader(&self) -> &R
{
170 impl<R
> From
<R
> for DebugStrOffsets
<R
> {
171 fn from(section
: R
) -> Self {
172 DebugStrOffsets { section }
176 /// The `DebugLineStr` struct represents the DWARF strings
177 /// found in the `.debug_line_str` section.
178 #[derive(Debug, Default, Clone, Copy)]
179 pub struct DebugLineStr
<R
> {
183 impl<R
: Reader
> DebugLineStr
<R
> {
184 /// Lookup a string from the `.debug_line_str` section by DebugLineStrOffset.
185 pub fn get_str(&self, offset
: DebugLineStrOffset
<R
::Offset
>) -> Result
<R
> {
186 let input
= &mut self.section
.clone();
187 input
.skip(offset
.0)?
;
188 input
.read_null_terminated_slice()
192 impl<T
> DebugLineStr
<T
> {
193 /// Create a `DebugLineStr` section that references the data in `self`.
195 /// This is useful when `R` implements `Reader` but `T` does not.
200 /// # let load_section = || unimplemented!();
201 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
202 /// let owned_section: gimli::DebugLineStr<Vec<u8>> = load_section();
203 /// // Create a reference to the DWARF section.
204 /// let section = owned_section.borrow(|section| {
205 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
208 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> DebugLineStr
<R
>
210 F
: FnMut(&'a T
) -> R
,
212 borrow(&self.section
).into()
216 impl<R
> Section
<R
> for DebugLineStr
<R
> {
217 fn id() -> SectionId
{
218 SectionId
::DebugLineStr
221 fn reader(&self) -> &R
{
226 impl<R
> From
<R
> for DebugLineStr
<R
> {
227 fn from(section
: R
) -> Self {
228 DebugLineStr { section }
235 use crate::test_util
::GimliSectionMethods
;
236 use crate::LittleEndian
;
237 use test_assembler
::{Endian, Label, LabelMaker, Section}
;
240 fn test_get_str_offset() {
241 for format
in vec
![Format
::Dwarf32
, Format
::Dwarf64
] {
242 let zero
= Label
::new();
243 let length
= Label
::new();
244 let start
= Label
::new();
245 let first
= Label
::new();
246 let end
= Label
::new();
247 let mut section
= Section
::with_endian(Endian
::Little
)
249 .initial_length(format
, &length
, &start
)
254 section
= section
.word(format
.word_size(), 1000 + i
);
256 section
= section
.mark(&end
);
257 length
.set_const((&end
- &start
) as u64);
259 let section
= section
.get_contents().unwrap();
260 let debug_str_offsets
= DebugStrOffsets
::from(EndianSlice
::new(§ion
, LittleEndian
));
261 let base
= DebugStrOffsetsBase((&first
- &zero
) as usize);
264 debug_str_offsets
.get_str_offset(format
, base
, DebugStrOffsetsIndex(0)),
265 Ok(DebugStrOffset(1000))
268 debug_str_offsets
.get_str_offset(format
, base
, DebugStrOffsetsIndex(19)),
269 Ok(DebugStrOffset(1019))