gimli/write/
section.rs

1use std::ops::DerefMut;
2use std::result;
3use std::vec::Vec;
4
5use crate::common::SectionId;
6use crate::write::{
7    DebugAbbrev, DebugFrame, DebugInfo, DebugInfoReference, DebugLine, DebugLineStr, DebugLoc,
8    DebugLocLists, DebugRanges, DebugRngLists, DebugStr, EhFrame, Writer,
9};
10
11macro_rules! define_section {
12    ($name:ident, $offset:ident, $docs:expr) => {
13        #[doc=$docs]
14        #[derive(Debug, Default)]
15        pub struct $name<W: Writer>(pub W);
16
17        impl<W: Writer> $name<W> {
18            /// Return the offset of the next write.
19            pub fn offset(&self) -> $offset {
20                $offset(self.len())
21            }
22        }
23
24        impl<W: Writer> From<W> for $name<W> {
25            #[inline]
26            fn from(w: W) -> Self {
27                $name(w)
28            }
29        }
30
31        impl<W: Writer> Deref for $name<W> {
32            type Target = W;
33
34            #[inline]
35            fn deref(&self) -> &W {
36                &self.0
37            }
38        }
39
40        impl<W: Writer> DerefMut for $name<W> {
41            #[inline]
42            fn deref_mut(&mut self) -> &mut W {
43                &mut self.0
44            }
45        }
46
47        impl<W: Writer> Section<W> for $name<W> {
48            #[inline]
49            fn id(&self) -> SectionId {
50                SectionId::$name
51            }
52        }
53    };
54}
55
56/// Functionality common to all writable DWARF sections.
57pub trait Section<W: Writer>: DerefMut<Target = W> {
58    /// Returns the DWARF section kind for this type.
59    fn id(&self) -> SectionId;
60
61    /// Returns the ELF section name for this type.
62    fn name(&self) -> &'static str {
63        self.id().name()
64    }
65}
66
67/// All of the writable DWARF sections.
68#[derive(Debug, Default)]
69pub struct Sections<W: Writer> {
70    /// The `.debug_abbrev` section.
71    pub debug_abbrev: DebugAbbrev<W>,
72    /// The `.debug_info` section.
73    pub debug_info: DebugInfo<W>,
74    /// The `.debug_line` section.
75    pub debug_line: DebugLine<W>,
76    /// The `.debug_line_str` section.
77    pub debug_line_str: DebugLineStr<W>,
78    /// The `.debug_ranges` section.
79    pub debug_ranges: DebugRanges<W>,
80    /// The `.debug_rnglists` section.
81    pub debug_rnglists: DebugRngLists<W>,
82    /// The `.debug_loc` section.
83    pub debug_loc: DebugLoc<W>,
84    /// The `.debug_loclists` section.
85    pub debug_loclists: DebugLocLists<W>,
86    /// The `.debug_str` section.
87    pub debug_str: DebugStr<W>,
88    /// The `.debug_frame` section.
89    pub debug_frame: DebugFrame<W>,
90    /// The `.eh_frame` section.
91    pub eh_frame: EhFrame<W>,
92    /// Unresolved references in the `.debug_info` section.
93    pub(crate) debug_info_refs: Vec<DebugInfoReference>,
94    /// Unresolved references in the `.debug_loc` section.
95    pub(crate) debug_loc_refs: Vec<DebugInfoReference>,
96    /// Unresolved references in the `.debug_loclists` section.
97    pub(crate) debug_loclists_refs: Vec<DebugInfoReference>,
98}
99
100impl<W: Writer + Clone> Sections<W> {
101    /// Create a new `Sections` using clones of the given `section`.
102    pub fn new(section: W) -> Self {
103        Sections {
104            debug_abbrev: DebugAbbrev(section.clone()),
105            debug_info: DebugInfo(section.clone()),
106            debug_line: DebugLine(section.clone()),
107            debug_line_str: DebugLineStr(section.clone()),
108            debug_ranges: DebugRanges(section.clone()),
109            debug_rnglists: DebugRngLists(section.clone()),
110            debug_loc: DebugLoc(section.clone()),
111            debug_loclists: DebugLocLists(section.clone()),
112            debug_str: DebugStr(section.clone()),
113            debug_frame: DebugFrame(section.clone()),
114            eh_frame: EhFrame(section),
115            debug_info_refs: Vec::new(),
116            debug_loc_refs: Vec::new(),
117            debug_loclists_refs: Vec::new(),
118        }
119    }
120}
121
122impl<W: Writer> Sections<W> {
123    /// Get the section with the given `id`.
124    pub fn get(&self, id: SectionId) -> Option<&W> {
125        match id {
126            SectionId::DebugAbbrev => Some(&self.debug_abbrev.0),
127            SectionId::DebugInfo => Some(&self.debug_info.0),
128            SectionId::DebugLine => Some(&self.debug_line.0),
129            SectionId::DebugLineStr => Some(&self.debug_line_str.0),
130            SectionId::DebugRanges => Some(&self.debug_ranges.0),
131            SectionId::DebugRngLists => Some(&self.debug_rnglists.0),
132            SectionId::DebugLoc => Some(&self.debug_loc.0),
133            SectionId::DebugLocLists => Some(&self.debug_loclists.0),
134            SectionId::DebugStr => Some(&self.debug_str.0),
135            SectionId::DebugFrame => Some(&self.debug_frame.0),
136            SectionId::EhFrame => Some(&self.eh_frame.0),
137            _ => None,
138        }
139    }
140
141    /// Get the section with the given `id`.
142    pub fn get_mut(&mut self, id: SectionId) -> Option<&mut W> {
143        match id {
144            SectionId::DebugAbbrev => Some(&mut self.debug_abbrev.0),
145            SectionId::DebugInfo => Some(&mut self.debug_info.0),
146            SectionId::DebugLine => Some(&mut self.debug_line.0),
147            SectionId::DebugLineStr => Some(&mut self.debug_line_str.0),
148            SectionId::DebugRanges => Some(&mut self.debug_ranges.0),
149            SectionId::DebugRngLists => Some(&mut self.debug_rnglists.0),
150            SectionId::DebugLoc => Some(&mut self.debug_loc.0),
151            SectionId::DebugLocLists => Some(&mut self.debug_loclists.0),
152            SectionId::DebugStr => Some(&mut self.debug_str.0),
153            SectionId::DebugFrame => Some(&mut self.debug_frame.0),
154            SectionId::EhFrame => Some(&mut self.eh_frame.0),
155            _ => None,
156        }
157    }
158
159    /// For each section, call `f` once with a shared reference.
160    pub fn for_each<'a, F, E>(&'a self, mut f: F) -> result::Result<(), E>
161    where
162        F: FnMut(SectionId, &'a W) -> result::Result<(), E>,
163    {
164        macro_rules! f {
165            ($s:expr) => {
166                f($s.id(), &$s)
167            };
168        }
169        // Ordered so that earlier sections do not reference later sections.
170        f!(self.debug_abbrev)?;
171        f!(self.debug_str)?;
172        f!(self.debug_line_str)?;
173        f!(self.debug_line)?;
174        f!(self.debug_ranges)?;
175        f!(self.debug_rnglists)?;
176        f!(self.debug_loc)?;
177        f!(self.debug_loclists)?;
178        f!(self.debug_info)?;
179        f!(self.debug_frame)?;
180        f!(self.eh_frame)?;
181        Ok(())
182    }
183
184    /// For each section, call `f` once with a mutable reference.
185    pub fn for_each_mut<'a, F, E>(&'a mut self, mut f: F) -> result::Result<(), E>
186    where
187        F: FnMut(SectionId, &'a mut W) -> result::Result<(), E>,
188    {
189        macro_rules! f {
190            ($s:expr) => {
191                f($s.id(), &mut $s)
192            };
193        }
194        // Ordered so that earlier sections do not reference later sections.
195        f!(self.debug_abbrev)?;
196        f!(self.debug_str)?;
197        f!(self.debug_line_str)?;
198        f!(self.debug_line)?;
199        f!(self.debug_ranges)?;
200        f!(self.debug_rnglists)?;
201        f!(self.debug_loc)?;
202        f!(self.debug_loclists)?;
203        f!(self.debug_info)?;
204        f!(self.debug_frame)?;
205        f!(self.eh_frame)?;
206        Ok(())
207    }
208}
209
210#[cfg(test)]
211#[cfg(feature = "read")]
212mod tests {
213    use super::*;
214    use crate::{read, write::EndianVec, Endianity};
215
216    impl<E: Endianity> Sections<EndianVec<E>> {
217        pub(crate) fn read(&self, endian: E) -> read::Dwarf<read::EndianSlice<'_, E>> {
218            read::Dwarf::load(|section_id| -> read::Result<_> {
219                Ok(read::EndianSlice::new(
220                    self.get(section_id).map(|w| w.slice()).unwrap_or_default(),
221                    endian,
222                ))
223            })
224            .unwrap()
225        }
226    }
227}