1*1db9f3b2SDimitry Andric //===- DIEGenerator.h -------------------------------------------*- C++ -*-===// 2*1db9f3b2SDimitry Andric // 3*1db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*1db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*1db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*1db9f3b2SDimitry Andric // 7*1db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 8*1db9f3b2SDimitry Andric 9*1db9f3b2SDimitry Andric #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H 10*1db9f3b2SDimitry Andric #define LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H 11*1db9f3b2SDimitry Andric 12*1db9f3b2SDimitry Andric #include "DWARFLinkerGlobalData.h" 13*1db9f3b2SDimitry Andric #include "DWARFLinkerUnit.h" 14*1db9f3b2SDimitry Andric #include "llvm/CodeGen/DIE.h" 15*1db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h" 16*1db9f3b2SDimitry Andric 17*1db9f3b2SDimitry Andric namespace llvm { 18*1db9f3b2SDimitry Andric namespace dwarf_linker { 19*1db9f3b2SDimitry Andric namespace parallel { 20*1db9f3b2SDimitry Andric 21*1db9f3b2SDimitry Andric /// This class is a helper to create output DIE tree. 22*1db9f3b2SDimitry Andric class DIEGenerator { 23*1db9f3b2SDimitry Andric public: DIEGenerator(BumpPtrAllocator & Allocator,DwarfUnit & CU)24*1db9f3b2SDimitry Andric DIEGenerator(BumpPtrAllocator &Allocator, DwarfUnit &CU) 25*1db9f3b2SDimitry Andric : Allocator(Allocator), CU(CU) {} 26*1db9f3b2SDimitry Andric DIEGenerator(DIE * OutputDIE,BumpPtrAllocator & Allocator,DwarfUnit & CU)27*1db9f3b2SDimitry Andric DIEGenerator(DIE *OutputDIE, BumpPtrAllocator &Allocator, DwarfUnit &CU) 28*1db9f3b2SDimitry Andric : Allocator(Allocator), CU(CU), OutputDIE(OutputDIE) {} 29*1db9f3b2SDimitry Andric 30*1db9f3b2SDimitry Andric /// Creates a DIE of specified tag \p DieTag and \p OutOffset. createDIE(dwarf::Tag DieTag,uint32_t OutOffset)31*1db9f3b2SDimitry Andric DIE *createDIE(dwarf::Tag DieTag, uint32_t OutOffset) { 32*1db9f3b2SDimitry Andric OutputDIE = DIE::get(Allocator, DieTag); 33*1db9f3b2SDimitry Andric 34*1db9f3b2SDimitry Andric OutputDIE->setOffset(OutOffset); 35*1db9f3b2SDimitry Andric 36*1db9f3b2SDimitry Andric return OutputDIE; 37*1db9f3b2SDimitry Andric } 38*1db9f3b2SDimitry Andric getDIE()39*1db9f3b2SDimitry Andric DIE *getDIE() { return OutputDIE; } 40*1db9f3b2SDimitry Andric 41*1db9f3b2SDimitry Andric /// Adds a specified \p Child to the current DIE. addChild(DIE * Child)42*1db9f3b2SDimitry Andric void addChild(DIE *Child) { 43*1db9f3b2SDimitry Andric assert(Child != nullptr); 44*1db9f3b2SDimitry Andric assert(OutputDIE != nullptr); 45*1db9f3b2SDimitry Andric 46*1db9f3b2SDimitry Andric OutputDIE->addChild(Child); 47*1db9f3b2SDimitry Andric } 48*1db9f3b2SDimitry Andric 49*1db9f3b2SDimitry Andric /// Adds specified scalar attribute to the current DIE. addScalarAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,uint64_t Value)50*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addScalarAttribute(dwarf::Attribute Attr, 51*1db9f3b2SDimitry Andric dwarf::Form AttrForm, 52*1db9f3b2SDimitry Andric uint64_t Value) { 53*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, DIEInteger(Value)); 54*1db9f3b2SDimitry Andric } 55*1db9f3b2SDimitry Andric 56*1db9f3b2SDimitry Andric /// Adds specified location attribute to the current DIE. addLocationAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,ArrayRef<uint8_t> Bytes)57*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addLocationAttribute(dwarf::Attribute Attr, 58*1db9f3b2SDimitry Andric dwarf::Form AttrForm, 59*1db9f3b2SDimitry Andric ArrayRef<uint8_t> Bytes) { 60*1db9f3b2SDimitry Andric DIELoc *Loc = new (Allocator) DIELoc; 61*1db9f3b2SDimitry Andric for (auto Byte : Bytes) 62*1db9f3b2SDimitry Andric static_cast<DIEValueList *>(Loc)->addValue( 63*1db9f3b2SDimitry Andric Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1, 64*1db9f3b2SDimitry Andric DIEInteger(Byte)); 65*1db9f3b2SDimitry Andric Loc->setSize(Bytes.size()); 66*1db9f3b2SDimitry Andric 67*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, Loc); 68*1db9f3b2SDimitry Andric } 69*1db9f3b2SDimitry Andric 70*1db9f3b2SDimitry Andric /// Adds specified block or exprloc attribute to the current DIE. addBlockAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,ArrayRef<uint8_t> Bytes)71*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addBlockAttribute(dwarf::Attribute Attr, 72*1db9f3b2SDimitry Andric dwarf::Form AttrForm, 73*1db9f3b2SDimitry Andric ArrayRef<uint8_t> Bytes) { 74*1db9f3b2SDimitry Andric // The expression location data might be updated and exceed the original 75*1db9f3b2SDimitry Andric // size. Check whether the new data fits into the original form. 76*1db9f3b2SDimitry Andric assert((AttrForm == dwarf::DW_FORM_block) || 77*1db9f3b2SDimitry Andric (AttrForm == dwarf::DW_FORM_exprloc) || 78*1db9f3b2SDimitry Andric (AttrForm == dwarf::DW_FORM_block1 && Bytes.size() <= UINT8_MAX) || 79*1db9f3b2SDimitry Andric (AttrForm == dwarf::DW_FORM_block2 && Bytes.size() <= UINT16_MAX) || 80*1db9f3b2SDimitry Andric (AttrForm == dwarf::DW_FORM_block4 && Bytes.size() <= UINT32_MAX)); 81*1db9f3b2SDimitry Andric 82*1db9f3b2SDimitry Andric DIEBlock *Block = new (Allocator) DIEBlock; 83*1db9f3b2SDimitry Andric for (auto Byte : Bytes) 84*1db9f3b2SDimitry Andric static_cast<DIEValueList *>(Block)->addValue( 85*1db9f3b2SDimitry Andric Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1, 86*1db9f3b2SDimitry Andric DIEInteger(Byte)); 87*1db9f3b2SDimitry Andric Block->setSize(Bytes.size()); 88*1db9f3b2SDimitry Andric 89*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, Block); 90*1db9f3b2SDimitry Andric } 91*1db9f3b2SDimitry Andric 92*1db9f3b2SDimitry Andric /// Adds specified location list attribute to the current DIE. addLocListAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,uint64_t Value)93*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addLocListAttribute(dwarf::Attribute Attr, 94*1db9f3b2SDimitry Andric dwarf::Form AttrForm, 95*1db9f3b2SDimitry Andric uint64_t Value) { 96*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, DIELocList(Value)); 97*1db9f3b2SDimitry Andric } 98*1db9f3b2SDimitry Andric 99*1db9f3b2SDimitry Andric /// Adds indexed string attribute. addIndexedStringAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,uint64_t Idx)100*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addIndexedStringAttribute(dwarf::Attribute Attr, 101*1db9f3b2SDimitry Andric dwarf::Form AttrForm, 102*1db9f3b2SDimitry Andric uint64_t Idx) { 103*1db9f3b2SDimitry Andric assert(AttrForm == dwarf::DW_FORM_strx); 104*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, DIEInteger(Idx)); 105*1db9f3b2SDimitry Andric } 106*1db9f3b2SDimitry Andric 107*1db9f3b2SDimitry Andric /// Adds string attribute with dummy offset to the current DIE. 108*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addStringPlaceholderAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm)109*1db9f3b2SDimitry Andric addStringPlaceholderAttribute(dwarf::Attribute Attr, dwarf::Form AttrForm) { 110*1db9f3b2SDimitry Andric assert(AttrForm == dwarf::DW_FORM_strp || 111*1db9f3b2SDimitry Andric AttrForm == dwarf::DW_FORM_line_strp); 112*1db9f3b2SDimitry Andric return addAttribute(Attr, AttrForm, DIEInteger(0xBADDEF)); 113*1db9f3b2SDimitry Andric } 114*1db9f3b2SDimitry Andric 115*1db9f3b2SDimitry Andric /// Adds inplace string attribute to the current DIE. addInplaceString(dwarf::Attribute Attr,StringRef String)116*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addInplaceString(dwarf::Attribute Attr, 117*1db9f3b2SDimitry Andric StringRef String) { 118*1db9f3b2SDimitry Andric DIEBlock *Block = new (Allocator) DIEBlock; 119*1db9f3b2SDimitry Andric for (auto Byte : String.bytes()) 120*1db9f3b2SDimitry Andric static_cast<DIEValueList *>(Block)->addValue( 121*1db9f3b2SDimitry Andric Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1, 122*1db9f3b2SDimitry Andric DIEInteger(Byte)); 123*1db9f3b2SDimitry Andric 124*1db9f3b2SDimitry Andric static_cast<DIEValueList *>(Block)->addValue( 125*1db9f3b2SDimitry Andric Allocator, static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1, 126*1db9f3b2SDimitry Andric DIEInteger(0)); 127*1db9f3b2SDimitry Andric Block->setSize(String.size() + 1); 128*1db9f3b2SDimitry Andric 129*1db9f3b2SDimitry Andric DIEValue &ValueRef = 130*1db9f3b2SDimitry Andric *OutputDIE->addValue(Allocator, Attr, dwarf::DW_FORM_string, Block); 131*1db9f3b2SDimitry Andric return std::pair<DIEValue &, size_t>(ValueRef, String.size() + 1); 132*1db9f3b2SDimitry Andric } 133*1db9f3b2SDimitry Andric 134*1db9f3b2SDimitry Andric /// Creates appreviations for the current DIE. Returns value of 135*1db9f3b2SDimitry Andric /// abbreviation number. Updates offsets with the size of abbreviation 136*1db9f3b2SDimitry Andric /// number. finalizeAbbreviations(bool CHILDREN_yes,OffsetsPtrVector * OffsetsList)137*1db9f3b2SDimitry Andric size_t finalizeAbbreviations(bool CHILDREN_yes, 138*1db9f3b2SDimitry Andric OffsetsPtrVector *OffsetsList) { 139*1db9f3b2SDimitry Andric // Create abbreviations for output DIE. 140*1db9f3b2SDimitry Andric DIEAbbrev NewAbbrev = OutputDIE->generateAbbrev(); 141*1db9f3b2SDimitry Andric if (CHILDREN_yes) 142*1db9f3b2SDimitry Andric NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); 143*1db9f3b2SDimitry Andric 144*1db9f3b2SDimitry Andric CU.assignAbbrev(NewAbbrev); 145*1db9f3b2SDimitry Andric OutputDIE->setAbbrevNumber(NewAbbrev.getNumber()); 146*1db9f3b2SDimitry Andric 147*1db9f3b2SDimitry Andric size_t AbbrevNumberSize = getULEB128Size(OutputDIE->getAbbrevNumber()); 148*1db9f3b2SDimitry Andric 149*1db9f3b2SDimitry Andric // Add size of abbreviation number to the offsets. 150*1db9f3b2SDimitry Andric if (OffsetsList != nullptr) { 151*1db9f3b2SDimitry Andric for (uint64_t *OffsetPtr : *OffsetsList) 152*1db9f3b2SDimitry Andric *OffsetPtr += AbbrevNumberSize; 153*1db9f3b2SDimitry Andric } 154*1db9f3b2SDimitry Andric 155*1db9f3b2SDimitry Andric return AbbrevNumberSize; 156*1db9f3b2SDimitry Andric } 157*1db9f3b2SDimitry Andric 158*1db9f3b2SDimitry Andric protected: 159*1db9f3b2SDimitry Andric template <typename T> addAttribute(dwarf::Attribute Attr,dwarf::Form AttrForm,T && Value)160*1db9f3b2SDimitry Andric std::pair<DIEValue &, size_t> addAttribute(dwarf::Attribute Attr, 161*1db9f3b2SDimitry Andric dwarf::Form AttrForm, T &&Value) { 162*1db9f3b2SDimitry Andric DIEValue &ValueRef = 163*1db9f3b2SDimitry Andric *OutputDIE->addValue(Allocator, Attr, AttrForm, std::forward<T>(Value)); 164*1db9f3b2SDimitry Andric unsigned ValueSize = ValueRef.sizeOf(CU.getFormParams()); 165*1db9f3b2SDimitry Andric return std::pair<DIEValue &, size_t>(ValueRef, ValueSize); 166*1db9f3b2SDimitry Andric } 167*1db9f3b2SDimitry Andric 168*1db9f3b2SDimitry Andric // Allocator for output DIEs and values. 169*1db9f3b2SDimitry Andric BumpPtrAllocator &Allocator; 170*1db9f3b2SDimitry Andric 171*1db9f3b2SDimitry Andric // Unit for the output DIE. 172*1db9f3b2SDimitry Andric DwarfUnit &CU; 173*1db9f3b2SDimitry Andric 174*1db9f3b2SDimitry Andric // OutputDIE. 175*1db9f3b2SDimitry Andric DIE *OutputDIE = nullptr; 176*1db9f3b2SDimitry Andric }; 177*1db9f3b2SDimitry Andric 178*1db9f3b2SDimitry Andric } // end of namespace parallel 179*1db9f3b2SDimitry Andric } // end of namespace dwarf_linker 180*1db9f3b2SDimitry Andric } // end of namespace llvm 181*1db9f3b2SDimitry Andric 182*1db9f3b2SDimitry Andric #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H 183