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