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