1use crate::common::{Format, SectionId};
2use crate::constants;
3use crate::endianity::Endianity;
4use crate::leb128::write::Leb128;
5use crate::write::{Address, Error, Result};
6
7#[allow(clippy::len_without_is_empty)]
11pub trait Writer {
12 type Endian: Endianity;
14
15 fn endian(&self) -> Self::Endian;
17
18 fn len(&self) -> usize;
22
23 fn write(&mut self, bytes: &[u8]) -> Result<()>;
25
26 fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>;
30
31 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 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 let val = match eh_pe.application() {
59 constants::DW_EH_PE_absptr => val,
60 constants::DW_EH_PE_pcrel => {
61 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 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 fn write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()> {
105 self.write_udata(val as u64, size)
106 }
107
108 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 fn write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()> {
127 Err(Error::InvalidReference)
128 }
129
130 fn write_u8(&mut self, val: u8) -> Result<()> {
132 let bytes = [val];
133 self.write(&bytes)
134 }
135
136 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 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 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 fn write_u128(&mut self, val: u128) -> Result<()> {
159 let mut bytes = [0; 16];
160 self.endian().write_u128(&mut bytes, val);
161 self.write(&bytes)
162 }
163
164 fn write_u8_at(&mut self, offset: usize, val: u8) -> Result<()> {
166 let bytes = [val];
167 self.write_at(offset, &bytes)
168 }
169
170 fn write_u16_at(&mut self, offset: usize, val: u16) -> Result<()> {
172 let mut bytes = [0; 2];
173 self.endian().write_u16(&mut bytes, val);
174 self.write_at(offset, &bytes)
175 }
176
177 fn write_u32_at(&mut self, offset: usize, val: u32) -> Result<()> {
179 let mut bytes = [0; 4];
180 self.endian().write_u32(&mut bytes, val);
181 self.write_at(offset, &bytes)
182 }
183
184 fn write_u64_at(&mut self, offset: usize, val: u64) -> Result<()> {
186 let mut bytes = [0; 8];
187 self.endian().write_u64(&mut bytes, val);
188 self.write_at(offset, &bytes)
189 }
190
191 fn write_u128_at(&mut self, offset: usize, val: u128) -> Result<()> {
193 let mut bytes = [0; 16];
194 self.endian().write_u128(&mut bytes, val);
195 self.write_at(offset, &bytes)
196 }
197
198 fn write_udata(&mut self, val: u64, size: u8) -> Result<()> {
203 match size {
204 1 => {
205 let write_val = val as u8;
206 if val != u64::from(write_val) {
207 return Err(Error::ValueTooLarge);
208 }
209 self.write_u8(write_val)
210 }
211 2 => {
212 let write_val = val as u16;
213 if val != u64::from(write_val) {
214 return Err(Error::ValueTooLarge);
215 }
216 self.write_u16(write_val)
217 }
218 4 => {
219 let write_val = val as u32;
220 if val != u64::from(write_val) {
221 return Err(Error::ValueTooLarge);
222 }
223 self.write_u32(write_val)
224 }
225 8 => self.write_u64(val),
226 otherwise => Err(Error::UnsupportedWordSize(otherwise)),
227 }
228 }
229
230 fn write_sdata(&mut self, val: i64, size: u8) -> Result<()> {
235 match size {
236 1 => {
237 let write_val = val as i8;
238 if val != i64::from(write_val) {
239 return Err(Error::ValueTooLarge);
240 }
241 self.write_u8(write_val as u8)
242 }
243 2 => {
244 let write_val = val as i16;
245 if val != i64::from(write_val) {
246 return Err(Error::ValueTooLarge);
247 }
248 self.write_u16(write_val as u16)
249 }
250 4 => {
251 let write_val = val as i32;
252 if val != i64::from(write_val) {
253 return Err(Error::ValueTooLarge);
254 }
255 self.write_u32(write_val as u32)
256 }
257 8 => self.write_u64(val as u64),
258 otherwise => Err(Error::UnsupportedWordSize(otherwise)),
259 }
260 }
261
262 fn write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()> {
267 match size {
268 1 => {
269 let write_val = val as u8;
270 if val != u64::from(write_val) {
271 return Err(Error::ValueTooLarge);
272 }
273 self.write_u8_at(offset, write_val)
274 }
275 2 => {
276 let write_val = val as u16;
277 if val != u64::from(write_val) {
278 return Err(Error::ValueTooLarge);
279 }
280 self.write_u16_at(offset, write_val)
281 }
282 4 => {
283 let write_val = val as u32;
284 if val != u64::from(write_val) {
285 return Err(Error::ValueTooLarge);
286 }
287 self.write_u32_at(offset, write_val)
288 }
289 8 => self.write_u64_at(offset, val),
290 otherwise => Err(Error::UnsupportedWordSize(otherwise)),
291 }
292 }
293
294 fn write_uleb128(&mut self, val: u64) -> Result<()> {
296 self.write(Leb128::unsigned(val).bytes())
297 }
298
299 fn write_sleb128(&mut self, val: i64) -> Result<()> {
301 self.write(Leb128::signed(val).bytes())
302 }
303
304 fn write_initial_length(&mut self, format: Format) -> Result<InitialLengthOffset> {
310 if format == Format::Dwarf64 {
311 self.write_u32(0xffff_ffff)?;
312 }
313 let offset = InitialLengthOffset(self.len());
314 self.write_udata(0, format.word_size())?;
315 Ok(offset)
316 }
317
318 fn write_initial_length_at(
322 &mut self,
323 offset: InitialLengthOffset,
324 length: u64,
325 format: Format,
326 ) -> Result<()> {
327 self.write_udata_at(offset.0, length, format.word_size())
328 }
329}
330
331#[derive(Debug, Clone, Copy)]
333pub struct InitialLengthOffset(usize);
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 use crate::write;
339 use crate::{BigEndian, LittleEndian};
340
341 #[test]
342 fn test_writer() {
343 let mut w = write::EndianVec::new(LittleEndian);
344 w.write_address(Address::Constant(0x1122_3344), 4).unwrap();
345 assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
346 assert_eq!(
347 w.write_address(
348 Address::Symbol {
349 symbol: 0,
350 addend: 0
351 },
352 4
353 ),
354 Err(Error::InvalidAddress)
355 );
356
357 let mut w = write::EndianVec::new(LittleEndian);
358 w.write_offset(0x1122_3344, SectionId::DebugInfo, 4)
359 .unwrap();
360 assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
361 w.write_offset_at(1, 0x5566, SectionId::DebugInfo, 2)
362 .unwrap();
363 assert_eq!(w.slice(), &[0x44, 0x66, 0x55, 0x11]);
364
365 let mut w = write::EndianVec::new(LittleEndian);
366 w.write_u8(0x11).unwrap();
367 w.write_u16(0x2233).unwrap();
368 w.write_u32(0x4455_6677).unwrap();
369 w.write_u64(0x8081_8283_8485_8687).unwrap();
370 #[rustfmt::skip]
371 assert_eq!(w.slice(), &[
372 0x11,
373 0x33, 0x22,
374 0x77, 0x66, 0x55, 0x44,
375 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
376 ]);
377 w.write_u8_at(14, 0x11).unwrap();
378 w.write_u16_at(12, 0x2233).unwrap();
379 w.write_u32_at(8, 0x4455_6677).unwrap();
380 w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
381 #[rustfmt::skip]
382 assert_eq!(w.slice(), &[
383 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
384 0x77, 0x66, 0x55, 0x44,
385 0x33, 0x22,
386 0x11,
387 ]);
388
389 let mut w = write::EndianVec::new(BigEndian);
390 w.write_u8(0x11).unwrap();
391 w.write_u16(0x2233).unwrap();
392 w.write_u32(0x4455_6677).unwrap();
393 w.write_u64(0x8081_8283_8485_8687).unwrap();
394 #[rustfmt::skip]
395 assert_eq!(w.slice(), &[
396 0x11,
397 0x22, 0x33,
398 0x44, 0x55, 0x66, 0x77,
399 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
400 ]);
401 w.write_u8_at(14, 0x11).unwrap();
402 w.write_u16_at(12, 0x2233).unwrap();
403 w.write_u32_at(8, 0x4455_6677).unwrap();
404 w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
405 #[rustfmt::skip]
406 assert_eq!(w.slice(), &[
407 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
408 0x44, 0x55, 0x66, 0x77,
409 0x22, 0x33,
410 0x11,
411 ]);
412
413 let mut w = write::EndianVec::new(LittleEndian);
414 w.write_udata(0x11, 1).unwrap();
415 w.write_udata(0x2233, 2).unwrap();
416 w.write_udata(0x4455_6677, 4).unwrap();
417 w.write_udata(0x8081_8283_8485_8687, 8).unwrap();
418 #[rustfmt::skip]
419 assert_eq!(w.slice(), &[
420 0x11,
421 0x33, 0x22,
422 0x77, 0x66, 0x55, 0x44,
423 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
424 ]);
425 assert_eq!(w.write_udata(0x100, 1), Err(Error::ValueTooLarge));
426 assert_eq!(w.write_udata(0x1_0000, 2), Err(Error::ValueTooLarge));
427 assert_eq!(w.write_udata(0x1_0000_0000, 4), Err(Error::ValueTooLarge));
428 assert_eq!(w.write_udata(0x00, 3), Err(Error::UnsupportedWordSize(3)));
429 w.write_udata_at(14, 0x11, 1).unwrap();
430 w.write_udata_at(12, 0x2233, 2).unwrap();
431 w.write_udata_at(8, 0x4455_6677, 4).unwrap();
432 w.write_udata_at(0, 0x8081_8283_8485_8687, 8).unwrap();
433 #[rustfmt::skip]
434 assert_eq!(w.slice(), &[
435 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
436 0x77, 0x66, 0x55, 0x44,
437 0x33, 0x22,
438 0x11,
439 ]);
440 assert_eq!(w.write_udata_at(0, 0x100, 1), Err(Error::ValueTooLarge));
441 assert_eq!(w.write_udata_at(0, 0x1_0000, 2), Err(Error::ValueTooLarge));
442 assert_eq!(
443 w.write_udata_at(0, 0x1_0000_0000, 4),
444 Err(Error::ValueTooLarge)
445 );
446 assert_eq!(
447 w.write_udata_at(0, 0x00, 3),
448 Err(Error::UnsupportedWordSize(3))
449 );
450
451 let mut w = write::EndianVec::new(LittleEndian);
452 w.write_uleb128(0).unwrap();
453 assert_eq!(w.slice(), &[0]);
454
455 let mut w = write::EndianVec::new(LittleEndian);
456 w.write_uleb128(u64::MAX).unwrap();
457 assert_eq!(
458 w.slice(),
459 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1]
460 );
461
462 let mut w = write::EndianVec::new(LittleEndian);
463 w.write_sleb128(0).unwrap();
464 assert_eq!(w.slice(), &[0]);
465
466 let mut w = write::EndianVec::new(LittleEndian);
467 w.write_sleb128(i64::MAX).unwrap();
468 assert_eq!(
469 w.slice(),
470 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0]
471 );
472
473 let mut w = write::EndianVec::new(LittleEndian);
474 w.write_sleb128(i64::MIN).unwrap();
475 assert_eq!(
476 w.slice(),
477 &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f]
478 );
479
480 let mut w = write::EndianVec::new(LittleEndian);
481 let offset = w.write_initial_length(Format::Dwarf32).unwrap();
482 assert_eq!(w.slice(), &[0, 0, 0, 0]);
483 w.write_initial_length_at(offset, 0x1122_3344, Format::Dwarf32)
484 .unwrap();
485 assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
486 assert_eq!(
487 w.write_initial_length_at(offset, 0x1_0000_0000, Format::Dwarf32),
488 Err(Error::ValueTooLarge)
489 );
490
491 let mut w = write::EndianVec::new(LittleEndian);
492 let offset = w.write_initial_length(Format::Dwarf64).unwrap();
493 assert_eq!(w.slice(), &[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0]);
494 w.write_initial_length_at(offset, 0x1122_3344_5566_7788, Format::Dwarf64)
495 .unwrap();
496 assert_eq!(
497 w.slice(),
498 &[
499 0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
500 ]
501 );
502 }
503}