1 use crate::common
::{Format, SectionId}
;
3 use crate::endianity
::Endianity
;
5 use crate::write
::{Address, Error, Result}
;
7 /// A trait for writing the data to a DWARF section.
9 /// All write operations append to the section unless otherwise specified.
10 #[allow(clippy::len_without_is_empty)]
12 /// The endianity of bytes that are written.
13 type Endian
: Endianity
;
15 /// Return the endianity of bytes that are written.
16 fn endian(&self) -> Self::Endian
;
18 /// Return the current section length.
20 /// This may be used as an offset for future `write_at` calls.
21 fn len(&self) -> usize;
24 fn write(&mut self, bytes
: &[u8]) -> Result
<()>;
26 /// Write a slice at a given offset.
28 /// The write must not extend past the current section length.
29 fn write_at(&mut self, offset
: usize, bytes
: &[u8]) -> Result
<()>;
33 /// If the writer supports relocations, then it must provide its own implementation
35 // TODO: use write_reference instead?
36 fn write_address(&mut self, address
: Address
, size
: u8) -> Result
<()> {
38 Address
::Constant(val
) => self.write_udata(val
, size
),
39 Address
::Symbol { .. }
=> Err(Error
::InvalidAddress
),
43 /// Write an address with a `.eh_frame` pointer encoding.
45 /// The given size is only used for `DW_EH_PE_absptr` formats.
47 /// If the writer supports relocations, then it must provide its own implementation
52 eh_pe
: constants
::DwEhPe
,
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
)
66 return Err(Error
::UnsupportedPointerEncoding(eh_pe
));
69 self.write_eh_pointer_data(val
, eh_pe
.format(), size
)
71 Address
::Symbol { .. }
=> Err(Error
::InvalidAddress
),
75 /// Write a value with a `.eh_frame` pointer format.
77 /// The given size is only used for `DW_EH_PE_absptr` formats.
79 /// This must not be used directly for values that may require relocation.
80 fn write_eh_pointer_data(
83 format
: constants
::DwEhPe
,
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),
97 return Err(Error
::UnsupportedPointerEncoding(format
));
102 /// Write an offset that is relative to the start of the given section.
104 /// If the writer supports relocations, then it must provide its own implementation
106 fn write_offset(&mut self, val
: usize, _section
: SectionId
, size
: u8) -> Result
<()> {
107 self.write_udata(val
as u64, size
)
110 /// Write an offset that is relative to the start of the given section.
112 /// If the writer supports relocations, then it must provide its own implementation
121 self.write_udata_at(offset
, val
as u64, size
)
124 /// Write a reference to a symbol.
126 /// If the writer supports symbols, then it must provide its own implementation
128 fn write_reference(&mut self, _symbol
: usize, _size
: u8) -> Result
<()> {
129 Err(Error
::InvalidReference
)
133 fn write_u8(&mut self, val
: u8) -> Result
<()> {
139 fn write_u16(&mut self, val
: u16) -> Result
<()> {
140 let mut bytes
= [0; 2];
141 self.endian().write_u16(&mut bytes
, val
);
146 fn write_u32(&mut self, val
: u32) -> Result
<()> {
147 let mut bytes
= [0; 4];
148 self.endian().write_u32(&mut bytes
, val
);
153 fn write_u64(&mut self, val
: u64) -> Result
<()> {
154 let mut bytes
= [0; 8];
155 self.endian().write_u64(&mut bytes
, val
);
159 /// Write a u8 at the given offset.
160 fn write_u8_at(&mut self, offset
: usize, val
: u8) -> Result
<()> {
162 self.write_at(offset
, &bytes
)
165 /// Write a u16 at the given offset.
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
)
172 /// Write a u32 at the given offset.
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
)
179 /// Write a u64 at the given offset.
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
)
186 /// Write unsigned data of the given size.
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.
190 fn write_udata(&mut self, val
: u64, size
: u8) -> Result
<()> {
193 let write_val
= val
as u8;
194 if val
!= u64::from(write_val
) {
195 return Err(Error
::ValueTooLarge
);
197 self.write_u8(write_val
)
200 let write_val
= val
as u16;
201 if val
!= u64::from(write_val
) {
202 return Err(Error
::ValueTooLarge
);
204 self.write_u16(write_val
)
207 let write_val
= val
as u32;
208 if val
!= u64::from(write_val
) {
209 return Err(Error
::ValueTooLarge
);
211 self.write_u32(write_val
)
213 8 => self.write_u64(val
),
214 otherwise
=> Err(Error
::UnsupportedWordSize(otherwise
)),
218 /// Write signed data of the given size.
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.
222 fn write_sdata(&mut self, val
: i64, size
: u8) -> Result
<()> {
225 let write_val
= val
as i8;
226 if val
!= i64::from(write_val
) {
227 return Err(Error
::ValueTooLarge
);
229 self.write_u8(write_val
as u8)
232 let write_val
= val
as i16;
233 if val
!= i64::from(write_val
) {
234 return Err(Error
::ValueTooLarge
);
236 self.write_u16(write_val
as u16)
239 let write_val
= val
as i32;
240 if val
!= i64::from(write_val
) {
241 return Err(Error
::ValueTooLarge
);
243 self.write_u32(write_val
as u32)
245 8 => self.write_u64(val
as u64),
246 otherwise
=> Err(Error
::UnsupportedWordSize(otherwise
)),
250 /// Write a word of the given size at the given offset.
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.
254 fn write_udata_at(&mut self, offset
: usize, val
: u64, size
: u8) -> Result
<()> {
257 let write_val
= val
as u8;
258 if val
!= u64::from(write_val
) {
259 return Err(Error
::ValueTooLarge
);
261 self.write_u8_at(offset
, write_val
)
264 let write_val
= val
as u16;
265 if val
!= u64::from(write_val
) {
266 return Err(Error
::ValueTooLarge
);
268 self.write_u16_at(offset
, write_val
)
271 let write_val
= val
as u32;
272 if val
!= u64::from(write_val
) {
273 return Err(Error
::ValueTooLarge
);
275 self.write_u32_at(offset
, write_val
)
277 8 => self.write_u64_at(offset
, val
),
278 otherwise
=> Err(Error
::UnsupportedWordSize(otherwise
)),
282 /// Write an unsigned LEB128 encoded integer.
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
])
290 /// Read an unsigned LEB128 encoded integer.
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
])
298 /// Write an initial length according to the given DWARF format.
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.
303 fn write_initial_length(&mut self, format
: Format
) -> Result
<InitialLengthOffset
> {
304 if format
== Format
::Dwarf64
{
305 self.write_u32(0xffff_ffff)?
;
307 let offset
= InitialLengthOffset(self.len());
308 self.write_udata(0, format
.word_size())?
;
312 /// Write an initial length at the given offset according to the given DWARF format.
314 /// `write_initial_length` must have previously returned the offset.
315 fn write_initial_length_at(
317 offset
: InitialLengthOffset
,
321 self.write_udata_at(offset
.0, length
, format
.word_size())
325 /// The offset at which an initial length should be written.
326 #[derive(Debug, Clone, Copy)]
327 pub struct InitialLengthOffset(usize);
333 use crate::{BigEndian, LittleEndian}
;
337 #[allow(clippy::cyclomatic_complexity)]
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]);
350 Err(Error
::InvalidAddress
)
353 let mut w
= write
::EndianVec
::new(LittleEndian
);
354 w
.write_offset(0x1122_3344, SectionId
::DebugInfo
, 4)
356 assert_eq
!(w
.slice(), &[0x44, 0x33, 0x22, 0x11]);
357 w
.write_offset_at(1, 0x5566, SectionId
::DebugInfo
, 2)
359 assert_eq
!(w
.slice(), &[0x44, 0x66, 0x55, 0x11]);
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();
367 assert_eq
!(w
.slice(), &[
370 0x77, 0x66, 0x55, 0x44,
371 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
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();
378 assert_eq
!(w
.slice(), &[
379 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
380 0x77, 0x66, 0x55, 0x44,
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();
391 assert_eq
!(w
.slice(), &[
394 0x44, 0x55, 0x66, 0x77,
395 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
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();
402 assert_eq
!(w
.slice(), &[
403 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
404 0x44, 0x55, 0x66, 0x77,
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();
415 assert_eq
!(w
.slice(), &[
418 0x77, 0x66, 0x55, 0x44,
419 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
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();
430 assert_eq
!(w
.slice(), &[
431 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
432 0x77, 0x66, 0x55, 0x44,
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
));
439 w
.write_udata_at(0, 0x1_0000_0000, 4),
440 Err(Error
::ValueTooLarge
)
443 w
.write_udata_at(0, 0x00, 3),
444 Err(Error
::UnsupportedWordSize(3))
447 let mut w
= write
::EndianVec
::new(LittleEndian
);
448 w
.write_uleb128(0).unwrap();
449 assert_eq
!(w
.slice(), &[0]);
451 let mut w
= write
::EndianVec
::new(LittleEndian
);
452 w
.write_uleb128(u64::MAX
).unwrap();
455 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1]
458 let mut w
= write
::EndianVec
::new(LittleEndian
);
459 w
.write_sleb128(0).unwrap();
460 assert_eq
!(w
.slice(), &[0]);
462 let mut w
= write
::EndianVec
::new(LittleEndian
);
463 w
.write_sleb128(i64::MAX
).unwrap();
466 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0]
469 let mut w
= write
::EndianVec
::new(LittleEndian
);
470 w
.write_sleb128(i64::MIN
).unwrap();
473 &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f]
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
)
481 assert_eq
!(w
.slice(), &[0x44, 0x33, 0x22, 0x11]);
483 w
.write_initial_length_at(offset
, 0x1_0000_0000, Format
::Dwarf32
),
484 Err(Error
::ValueTooLarge
)
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
)
494 &[0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]