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