/// Climb up the parent chain to get the compile unit DIE to which this DIE /// belongs. DIE *DIE::getCompileUnit() { DIE *p = this; while (p) { if (p->getTag() == dwarf::DW_TAG_compile_unit) return p; p = p->getParent(); } llvm_unreachable("We should not have orphaned DIEs."); }
// Construct a DIE for this scope. void DwarfCompileUnit::constructScopeDIE( LexicalScope *Scope, SmallVectorImpl<DIE *> &FinalChildren) { if (!Scope || !Scope->getScopeNode()) return; auto *DS = Scope->getScopeNode(); assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) && "Only handle inlined subprograms here, use " "constructSubprogramScopeDIE for non-inlined " "subprograms"); SmallVector<DIE *, 8> Children; // We try to create the scope DIE first, then the children DIEs. This will // avoid creating un-used children then removing them later when we find out // the scope DIE is null. DIE *ScopeDIE; if (Scope->getParent() && isa<DISubprogram>(DS)) { ScopeDIE = constructInlinedScopeDIE(Scope); if (!ScopeDIE) return; // We create children when the scope DIE is not null. createScopeChildrenDIE(Scope, Children); } else { // Early exit when we know the scope DIE is going to be null. if (DD->isLexicalScopeDIENull(Scope)) return; bool HasNonScopeChildren = false; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. createScopeChildrenDIE(Scope, Children, &HasNonScopeChildren); // If there are only other scopes as children, put them directly in the // parent instead, as this scope would serve no purpose. if (!HasNonScopeChildren) { FinalChildren.insert(FinalChildren.end(), std::make_move_iterator(Children.begin()), std::make_move_iterator(Children.end())); return; } ScopeDIE = constructLexicalScopeDIE(Scope); assert(ScopeDIE && "Scope DIE should not be null."); } // Add children for (auto &I : Children) ScopeDIE->addChild(std::move(I)); FinalChildren.push_back(std::move(ScopeDIE)); }
void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label) { if (Label) DD->addArangeLabel(SymbolCU(this, Label)); if (Label) Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, DIELabel(Label)); else Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, DIEInteger(0)); }
/// addTemplateParams - Add template parameters in buffer. void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { // Add template parameters. for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { DIDescriptor Element = TParams.getElement(i); if (Element.isTemplateTypeParameter()) Buffer.addChild(getOrCreateTemplateTypeParameterDIE( DITemplateTypeParameter(Element))); else if (Element.isTemplateValueParameter()) Buffer.addChild(getOrCreateTemplateValueParameterDIE( DITemplateValueParameter(Element))); } }
void CompileUnit::fixupForwardReferences() { for (const auto &Ref : ForwardDIEReferences) { DIE *RefDie; const CompileUnit *RefUnit; PatchLocation Attr; DeclContext *Ctxt; std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref; if (Ctxt && Ctxt->getCanonicalDIEOffset()) Attr.set(Ctxt->getCanonicalDIEOffset()); else Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); } }
void test (DIE die, DIE *Die, DIE INT, DIE *FLOAT) { DIE.foo(); // expected-error {{cannot use dot operator on a type}} die.foo(); DIE->foo(); // expected-error {{cannot use arrow operator on a type}} Die->foo(); int.foo(); // expected-error {{cannot use dot operator on a type}} INT.foo(); float->foo(); // expected-error {{cannot use arrow operator on a type}} FLOAT->foo(); }
void AsmPrinter::emitDwarfDIE(const DIE &Die) const { // Emit the code (index) for the abbreviation. if (isVerbose()) OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + Twine::utohexstr(Die.getOffset()) + ":0x" + Twine::utohexstr(Die.getSize()) + " " + dwarf::TagString(Die.getTag())); EmitULEB128(Die.getAbbrevNumber()); // Emit the DIE attribute values. for (const auto &V : Die.values()) { dwarf::Attribute Attr = V.getAttribute(); assert(V.getForm() && "Too many attributes for DIE (check abbreviation)"); if (isVerbose()) { OutStreamer->AddComment(dwarf::AttributeString(Attr)); if (Attr == dwarf::DW_AT_accessibility) OutStreamer->AddComment( dwarf::AccessibilityString(V.getDIEInteger().getValue())); } // Emit an attribute using the defined form. V.EmitValue(this); } // Emit the DIE children if any. if (Die.hasChildren()) { for (auto &Child : Die.children()) emitDwarfDIE(Child); OutStreamer->AddComment("End Of Children Mark"); EmitInt8(0); } }
/// constructTypeDIE - Construct derived type die from DIDerivedType. void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { // Get core information. StringRef Name = DTy.getName(); uint64_t Size = DTy.getSizeInBits() >> 3; unsigned Tag = DTy.getTag(); // FIXME - Workaround for templates. if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; Buffer.setTag(Tag); // Map to main type, void will not have a type. DIType FromTy = DTy.getTypeDerivedFrom(); addType(&Buffer, FromTy); // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); // Add size if non-zero (derived types might be zero-sized.) if (Size) addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); // Add source line info if available and TyDesc is not a forward declaration. if (!DTy.isForwardDecl()) addSourceLine(&Buffer, DTy); }
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType *CTy) { Buffer.setTag(dwarf::DW_TAG_array_type); if (CTy->getTag() == dwarf::DW_TAG_vector_type) addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); // Emit derived type. addType(&Buffer, CTy->getTypeDerivedFrom()); DIArray Elements = CTy->getTypeArray(); // Get an anonymous type for index type. DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { // Construct an anonymous type for index type. IdxTy = new DIE(dwarf::DW_TAG_base_type); addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, dwarf::DW_ATE_signed); addDie(IdxTy); setIndexTyDie(IdxTy); } // Add subranges to array type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.getTag() == dwarf::DW_TAG_subrange_type) constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); } }
void AsmPrinter::emitDwarfDIE(const DIE &Die) const { // Get the abbreviation for this DIE. const DIEAbbrev &Abbrev = Die.getAbbrev(); // Emit the code (index) for the abbreviation. if (isVerbose()) OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) + "] 0x" + Twine::utohexstr(Die.getOffset()) + ":0x" + Twine::utohexstr(Die.getSize()) + " " + dwarf::TagString(Abbrev.getTag())); EmitULEB128(Abbrev.getNumber()); const SmallVectorImpl<DIEValue *> &Values = Die.getValues(); const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Emit the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) { dwarf::Attribute Attr = AbbrevData[i].getAttribute(); dwarf::Form Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); if (isVerbose()) { OutStreamer.AddComment(dwarf::AttributeString(Attr)); if (Attr == dwarf::DW_AT_accessibility) OutStreamer.AddComment(dwarf::AccessibilityString( cast<DIEInteger>(Values[i])->getValue())); } // Emit an attribute using the defined form. Values[i]->EmitValue(this, Form); } // Emit the DIE children if any. if (Abbrev.hasChildren()) { for (auto &Child : Die.getChildren()) emitDwarfDIE(Child); OutStreamer.AddComment("End Of Children Mark"); EmitInt8(0); } }
/// constructSubrangeDIE - Construct subrange DIE from DISubrange. void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); int64_t L = SR.getLo(); int64_t H = SR.getHi(); // The L value defines the lower bounds which is typically zero for C/C++. The // H value is the upper bounds. Values are 64 bit. H - L + 1 is the size // of the array. If L > H then do not emit DW_AT_lower_bound and // DW_AT_upper_bound attributes. If L is zero and H is also zero then the // array has one element and in such case do not emit lower bound. if (L > H) { Buffer.addChild(DW_Subrange); return; } if (L) addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); Buffer.addChild(DW_Subrange); }
/// constructTypeDIE - Construct basic type die from DIBasicType. void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { // Get core information. StringRef Name = BTy.getName(); Buffer.setTag(dwarf::DW_TAG_base_type); addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy.getEncoding()); // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); uint64_t Size = BTy.getSizeInBits() >> 3; addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); }
void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( LexicalScope *Scope) { DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()]; if (AbsDef) return; auto *SP = cast<DISubprogram>(Scope->getScopeNode()); DIE *ContextDIE; DwarfCompileUnit *ContextCU = this; if (includeMinimalInlineScopes()) ContextDIE = &getUnitDie(); // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with // the important distinction that the debug node is not associated with the // DIE (since the debug node will be associated with the concrete DIE, if // any). It could be refactored to some common utility function. else if (auto *SPDecl = SP->getDeclaration()) { ContextDIE = &getUnitDie(); getOrCreateSubprogramDIE(SPDecl); } else { ContextDIE = getOrCreateContextDIE(resolve(SP->getScope())); // The scope may be shared with a subprogram that has already been // constructed in another CU, in which case we need to construct this // subprogram in the same CU. ContextCU = DD->lookupCU(ContextDIE->getUnitDie()); } // Passing null as the associated node because the abstract definition // shouldn't be found by lookup. AbsDef = &ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr); ContextCU->applySubprogramAttributesToDefinition(SP, *AbsDef); if (!ContextCU->includeMinimalInlineScopes()) ContextCU->addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef)) ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); }
/// addLabelAddress - Add a dwarf label attribute data and value using /// DW_FORM_addr or DW_FORM_GNU_addr_index. void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label) { // Don't use the address pool in non-fission or in the skeleton unit itself. // FIXME: Once GDB supports this, it's probably worthwhile using the address // pool from the skeleton - maybe even in non-fission (possibly fewer // relocations by sharing them in the pool, but we have other ideas about how // to reduce the number of relocations as well/instead). if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5) return addLocalLabelAddress(Die, Attribute, Label); if (Label) DD->addArangeLabel(SymbolCU(this, Label)); unsigned idx = DD->getAddressPool().getIndex(Label); Die.addValue(DIEValueAllocator, Attribute, DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx : dwarf::DW_FORM_GNU_addr_index, DIEInteger(idx)); }
/// addToContextOwner - Add Die into the list of its context owner's children. void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { if (Context.isType()) { DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); ContextDIE->addChild(Die); } else if (Context.isNameSpace()) { DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); ContextDIE->addChild(Die); } else if (Context.isSubprogram()) { DIE *ContextDIE = DD->createSubprogramDIE(DISubprogram(Context)); ContextDIE->addChild(Die); } else if (DIE *ContextDIE = getDIE(Context)) ContextDIE->addChild(Die); else addDie(Die); }
// Compute the size and offset of a DIE. The offset is relative to start of the // CU. It returns the offset after laying out the DIE. unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) { // Record the abbreviation. assignAbbrevNumber(Die.getAbbrev()); // Get the abbreviation for this DIE. const DIEAbbrev &Abbrev = Die.getAbbrev(); // Set DIE offset Die.setOffset(Offset); // Start the size with the size of abbreviation code. Offset += getULEB128Size(Die.getAbbrevNumber()); const SmallVectorImpl<DIEValue *> &Values = Die.getValues(); const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); // Get the children. const auto &Children = Die.getChildren(); // Size the DIE children if any. if (!Children.empty()) { assert(Abbrev.hasChildren() && "Children flag not set"); for (auto &Child : Children) Offset = computeSizeAndOffset(*Child, Offset); // End of children marker. Offset += sizeof(int8_t); } Die.setSize(Offset - Die.getOffset()); return Offset; }
void DwarfCompileUnit::applyStmtList(DIE &D) { D.addValue(DIEValueAllocator, *StmtListValue); }
void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr) { Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, DIEExpr(Expr)); }
/// Add a Dwarf loclistptr attribute data and value. void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index) { dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset : dwarf::DW_FORM_data4; Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index)); }
/// constructTypeDIE - Construct type DIE from DICompositeType. void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Get core information. StringRef Name = CTy.getName(); uint64_t Size = CTy.getSizeInBits() >> 3; unsigned Tag = CTy.getTag(); Buffer.setTag(Tag); switch (Tag) { case dwarf::DW_TAG_vector_type: case dwarf::DW_TAG_array_type: constructArrayTypeDIE(Buffer, &CTy); break; case dwarf::DW_TAG_enumeration_type: { DIArray Elements = CTy.getTypeArray(); // Add enumerators to enumeration type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIE *ElemDie = NULL; DIDescriptor Enum(Elements.getElement(i)); if (Enum.isEnumerator()) { ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); Buffer.addChild(ElemDie); } } } break; case dwarf::DW_TAG_subroutine_type: { // Add return type. DIArray Elements = CTy.getTypeArray(); DIDescriptor RTy = Elements.getElement(0); addType(&Buffer, DIType(RTy)); bool isPrototyped = true; // Add arguments. for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Ty = Elements.getElement(i); if (Ty.isUnspecifiedParameter()) { DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); Buffer.addChild(Arg); isPrototyped = false; } else { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); addType(Arg, DIType(Ty)); Buffer.addChild(Arg); } } // Add prototype flag. if (isPrototyped) addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); } break; case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_class_type: { // Add elements to structure type. DIArray Elements = CTy.getTypeArray(); // A forward struct declared type may not have elements available. unsigned N = Elements.getNumElements(); if (N == 0) break; // Add elements to structure type. for (unsigned i = 0; i < N; ++i) { DIDescriptor Element = Elements.getElement(i); DIE *ElemDie = NULL; if (Element.isSubprogram()) { DISubprogram SP(Element); ElemDie = DD->createSubprogramDIE(DISubprogram(Element)); if (SP.isProtected()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_protected); else if (SP.isPrivate()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_private); else addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_public); if (SP.isExplicit()) addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); } else if (Element.isVariable()) { DIVariable DV(Element); ElemDie = new DIE(dwarf::DW_TAG_variable); addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, DV.getName()); addType(ElemDie, DV.getType()); addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); addSourceLine(ElemDie, DV); } else if (Element.isDerivedType()) ElemDie = createMemberDIE(DIDerivedType(Element)); else continue; Buffer.addChild(ElemDie); } if (CTy.isAppleBlockExtension()) addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); unsigned RLang = CTy.getRunTimeLang(); if (RLang) addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); DICompositeType ContainingType = CTy.getContainingType(); if (DIDescriptor(ContainingType).isCompositeType()) addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, getOrCreateTypeDIE(DIType(ContainingType))); else { DIDescriptor Context = CTy.getContext(); addToContextOwner(&Buffer, Context); } if (CTy.isObjcClassComplete()) addUInt(&Buffer, dwarf::DW_AT_APPLE_objc_complete_type, dwarf::DW_FORM_flag, 1); if (Tag == dwarf::DW_TAG_class_type) addTemplateParams(Buffer, CTy.getTemplateParams()); break; } default: break; } // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { // Add size if non-zero (derived types might be zero-sized.) if (Size) addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); else { // Add zero size if it is not a forward declaration. if (CTy.isForwardDecl()) addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); else addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); } // Add source line info if available. if (!CTy.isForwardDecl()) addSourceLine(&Buffer, CTy); } }
void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) { if (Die.getTag() != dwarf::DW_TAG_compile_unit) RangeAttributes.push_back(Attr); else UnitRangeAttribute = Attr; }