125 lines · cpp
1//===- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework -----------===//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 "DwarfStringPool.h"10#include "llvm/ADT/SmallVector.h"11#include "llvm/ADT/Twine.h"12#include "llvm/CodeGen/AsmPrinter.h"13#include "llvm/MC/MCAsmInfo.h"14#include "llvm/MC/MCStreamer.h"15#include <cassert>16 17using namespace llvm;18 19DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,20 StringRef Prefix)21 : Pool(A), Prefix(Prefix),22 ShouldCreateSymbols(Asm.doesDwarfUseRelocationsAcrossSections()) {}23 24StringMapEntry<DwarfStringPool::EntryTy> &25DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {26 auto I = Pool.try_emplace(Str);27 auto &Entry = I.first->second;28 if (I.second) {29 Entry.Index = EntryTy::NotIndexed;30 Entry.Offset = NumBytes;31 Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;32 33 NumBytes += Str.size() + 1;34 }35 return *I.first;36}37 38DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,39 StringRef Str) {40 auto &MapEntry = getEntryImpl(Asm, Str);41 return EntryRef(MapEntry);42}43 44DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,45 StringRef Str) {46 auto &MapEntry = getEntryImpl(Asm, Str);47 if (!MapEntry.getValue().isIndexed())48 MapEntry.getValue().Index = NumIndexedStrings++;49 return EntryRef(MapEntry);50}51 52void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,53 MCSection *Section,54 MCSymbol *StartSym) {55 if (getNumIndexedStrings() == 0)56 return;57 Asm.OutStreamer->switchSection(Section);58 unsigned EntrySize = Asm.getDwarfOffsetByteSize();59 // We are emitting the header for a contribution to the string offsets60 // table. The header consists of an entry with the contribution's61 // size (not including the size of the length field), the DWARF version and62 // 2 bytes of padding.63 Asm.emitDwarfUnitLength(getNumIndexedStrings() * EntrySize + 4,64 "Length of String Offsets Set");65 Asm.emitInt16(Asm.getDwarfVersion());66 Asm.emitInt16(0);67 // Define the symbol that marks the start of the contribution. It is68 // referenced by most unit headers via DW_AT_str_offsets_base.69 // Split units do not use the attribute.70 if (StartSym)71 Asm.OutStreamer->emitLabel(StartSym);72}73 74void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,75 MCSection *OffsetSection, bool UseRelativeOffsets) {76 if (Pool.empty())77 return;78 79 // Start the dwarf str section.80 Asm.OutStreamer->switchSection(StrSection);81 82 // Get all of the string pool entries and sort them by their offset.83 SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(84 llvm::make_pointer_range(Pool));85 86 llvm::sort(Entries, [](const StringMapEntry<EntryTy> *A,87 const StringMapEntry<EntryTy> *B) {88 return A->getValue().Offset < B->getValue().Offset;89 });90 91 for (const auto &Entry : Entries) {92 assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&93 "Mismatch between setting and entry");94 95 // Emit a label for reference from debug information entries.96 if (ShouldCreateSymbols)97 Asm.OutStreamer->emitLabel(Entry->getValue().Symbol);98 99 // Emit the string itself with a terminating null byte.100 Asm.OutStreamer->AddComment("string offset=" +101 Twine(Entry->getValue().Offset));102 Asm.OutStreamer->emitBytes(103 StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1));104 }105 106 // If we've got an offset section go ahead and emit that now as well.107 if (OffsetSection) {108 // Now only take the indexed entries and put them in an array by their ID so109 // we can emit them in order.110 Entries.resize(NumIndexedStrings);111 for (const auto &Entry : Pool) {112 if (Entry.getValue().isIndexed())113 Entries[Entry.getValue().Index] = &Entry;114 }115 116 Asm.OutStreamer->switchSection(OffsetSection);117 unsigned size = Asm.getDwarfOffsetByteSize();118 for (const auto &Entry : Entries)119 if (UseRelativeOffsets)120 Asm.emitDwarfStringOffset(Entry->getValue());121 else122 Asm.OutStreamer->emitIntValue(Entry->getValue().Offset, size);123 }124}125