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