brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 2341dba Raw
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