183 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H10#define LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H11 12#include "DWARFLinkerGlobalData.h"13#include "DWARFLinkerUnit.h"14#include "llvm/CodeGen/DIE.h"15#include "llvm/Support/LEB128.h"16 17namespace llvm {18namespace dwarf_linker {19namespace parallel {20 21/// This class is a helper to create output DIE tree.22class DIEGenerator {23public: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 original75 // 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 of135 /// abbreviation number. Updates offsets with the size of abbreviation136 /// 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 158protected: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 parallel179} // end of namespace dwarf_linker180} // end of namespace llvm181 182#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DIEGENERATOR_H183