1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
//===- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DwarfStringPool.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h"
#include <cassert>
#include <utility>
using namespace llvm;
DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
StringRef Prefix)
: Pool(A), Prefix(Prefix),
ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
StringMapEntry<DwarfStringPool::EntryTy> &
DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {
auto I = Pool.insert(std::make_pair(Str, EntryTy()));
auto &Entry = I.first->second;
if (I.second) {
Entry.Index = EntryTy::NotIndexed;
Entry.Offset = NumBytes;
Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;
NumBytes += Str.size() + 1;
assert(NumBytes > Entry.Offset && "Unexpected overflow");
}
return *I.first;
}
DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
StringRef Str) {
auto &MapEntry = getEntryImpl(Asm, Str);
return EntryRef(MapEntry, false);
}
DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,
StringRef Str) {
auto &MapEntry = getEntryImpl(Asm, Str);
if (!MapEntry.getValue().isIndexed())
MapEntry.getValue().Index = NumIndexedStrings++;
return EntryRef(MapEntry, true);
}
void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
MCSection *Section,
MCSymbol *StartSym) {
if (getNumIndexedStrings() == 0)
return;
Asm.OutStreamer->SwitchSection(Section);
unsigned EntrySize = 4;
// FIXME: DWARF64
// We are emitting the header for a contribution to the string offsets
// table. The header consists of an entry with the contribution's
// size (not including the size of the length field), the DWARF version and
// 2 bytes of padding.
Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4);
Asm.emitInt16(Asm.getDwarfVersion());
Asm.emitInt16(0);
// Define the symbol that marks the start of the contribution. It is
// referenced by most unit headers via DW_AT_str_offsets_base.
// Split units do not use the attribute.
if (StartSym)
Asm.OutStreamer->EmitLabel(StartSym);
}
void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
MCSection *OffsetSection, bool UseRelativeOffsets) {
if (Pool.empty())
return;
// Start the dwarf str section.
Asm.OutStreamer->SwitchSection(StrSection);
// Get all of the string pool entries and sort them by their offset.
SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;
Entries.reserve(Pool.size());
for (const auto &E : Pool)
Entries.push_back(&E);
llvm::sort(Entries, [](const StringMapEntry<EntryTy> *A,
const StringMapEntry<EntryTy> *B) {
return A->getValue().Offset < B->getValue().Offset;
});
for (const auto &Entry : Entries) {
assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&
"Mismatch between setting and entry");
// Emit a label for reference from debug information entries.
if (ShouldCreateSymbols)
Asm.OutStreamer->EmitLabel(Entry->getValue().Symbol);
// Emit the string itself with a terminating null byte.
Asm.OutStreamer->AddComment("string offset=" +
Twine(Entry->getValue().Offset));
Asm.OutStreamer->EmitBytes(
StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1));
}
// If we've got an offset section go ahead and emit that now as well.
if (OffsetSection) {
// Now only take the indexed entries and put them in an array by their ID so
// we can emit them in order.
Entries.resize(NumIndexedStrings);
for (const auto &Entry : Pool) {
if (Entry.getValue().isIndexed())
Entries[Entry.getValue().Index] = &Entry;
}
Asm.OutStreamer->SwitchSection(OffsetSection);
unsigned size = 4; // FIXME: DWARF64 is 8.
for (const auto &Entry : Entries)
if (UseRelativeOffsets)
Asm.emitDwarfStringOffset(Entry->getValue());
else
Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
}
}
|