10b2c9d72SSingleAccretion use crate::debug::Reader;
290ac295eSAlex Crichton use crate::debug::transform::utils::resolve_die_ref;
30b2c9d72SSingleAccretion 
487c33c29SAlex Crichton use super::address_transform::AddressTransform;
5*c4a38d67SPhilip Craig use super::dbi_log;
690ac295eSAlex Crichton use super::expression::{CompiledExpression, FunctionFrameInfo, compile_expression};
787c33c29SAlex Crichton use super::range_info_builder::RangeInfoBuilder;
80b2c9d72SSingleAccretion use super::unit::InheritedAttr;
987c33c29SAlex Crichton use cranelift_codegen::isa::TargetIsa;
10*c4a38d67SPhilip Craig use gimli::{AttributeValue, UnitOffset, write};
11*c4a38d67SPhilip Craig use wasmtime_environ::error::Error;
1287c33c29SAlex Crichton 
1387c33c29SAlex Crichton #[derive(Debug)]
14*c4a38d67SPhilip Craig pub(crate) struct EntryAttributesContext<'a> {
15*c4a38d67SPhilip Craig     pub subprograms: &'a mut InheritedAttr<SubprogramContext>,
16*c4a38d67SPhilip Craig     pub frame_base: Option<&'a CompiledExpression>,
1787c33c29SAlex Crichton }
1887c33c29SAlex Crichton 
190b2c9d72SSingleAccretion #[derive(Debug)]
200b2c9d72SSingleAccretion pub struct SubprogramContext {
210b2c9d72SSingleAccretion     pub obj_ptr: UnitOffset,
220b2c9d72SSingleAccretion     pub param_num: isize,
230b2c9d72SSingleAccretion }
240b2c9d72SSingleAccretion 
is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool2587c33c29SAlex Crichton fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool {
2687c33c29SAlex Crichton     match attr_name {
2787c33c29SAlex Crichton         gimli::DW_AT_location
2887c33c29SAlex Crichton         | gimli::DW_AT_string_length
2987c33c29SAlex Crichton         | gimli::DW_AT_return_addr
3087c33c29SAlex Crichton         | gimli::DW_AT_data_member_location
3187c33c29SAlex Crichton         | gimli::DW_AT_frame_base
3287c33c29SAlex Crichton         | gimli::DW_AT_segment
3387c33c29SAlex Crichton         | gimli::DW_AT_static_link
3487c33c29SAlex Crichton         | gimli::DW_AT_use_location
3587c33c29SAlex Crichton         | gimli::DW_AT_vtable_elem_location => true,
3687c33c29SAlex Crichton         _ => false,
3787c33c29SAlex Crichton     }
3887c33c29SAlex Crichton }
3987c33c29SAlex Crichton 
clone_die_attributes<'a>( convert_unit: &mut gimli::write::ConvertUnit<Reader<'a>>, entry: &gimli::write::ConvertUnitEntry<Reader<'a>>, addr_tr: &AddressTransform, frame_info: Option<&FunctionFrameInfo>, out_entry_id: write::UnitEntryId, subprogram_range_builder: Option<RangeInfoBuilder>, scope_ranges: Option<&Vec<(u64, u64)>>, mut attr_context: EntryAttributesContext, isa: &dyn TargetIsa, ) -> Result<(), Error>400b2c9d72SSingleAccretion pub(crate) fn clone_die_attributes<'a>(
41*c4a38d67SPhilip Craig     convert_unit: &mut gimli::write::ConvertUnit<Reader<'a>>,
42*c4a38d67SPhilip Craig     entry: &gimli::write::ConvertUnitEntry<Reader<'a>>,
43bd7b59daSPhilip Craig     addr_tr: &AddressTransform,
4487c33c29SAlex Crichton     frame_info: Option<&FunctionFrameInfo>,
450b2c9d72SSingleAccretion     out_entry_id: write::UnitEntryId,
4687c33c29SAlex Crichton     subprogram_range_builder: Option<RangeInfoBuilder>,
4787c33c29SAlex Crichton     scope_ranges: Option<&Vec<(u64, u64)>>,
48*c4a38d67SPhilip Craig     mut attr_context: EntryAttributesContext,
4987c33c29SAlex Crichton     isa: &dyn TargetIsa,
500b2c9d72SSingleAccretion ) -> Result<(), Error> {
51*c4a38d67SPhilip Craig     let unit = entry.read_unit;
5287c33c29SAlex Crichton     let unit_encoding = unit.encoding();
5387c33c29SAlex Crichton 
5487c33c29SAlex Crichton     let range_info = if let Some(subprogram_range_builder) = subprogram_range_builder {
5587c33c29SAlex Crichton         subprogram_range_builder
5687c33c29SAlex Crichton     } else {
5787c33c29SAlex Crichton         // FIXME for CU: currently address_transform operate on a single
5887c33c29SAlex Crichton         // function range, and when CU spans multiple ranges the
5987c33c29SAlex Crichton         // transformation may be incomplete.
60*c4a38d67SPhilip Craig         RangeInfoBuilder::from(entry)?
6187c33c29SAlex Crichton     };
62*c4a38d67SPhilip Craig     range_info.build(addr_tr, convert_unit.unit, out_entry_id);
630b2c9d72SSingleAccretion 
640b2c9d72SSingleAccretion     let mut is_obj_ptr = false;
65*c4a38d67SPhilip Craig     prepare_die_context(entry, &mut attr_context, &mut is_obj_ptr)?;
6687c33c29SAlex Crichton 
67*c4a38d67SPhilip Craig     for attr in &entry.attrs {
687e15d87bSPhilip Craig         match attr.name() {
697e15d87bSPhilip Craig             gimli::DW_AT_low_pc | gimli::DW_AT_high_pc | gimli::DW_AT_ranges => {
707e15d87bSPhilip Craig                 // Handled by RangeInfoBuilder.
7187c33c29SAlex Crichton                 continue;
7287c33c29SAlex Crichton             }
730b2c9d72SSingleAccretion             gimli::DW_AT_object_pointer => {
740b2c9d72SSingleAccretion                 // Our consumers cannot handle 'this' typed as a non-pointer (recall
750b2c9d72SSingleAccretion                 // we translate all pointers to wrapper types), making it unusable.
760b2c9d72SSingleAccretion                 // To remedy this, we 'strip' instance-ness off of methods by removing
770b2c9d72SSingleAccretion                 // DW_AT_object_pointer and renaming 'this' to '__this'.
78*c4a38d67SPhilip Craig                 if let Some(ref mut subprogram) =
79*c4a38d67SPhilip Craig                     attr_context.subprograms.top_with_depth_mut(entry.depth)
800b2c9d72SSingleAccretion                 {
810b2c9d72SSingleAccretion                     // We expect this to reference a child entry in the same unit.
820b2c9d72SSingleAccretion                     if let Some(unit_offs) = match attr.value() {
83*c4a38d67SPhilip Craig                         AttributeValue::DebugInfoRef(di_ref) => di_ref.to_unit_offset(&unit.header),
840b2c9d72SSingleAccretion                         AttributeValue::UnitRef(unit_ref) => Some(unit_ref),
850b2c9d72SSingleAccretion                         _ => None,
860b2c9d72SSingleAccretion                     } {
870b2c9d72SSingleAccretion                         subprogram.obj_ptr = unit_offs;
880b2c9d72SSingleAccretion                         dbi_log!("Stripped DW_AT_object_pointer");
890b2c9d72SSingleAccretion                         continue;
900b2c9d72SSingleAccretion                     }
910b2c9d72SSingleAccretion                 }
920b2c9d72SSingleAccretion             }
937e15d87bSPhilip Craig             _ => {}
9487c33c29SAlex Crichton         }
950b2c9d72SSingleAccretion 
960b2c9d72SSingleAccretion         if is_obj_ptr {
970b2c9d72SSingleAccretion             match attr.name() {
980b2c9d72SSingleAccretion                 gimli::DW_AT_artificial => {
990b2c9d72SSingleAccretion                     dbi_log!("Object pointer: stripped DW_AT_artificial");
1000b2c9d72SSingleAccretion                     continue;
1010b2c9d72SSingleAccretion                 }
1020b2c9d72SSingleAccretion                 gimli::DW_AT_name => {
103bd7b59daSPhilip Craig                     let old_name: &str = &unit.attr_string(attr.value())?.to_string_lossy();
1040b2c9d72SSingleAccretion                     let new_name = format!("__{old_name}");
1050b2c9d72SSingleAccretion                     dbi_log!(
1060b2c9d72SSingleAccretion                         "Object pointer: renamed '{}' -> '{}'",
1070b2c9d72SSingleAccretion                         old_name,
1080b2c9d72SSingleAccretion                         new_name.as_str()
1090b2c9d72SSingleAccretion                     );
1100b2c9d72SSingleAccretion 
111*c4a38d67SPhilip Craig                     let attr_value =
112*c4a38d67SPhilip Craig                         write::AttributeValue::StringRef(convert_unit.strings.add(new_name));
113*c4a38d67SPhilip Craig                     convert_unit
114*c4a38d67SPhilip Craig                         .unit
1150b2c9d72SSingleAccretion                         .get_mut(out_entry_id)
1160b2c9d72SSingleAccretion                         .set(gimli::DW_AT_name, attr_value);
1170b2c9d72SSingleAccretion                     continue;
1180b2c9d72SSingleAccretion                 }
1190b2c9d72SSingleAccretion                 _ => {}
1200b2c9d72SSingleAccretion             }
1210b2c9d72SSingleAccretion         }
1220b2c9d72SSingleAccretion 
1237e15d87bSPhilip Craig         let attr_value = attr.value();
1247e15d87bSPhilip Craig         let out_attr_value = match attr_value {
12587c33c29SAlex Crichton             AttributeValue::Addr(u) => {
12687c33c29SAlex Crichton                 let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
12787c33c29SAlex Crichton                 write::AttributeValue::Address(addr)
12887c33c29SAlex Crichton             }
12987c33c29SAlex Crichton             AttributeValue::DebugAddrIndex(i) => {
130bd7b59daSPhilip Craig                 let u = unit.address(i)?;
13187c33c29SAlex Crichton                 let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
13287c33c29SAlex Crichton                 write::AttributeValue::Address(addr)
13387c33c29SAlex Crichton             }
1347e15d87bSPhilip Craig             AttributeValue::RangeListsRef(_) | AttributeValue::DebugRngListsIndex(_) => {
135bd7b59daSPhilip Craig                 let r = unit.attr_ranges_offset(attr_value)?.unwrap();
136bd7b59daSPhilip Craig                 let range_info = RangeInfoBuilder::from_ranges_ref(unit, r)?;
137*c4a38d67SPhilip Craig                 let range_list_id = range_info.build_ranges(addr_tr, &mut convert_unit.unit.ranges);
13887c33c29SAlex Crichton                 write::AttributeValue::RangeListRef(range_list_id)
13987c33c29SAlex Crichton             }
1407e15d87bSPhilip Craig             AttributeValue::LocationListsRef(_) | AttributeValue::DebugLocListsIndex(_) => {
141*c4a38d67SPhilip Craig                 let mut locs = unit.attr_locations(attr_value)?.unwrap();
142*c4a38d67SPhilip Craig                 let frame_base = attr_context.frame_base;
14387c33c29SAlex Crichton 
14487c33c29SAlex Crichton                 let mut result: Option<Vec<_>> = None;
14587c33c29SAlex Crichton                 while let Some(loc) = locs.next()? {
14687c33c29SAlex Crichton                     if let Some(expr) = compile_expression(&loc.data, unit_encoding, frame_base)? {
14787c33c29SAlex Crichton                         let chunk = expr
14887c33c29SAlex Crichton                             .build_with_locals(
14987c33c29SAlex Crichton                                 &[(loc.range.begin, loc.range.end)],
15087c33c29SAlex Crichton                                 addr_tr,
15187c33c29SAlex Crichton                                 frame_info,
15287c33c29SAlex Crichton                                 isa,
15387c33c29SAlex Crichton                             )
154d2c9d2a2SSingleAccretion                             .expressions
15587c33c29SAlex Crichton                             .filter(|i| {
15687c33c29SAlex Crichton                                 // Ignore empty range
15790ac295eSAlex Crichton                                 if let Ok((_, 0, _)) = i { false } else { true }
15887c33c29SAlex Crichton                             })
15987c33c29SAlex Crichton                             .map(|i| {
16087c33c29SAlex Crichton                                 i.map(|(start, len, expr)| write::Location::StartLength {
16187c33c29SAlex Crichton                                     begin: start,
16287c33c29SAlex Crichton                                     length: len,
16387c33c29SAlex Crichton                                     data: expr,
16487c33c29SAlex Crichton                                 })
16587c33c29SAlex Crichton                             })
16687c33c29SAlex Crichton                             .collect::<Result<Vec<_>, _>>()?;
16787c33c29SAlex Crichton                         match &mut result {
16887c33c29SAlex Crichton                             Some(r) => r.extend(chunk),
16987c33c29SAlex Crichton                             x @ None => *x = Some(chunk),
17087c33c29SAlex Crichton                         }
17187c33c29SAlex Crichton                     } else {
17287c33c29SAlex Crichton                         // FIXME _expr contains invalid expression
17387c33c29SAlex Crichton                         continue; // ignore entry
17487c33c29SAlex Crichton                     }
17587c33c29SAlex Crichton                 }
17687c33c29SAlex Crichton                 if result.is_none() {
17787c33c29SAlex Crichton                     continue; // no valid locations
17887c33c29SAlex Crichton                 }
179*c4a38d67SPhilip Craig                 let list_id = convert_unit
180*c4a38d67SPhilip Craig                     .unit
181*c4a38d67SPhilip Craig                     .locations
182*c4a38d67SPhilip Craig                     .add(write::LocationList(result.unwrap()));
18387c33c29SAlex Crichton                 write::AttributeValue::LocationListRef(list_id)
18487c33c29SAlex Crichton             }
1857b16eccdSSingleAccretion             AttributeValue::Exprloc(_) if attr.name() == gimli::DW_AT_frame_base => {
1867b16eccdSSingleAccretion                 // We do not really "rewrite" the frame base so much as replace it outright.
1877b16eccdSSingleAccretion                 // References to it through the DW_OP_fbreg opcode will be expanded below.
1887b16eccdSSingleAccretion                 let mut cfa = write::Expression::new();
1897b16eccdSSingleAccretion                 cfa.op(gimli::DW_OP_call_frame_cfa);
1907b16eccdSSingleAccretion                 write::AttributeValue::Exprloc(cfa)
1917b16eccdSSingleAccretion             }
19287c33c29SAlex Crichton             AttributeValue::Exprloc(ref expr) => {
193*c4a38d67SPhilip Craig                 let frame_base = attr_context.frame_base;
19487c33c29SAlex Crichton                 if let Some(expr) = compile_expression(expr, unit_encoding, frame_base)? {
19587c33c29SAlex Crichton                     if expr.is_simple() {
19687c33c29SAlex Crichton                         if let Some(expr) = expr.build() {
19787c33c29SAlex Crichton                             write::AttributeValue::Exprloc(expr)
19887c33c29SAlex Crichton                         } else {
19987c33c29SAlex Crichton                             continue;
20087c33c29SAlex Crichton                         }
20187c33c29SAlex Crichton                     } else {
20287c33c29SAlex Crichton                         // Conversion to loclist is required.
20387c33c29SAlex Crichton                         if let Some(scope_ranges) = scope_ranges {
204d2c9d2a2SSingleAccretion                             let built_expression =
205d2c9d2a2SSingleAccretion                                 expr.build_with_locals(scope_ranges, addr_tr, frame_info, isa);
206d2c9d2a2SSingleAccretion                             let exprs = built_expression
207d2c9d2a2SSingleAccretion                                 .expressions
20887c33c29SAlex Crichton                                 .collect::<Result<Vec<_>, _>>()?;
20987c33c29SAlex Crichton                             if exprs.is_empty() {
21087c33c29SAlex Crichton                                 continue;
21187c33c29SAlex Crichton                             }
21287c33c29SAlex Crichton                             // Micro-optimization all expressions alike, use one exprloc.
213d2c9d2a2SSingleAccretion                             let mut single_expr: Option<write::Expression> = None;
214d2c9d2a2SSingleAccretion                             if built_expression.covers_entire_scope {
21587c33c29SAlex Crichton                                 for (_, _, expr) in &exprs {
216d2c9d2a2SSingleAccretion                                     if let Some(ref prev_expr) = single_expr {
21787c33c29SAlex Crichton                                         if expr == prev_expr {
21887c33c29SAlex Crichton                                             continue; // the same expression
21987c33c29SAlex Crichton                                         }
220d2c9d2a2SSingleAccretion                                         single_expr = None;
22187c33c29SAlex Crichton                                         break;
22287c33c29SAlex Crichton                                     }
223d2c9d2a2SSingleAccretion                                     single_expr = Some(expr.clone())
22487c33c29SAlex Crichton                                 }
225d2c9d2a2SSingleAccretion                             }
226d2c9d2a2SSingleAccretion                             if let Some(expr) = single_expr {
22787c33c29SAlex Crichton                                 write::AttributeValue::Exprloc(expr)
22887c33c29SAlex Crichton                             } else if is_exprloc_to_loclist_allowed(attr.name()) {
22987c33c29SAlex Crichton                                 // Converting exprloc to loclist.
23087c33c29SAlex Crichton                                 let mut locs = Vec::new();
23187c33c29SAlex Crichton                                 for (begin, length, data) in exprs {
23287c33c29SAlex Crichton                                     if length == 0 {
23387c33c29SAlex Crichton                                         // Ignore empty range
23487c33c29SAlex Crichton                                         continue;
23587c33c29SAlex Crichton                                     }
23687c33c29SAlex Crichton                                     locs.push(write::Location::StartLength {
23787c33c29SAlex Crichton                                         begin,
23887c33c29SAlex Crichton                                         length,
23987c33c29SAlex Crichton                                         data,
24087c33c29SAlex Crichton                                     });
24187c33c29SAlex Crichton                                 }
242*c4a38d67SPhilip Craig                                 let list_id =
243*c4a38d67SPhilip Craig                                     convert_unit.unit.locations.add(write::LocationList(locs));
24487c33c29SAlex Crichton                                 write::AttributeValue::LocationListRef(list_id)
24587c33c29SAlex Crichton                             } else {
24687c33c29SAlex Crichton                                 continue;
24787c33c29SAlex Crichton                             }
24887c33c29SAlex Crichton                         } else {
24987c33c29SAlex Crichton                             continue;
25087c33c29SAlex Crichton                         }
25187c33c29SAlex Crichton                     }
25287c33c29SAlex Crichton                 } else {
25387c33c29SAlex Crichton                     // FIXME _expr contains invalid expression
25487c33c29SAlex Crichton                     continue; // ignore attribute
25587c33c29SAlex Crichton                 }
25687c33c29SAlex Crichton             }
257*c4a38d67SPhilip Craig             // No other attributes contain addresses or address offsets.
258*c4a38d67SPhilip Craig             _ => match convert_unit.convert_attribute_value(unit, attr, &|_| None) {
259*c4a38d67SPhilip Craig                 Ok(value) => value,
260*c4a38d67SPhilip Craig                 Err(e) => {
261*c4a38d67SPhilip Craig                     // Invalid `FileIndex` was seen in #8884 and #8904. In general it's
262*c4a38d67SPhilip Craig                     // better to ignore invalid or unknown DWARF rather then failing outright.
263*c4a38d67SPhilip Craig                     dbi_log!(
264*c4a38d67SPhilip Craig                         "Ignoring entry {:x?} attribute {} = {:x?}: {e}",
265*c4a38d67SPhilip Craig                         entry.offset.to_unit_section_offset(&convert_unit.read_unit),
266*c4a38d67SPhilip Craig                         attr.name(),
267*c4a38d67SPhilip Craig                         attr_value,
268*c4a38d67SPhilip Craig                     );
26987c33c29SAlex Crichton                     continue;
27087c33c29SAlex Crichton                 }
271*c4a38d67SPhilip Craig             },
27287c33c29SAlex Crichton         };
273*c4a38d67SPhilip Craig         let out_entry = convert_unit.unit.get_mut(out_entry_id);
2740b2c9d72SSingleAccretion         out_entry.set(attr.name(), out_attr_value);
27587c33c29SAlex Crichton     }
27687c33c29SAlex Crichton     Ok(())
27787c33c29SAlex Crichton }
2780b2c9d72SSingleAccretion 
prepare_die_context<'a>( entry: &gimli::write::ConvertUnitEntry<Reader<'a>>, attr_context: &mut EntryAttributesContext, is_obj_ptr: &mut bool, ) -> Result<(), Error>279bd7b59daSPhilip Craig fn prepare_die_context<'a>(
280*c4a38d67SPhilip Craig     entry: &gimli::write::ConvertUnitEntry<Reader<'a>>,
281*c4a38d67SPhilip Craig     attr_context: &mut EntryAttributesContext,
2820b2c9d72SSingleAccretion     is_obj_ptr: &mut bool,
2830b2c9d72SSingleAccretion ) -> Result<(), Error> {
284*c4a38d67SPhilip Craig     let subprograms = &mut attr_context.subprograms;
2850b2c9d72SSingleAccretion 
2860b2c9d72SSingleAccretion     // Update the current context based on what kind of entry this is.
287*c4a38d67SPhilip Craig     match entry.tag {
2880b2c9d72SSingleAccretion         gimli::DW_TAG_subprogram | gimli::DW_TAG_inlined_subroutine | gimli::DW_TAG_entry_point => {
2890b2c9d72SSingleAccretion             // Push the 'context' of there being no parameters (yet).
2900b2c9d72SSingleAccretion             subprograms.push(
291*c4a38d67SPhilip Craig                 entry.depth,
2920b2c9d72SSingleAccretion                 SubprogramContext {
2930b2c9d72SSingleAccretion                     obj_ptr: UnitOffset { 0: 0 },
2940b2c9d72SSingleAccretion                     param_num: -1,
2950b2c9d72SSingleAccretion                 },
2960b2c9d72SSingleAccretion             );
2970b2c9d72SSingleAccretion         }
2980b2c9d72SSingleAccretion         gimli::DW_TAG_formal_parameter => {
2990b2c9d72SSingleAccretion             // Formal parameter tags can be parented by catch blocks
3000b2c9d72SSingleAccretion             // and such - not just subprogram DIEs. So we need to check
3010b2c9d72SSingleAccretion             // that this DIE is indeed a direct child of a subprogram.
302*c4a38d67SPhilip Craig             if let Some(subprogram) = subprograms.top_with_depth_mut(entry.depth - 1) {
3030b2c9d72SSingleAccretion                 subprogram.param_num += 1;
3040b2c9d72SSingleAccretion 
305*c4a38d67SPhilip Craig                 if subprogram.obj_ptr == entry.offset
306*c4a38d67SPhilip Craig                     || is_obj_ptr_param(entry, subprogram.param_num)?
3070b2c9d72SSingleAccretion                 {
3080b2c9d72SSingleAccretion                     *is_obj_ptr = true;
3090b2c9d72SSingleAccretion                 }
3100b2c9d72SSingleAccretion             }
3110b2c9d72SSingleAccretion         }
3120b2c9d72SSingleAccretion         _ => {}
3130b2c9d72SSingleAccretion     }
3140b2c9d72SSingleAccretion     Ok(())
3150b2c9d72SSingleAccretion }
3160b2c9d72SSingleAccretion 
is_obj_ptr_param( entry: &gimli::write::ConvertUnitEntry<Reader<'_>>, param_num: isize, ) -> Result<bool, Error>317*c4a38d67SPhilip Craig fn is_obj_ptr_param(
318*c4a38d67SPhilip Craig     entry: &gimli::write::ConvertUnitEntry<Reader<'_>>,
3190b2c9d72SSingleAccretion     param_num: isize,
3200b2c9d72SSingleAccretion ) -> Result<bool, Error> {
321*c4a38d67SPhilip Craig     debug_assert_eq!(entry.tag, gimli::DW_TAG_formal_parameter);
322*c4a38d67SPhilip Craig     let unit = entry.read_unit;
3230b2c9d72SSingleAccretion 
3240b2c9d72SSingleAccretion     // This logic was taken loosely from LLDB. It is known
3250b2c9d72SSingleAccretion     // that it is not fully correct (doesn't handle 'deduced
3260b2c9d72SSingleAccretion     // this', for example).
3270b2c9d72SSingleAccretion     // Q: DWARF includes DW_AT_object_pointer as we use it,
3280b2c9d72SSingleAccretion     // why do we need this heuristic as well?
3290b2c9d72SSingleAccretion     // A: Declarations do not include DW_AT_object_pointer.
3300b2c9d72SSingleAccretion     if param_num == 0
3317ee620a5SPhilip Craig         && entry.attr_value(gimli::DW_AT_artificial) == Some(AttributeValue::Flag(true))
3320b2c9d72SSingleAccretion     {
3330b2c9d72SSingleAccretion         // Either this has no name (declarations omit them), or its explicitly "this".
3347ee620a5SPhilip Craig         let name = entry.attr_value(gimli::DW_AT_name);
335bd7b59daSPhilip Craig         if name.is_none() || unit.attr_string(name.unwrap())?.slice().eq(b"this") {
3360b2c9d72SSingleAccretion             // Finally, a type check. We expect a pointer.
3377ee620a5SPhilip Craig             if let Some(type_attr) = entry.attr_value(gimli::DW_AT_type) {
3380b2c9d72SSingleAccretion                 if let Some(type_die) = resolve_die_ref(unit, &type_attr)? {
339*c4a38d67SPhilip Craig                     return Ok(type_die.tag == gimli::DW_TAG_pointer_type);
3400b2c9d72SSingleAccretion                 }
3410b2c9d72SSingleAccretion             }
3420b2c9d72SSingleAccretion         }
3430b2c9d72SSingleAccretion     };
3440b2c9d72SSingleAccretion 
3450b2c9d72SSingleAccretion     return Ok(false);
3460b2c9d72SSingleAccretion }
347