1 use alloc::boxed::Box; 2 use alloc::vec::Vec; 3 4 use crate::common::{Encoding, Register}; 5 use crate::constants::{self, DwOp}; 6 use crate::leb128::write::{sleb128_size, uleb128_size}; 7 use crate::write::{ 8 Address, DebugInfoReference, Error, Reference, Result, UnitEntryId, UnitOffsets, Writer, 9 }; 10 11 /// The bytecode for a DWARF expression or location description. 12 #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] 13 pub struct Expression { 14 operations: Vec<Operation>, 15 } 16 17 impl Expression { 18 /// Create an empty expression. 19 #[inline] new() -> Self20 pub fn new() -> Self { 21 Self::default() 22 } 23 24 /// Create an expression from raw bytecode. 25 /// 26 /// This does not support operations that require references, such as `DW_OP_addr`. 27 #[inline] raw(bytecode: Vec<u8>) -> Self28 pub fn raw(bytecode: Vec<u8>) -> Self { 29 Expression { 30 operations: vec![Operation::Raw(bytecode)], 31 } 32 } 33 34 /// Add an operation to the expression. 35 /// 36 /// This should only be used for operations that have no explicit operands. op(&mut self, opcode: DwOp)37 pub fn op(&mut self, opcode: DwOp) { 38 self.operations.push(Operation::Simple(opcode)); 39 } 40 41 /// Add a `DW_OP_addr` operation to the expression. op_addr(&mut self, address: Address)42 pub fn op_addr(&mut self, address: Address) { 43 self.operations.push(Operation::Address(address)); 44 } 45 46 /// Add a `DW_OP_constu` operation to the expression. 47 /// 48 /// This may be emitted as a smaller equivalent operation. op_constu(&mut self, value: u64)49 pub fn op_constu(&mut self, value: u64) { 50 self.operations.push(Operation::UnsignedConstant(value)); 51 } 52 53 /// Add a `DW_OP_consts` operation to the expression. 54 /// 55 /// This may be emitted as a smaller equivalent operation. op_consts(&mut self, value: i64)56 pub fn op_consts(&mut self, value: i64) { 57 self.operations.push(Operation::SignedConstant(value)); 58 } 59 60 /// Add a `DW_OP_const_type` or `DW_OP_GNU_const_type` operation to the expression. op_const_type(&mut self, base: UnitEntryId, value: Box<[u8]>)61 pub fn op_const_type(&mut self, base: UnitEntryId, value: Box<[u8]>) { 62 self.operations.push(Operation::ConstantType(base, value)); 63 } 64 65 /// Add a `DW_OP_fbreg` operation to the expression. op_fbreg(&mut self, offset: i64)66 pub fn op_fbreg(&mut self, offset: i64) { 67 self.operations.push(Operation::FrameOffset(offset)); 68 } 69 70 /// Add a `DW_OP_bregx` operation to the expression. 71 /// 72 /// This may be emitted as a smaller equivalent operation. op_breg(&mut self, register: Register, offset: i64)73 pub fn op_breg(&mut self, register: Register, offset: i64) { 74 self.operations 75 .push(Operation::RegisterOffset(register, offset)); 76 } 77 78 /// Add a `DW_OP_regval_type` or `DW_OP_GNU_regval_type` operation to the expression. 79 /// 80 /// This may be emitted as a smaller equivalent operation. op_regval_type(&mut self, register: Register, base: UnitEntryId)81 pub fn op_regval_type(&mut self, register: Register, base: UnitEntryId) { 82 self.operations 83 .push(Operation::RegisterType(register, base)); 84 } 85 86 /// Add a `DW_OP_pick` operation to the expression. 87 /// 88 /// This may be emitted as a `DW_OP_dup` or `DW_OP_over` operation. op_pick(&mut self, index: u8)89 pub fn op_pick(&mut self, index: u8) { 90 self.operations.push(Operation::Pick(index)); 91 } 92 93 /// Add a `DW_OP_deref` operation to the expression. op_deref(&mut self)94 pub fn op_deref(&mut self) { 95 self.operations.push(Operation::Deref { space: false }); 96 } 97 98 /// Add a `DW_OP_xderef` operation to the expression. op_xderef(&mut self)99 pub fn op_xderef(&mut self) { 100 self.operations.push(Operation::Deref { space: true }); 101 } 102 103 /// Add a `DW_OP_deref_size` operation to the expression. op_deref_size(&mut self, size: u8)104 pub fn op_deref_size(&mut self, size: u8) { 105 self.operations 106 .push(Operation::DerefSize { size, space: false }); 107 } 108 109 /// Add a `DW_OP_xderef_size` operation to the expression. op_xderef_size(&mut self, size: u8)110 pub fn op_xderef_size(&mut self, size: u8) { 111 self.operations 112 .push(Operation::DerefSize { size, space: true }); 113 } 114 115 /// Add a `DW_OP_deref_type` or `DW_OP_GNU_deref_type` operation to the expression. op_deref_type(&mut self, size: u8, base: UnitEntryId)116 pub fn op_deref_type(&mut self, size: u8, base: UnitEntryId) { 117 self.operations.push(Operation::DerefType { 118 size, 119 base, 120 space: false, 121 }); 122 } 123 124 /// Add a `DW_OP_xderef_type` operation to the expression. op_xderef_type(&mut self, size: u8, base: UnitEntryId)125 pub fn op_xderef_type(&mut self, size: u8, base: UnitEntryId) { 126 self.operations.push(Operation::DerefType { 127 size, 128 base, 129 space: true, 130 }); 131 } 132 133 /// Add a `DW_OP_plus_uconst` operation to the expression. op_plus_uconst(&mut self, value: u64)134 pub fn op_plus_uconst(&mut self, value: u64) { 135 self.operations.push(Operation::PlusConstant(value)); 136 } 137 138 /// Add a `DW_OP_skip` operation to the expression. 139 /// 140 /// Returns the index of the operation. The caller must call `set_target` with 141 /// this index to set the target of the branch. op_skip(&mut self) -> usize142 pub fn op_skip(&mut self) -> usize { 143 let index = self.next_index(); 144 self.operations.push(Operation::Skip(!0)); 145 index 146 } 147 148 /// Add a `DW_OP_bra` operation to the expression. 149 /// 150 /// Returns the index of the operation. The caller must call `set_target` with 151 /// this index to set the target of the branch. op_bra(&mut self) -> usize152 pub fn op_bra(&mut self) -> usize { 153 let index = self.next_index(); 154 self.operations.push(Operation::Branch(!0)); 155 index 156 } 157 158 /// Return the index that will be assigned to the next operation. 159 /// 160 /// This can be passed to `set_target`. 161 #[inline] next_index(&self) -> usize162 pub fn next_index(&self) -> usize { 163 self.operations.len() 164 } 165 166 /// Set the target of a `DW_OP_skip` or `DW_OP_bra` operation . set_target(&mut self, operation: usize, new_target: usize)167 pub fn set_target(&mut self, operation: usize, new_target: usize) { 168 debug_assert!(new_target <= self.next_index()); 169 debug_assert_ne!(operation, new_target); 170 match self.operations[operation] { 171 Operation::Skip(ref mut target) | Operation::Branch(ref mut target) => { 172 *target = new_target; 173 } 174 _ => unimplemented!(), 175 } 176 } 177 178 /// Add a `DW_OP_call4` operation to the expression. op_call(&mut self, entry: UnitEntryId)179 pub fn op_call(&mut self, entry: UnitEntryId) { 180 self.operations.push(Operation::Call(entry)); 181 } 182 183 /// Add a `DW_OP_call_ref` operation to the expression. op_call_ref(&mut self, entry: Reference)184 pub fn op_call_ref(&mut self, entry: Reference) { 185 self.operations.push(Operation::CallRef(entry)); 186 } 187 188 /// Add a `DW_OP_convert` or `DW_OP_GNU_convert` operation to the expression. 189 /// 190 /// `base` is the DIE of the base type, or `None` for the generic type. op_convert(&mut self, base: Option<UnitEntryId>)191 pub fn op_convert(&mut self, base: Option<UnitEntryId>) { 192 self.operations.push(Operation::Convert(base)); 193 } 194 195 /// Add a `DW_OP_reinterpret` or `DW_OP_GNU_reinterpret` operation to the expression. 196 /// 197 /// `base` is the DIE of the base type, or `None` for the generic type. op_reinterpret(&mut self, base: Option<UnitEntryId>)198 pub fn op_reinterpret(&mut self, base: Option<UnitEntryId>) { 199 self.operations.push(Operation::Reinterpret(base)); 200 } 201 202 /// Add a `DW_OP_entry_value` or `DW_OP_GNU_entry_value` operation to the expression. op_entry_value(&mut self, expression: Expression)203 pub fn op_entry_value(&mut self, expression: Expression) { 204 self.operations.push(Operation::EntryValue(expression)); 205 } 206 207 /// Add a `DW_OP_regx` operation to the expression. 208 /// 209 /// This may be emitted as a smaller equivalent operation. op_reg(&mut self, register: Register)210 pub fn op_reg(&mut self, register: Register) { 211 self.operations.push(Operation::Register(register)); 212 } 213 214 /// Add a `DW_OP_implicit_value` operation to the expression. op_implicit_value(&mut self, data: Box<[u8]>)215 pub fn op_implicit_value(&mut self, data: Box<[u8]>) { 216 self.operations.push(Operation::ImplicitValue(data)); 217 } 218 219 /// Add a `DW_OP_implicit_pointer` or `DW_OP_GNU_implicit_pointer` operation to the expression. op_implicit_pointer(&mut self, entry: Reference, byte_offset: i64)220 pub fn op_implicit_pointer(&mut self, entry: Reference, byte_offset: i64) { 221 self.operations 222 .push(Operation::ImplicitPointer { entry, byte_offset }); 223 } 224 225 /// Add a `DW_OP_piece` operation to the expression. op_piece(&mut self, size_in_bytes: u64)226 pub fn op_piece(&mut self, size_in_bytes: u64) { 227 self.operations.push(Operation::Piece { size_in_bytes }); 228 } 229 230 /// Add a `DW_OP_bit_piece` operation to the expression. op_bit_piece(&mut self, size_in_bits: u64, bit_offset: u64)231 pub fn op_bit_piece(&mut self, size_in_bits: u64, bit_offset: u64) { 232 self.operations.push(Operation::BitPiece { 233 size_in_bits, 234 bit_offset, 235 }); 236 } 237 238 /// Add a `DW_OP_GNU_parameter_ref` operation to the expression. op_gnu_parameter_ref(&mut self, entry: UnitEntryId)239 pub fn op_gnu_parameter_ref(&mut self, entry: UnitEntryId) { 240 self.operations.push(Operation::ParameterRef(entry)); 241 } 242 size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize243 pub(crate) fn size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize { 244 let mut size = 0; 245 for operation in &self.operations { 246 size += operation.size(encoding, unit_offsets); 247 } 248 size 249 } 250 write<W: Writer>( &self, w: &mut W, mut refs: Option<&mut Vec<DebugInfoReference>>, encoding: Encoding, unit_offsets: Option<&UnitOffsets>, ) -> Result<()>251 pub(crate) fn write<W: Writer>( 252 &self, 253 w: &mut W, 254 mut refs: Option<&mut Vec<DebugInfoReference>>, 255 encoding: Encoding, 256 unit_offsets: Option<&UnitOffsets>, 257 ) -> Result<()> { 258 // TODO: only calculate offsets if needed? 259 let mut offsets = Vec::with_capacity(self.operations.len()); 260 let mut offset = w.len(); 261 for operation in &self.operations { 262 offsets.push(offset); 263 offset += operation.size(encoding, unit_offsets); 264 } 265 offsets.push(offset); 266 for (operation, offset) in self.operations.iter().zip(offsets.iter().copied()) { 267 let refs = match refs { 268 Some(ref mut refs) => Some(&mut **refs), 269 None => None, 270 }; 271 debug_assert_eq!(w.len(), offset); 272 operation.write(w, refs, encoding, unit_offsets, &offsets)?; 273 } 274 Ok(()) 275 } 276 } 277 278 /// A single DWARF operation. 279 // 280 // This type is intentionally not public so that we can change the 281 // representation of expressions as needed. 282 // 283 // Variants are listed in the order they appear in Section 2.5. 284 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 285 enum Operation { 286 /// Raw bytecode. 287 /// 288 /// Does not support references. 289 Raw(Vec<u8>), 290 /// An operation that has no explicit operands. 291 /// 292 /// Represents: 293 /// - `DW_OP_drop`, `DW_OP_swap`, `DW_OP_rot` 294 /// - `DW_OP_push_object_address`, `DW_OP_form_tls_address`, `DW_OP_call_frame_cfa` 295 /// - `DW_OP_abs`, `DW_OP_and`, `DW_OP_div`, `DW_OP_minus`, `DW_OP_mod`, `DW_OP_mul`, 296 /// `DW_OP_neg`, `DW_OP_not`, `DW_OP_or`, `DW_OP_plus`, `DW_OP_shl`, `DW_OP_shr`, 297 /// `DW_OP_shra`, `DW_OP_xor` 298 /// - `DW_OP_le`, `DW_OP_ge`, `DW_OP_eq`, `DW_OP_lt`, `DW_OP_gt`, `DW_OP_ne` 299 /// - `DW_OP_nop` 300 /// - `DW_OP_stack_value` 301 Simple(DwOp), 302 /// Relocate the address if needed, and push it on the stack. 303 /// 304 /// Represents `DW_OP_addr`. 305 Address(Address), 306 /// Push an unsigned constant value on the stack. 307 /// 308 /// Represents `DW_OP_constu`. 309 UnsignedConstant(u64), 310 /// Push a signed constant value on the stack. 311 /// 312 /// Represents `DW_OP_consts`. 313 SignedConstant(i64), 314 /* TODO: requires .debug_addr write support 315 /// Read the address at the given index in `.debug_addr, relocate the address if needed, 316 /// and push it on the stack. 317 /// 318 /// Represents `DW_OP_addrx`. 319 AddressIndex(DebugAddrIndex<Offset>), 320 /// Read the address at the given index in `.debug_addr, and push it on the stack. 321 /// Do not relocate the address. 322 /// 323 /// Represents `DW_OP_constx`. 324 ConstantIndex(DebugAddrIndex<Offset>), 325 */ 326 /// Interpret the value bytes as a constant of a given type, and push it on the stack. 327 /// 328 /// Represents `DW_OP_const_type`. 329 ConstantType(UnitEntryId, Box<[u8]>), 330 /// Compute the frame base (using `DW_AT_frame_base`), add the 331 /// given offset, and then push the resulting sum on the stack. 332 /// 333 /// Represents `DW_OP_fbreg`. 334 FrameOffset(i64), 335 /// Find the contents of the given register, add the offset, and then 336 /// push the resulting sum on the stack. 337 /// 338 /// Represents `DW_OP_bregx`. 339 RegisterOffset(Register, i64), 340 /// Interpret the contents of the given register as a value of the given type, 341 /// and push it on the stack. 342 /// 343 /// Represents `DW_OP_regval_type`. 344 RegisterType(Register, UnitEntryId), 345 /// Copy the item at a stack index and push it on top of the stack. 346 /// 347 /// Represents `DW_OP_pick`, `DW_OP_dup`, and `DW_OP_over`. 348 Pick(u8), 349 /// Pop the topmost value of the stack, dereference it, and push the 350 /// resulting value. 351 /// 352 /// Represents `DW_OP_deref` and `DW_OP_xderef`. 353 Deref { 354 /// True if the dereference operation takes an address space 355 /// argument from the stack; false otherwise. 356 space: bool, 357 }, 358 /// Pop the topmost value of the stack, dereference it to obtain a value 359 /// of the given size, and push the resulting value. 360 /// 361 /// Represents `DW_OP_deref_size` and `DW_OP_xderef_size`. 362 DerefSize { 363 /// True if the dereference operation takes an address space 364 /// argument from the stack; false otherwise. 365 space: bool, 366 /// The size of the data to dereference. 367 size: u8, 368 }, 369 /// Pop the topmost value of the stack, dereference it to obtain a value 370 /// of the given type, and push the resulting value. 371 /// 372 /// Represents `DW_OP_deref_type` and `DW_OP_xderef_type`. 373 DerefType { 374 /// True if the dereference operation takes an address space 375 /// argument from the stack; false otherwise. 376 space: bool, 377 /// The size of the data to dereference. 378 size: u8, 379 /// The DIE of the base type, or `None` for the generic type. 380 base: UnitEntryId, 381 }, 382 /// Add an unsigned constant to the topmost value on the stack. 383 /// 384 /// Represents `DW_OP_plus_uconst`. 385 PlusConstant(u64), 386 /// Unconditional branch to the target location. 387 /// 388 /// The value is the index within the expression of the operation to branch to. 389 /// This will be converted to a relative offset when writing. 390 /// 391 /// Represents `DW_OP_skip`. 392 Skip(usize), 393 /// Branch to the target location if the top of stack is nonzero. 394 /// 395 /// The value is the index within the expression of the operation to branch to. 396 /// This will be converted to a relative offset when writing. 397 /// 398 /// Represents `DW_OP_bra`. 399 Branch(usize), 400 /// Evaluate a DWARF expression as a subroutine. 401 /// 402 /// The expression comes from the `DW_AT_location` attribute of the indicated DIE. 403 /// 404 /// Represents `DW_OP_call4`. 405 Call(UnitEntryId), 406 /// Evaluate an external DWARF expression as a subroutine. 407 /// 408 /// The expression comes from the `DW_AT_location` attribute of the indicated DIE, 409 /// which may be in another compilation unit or shared object. 410 /// 411 /// Represents `DW_OP_call_ref`. 412 CallRef(Reference), 413 /// Pop the top stack entry, convert it to a different type, and push it on the stack. 414 /// 415 /// Represents `DW_OP_convert`. 416 Convert(Option<UnitEntryId>), 417 /// Pop the top stack entry, reinterpret the bits in its value as a different type, 418 /// and push it on the stack. 419 /// 420 /// Represents `DW_OP_reinterpret`. 421 Reinterpret(Option<UnitEntryId>), 422 /// Evaluate an expression at the entry to the current subprogram, and push it on the stack. 423 /// 424 /// Represents `DW_OP_entry_value`. 425 EntryValue(Expression), 426 // FIXME: EntryRegister 427 /// Indicate that this piece's location is in the given register. 428 /// 429 /// Completes the piece or expression. 430 /// 431 /// Represents `DW_OP_regx`. 432 Register(Register), 433 /// The object has no location, but has a known constant value. 434 /// 435 /// Completes the piece or expression. 436 /// 437 /// Represents `DW_OP_implicit_value`. 438 ImplicitValue(Box<[u8]>), 439 /// The object is a pointer to a value which has no actual location, such as 440 /// an implicit value or a stack value. 441 /// 442 /// Completes the piece or expression. 443 /// 444 /// Represents `DW_OP_implicit_pointer`. 445 ImplicitPointer { 446 /// The DIE of the value that this is an implicit pointer into. 447 entry: Reference, 448 /// The byte offset into the value that the implicit pointer points to. 449 byte_offset: i64, 450 }, 451 /// Terminate a piece. 452 /// 453 /// Represents `DW_OP_piece`. 454 Piece { 455 /// The size of this piece in bytes. 456 size_in_bytes: u64, 457 }, 458 /// Terminate a piece with a size in bits. 459 /// 460 /// Represents `DW_OP_bit_piece`. 461 BitPiece { 462 /// The size of this piece in bits. 463 size_in_bits: u64, 464 /// The bit offset of this piece. 465 bit_offset: u64, 466 }, 467 /// This represents a parameter that was optimized out. 468 /// 469 /// The entry is the definition of the parameter, and is matched to 470 /// the `DW_TAG_GNU_call_site_parameter` in the caller that also 471 /// points to the same definition of the parameter. 472 /// 473 /// Represents `DW_OP_GNU_parameter_ref`. 474 ParameterRef(UnitEntryId), 475 } 476 477 impl Operation { size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize478 fn size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize { 479 let base_size = |base| { 480 // Errors are handled during writes. 481 match unit_offsets { 482 Some(offsets) => uleb128_size(offsets.unit_offset(base)), 483 None => 0, 484 } 485 }; 486 1 + match *self { 487 Operation::Raw(ref bytecode) => return bytecode.len(), 488 Operation::Simple(_) => 0, 489 Operation::Address(_) => encoding.address_size as usize, 490 Operation::UnsignedConstant(value) => { 491 if value < 32 { 492 0 493 } else { 494 uleb128_size(value) 495 } 496 } 497 Operation::SignedConstant(value) => sleb128_size(value), 498 Operation::ConstantType(base, ref value) => base_size(base) + 1 + value.len(), 499 Operation::FrameOffset(offset) => sleb128_size(offset), 500 Operation::RegisterOffset(register, offset) => { 501 if register.0 < 32 { 502 sleb128_size(offset) 503 } else { 504 uleb128_size(register.0.into()) + sleb128_size(offset) 505 } 506 } 507 Operation::RegisterType(register, base) => { 508 uleb128_size(register.0.into()) + base_size(base) 509 } 510 Operation::Pick(index) => { 511 if index > 1 { 512 1 513 } else { 514 0 515 } 516 } 517 Operation::Deref { .. } => 0, 518 Operation::DerefSize { .. } => 1, 519 Operation::DerefType { base, .. } => 1 + base_size(base), 520 Operation::PlusConstant(value) => uleb128_size(value), 521 Operation::Skip(_) => 2, 522 Operation::Branch(_) => 2, 523 Operation::Call(_) => 4, 524 Operation::CallRef(_) => encoding.format.word_size() as usize, 525 Operation::Convert(base) => match base { 526 Some(base) => base_size(base), 527 None => 1, 528 }, 529 Operation::Reinterpret(base) => match base { 530 Some(base) => base_size(base), 531 None => 1, 532 }, 533 Operation::EntryValue(ref expression) => { 534 let length = expression.size(encoding, unit_offsets); 535 uleb128_size(length as u64) + length 536 } 537 Operation::Register(register) => { 538 if register.0 < 32 { 539 0 540 } else { 541 uleb128_size(register.0.into()) 542 } 543 } 544 Operation::ImplicitValue(ref data) => uleb128_size(data.len() as u64) + data.len(), 545 Operation::ImplicitPointer { byte_offset, .. } => { 546 encoding.format.word_size() as usize + sleb128_size(byte_offset) 547 } 548 Operation::Piece { size_in_bytes } => uleb128_size(size_in_bytes), 549 Operation::BitPiece { 550 size_in_bits, 551 bit_offset, 552 } => uleb128_size(size_in_bits) + uleb128_size(bit_offset), 553 Operation::ParameterRef(_) => 4, 554 } 555 } 556 write<W: Writer>( &self, w: &mut W, refs: Option<&mut Vec<DebugInfoReference>>, encoding: Encoding, unit_offsets: Option<&UnitOffsets>, offsets: &[usize], ) -> Result<()>557 pub(crate) fn write<W: Writer>( 558 &self, 559 w: &mut W, 560 refs: Option<&mut Vec<DebugInfoReference>>, 561 encoding: Encoding, 562 unit_offsets: Option<&UnitOffsets>, 563 offsets: &[usize], 564 ) -> Result<()> { 565 let entry_offset = |entry| match unit_offsets { 566 Some(offsets) => { 567 let offset = offsets.unit_offset(entry); 568 if offset == 0 { 569 Err(Error::UnsupportedExpressionForwardReference) 570 } else { 571 Ok(offset) 572 } 573 } 574 None => Err(Error::UnsupportedCfiExpressionReference), 575 }; 576 match *self { 577 Operation::Raw(ref bytecode) => w.write(bytecode)?, 578 Operation::Simple(opcode) => w.write_u8(opcode.0)?, 579 Operation::Address(address) => { 580 w.write_u8(constants::DW_OP_addr.0)?; 581 w.write_address(address, encoding.address_size)?; 582 } 583 Operation::UnsignedConstant(value) => { 584 if value < 32 { 585 w.write_u8(constants::DW_OP_lit0.0 + value as u8)?; 586 } else { 587 w.write_u8(constants::DW_OP_constu.0)?; 588 w.write_uleb128(value)?; 589 } 590 } 591 Operation::SignedConstant(value) => { 592 w.write_u8(constants::DW_OP_consts.0)?; 593 w.write_sleb128(value)?; 594 } 595 Operation::ConstantType(base, ref value) => { 596 if encoding.version >= 5 { 597 w.write_u8(constants::DW_OP_const_type.0)?; 598 } else { 599 w.write_u8(constants::DW_OP_GNU_const_type.0)?; 600 } 601 w.write_uleb128(entry_offset(base)?)?; 602 w.write_udata(value.len() as u64, 1)?; 603 w.write(&value)?; 604 } 605 Operation::FrameOffset(offset) => { 606 w.write_u8(constants::DW_OP_fbreg.0)?; 607 w.write_sleb128(offset)?; 608 } 609 Operation::RegisterOffset(register, offset) => { 610 if register.0 < 32 { 611 w.write_u8(constants::DW_OP_breg0.0 + register.0 as u8)?; 612 } else { 613 w.write_u8(constants::DW_OP_bregx.0)?; 614 w.write_uleb128(register.0.into())?; 615 } 616 w.write_sleb128(offset)?; 617 } 618 Operation::RegisterType(register, base) => { 619 if encoding.version >= 5 { 620 w.write_u8(constants::DW_OP_regval_type.0)?; 621 } else { 622 w.write_u8(constants::DW_OP_GNU_regval_type.0)?; 623 } 624 w.write_uleb128(register.0.into())?; 625 w.write_uleb128(entry_offset(base)?)?; 626 } 627 Operation::Pick(index) => match index { 628 0 => w.write_u8(constants::DW_OP_dup.0)?, 629 1 => w.write_u8(constants::DW_OP_over.0)?, 630 _ => { 631 w.write_u8(constants::DW_OP_pick.0)?; 632 w.write_u8(index)?; 633 } 634 }, 635 Operation::Deref { space } => { 636 if space { 637 w.write_u8(constants::DW_OP_xderef.0)?; 638 } else { 639 w.write_u8(constants::DW_OP_deref.0)?; 640 } 641 } 642 Operation::DerefSize { space, size } => { 643 if space { 644 w.write_u8(constants::DW_OP_xderef_size.0)?; 645 } else { 646 w.write_u8(constants::DW_OP_deref_size.0)?; 647 } 648 w.write_u8(size)?; 649 } 650 Operation::DerefType { space, size, base } => { 651 if space { 652 w.write_u8(constants::DW_OP_xderef_type.0)?; 653 } else { 654 if encoding.version >= 5 { 655 w.write_u8(constants::DW_OP_deref_type.0)?; 656 } else { 657 w.write_u8(constants::DW_OP_GNU_deref_type.0)?; 658 } 659 } 660 w.write_u8(size)?; 661 w.write_uleb128(entry_offset(base)?)?; 662 } 663 Operation::PlusConstant(value) => { 664 w.write_u8(constants::DW_OP_plus_uconst.0)?; 665 w.write_uleb128(value)?; 666 } 667 Operation::Skip(target) => { 668 w.write_u8(constants::DW_OP_skip.0)?; 669 let offset = offsets[target] as i64 - (w.len() as i64 + 2); 670 w.write_sdata(offset, 2)?; 671 } 672 Operation::Branch(target) => { 673 w.write_u8(constants::DW_OP_bra.0)?; 674 let offset = offsets[target] as i64 - (w.len() as i64 + 2); 675 w.write_sdata(offset, 2)?; 676 } 677 Operation::Call(entry) => { 678 w.write_u8(constants::DW_OP_call4.0)?; 679 // TODO: this probably won't work in practice, because we may 680 // only know the offsets of base type DIEs at this point. 681 w.write_udata(entry_offset(entry)?, 4)?; 682 } 683 Operation::CallRef(entry) => { 684 w.write_u8(constants::DW_OP_call_ref.0)?; 685 let size = encoding.format.word_size(); 686 match entry { 687 Reference::Symbol(symbol) => w.write_reference(symbol, size)?, 688 Reference::Entry(unit, entry) => { 689 let refs = refs.ok_or(Error::InvalidReference)?; 690 refs.push(DebugInfoReference { 691 offset: w.len(), 692 unit, 693 entry, 694 size, 695 }); 696 w.write_udata(0, size)?; 697 } 698 } 699 } 700 Operation::Convert(base) => { 701 if encoding.version >= 5 { 702 w.write_u8(constants::DW_OP_convert.0)?; 703 } else { 704 w.write_u8(constants::DW_OP_GNU_convert.0)?; 705 } 706 match base { 707 Some(base) => w.write_uleb128(entry_offset(base)?)?, 708 None => w.write_u8(0)?, 709 } 710 } 711 Operation::Reinterpret(base) => { 712 if encoding.version >= 5 { 713 w.write_u8(constants::DW_OP_reinterpret.0)?; 714 } else { 715 w.write_u8(constants::DW_OP_GNU_reinterpret.0)?; 716 } 717 match base { 718 Some(base) => w.write_uleb128(entry_offset(base)?)?, 719 None => w.write_u8(0)?, 720 } 721 } 722 Operation::EntryValue(ref expression) => { 723 if encoding.version >= 5 { 724 w.write_u8(constants::DW_OP_entry_value.0)?; 725 } else { 726 w.write_u8(constants::DW_OP_GNU_entry_value.0)?; 727 } 728 let length = expression.size(encoding, unit_offsets); 729 w.write_uleb128(length as u64)?; 730 expression.write(w, refs, encoding, unit_offsets)?; 731 } 732 Operation::Register(register) => { 733 if register.0 < 32 { 734 w.write_u8(constants::DW_OP_reg0.0 + register.0 as u8)?; 735 } else { 736 w.write_u8(constants::DW_OP_regx.0)?; 737 w.write_uleb128(register.0.into())?; 738 } 739 } 740 Operation::ImplicitValue(ref data) => { 741 w.write_u8(constants::DW_OP_implicit_value.0)?; 742 w.write_uleb128(data.len() as u64)?; 743 w.write(&data)?; 744 } 745 Operation::ImplicitPointer { entry, byte_offset } => { 746 if encoding.version >= 5 { 747 w.write_u8(constants::DW_OP_implicit_pointer.0)?; 748 } else { 749 w.write_u8(constants::DW_OP_GNU_implicit_pointer.0)?; 750 } 751 let size = encoding.format.word_size(); 752 match entry { 753 Reference::Symbol(symbol) => { 754 w.write_reference(symbol, size)?; 755 } 756 Reference::Entry(unit, entry) => { 757 let refs = refs.ok_or(Error::InvalidReference)?; 758 refs.push(DebugInfoReference { 759 offset: w.len(), 760 unit, 761 entry, 762 size, 763 }); 764 w.write_udata(0, size)?; 765 } 766 } 767 w.write_sleb128(byte_offset)?; 768 } 769 Operation::Piece { size_in_bytes } => { 770 w.write_u8(constants::DW_OP_piece.0)?; 771 w.write_uleb128(size_in_bytes)?; 772 } 773 Operation::BitPiece { 774 size_in_bits, 775 bit_offset, 776 } => { 777 w.write_u8(constants::DW_OP_bit_piece.0)?; 778 w.write_uleb128(size_in_bits)?; 779 w.write_uleb128(bit_offset)?; 780 } 781 Operation::ParameterRef(entry) => { 782 w.write_u8(constants::DW_OP_GNU_parameter_ref.0)?; 783 w.write_udata(entry_offset(entry)?, 4)?; 784 } 785 } 786 Ok(()) 787 } 788 } 789 790 #[cfg(feature = "read")] 791 pub(crate) mod convert { 792 use super::*; 793 use crate::common::UnitSectionOffset; 794 use crate::read::{self, Reader}; 795 use crate::write::{ConvertError, ConvertResult, UnitEntryId, UnitId}; 796 use std::collections::HashMap; 797 798 impl Expression { 799 /// Create an expression from the input expression. from<R: Reader<Offset = usize>>( from_expression: read::Expression<R>, encoding: Encoding, dwarf: Option<&read::Dwarf<R>>, unit: Option<&read::Unit<R>>, entry_ids: Option<&HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>>, convert_address: &dyn Fn(u64) -> Option<Address>, ) -> ConvertResult<Expression>800 pub fn from<R: Reader<Offset = usize>>( 801 from_expression: read::Expression<R>, 802 encoding: Encoding, 803 dwarf: Option<&read::Dwarf<R>>, 804 unit: Option<&read::Unit<R>>, 805 entry_ids: Option<&HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>>, 806 convert_address: &dyn Fn(u64) -> Option<Address>, 807 ) -> ConvertResult<Expression> { 808 let convert_unit_offset = |offset: read::UnitOffset| -> ConvertResult<_> { 809 let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?; 810 let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; 811 let id = entry_ids 812 .get(&offset.to_unit_section_offset(unit)) 813 .ok_or(ConvertError::InvalidUnitRef)?; 814 Ok(id.1) 815 }; 816 let convert_debug_info_offset = |offset| -> ConvertResult<_> { 817 // TODO: support relocations 818 let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?; 819 let id = entry_ids 820 .get(&UnitSectionOffset::DebugInfoOffset(offset)) 821 .ok_or(ConvertError::InvalidDebugInfoRef)?; 822 Ok(Reference::Entry(id.0, id.1)) 823 }; 824 825 // Calculate offsets for use in branch/skip operations. 826 let mut offsets = Vec::new(); 827 let mut offset = 0; 828 let mut from_operations = from_expression.clone().operations(encoding); 829 while let Some(_) = from_operations.next()? { 830 offsets.push(offset); 831 offset = from_operations.offset_from(&from_expression); 832 } 833 offsets.push(from_expression.0.len()); 834 835 let mut from_operations = from_expression.clone().operations(encoding); 836 let mut operations = Vec::new(); 837 while let Some(from_operation) = from_operations.next()? { 838 let operation = match from_operation { 839 read::Operation::Deref { 840 base_type, 841 size, 842 space, 843 } => { 844 if base_type.0 != 0 { 845 let base = convert_unit_offset(base_type)?; 846 Operation::DerefType { space, size, base } 847 } else if size != encoding.address_size { 848 Operation::DerefSize { space, size } 849 } else { 850 Operation::Deref { space } 851 } 852 } 853 read::Operation::Drop => Operation::Simple(constants::DW_OP_drop), 854 read::Operation::Pick { index } => Operation::Pick(index), 855 read::Operation::Swap => Operation::Simple(constants::DW_OP_swap), 856 read::Operation::Rot => Operation::Simple(constants::DW_OP_rot), 857 read::Operation::Abs => Operation::Simple(constants::DW_OP_abs), 858 read::Operation::And => Operation::Simple(constants::DW_OP_and), 859 read::Operation::Div => Operation::Simple(constants::DW_OP_div), 860 read::Operation::Minus => Operation::Simple(constants::DW_OP_minus), 861 read::Operation::Mod => Operation::Simple(constants::DW_OP_mod), 862 read::Operation::Mul => Operation::Simple(constants::DW_OP_mul), 863 read::Operation::Neg => Operation::Simple(constants::DW_OP_neg), 864 read::Operation::Not => Operation::Simple(constants::DW_OP_not), 865 read::Operation::Or => Operation::Simple(constants::DW_OP_or), 866 read::Operation::Plus => Operation::Simple(constants::DW_OP_plus), 867 read::Operation::PlusConstant { value } => Operation::PlusConstant(value), 868 read::Operation::Shl => Operation::Simple(constants::DW_OP_shl), 869 read::Operation::Shr => Operation::Simple(constants::DW_OP_shr), 870 read::Operation::Shra => Operation::Simple(constants::DW_OP_shra), 871 read::Operation::Xor => Operation::Simple(constants::DW_OP_xor), 872 read::Operation::Eq => Operation::Simple(constants::DW_OP_eq), 873 read::Operation::Ge => Operation::Simple(constants::DW_OP_ge), 874 read::Operation::Gt => Operation::Simple(constants::DW_OP_gt), 875 read::Operation::Le => Operation::Simple(constants::DW_OP_le), 876 read::Operation::Lt => Operation::Simple(constants::DW_OP_lt), 877 read::Operation::Ne => Operation::Simple(constants::DW_OP_ne), 878 read::Operation::Bra { target } => { 879 let offset = from_operations 880 .offset_from(&from_expression) 881 .wrapping_add(i64::from(target) as usize); 882 let index = offsets 883 .binary_search(&offset) 884 .map_err(|_| ConvertError::InvalidBranchTarget)?; 885 Operation::Branch(index) 886 } 887 read::Operation::Skip { target } => { 888 let offset = from_operations 889 .offset_from(&from_expression) 890 .wrapping_add(i64::from(target) as usize); 891 let index = offsets 892 .binary_search(&offset) 893 .map_err(|_| ConvertError::InvalidBranchTarget)?; 894 Operation::Skip(index) 895 } 896 read::Operation::UnsignedConstant { value } => { 897 Operation::UnsignedConstant(value) 898 } 899 read::Operation::SignedConstant { value } => Operation::SignedConstant(value), 900 read::Operation::Register { register } => Operation::Register(register), 901 read::Operation::RegisterOffset { 902 register, 903 offset, 904 base_type, 905 } => { 906 if base_type.0 != 0 { 907 Operation::RegisterType(register, convert_unit_offset(base_type)?) 908 } else { 909 Operation::RegisterOffset(register, offset) 910 } 911 } 912 read::Operation::FrameOffset { offset } => Operation::FrameOffset(offset), 913 read::Operation::Nop => Operation::Simple(constants::DW_OP_nop), 914 read::Operation::PushObjectAddress => { 915 Operation::Simple(constants::DW_OP_push_object_address) 916 } 917 read::Operation::Call { offset } => match offset { 918 read::DieReference::UnitRef(offset) => { 919 Operation::Call(convert_unit_offset(offset)?) 920 } 921 read::DieReference::DebugInfoRef(offset) => { 922 Operation::CallRef(convert_debug_info_offset(offset)?) 923 } 924 }, 925 read::Operation::TLS => Operation::Simple(constants::DW_OP_form_tls_address), 926 read::Operation::CallFrameCFA => { 927 Operation::Simple(constants::DW_OP_call_frame_cfa) 928 } 929 read::Operation::Piece { 930 size_in_bits, 931 bit_offset: None, 932 } => Operation::Piece { 933 size_in_bytes: size_in_bits / 8, 934 }, 935 read::Operation::Piece { 936 size_in_bits, 937 bit_offset: Some(bit_offset), 938 } => Operation::BitPiece { 939 size_in_bits, 940 bit_offset, 941 }, 942 read::Operation::ImplicitValue { data } => { 943 Operation::ImplicitValue(data.to_slice()?.into_owned().into()) 944 } 945 read::Operation::StackValue => Operation::Simple(constants::DW_OP_stack_value), 946 read::Operation::ImplicitPointer { value, byte_offset } => { 947 let entry = convert_debug_info_offset(value)?; 948 Operation::ImplicitPointer { entry, byte_offset } 949 } 950 read::Operation::EntryValue { expression } => { 951 let expression = Expression::from( 952 read::Expression(expression), 953 encoding, 954 dwarf, 955 unit, 956 entry_ids, 957 convert_address, 958 )?; 959 Operation::EntryValue(expression) 960 } 961 read::Operation::ParameterRef { offset } => { 962 let entry = convert_unit_offset(offset)?; 963 Operation::ParameterRef(entry) 964 } 965 read::Operation::Address { address } => { 966 let address = 967 convert_address(address).ok_or(ConvertError::InvalidAddress)?; 968 Operation::Address(address) 969 } 970 read::Operation::AddressIndex { index } => { 971 let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?; 972 let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; 973 let val = dwarf.address(unit, index)?; 974 let address = convert_address(val).ok_or(ConvertError::InvalidAddress)?; 975 Operation::Address(address) 976 } 977 read::Operation::ConstantIndex { index } => { 978 let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?; 979 let unit = unit.ok_or(ConvertError::UnsupportedOperation)?; 980 let val = dwarf.address(unit, index)?; 981 Operation::UnsignedConstant(val) 982 } 983 read::Operation::TypedLiteral { base_type, value } => { 984 let entry = convert_unit_offset(base_type)?; 985 Operation::ConstantType(entry, value.to_slice()?.into_owned().into()) 986 } 987 read::Operation::Convert { base_type } => { 988 if base_type.0 == 0 { 989 Operation::Convert(None) 990 } else { 991 let entry = convert_unit_offset(base_type)?; 992 Operation::Convert(Some(entry)) 993 } 994 } 995 read::Operation::Reinterpret { base_type } => { 996 if base_type.0 == 0 { 997 Operation::Reinterpret(None) 998 } else { 999 let entry = convert_unit_offset(base_type)?; 1000 Operation::Reinterpret(Some(entry)) 1001 } 1002 } 1003 }; 1004 operations.push(operation); 1005 } 1006 Ok(Expression { operations }) 1007 } 1008 } 1009 } 1010 1011 #[cfg(test)] 1012 #[cfg(feature = "read")] 1013 mod tests { 1014 use super::*; 1015 use crate::common::{ 1016 DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase, 1017 DebugStrOffsetsBase, Format, SectionId, UnitSectionOffset, 1018 }; 1019 use crate::read; 1020 use crate::write::{ 1021 DebugLineStrOffsets, DebugStrOffsets, EndianVec, LineProgram, Sections, Unit, UnitTable, 1022 }; 1023 use crate::LittleEndian; 1024 use std::collections::HashMap; 1025 1026 #[test] test_operation()1027 fn test_operation() { 1028 for &version in &[3, 4, 5] { 1029 for &address_size in &[4, 8] { 1030 for &format in &[Format::Dwarf32, Format::Dwarf64] { 1031 let encoding = Encoding { 1032 format, 1033 version, 1034 address_size, 1035 }; 1036 1037 let mut units = UnitTable::default(); 1038 let unit_id = units.add(Unit::new(encoding, LineProgram::none())); 1039 let unit = units.get_mut(unit_id); 1040 let entry_id = unit.add(unit.root(), constants::DW_TAG_base_type); 1041 let reference = Reference::Entry(unit_id, entry_id); 1042 1043 let mut sections = Sections::new(EndianVec::new(LittleEndian)); 1044 let debug_line_str_offsets = DebugLineStrOffsets::none(); 1045 let debug_str_offsets = DebugStrOffsets::none(); 1046 let debug_info_offsets = units 1047 .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets) 1048 .unwrap(); 1049 let unit_offsets = debug_info_offsets.unit_offsets(unit_id); 1050 let debug_info_offset = unit_offsets.debug_info_offset(entry_id); 1051 let entry_offset = 1052 read::UnitOffset(unit_offsets.unit_offset(entry_id) as usize); 1053 1054 let mut reg_expression = Expression::new(); 1055 reg_expression.op_reg(Register(23)); 1056 1057 let operations: &[(&dyn Fn(&mut Expression), Operation, read::Operation<_>)] = 1058 &[ 1059 ( 1060 &|x| x.op_deref(), 1061 Operation::Deref { space: false }, 1062 read::Operation::Deref { 1063 base_type: read::UnitOffset(0), 1064 size: address_size, 1065 space: false, 1066 }, 1067 ), 1068 ( 1069 &|x| x.op_xderef(), 1070 Operation::Deref { space: true }, 1071 read::Operation::Deref { 1072 base_type: read::UnitOffset(0), 1073 size: address_size, 1074 space: true, 1075 }, 1076 ), 1077 ( 1078 &|x| x.op_deref_size(2), 1079 Operation::DerefSize { 1080 space: false, 1081 size: 2, 1082 }, 1083 read::Operation::Deref { 1084 base_type: read::UnitOffset(0), 1085 size: 2, 1086 space: false, 1087 }, 1088 ), 1089 ( 1090 &|x| x.op_xderef_size(2), 1091 Operation::DerefSize { 1092 space: true, 1093 size: 2, 1094 }, 1095 read::Operation::Deref { 1096 base_type: read::UnitOffset(0), 1097 size: 2, 1098 space: true, 1099 }, 1100 ), 1101 ( 1102 &|x| x.op_deref_type(2, entry_id), 1103 Operation::DerefType { 1104 space: false, 1105 size: 2, 1106 base: entry_id, 1107 }, 1108 read::Operation::Deref { 1109 base_type: entry_offset, 1110 size: 2, 1111 space: false, 1112 }, 1113 ), 1114 ( 1115 &|x| x.op_xderef_type(2, entry_id), 1116 Operation::DerefType { 1117 space: true, 1118 size: 2, 1119 base: entry_id, 1120 }, 1121 read::Operation::Deref { 1122 base_type: entry_offset, 1123 size: 2, 1124 space: true, 1125 }, 1126 ), 1127 ( 1128 &|x| x.op(constants::DW_OP_drop), 1129 Operation::Simple(constants::DW_OP_drop), 1130 read::Operation::Drop, 1131 ), 1132 ( 1133 &|x| x.op_pick(0), 1134 Operation::Pick(0), 1135 read::Operation::Pick { index: 0 }, 1136 ), 1137 ( 1138 &|x| x.op_pick(1), 1139 Operation::Pick(1), 1140 read::Operation::Pick { index: 1 }, 1141 ), 1142 ( 1143 &|x| x.op_pick(2), 1144 Operation::Pick(2), 1145 read::Operation::Pick { index: 2 }, 1146 ), 1147 ( 1148 &|x| x.op(constants::DW_OP_swap), 1149 Operation::Simple(constants::DW_OP_swap), 1150 read::Operation::Swap, 1151 ), 1152 ( 1153 &|x| x.op(constants::DW_OP_rot), 1154 Operation::Simple(constants::DW_OP_rot), 1155 read::Operation::Rot, 1156 ), 1157 ( 1158 &|x| x.op(constants::DW_OP_abs), 1159 Operation::Simple(constants::DW_OP_abs), 1160 read::Operation::Abs, 1161 ), 1162 ( 1163 &|x| x.op(constants::DW_OP_and), 1164 Operation::Simple(constants::DW_OP_and), 1165 read::Operation::And, 1166 ), 1167 ( 1168 &|x| x.op(constants::DW_OP_div), 1169 Operation::Simple(constants::DW_OP_div), 1170 read::Operation::Div, 1171 ), 1172 ( 1173 &|x| x.op(constants::DW_OP_minus), 1174 Operation::Simple(constants::DW_OP_minus), 1175 read::Operation::Minus, 1176 ), 1177 ( 1178 &|x| x.op(constants::DW_OP_mod), 1179 Operation::Simple(constants::DW_OP_mod), 1180 read::Operation::Mod, 1181 ), 1182 ( 1183 &|x| x.op(constants::DW_OP_mul), 1184 Operation::Simple(constants::DW_OP_mul), 1185 read::Operation::Mul, 1186 ), 1187 ( 1188 &|x| x.op(constants::DW_OP_neg), 1189 Operation::Simple(constants::DW_OP_neg), 1190 read::Operation::Neg, 1191 ), 1192 ( 1193 &|x| x.op(constants::DW_OP_not), 1194 Operation::Simple(constants::DW_OP_not), 1195 read::Operation::Not, 1196 ), 1197 ( 1198 &|x| x.op(constants::DW_OP_or), 1199 Operation::Simple(constants::DW_OP_or), 1200 read::Operation::Or, 1201 ), 1202 ( 1203 &|x| x.op(constants::DW_OP_plus), 1204 Operation::Simple(constants::DW_OP_plus), 1205 read::Operation::Plus, 1206 ), 1207 ( 1208 &|x| x.op_plus_uconst(23), 1209 Operation::PlusConstant(23), 1210 read::Operation::PlusConstant { value: 23 }, 1211 ), 1212 ( 1213 &|x| x.op(constants::DW_OP_shl), 1214 Operation::Simple(constants::DW_OP_shl), 1215 read::Operation::Shl, 1216 ), 1217 ( 1218 &|x| x.op(constants::DW_OP_shr), 1219 Operation::Simple(constants::DW_OP_shr), 1220 read::Operation::Shr, 1221 ), 1222 ( 1223 &|x| x.op(constants::DW_OP_shra), 1224 Operation::Simple(constants::DW_OP_shra), 1225 read::Operation::Shra, 1226 ), 1227 ( 1228 &|x| x.op(constants::DW_OP_xor), 1229 Operation::Simple(constants::DW_OP_xor), 1230 read::Operation::Xor, 1231 ), 1232 ( 1233 &|x| x.op(constants::DW_OP_eq), 1234 Operation::Simple(constants::DW_OP_eq), 1235 read::Operation::Eq, 1236 ), 1237 ( 1238 &|x| x.op(constants::DW_OP_ge), 1239 Operation::Simple(constants::DW_OP_ge), 1240 read::Operation::Ge, 1241 ), 1242 ( 1243 &|x| x.op(constants::DW_OP_gt), 1244 Operation::Simple(constants::DW_OP_gt), 1245 read::Operation::Gt, 1246 ), 1247 ( 1248 &|x| x.op(constants::DW_OP_le), 1249 Operation::Simple(constants::DW_OP_le), 1250 read::Operation::Le, 1251 ), 1252 ( 1253 &|x| x.op(constants::DW_OP_lt), 1254 Operation::Simple(constants::DW_OP_lt), 1255 read::Operation::Lt, 1256 ), 1257 ( 1258 &|x| x.op(constants::DW_OP_ne), 1259 Operation::Simple(constants::DW_OP_ne), 1260 read::Operation::Ne, 1261 ), 1262 ( 1263 &|x| x.op_constu(23), 1264 Operation::UnsignedConstant(23), 1265 read::Operation::UnsignedConstant { value: 23 }, 1266 ), 1267 ( 1268 &|x| x.op_consts(-23), 1269 Operation::SignedConstant(-23), 1270 read::Operation::SignedConstant { value: -23 }, 1271 ), 1272 ( 1273 &|x| x.op_reg(Register(23)), 1274 Operation::Register(Register(23)), 1275 read::Operation::Register { 1276 register: Register(23), 1277 }, 1278 ), 1279 ( 1280 &|x| x.op_reg(Register(123)), 1281 Operation::Register(Register(123)), 1282 read::Operation::Register { 1283 register: Register(123), 1284 }, 1285 ), 1286 ( 1287 &|x| x.op_breg(Register(23), 34), 1288 Operation::RegisterOffset(Register(23), 34), 1289 read::Operation::RegisterOffset { 1290 register: Register(23), 1291 offset: 34, 1292 base_type: read::UnitOffset(0), 1293 }, 1294 ), 1295 ( 1296 &|x| x.op_breg(Register(123), 34), 1297 Operation::RegisterOffset(Register(123), 34), 1298 read::Operation::RegisterOffset { 1299 register: Register(123), 1300 offset: 34, 1301 base_type: read::UnitOffset(0), 1302 }, 1303 ), 1304 ( 1305 &|x| x.op_regval_type(Register(23), entry_id), 1306 Operation::RegisterType(Register(23), entry_id), 1307 read::Operation::RegisterOffset { 1308 register: Register(23), 1309 offset: 0, 1310 base_type: entry_offset, 1311 }, 1312 ), 1313 ( 1314 &|x| x.op_fbreg(34), 1315 Operation::FrameOffset(34), 1316 read::Operation::FrameOffset { offset: 34 }, 1317 ), 1318 ( 1319 &|x| x.op(constants::DW_OP_nop), 1320 Operation::Simple(constants::DW_OP_nop), 1321 read::Operation::Nop, 1322 ), 1323 ( 1324 &|x| x.op(constants::DW_OP_push_object_address), 1325 Operation::Simple(constants::DW_OP_push_object_address), 1326 read::Operation::PushObjectAddress, 1327 ), 1328 ( 1329 &|x| x.op_call(entry_id), 1330 Operation::Call(entry_id), 1331 read::Operation::Call { 1332 offset: read::DieReference::UnitRef(entry_offset), 1333 }, 1334 ), 1335 ( 1336 &|x| x.op_call_ref(reference), 1337 Operation::CallRef(reference), 1338 read::Operation::Call { 1339 offset: read::DieReference::DebugInfoRef(debug_info_offset), 1340 }, 1341 ), 1342 ( 1343 &|x| x.op(constants::DW_OP_form_tls_address), 1344 Operation::Simple(constants::DW_OP_form_tls_address), 1345 read::Operation::TLS, 1346 ), 1347 ( 1348 &|x| x.op(constants::DW_OP_call_frame_cfa), 1349 Operation::Simple(constants::DW_OP_call_frame_cfa), 1350 read::Operation::CallFrameCFA, 1351 ), 1352 ( 1353 &|x| x.op_piece(23), 1354 Operation::Piece { size_in_bytes: 23 }, 1355 read::Operation::Piece { 1356 size_in_bits: 23 * 8, 1357 bit_offset: None, 1358 }, 1359 ), 1360 ( 1361 &|x| x.op_bit_piece(23, 34), 1362 Operation::BitPiece { 1363 size_in_bits: 23, 1364 bit_offset: 34, 1365 }, 1366 read::Operation::Piece { 1367 size_in_bits: 23, 1368 bit_offset: Some(34), 1369 }, 1370 ), 1371 ( 1372 &|x| x.op_implicit_value(vec![23].into()), 1373 Operation::ImplicitValue(vec![23].into()), 1374 read::Operation::ImplicitValue { 1375 data: read::EndianSlice::new(&[23], LittleEndian), 1376 }, 1377 ), 1378 ( 1379 &|x| x.op(constants::DW_OP_stack_value), 1380 Operation::Simple(constants::DW_OP_stack_value), 1381 read::Operation::StackValue, 1382 ), 1383 ( 1384 &|x| x.op_implicit_pointer(reference, 23), 1385 Operation::ImplicitPointer { 1386 entry: reference, 1387 byte_offset: 23, 1388 }, 1389 read::Operation::ImplicitPointer { 1390 value: debug_info_offset, 1391 byte_offset: 23, 1392 }, 1393 ), 1394 ( 1395 &|x| x.op_entry_value(reg_expression.clone()), 1396 Operation::EntryValue(reg_expression.clone()), 1397 read::Operation::EntryValue { 1398 expression: read::EndianSlice::new( 1399 &[constants::DW_OP_reg23.0], 1400 LittleEndian, 1401 ), 1402 }, 1403 ), 1404 ( 1405 &|x| x.op_gnu_parameter_ref(entry_id), 1406 Operation::ParameterRef(entry_id), 1407 read::Operation::ParameterRef { 1408 offset: entry_offset, 1409 }, 1410 ), 1411 ( 1412 &|x| x.op_addr(Address::Constant(23)), 1413 Operation::Address(Address::Constant(23)), 1414 read::Operation::Address { address: 23 }, 1415 ), 1416 ( 1417 &|x| x.op_const_type(entry_id, vec![23].into()), 1418 Operation::ConstantType(entry_id, vec![23].into()), 1419 read::Operation::TypedLiteral { 1420 base_type: entry_offset, 1421 value: read::EndianSlice::new(&[23], LittleEndian), 1422 }, 1423 ), 1424 ( 1425 &|x| x.op_convert(None), 1426 Operation::Convert(None), 1427 read::Operation::Convert { 1428 base_type: read::UnitOffset(0), 1429 }, 1430 ), 1431 ( 1432 &|x| x.op_convert(Some(entry_id)), 1433 Operation::Convert(Some(entry_id)), 1434 read::Operation::Convert { 1435 base_type: entry_offset, 1436 }, 1437 ), 1438 ( 1439 &|x| x.op_reinterpret(None), 1440 Operation::Reinterpret(None), 1441 read::Operation::Reinterpret { 1442 base_type: read::UnitOffset(0), 1443 }, 1444 ), 1445 ( 1446 &|x| x.op_reinterpret(Some(entry_id)), 1447 Operation::Reinterpret(Some(entry_id)), 1448 read::Operation::Reinterpret { 1449 base_type: entry_offset, 1450 }, 1451 ), 1452 ]; 1453 1454 let mut expression = Expression::new(); 1455 let start_index = expression.next_index(); 1456 for (f, o, _) in operations { 1457 f(&mut expression); 1458 assert_eq!(expression.operations.last(), Some(o)); 1459 } 1460 1461 let bra_index = expression.op_bra(); 1462 let skip_index = expression.op_skip(); 1463 expression.op(constants::DW_OP_nop); 1464 let end_index = expression.next_index(); 1465 expression.set_target(bra_index, start_index); 1466 expression.set_target(skip_index, end_index); 1467 1468 let mut w = EndianVec::new(LittleEndian); 1469 let mut refs = Vec::new(); 1470 expression 1471 .write(&mut w, Some(&mut refs), encoding, Some(&unit_offsets)) 1472 .unwrap(); 1473 for r in &refs { 1474 assert_eq!(r.unit, unit_id); 1475 assert_eq!(r.entry, entry_id); 1476 w.write_offset_at( 1477 r.offset, 1478 debug_info_offset.0, 1479 SectionId::DebugInfo, 1480 r.size, 1481 ) 1482 .unwrap(); 1483 } 1484 1485 let read_expression = 1486 read::Expression(read::EndianSlice::new(w.slice(), LittleEndian)); 1487 let mut read_operations = read_expression.operations(encoding); 1488 for (_, _, operation) in operations { 1489 assert_eq!(read_operations.next(), Ok(Some(*operation))); 1490 } 1491 1492 // 4 = DW_OP_skip + i16 + DW_OP_nop 1493 assert_eq!( 1494 read_operations.next(), 1495 Ok(Some(read::Operation::Bra { 1496 target: -(w.len() as i16) + 4 1497 })) 1498 ); 1499 // 1 = DW_OP_nop 1500 assert_eq!( 1501 read_operations.next(), 1502 Ok(Some(read::Operation::Skip { target: 1 })) 1503 ); 1504 assert_eq!(read_operations.next(), Ok(Some(read::Operation::Nop))); 1505 assert_eq!(read_operations.next(), Ok(None)); 1506 1507 // Fake the unit. 1508 let unit = read::Unit { 1509 offset: UnitSectionOffset::DebugInfoOffset(DebugInfoOffset(0)), 1510 header: read::UnitHeader::new( 1511 encoding, 1512 0, 1513 DebugAbbrevOffset(0), 1514 read::EndianSlice::new(&[], LittleEndian), 1515 ), 1516 abbreviations: read::Abbreviations::default(), 1517 name: None, 1518 comp_dir: None, 1519 low_pc: 0, 1520 str_offsets_base: DebugStrOffsetsBase(0), 1521 addr_base: DebugAddrBase(0), 1522 loclists_base: DebugLocListsBase(0), 1523 rnglists_base: DebugRngListsBase(0), 1524 line_program: None, 1525 }; 1526 1527 let mut entry_ids = HashMap::new(); 1528 entry_ids.insert( 1529 UnitSectionOffset::DebugInfoOffset(debug_info_offset), 1530 (unit_id, entry_id), 1531 ); 1532 let convert_expression = Expression::from( 1533 read_expression, 1534 encoding, 1535 None, /* dwarf */ 1536 Some(&unit), 1537 Some(&entry_ids), 1538 &|address| Some(Address::Constant(address)), 1539 ) 1540 .unwrap(); 1541 let mut convert_operations = convert_expression.operations.iter(); 1542 for (_, operation, _) in operations { 1543 assert_eq!(convert_operations.next(), Some(operation)); 1544 } 1545 assert_eq!( 1546 convert_operations.next(), 1547 Some(&Operation::Branch(start_index)) 1548 ); 1549 assert_eq!(convert_operations.next(), Some(&Operation::Skip(end_index))); 1550 assert_eq!( 1551 convert_operations.next(), 1552 Some(&Operation::Simple(constants::DW_OP_nop)) 1553 ); 1554 } 1555 } 1556 } 1557 } 1558 } 1559