brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · c992a23 Raw
247 lines · cpp
1//===- DWARFLinkerUnit.cpp ------------------------------------------------===//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#include "DWARFLinkerUnit.h"10#include "DWARFEmitterImpl.h"11#include "DebugLineSectionEmitter.h"12 13using namespace llvm;14using namespace dwarf_linker;15using namespace dwarf_linker::parallel;16 17void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {18  // Check the set for priors.19  FoldingSetNodeID ID;20  Abbrev.Profile(ID);21  void *InsertToken;22 23  DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);24  // If it's newly added.25  if (InSet) {26    // Assign existing abbreviation number.27    Abbrev.setNumber(InSet->getNumber());28  } else {29    // Add to abbreviation list.30    Abbreviations.push_back(31        std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));32    for (const auto &Attr : Abbrev.getData())33      Abbreviations.back()->AddAttribute(Attr);34    AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);35    // Assign the unique abbreviation number.36    Abbrev.setNumber(Abbreviations.size());37    Abbreviations.back()->setNumber(Abbreviations.size());38  }39}40 41Error DwarfUnit::emitAbbreviations() {42  const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();43  if (Abbrevs.empty())44    return Error::success();45 46  SectionDescriptor &AbbrevSection =47      getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);48 49  // For each abbreviation.50  for (const auto &Abbrev : Abbrevs)51    emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);52 53  // Mark end of abbreviations.54  encodeULEB128(0, AbbrevSection.OS);55 56  return Error::success();57}58 59void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,60                                     SectionDescriptor &AbbrevSection) {61  // Emit the abbreviations code (base 1 index.)62  encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);63 64  // Emit the abbreviations data.65  // Emit its Dwarf tag type.66  encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);67 68  // Emit whether it has children DIEs.69  encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);70 71  // For each attribute description.72  const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();73  for (const DIEAbbrevData &AttrData : Data) {74    // Emit attribute type.75    encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);76 77    // Emit form type.78    encodeULEB128(AttrData.getForm(), AbbrevSection.OS);79 80    // Emit value for DW_FORM_implicit_const.81    if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)82      encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);83  }84 85  // Mark end of abbreviation.86  encodeULEB128(0, AbbrevSection.OS);87  encodeULEB128(0, AbbrevSection.OS);88}89 90Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {91  DIE *OutUnitDIE = getOutUnitDIE();92  if (OutUnitDIE == nullptr)93    return Error::success();94 95  // FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs96  // directly.97 98  SectionDescriptor &OutSection =99      getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);100  DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);101  if (Error Err = Emitter.init(TargetTriple, "__DWARF"))102    return Err;103 104  // Emit compile unit header.105  Emitter.emitCompileUnitHeader(*this);106  size_t OffsetToAbbreviationTableOffset =107      (getFormParams().Version >= 5) ? 8 : 6;108  OutSection.notePatch(DebugOffsetPatch{109      OffsetToAbbreviationTableOffset,110      &getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});111 112  // Emit DIEs.113  Emitter.emitDIE(*OutUnitDIE);114  Emitter.finish();115 116  // Set start offset ans size for .debug_info section.117  OutSection.setSizesForSectionCreatedByAsmPrinter();118  return Error::success();119}120 121Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,122                               const DWARFDebugLine::LineTable &OutLineTable) {123  DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);124 125  return DebugLineEmitter.emit(OutLineTable);126}127 128Error DwarfUnit::emitDebugStringOffsetSection() {129  if (getVersion() < 5)130    return Error::success();131 132  if (DebugStringIndexMap.empty())133    return Error::success();134 135  SectionDescriptor &OutDebugStrOffsetsSection =136      getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);137 138  // Emit section header.139 140  //   Emit length.141  OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);142  uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();143 144  //   Emit version.145  OutDebugStrOffsetsSection.emitIntVal(5, 2);146 147  //   Emit padding.148  OutDebugStrOffsetsSection.emitIntVal(0, 2);149 150  //   Emit index to offset map.151  for (const StringEntry *String : DebugStringIndexMap.getValues()) {152    // Note patch for string offset value.153    OutDebugStrOffsetsSection.notePatch(154        DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});155 156    // Emit placeholder for offset value.157    OutDebugStrOffsetsSection.emitOffset(0xBADDEF);158  }159 160  // Patch section length.161  OutDebugStrOffsetsSection.apply(162      OffsetAfterSectionLength -163          OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),164      dwarf::DW_FORM_sec_offset,165      OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);166 167  return Error::success();168}169 170/// Emit the pubnames or pubtypes section contribution for \p171/// Unit into \p Sec. The data is provided in \p Info.172std::optional<uint64_t>173DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,174                                   const DwarfUnit::AccelInfo &Info,175                                   std::optional<uint64_t> LengthOffset) {176  if (!LengthOffset) {177    // Emit the header.178    OutSection.emitIntVal(0xBADDEF,179                          getFormParams().getDwarfOffsetByteSize()); // Length180    LengthOffset = OutSection.OS.tell();181 182    OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version183 184    OutSection.notePatch(DebugOffsetPatch{185        OutSection.OS.tell(),186        &getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});187    OutSection.emitOffset(0xBADDEF); // Unit offset188 189    OutSection.emitIntVal(getUnitSize(), 4); // Size190  }191  OutSection.emitOffset(Info.OutOffset);192 193  // Emit the string itself.194  OutSection.emitInplaceString(Info.String->first());195 196  return LengthOffset;197}198 199/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.200void DwarfUnit::emitPubAccelerators() {201  std::optional<uint64_t> NamesLengthOffset;202  std::optional<uint64_t> TypesLengthOffset;203 204  forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {205    if (Info.AvoidForPubSections)206      return;207 208    switch (Info.Type) {209    case DwarfUnit::AccelType::Name: {210      NamesLengthOffset = emitPubAcceleratorEntry(211          getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,212          NamesLengthOffset);213    } break;214    case DwarfUnit::AccelType::Type: {215      TypesLengthOffset = emitPubAcceleratorEntry(216          getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,217          TypesLengthOffset);218    } break;219    default: {220      // Nothing to do.221    } break;222    }223  });224 225  if (NamesLengthOffset) {226    SectionDescriptor &OutSection =227        getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);228    OutSection.emitIntVal(0, 4); // End marker.229 230    OutSection.apply(*NamesLengthOffset -231                         OutSection.getFormParams().getDwarfOffsetByteSize(),232                     dwarf::DW_FORM_sec_offset,233                     OutSection.OS.tell() - *NamesLengthOffset);234  }235 236  if (TypesLengthOffset) {237    SectionDescriptor &OutSection =238        getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);239    OutSection.emitIntVal(0, 4); // End marker.240 241    OutSection.apply(*TypesLengthOffset -242                         OutSection.getFormParams().getDwarfOffsetByteSize(),243                     dwarf::DW_FORM_sec_offset,244                     OutSection.OS.tell() - *TypesLengthOffset);245  }246}247