1 use crate::common::{Format, SectionId};
2 use crate::constants;
3 use crate::endianity::Endianity;
4 use crate::leb128;
5 use crate::write::{Address, Error, Result};
6 
7 /// A trait for writing the data to a DWARF section.
8 ///
9 /// All write operations append to the section unless otherwise specified.
10 #[allow(clippy::len_without_is_empty)]
11 pub trait Writer {
12     /// The endianity of bytes that are written.
13     type Endian: Endianity;
14 
15     /// Return the endianity of bytes that are written.
endian(&self) -> Self::Endian16     fn endian(&self) -> Self::Endian;
17 
18     /// Return the current section length.
19     ///
20     /// This may be used as an offset for future `write_at` calls.
len(&self) -> usize21     fn len(&self) -> usize;
22 
23     /// Write a slice.
write(&mut self, bytes: &[u8]) -> Result<()>24     fn write(&mut self, bytes: &[u8]) -> Result<()>;
25 
26     /// Write a slice at a given offset.
27     ///
28     /// The write must not extend past the current section length.
write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>29     fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>;
30 
31     /// Write an address.
32     ///
33     /// If the writer supports relocations, then it must provide its own implementation
34     /// of this method.
35     // TODO: use write_reference instead?
write_address(&mut self, address: Address, size: u8) -> Result<()>36     fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
37         match address {
38             Address::Constant(val) => self.write_udata(val, size),
39             Address::Symbol { .. } => Err(Error::InvalidAddress),
40         }
41     }
42 
43     /// Write an address with a `.eh_frame` pointer encoding.
44     ///
45     /// The given size is only used for `DW_EH_PE_absptr` formats.
46     ///
47     /// If the writer supports relocations, then it must provide its own implementation
48     /// of this method.
write_eh_pointer( &mut self, address: Address, eh_pe: constants::DwEhPe, size: u8, ) -> Result<()>49     fn write_eh_pointer(
50         &mut self,
51         address: Address,
52         eh_pe: constants::DwEhPe,
53         size: u8,
54     ) -> Result<()> {
55         match address {
56             Address::Constant(val) => {
57                 // Indirect doesn't matter here.
58                 let val = match eh_pe.application() {
59                     constants::DW_EH_PE_absptr => val,
60                     constants::DW_EH_PE_pcrel => {
61                         // TODO: better handling of sign
62                         let offset = self.len() as u64;
63                         offset.wrapping_sub(val)
64                     }
65                     _ => {
66                         return Err(Error::UnsupportedPointerEncoding(eh_pe));
67                     }
68                 };
69                 self.write_eh_pointer_data(val, eh_pe.format(), size)
70             }
71             Address::Symbol { .. } => Err(Error::InvalidAddress),
72         }
73     }
74 
75     /// Write a value with a `.eh_frame` pointer format.
76     ///
77     /// The given size is only used for `DW_EH_PE_absptr` formats.
78     ///
79     /// This must not be used directly for values that may require relocation.
write_eh_pointer_data( &mut self, val: u64, format: constants::DwEhPe, size: u8, ) -> Result<()>80     fn write_eh_pointer_data(
81         &mut self,
82         val: u64,
83         format: constants::DwEhPe,
84         size: u8,
85     ) -> Result<()> {
86         match format {
87             constants::DW_EH_PE_absptr => self.write_udata(val, size),
88             constants::DW_EH_PE_uleb128 => self.write_uleb128(val),
89             constants::DW_EH_PE_udata2 => self.write_udata(val, 2),
90             constants::DW_EH_PE_udata4 => self.write_udata(val, 4),
91             constants::DW_EH_PE_udata8 => self.write_udata(val, 8),
92             constants::DW_EH_PE_sleb128 => self.write_sleb128(val as i64),
93             constants::DW_EH_PE_sdata2 => self.write_sdata(val as i64, 2),
94             constants::DW_EH_PE_sdata4 => self.write_sdata(val as i64, 4),
95             constants::DW_EH_PE_sdata8 => self.write_sdata(val as i64, 8),
96             _ => {
97                 return Err(Error::UnsupportedPointerEncoding(format));
98             }
99         }
100     }
101 
102     /// Write an offset that is relative to the start of the given section.
103     ///
104     /// If the writer supports relocations, then it must provide its own implementation
105     /// of this method.
write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()>106     fn write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()> {
107         self.write_udata(val as u64, size)
108     }
109 
110     /// Write an offset that is relative to the start of the given section.
111     ///
112     /// If the writer supports relocations, then it must provide its own implementation
113     /// of this method.
write_offset_at( &mut self, offset: usize, val: usize, _section: SectionId, size: u8, ) -> Result<()>114     fn write_offset_at(
115         &mut self,
116         offset: usize,
117         val: usize,
118         _section: SectionId,
119         size: u8,
120     ) -> Result<()> {
121         self.write_udata_at(offset, val as u64, size)
122     }
123 
124     /// Write a reference to a symbol.
125     ///
126     /// If the writer supports symbols, then it must provide its own implementation
127     /// of this method.
write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()>128     fn write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()> {
129         Err(Error::InvalidReference)
130     }
131 
132     /// Write a u8.
write_u8(&mut self, val: u8) -> Result<()>133     fn write_u8(&mut self, val: u8) -> Result<()> {
134         let bytes = [val];
135         self.write(&bytes)
136     }
137 
138     /// Write a u16.
write_u16(&mut self, val: u16) -> Result<()>139     fn write_u16(&mut self, val: u16) -> Result<()> {
140         let mut bytes = [0; 2];
141         self.endian().write_u16(&mut bytes, val);
142         self.write(&bytes)
143     }
144 
145     /// Write a u32.
write_u32(&mut self, val: u32) -> Result<()>146     fn write_u32(&mut self, val: u32) -> Result<()> {
147         let mut bytes = [0; 4];
148         self.endian().write_u32(&mut bytes, val);
149         self.write(&bytes)
150     }
151 
152     /// Write a u64.
write_u64(&mut self, val: u64) -> Result<()>153     fn write_u64(&mut self, val: u64) -> Result<()> {
154         let mut bytes = [0; 8];
155         self.endian().write_u64(&mut bytes, val);
156         self.write(&bytes)
157     }
158 
159     /// Write a u8 at the given offset.
write_u8_at(&mut self, offset: usize, val: u8) -> Result<()>160     fn write_u8_at(&mut self, offset: usize, val: u8) -> Result<()> {
161         let bytes = [val];
162         self.write_at(offset, &bytes)
163     }
164 
165     /// Write a u16 at the given offset.
write_u16_at(&mut self, offset: usize, val: u16) -> Result<()>166     fn write_u16_at(&mut self, offset: usize, val: u16) -> Result<()> {
167         let mut bytes = [0; 2];
168         self.endian().write_u16(&mut bytes, val);
169         self.write_at(offset, &bytes)
170     }
171 
172     /// Write a u32 at the given offset.
write_u32_at(&mut self, offset: usize, val: u32) -> Result<()>173     fn write_u32_at(&mut self, offset: usize, val: u32) -> Result<()> {
174         let mut bytes = [0; 4];
175         self.endian().write_u32(&mut bytes, val);
176         self.write_at(offset, &bytes)
177     }
178 
179     /// Write a u64 at the given offset.
write_u64_at(&mut self, offset: usize, val: u64) -> Result<()>180     fn write_u64_at(&mut self, offset: usize, val: u64) -> Result<()> {
181         let mut bytes = [0; 8];
182         self.endian().write_u64(&mut bytes, val);
183         self.write_at(offset, &bytes)
184     }
185 
186     /// Write unsigned data of the given size.
187     ///
188     /// Returns an error if the value is too large for the size.
189     /// This must not be used directly for values that may require relocation.
write_udata(&mut self, val: u64, size: u8) -> Result<()>190     fn write_udata(&mut self, val: u64, size: u8) -> Result<()> {
191         match size {
192             1 => {
193                 let write_val = val as u8;
194                 if val != u64::from(write_val) {
195                     return Err(Error::ValueTooLarge);
196                 }
197                 self.write_u8(write_val)
198             }
199             2 => {
200                 let write_val = val as u16;
201                 if val != u64::from(write_val) {
202                     return Err(Error::ValueTooLarge);
203                 }
204                 self.write_u16(write_val)
205             }
206             4 => {
207                 let write_val = val as u32;
208                 if val != u64::from(write_val) {
209                     return Err(Error::ValueTooLarge);
210                 }
211                 self.write_u32(write_val)
212             }
213             8 => self.write_u64(val),
214             otherwise => Err(Error::UnsupportedWordSize(otherwise)),
215         }
216     }
217 
218     /// Write signed data of the given size.
219     ///
220     /// Returns an error if the value is too large for the size.
221     /// This must not be used directly for values that may require relocation.
write_sdata(&mut self, val: i64, size: u8) -> Result<()>222     fn write_sdata(&mut self, val: i64, size: u8) -> Result<()> {
223         match size {
224             1 => {
225                 let write_val = val as i8;
226                 if val != i64::from(write_val) {
227                     return Err(Error::ValueTooLarge);
228                 }
229                 self.write_u8(write_val as u8)
230             }
231             2 => {
232                 let write_val = val as i16;
233                 if val != i64::from(write_val) {
234                     return Err(Error::ValueTooLarge);
235                 }
236                 self.write_u16(write_val as u16)
237             }
238             4 => {
239                 let write_val = val as i32;
240                 if val != i64::from(write_val) {
241                     return Err(Error::ValueTooLarge);
242                 }
243                 self.write_u32(write_val as u32)
244             }
245             8 => self.write_u64(val as u64),
246             otherwise => Err(Error::UnsupportedWordSize(otherwise)),
247         }
248     }
249 
250     /// Write a word of the given size at the given offset.
251     ///
252     /// Returns an error if the value is too large for the size.
253     /// This must not be used directly for values that may require relocation.
write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()>254     fn write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()> {
255         match size {
256             1 => {
257                 let write_val = val as u8;
258                 if val != u64::from(write_val) {
259                     return Err(Error::ValueTooLarge);
260                 }
261                 self.write_u8_at(offset, write_val)
262             }
263             2 => {
264                 let write_val = val as u16;
265                 if val != u64::from(write_val) {
266                     return Err(Error::ValueTooLarge);
267                 }
268                 self.write_u16_at(offset, write_val)
269             }
270             4 => {
271                 let write_val = val as u32;
272                 if val != u64::from(write_val) {
273                     return Err(Error::ValueTooLarge);
274                 }
275                 self.write_u32_at(offset, write_val)
276             }
277             8 => self.write_u64_at(offset, val),
278             otherwise => Err(Error::UnsupportedWordSize(otherwise)),
279         }
280     }
281 
282     /// Write an unsigned LEB128 encoded integer.
write_uleb128(&mut self, val: u64) -> Result<()>283     fn write_uleb128(&mut self, val: u64) -> Result<()> {
284         let mut bytes = [0u8; 10];
285         // bytes is long enough so this will never fail.
286         let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap();
287         self.write(&bytes[..len])
288     }
289 
290     /// Read an unsigned LEB128 encoded integer.
write_sleb128(&mut self, val: i64) -> Result<()>291     fn write_sleb128(&mut self, val: i64) -> Result<()> {
292         let mut bytes = [0u8; 10];
293         // bytes is long enough so this will never fail.
294         let len = leb128::write::signed(&mut { &mut bytes[..] }, val).unwrap();
295         self.write(&bytes[..len])
296     }
297 
298     /// Write an initial length according to the given DWARF format.
299     ///
300     /// This will only write a length of zero, since the length isn't
301     /// known yet, and a subsequent call to `write_initial_length_at`
302     /// will write the actual length.
write_initial_length(&mut self, format: Format) -> Result<InitialLengthOffset>303     fn write_initial_length(&mut self, format: Format) -> Result<InitialLengthOffset> {
304         if format == Format::Dwarf64 {
305             self.write_u32(0xffff_ffff)?;
306         }
307         let offset = InitialLengthOffset(self.len());
308         self.write_udata(0, format.word_size())?;
309         Ok(offset)
310     }
311 
312     /// Write an initial length at the given offset according to the given DWARF format.
313     ///
314     /// `write_initial_length` must have previously returned the offset.
write_initial_length_at( &mut self, offset: InitialLengthOffset, length: u64, format: Format, ) -> Result<()>315     fn write_initial_length_at(
316         &mut self,
317         offset: InitialLengthOffset,
318         length: u64,
319         format: Format,
320     ) -> Result<()> {
321         self.write_udata_at(offset.0, length, format.word_size())
322     }
323 }
324 
325 /// The offset at which an initial length should be written.
326 #[derive(Debug, Clone, Copy)]
327 pub struct InitialLengthOffset(usize);
328 
329 #[cfg(test)]
330 mod tests {
331     use super::*;
332     use crate::write;
333     use crate::{BigEndian, LittleEndian};
334     use std::{i64, u64};
335 
336     #[test]
337     #[allow(clippy::cyclomatic_complexity)]
test_writer()338     fn test_writer() {
339         let mut w = write::EndianVec::new(LittleEndian);
340         w.write_address(Address::Constant(0x1122_3344), 4).unwrap();
341         assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
342         assert_eq!(
343             w.write_address(
344                 Address::Symbol {
345                     symbol: 0,
346                     addend: 0
347                 },
348                 4
349             ),
350             Err(Error::InvalidAddress)
351         );
352 
353         let mut w = write::EndianVec::new(LittleEndian);
354         w.write_offset(0x1122_3344, SectionId::DebugInfo, 4)
355             .unwrap();
356         assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
357         w.write_offset_at(1, 0x5566, SectionId::DebugInfo, 2)
358             .unwrap();
359         assert_eq!(w.slice(), &[0x44, 0x66, 0x55, 0x11]);
360 
361         let mut w = write::EndianVec::new(LittleEndian);
362         w.write_u8(0x11).unwrap();
363         w.write_u16(0x2233).unwrap();
364         w.write_u32(0x4455_6677).unwrap();
365         w.write_u64(0x8081_8283_8485_8687).unwrap();
366         #[rustfmt::skip]
367         assert_eq!(w.slice(), &[
368             0x11,
369             0x33, 0x22,
370             0x77, 0x66, 0x55, 0x44,
371             0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
372         ]);
373         w.write_u8_at(14, 0x11).unwrap();
374         w.write_u16_at(12, 0x2233).unwrap();
375         w.write_u32_at(8, 0x4455_6677).unwrap();
376         w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
377         #[rustfmt::skip]
378         assert_eq!(w.slice(), &[
379             0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
380             0x77, 0x66, 0x55, 0x44,
381             0x33, 0x22,
382             0x11,
383         ]);
384 
385         let mut w = write::EndianVec::new(BigEndian);
386         w.write_u8(0x11).unwrap();
387         w.write_u16(0x2233).unwrap();
388         w.write_u32(0x4455_6677).unwrap();
389         w.write_u64(0x8081_8283_8485_8687).unwrap();
390         #[rustfmt::skip]
391         assert_eq!(w.slice(), &[
392             0x11,
393             0x22, 0x33,
394             0x44, 0x55, 0x66, 0x77,
395             0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
396         ]);
397         w.write_u8_at(14, 0x11).unwrap();
398         w.write_u16_at(12, 0x2233).unwrap();
399         w.write_u32_at(8, 0x4455_6677).unwrap();
400         w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
401         #[rustfmt::skip]
402         assert_eq!(w.slice(), &[
403             0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
404             0x44, 0x55, 0x66, 0x77,
405             0x22, 0x33,
406             0x11,
407         ]);
408 
409         let mut w = write::EndianVec::new(LittleEndian);
410         w.write_udata(0x11, 1).unwrap();
411         w.write_udata(0x2233, 2).unwrap();
412         w.write_udata(0x4455_6677, 4).unwrap();
413         w.write_udata(0x8081_8283_8485_8687, 8).unwrap();
414         #[rustfmt::skip]
415         assert_eq!(w.slice(), &[
416             0x11,
417             0x33, 0x22,
418             0x77, 0x66, 0x55, 0x44,
419             0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
420         ]);
421         assert_eq!(w.write_udata(0x100, 1), Err(Error::ValueTooLarge));
422         assert_eq!(w.write_udata(0x1_0000, 2), Err(Error::ValueTooLarge));
423         assert_eq!(w.write_udata(0x1_0000_0000, 4), Err(Error::ValueTooLarge));
424         assert_eq!(w.write_udata(0x00, 3), Err(Error::UnsupportedWordSize(3)));
425         w.write_udata_at(14, 0x11, 1).unwrap();
426         w.write_udata_at(12, 0x2233, 2).unwrap();
427         w.write_udata_at(8, 0x4455_6677, 4).unwrap();
428         w.write_udata_at(0, 0x8081_8283_8485_8687, 8).unwrap();
429         #[rustfmt::skip]
430         assert_eq!(w.slice(), &[
431             0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
432             0x77, 0x66, 0x55, 0x44,
433             0x33, 0x22,
434             0x11,
435         ]);
436         assert_eq!(w.write_udata_at(0, 0x100, 1), Err(Error::ValueTooLarge));
437         assert_eq!(w.write_udata_at(0, 0x1_0000, 2), Err(Error::ValueTooLarge));
438         assert_eq!(
439             w.write_udata_at(0, 0x1_0000_0000, 4),
440             Err(Error::ValueTooLarge)
441         );
442         assert_eq!(
443             w.write_udata_at(0, 0x00, 3),
444             Err(Error::UnsupportedWordSize(3))
445         );
446 
447         let mut w = write::EndianVec::new(LittleEndian);
448         w.write_uleb128(0).unwrap();
449         assert_eq!(w.slice(), &[0]);
450 
451         let mut w = write::EndianVec::new(LittleEndian);
452         w.write_uleb128(u64::MAX).unwrap();
453         assert_eq!(
454             w.slice(),
455             &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1]
456         );
457 
458         let mut w = write::EndianVec::new(LittleEndian);
459         w.write_sleb128(0).unwrap();
460         assert_eq!(w.slice(), &[0]);
461 
462         let mut w = write::EndianVec::new(LittleEndian);
463         w.write_sleb128(i64::MAX).unwrap();
464         assert_eq!(
465             w.slice(),
466             &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0]
467         );
468 
469         let mut w = write::EndianVec::new(LittleEndian);
470         w.write_sleb128(i64::MIN).unwrap();
471         assert_eq!(
472             w.slice(),
473             &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f]
474         );
475 
476         let mut w = write::EndianVec::new(LittleEndian);
477         let offset = w.write_initial_length(Format::Dwarf32).unwrap();
478         assert_eq!(w.slice(), &[0, 0, 0, 0]);
479         w.write_initial_length_at(offset, 0x1122_3344, Format::Dwarf32)
480             .unwrap();
481         assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
482         assert_eq!(
483             w.write_initial_length_at(offset, 0x1_0000_0000, Format::Dwarf32),
484             Err(Error::ValueTooLarge)
485         );
486 
487         let mut w = write::EndianVec::new(LittleEndian);
488         let offset = w.write_initial_length(Format::Dwarf64).unwrap();
489         assert_eq!(w.slice(), &[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0]);
490         w.write_initial_length_at(offset, 0x1122_3344_5566_7788, Format::Dwarf64)
491             .unwrap();
492         assert_eq!(
493             w.slice(),
494             &[0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]
495         );
496     }
497 }
498