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