void ObjectLoadListener::extractLocalLocations( const DWARFUnit *CU, const DWARFDebugInfoEntryMinimal *DebugEntry, std::vector<uint64_t> &Offsets) { if (DebugEntry->isNULL()) return; if (DebugEntry->getTag() == dwarf::DW_TAG_formal_parameter || DebugEntry->getTag() == dwarf::DW_TAG_variable) { uint64_t Offset; // Extract offset for each local found DWARFFormValue FormValue; if (DebugEntry->getAttributeValue(CU, dwarf::DW_AT_location, FormValue)) { Optional<ArrayRef<uint8_t>> FormValues = FormValue.getAsBlock(); Offset = FormValues->back(); } Offsets.push_back(Offset); } const DWARFDebugInfoEntryMinimal *Child = DebugEntry->getFirstChild(); // Extract info for DebugEntry's child and its child's siblings. while (Child) { extractLocalLocations(CU, Child, Offsets); Child = Child->getSibling(); } }
static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, DWARFUnit *U, unsigned Indent, DIDumpOptions DumpOpts) { DWARFContext &Ctx = U->getContext(); const DWARFObject &Obj = Ctx.getDWARFObj(); const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); if (FormValue.isFormClass(DWARFFormValue::FC_Block) || FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) .print(OS, MRI); return; } FormValue.dump(OS, DumpOpts); if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { const DWARFSection &LocSection = Obj.getLocSection(); const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); uint32_t Offset = *FormValue.getAsSectionOffset(); if (!LocSection.Data.empty()) { DWARFDebugLoc DebugLoc; DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), Obj.getAddressSize()); auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { uint64_t BaseAddr = 0; if (Optional<BaseAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr, Indent); } else OS << "error extracting location list."; } else if (!LocDWOSection.Data.empty()) { DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0); auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); if (LL) LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); else OS << "error extracting location list."; } } }
void ObjectLoadListener::getDebugInfoForLocals( DWARFContextInMemory &DwarfContext, uint64_t Addr, uint64_t Size) { for (const auto &CU : DwarfContext.compile_units()) { const DWARFDebugInfoEntryMinimal *UnitDIE = CU->getUnitDIE(false); const DWARFDebugInfoEntryMinimal *SubprogramDIE = getSubprogramDIE(UnitDIE); ICorDebugInfo::RegNum FrameBaseRegister = ICorDebugInfo::REGNUM_COUNT; DWARFFormValue FormValue; // Find the frame_base register value if (SubprogramDIE->getAttributeValue(CU.get(), dwarf::DW_AT_frame_base, FormValue)) { Optional<ArrayRef<uint8_t>> FormValues = FormValue.getAsBlock(); FrameBaseRegister = mapDwarfRegisterToRegNum(FormValues->back()); } if (SubprogramDIE->getAttributeValue(CU.get(), dwarf::DW_AT_low_pc, FormValue)) { Optional<uint64_t> FormAddress = FormValue.getAsAddress(CU.get()); // If the Form address doesn't match the address for the function passed // do not collect debug for locals since they do not go with the current // function being processed if (FormAddress.getValue() != Addr) { return; } } std::vector<uint64_t> Offsets; extractLocalLocations(CU.get(), SubprogramDIE, Offsets); // Allocate the array of NativeVarInfo objects that will be sent to the EE ICorDebugInfo::NativeVarInfo *LocalVars; unsigned SizeOfArray = Offsets.size() * sizeof(ICorDebugInfo::NativeVarInfo); if (SizeOfArray > 0) { LocalVars = (ICorDebugInfo::NativeVarInfo *)Context->JitInfo->allocateArray( SizeOfArray); unsigned CurrentDebugEntry = 0; for (auto &Offset : Offsets) { LocalVars[CurrentDebugEntry].startOffset = Addr; LocalVars[CurrentDebugEntry].endOffset = Addr + Size; LocalVars[CurrentDebugEntry].varNumber = CurrentDebugEntry; // Assume all locals are on the stack ICorDebugInfo::VarLoc VarLoc; VarLoc.vlType = ICorDebugInfo::VLT_STK; VarLoc.vlStk.vlsBaseReg = FrameBaseRegister; VarLoc.vlStk.vlsOffset = Offset; LocalVars[CurrentDebugEntry].loc = VarLoc; CurrentDebugEntry++; } CORINFO_METHOD_INFO *MethodInfo = Context->MethodInfo; CORINFO_METHOD_HANDLE MethodHandle = MethodInfo->ftn; Context->JitInfo->setVars(MethodHandle, Offsets.size(), LocalVars); } } }
static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, DWARFUnit *U, unsigned Indent, DIDumpOptions DumpOpts) { DWARFContext &Ctx = U->getContext(); const DWARFObject &Obj = Ctx.getDWARFObj(); const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); if (FormValue.isFormClass(DWARFFormValue::FC_Block) || FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) .print(OS, MRI, U); return; } FormValue.dump(OS, DumpOpts); if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { uint32_t Offset = *FormValue.getAsSectionOffset(); if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) { DWARFDebugLoc DebugLoc; DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), Obj.getAddressSize()); auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { uint64_t BaseAddr = 0; if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, BaseAddr, Indent); } else OS << "error extracting location list."; return; } bool UseLocLists = !U->isDWOUnit(); StringRef LoclistsSectionData = UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); if (!LoclistsSectionData.empty()) { DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), Obj.getAddressSize()); // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). // Modern locations list (.debug_loclists) are used starting from v5. // Ideally we should take the version from the .debug_loclists section // header, but using CU's version for simplicity. auto LL = DWARFDebugLoclists::parseOneLocationList( Data, &Offset, UseLocLists ? U->getVersion() : 4); uint64_t BaseAddr = 0; if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; if (LL) LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, Indent); else OS << "error extracting location list."; } } }