#include "BinaryHolder.h"
#include "DebugMap.h"
#include "dsymutil.h"
+#include "NonRelocatableStringpool.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
namespace {
-void warn(const Twine &Warning, const Twine &Context) {
- errs() << Twine("while processing ") + Context + ":\n";
- errs() << Twine("warning: ") + Warning + "\n";
-}
-
-bool error(const Twine &Error, const Twine &Context) {
- errs() << Twine("while processing ") + Context + ":\n";
- errs() << Twine("error: ") + Error + "\n";
- return false;
-}
-
template <typename KeyT, typename ValT>
using HalfOpenIntervalMap =
IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
class CompileUnit;
struct DeclMapInfo;
-class NonRelocatableStringpool;
/// A DeclContext is a named program scope that is used for ODR
/// uniquing of types.
Pubtypes.emplace_back(Name, Die, Offset, false);
}
-/// \brief A string table that doesn't need relocations.
-///
-/// We are doing a final link, no need for a string table that
-/// has relocation entries for every reference to it. This class
-/// provides this ablitity by just associating offsets with
-/// strings.
-class NonRelocatableStringpool {
-public:
- /// \brief Entries are stored into the StringMap and simply linked
- /// together through the second element of this pair in order to
- /// keep track of insertion order.
- typedef StringMap<std::pair<uint32_t, StringMapEntryBase *>, BumpPtrAllocator>
- MapTy;
-
- NonRelocatableStringpool()
- : CurrentEndOffset(0), Sentinel(0), Last(&Sentinel) {
- // Legacy dsymutil puts an empty string at the start of the line
- // table.
- getStringOffset("");
- }
-
- /// \brief Get the offset of string \p S in the string table. This
- /// can insert a new element or return the offset of a preexisitng
- /// one.
- uint32_t getStringOffset(StringRef S);
-
- /// \brief Get permanent storage for \p S (but do not necessarily
- /// emit \p S in the output section).
- /// \returns The StringRef that points to permanent storage to use
- /// in place of \p S.
- StringRef internString(StringRef S);
-
- // \brief Return the first entry of the string table.
- const MapTy::MapEntryTy *getFirstEntry() const {
- return getNextEntry(&Sentinel);
- }
-
- // \brief Get the entry following \p E in the string table or null
- // if \p E was the last entry.
- const MapTy::MapEntryTy *getNextEntry(const MapTy::MapEntryTy *E) const {
- return static_cast<const MapTy::MapEntryTy *>(E->getValue().second);
- }
-
- uint64_t getSize() { return CurrentEndOffset; }
-
-private:
- MapTy Strings;
- uint32_t CurrentEndOffset;
- MapTy::MapEntryTy Sentinel, *Last;
-};
-
-/// \brief Get the offset of string \p S in the string table. This
-/// can insert a new element or return the offset of a preexisitng
-/// one.
-uint32_t NonRelocatableStringpool::getStringOffset(StringRef S) {
- if (S.empty() && !Strings.empty())
- return 0;
-
- std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
- MapTy::iterator It;
- bool Inserted;
-
- // A non-empty string can't be at offset 0, so if we have an entry
- // with a 0 offset, it must be a previously interned string.
- std::tie(It, Inserted) = Strings.insert(std::make_pair(S, Entry));
- if (Inserted || It->getValue().first == 0) {
- // Set offset and chain at the end of the entries list.
- It->getValue().first = CurrentEndOffset;
- CurrentEndOffset += S.size() + 1; // +1 for the '\0'.
- Last->getValue().second = &*It;
- Last = &*It;
- }
- return It->getValue().first;
-}
-
-/// \brief Put \p S into the StringMap so that it gets permanent
-/// storage, but do not actually link it in the chain of elements
-/// that go into the output section. A latter call to
-/// getStringOffset() with the same string will chain it though.
-StringRef NonRelocatableStringpool::internString(StringRef S) {
- std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
- auto InsertResult = Strings.insert(std::make_pair(S, Entry));
- return InsertResult.first->getKey();
-}
-
/// \brief The Dwarf streaming logic
///
/// All interactions with the MC layer that is used to build the debug
/// \brief Emit the line table described in \p Rows into the
/// debug_line section.
- void emitLineTableForUnit(StringRef PrologueBytes, unsigned MinInstLength,
+ void emitLineTableForUnit(MCDwarfLineTableParams Params,
+ StringRef PrologueBytes, unsigned MinInstLength,
std::vector<DWARFDebugLine::Row> &Rows,
unsigned AdddressSize);
}
}
-void DwarfStreamer::emitLineTableForUnit(StringRef PrologueBytes,
+void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
+ StringRef PrologueBytes,
unsigned MinInstLength,
std::vector<DWARFDebugLine::Row> &Rows,
unsigned PointerSize) {
if (Rows.empty()) {
// We only have the dummy entry, dsymutil emits an entry with a 0
// address in that case.
- MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
+ MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
MS->EmitBytes(EncodingOS.str());
LineSectionSize += EncodingBuffer.size();
MS->EmitLabel(LineEndSym);
int64_t LineDelta = int64_t(Row.Line) - LastLine;
if (!Row.EndSequence) {
- MCDwarfLineAddr::Encode(*MC, LineDelta, AddressDelta, EncodingOS);
+ MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
MS->EmitBytes(EncodingOS.str());
LineSectionSize += EncodingBuffer.size();
EncodingBuffer.resize(0);
- EncodingOS.resync();
Address = Row.Address;
LastLine = Row.Line;
RowsSinceLastSequence++;
MS->EmitULEB128IntValue(AddressDelta);
LineSectionSize += 1 + getULEB128Size(AddressDelta);
}
- MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
+ MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
MS->EmitBytes(EncodingOS.str());
LineSectionSize += EncodingBuffer.size();
EncodingBuffer.resize(0);
- EncodingOS.resync();
Address = -1ULL;
LastLine = FileNum = IsStatement = 1;
RowsSinceLastSequence = Column = Isa = 0;
}
if (RowsSinceLastSequence) {
- MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
+ MCDwarfLineAddr::Encode(*MC, Params, INT64_MAX, 0, EncodingOS);
MS->EmitBytes(EncodingOS.str());
LineSectionSize += EncodingBuffer.size();
EncodingBuffer.resize(0);
- EncodingOS.resync();
}
MS->EmitLabel(LineEndSym);
unsigned DwarfLinker::cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
unsigned AttrSize) {
- DIE *Attr;
+ DIEValueList *Attr;
DIEValue Value;
DIELoc *Loc = nullptr;
DIEBlock *Block = nullptr;
Block = new (DIEAlloc) DIEBlock;
DIEBlocks.push_back(Block);
}
- Attr = Loc ? static_cast<DIE *>(Loc) : static_cast<DIE *>(Block);
+ Attr = Loc ? static_cast<DIEValueList *>(Loc)
+ : static_cast<DIEValueList *>(Block);
if (Loc)
Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
if (StopAddress != -1ULL && !Seq.empty()) {
// Insert end sequence row with the computed end address, but
// the same line as the previous one.
- Seq.emplace_back(Seq.back());
- Seq.back().Address = StopAddress;
- Seq.back().EndSequence = 1;
- Seq.back().PrologueEnd = 0;
- Seq.back().BasicBlock = 0;
- Seq.back().EpilogueBegin = 0;
+ auto NextLine = Seq.back();
+ NextLine.Address = StopAddress;
+ NextLine.EndSequence = 1;
+ NextLine.PrologueEnd = 0;
+ NextLine.BasicBlock = 0;
+ NextLine.EpilogueBegin = 0;
+ Seq.push_back(NextLine);
insertLineSequence(Seq, NewRows);
}
// table emitter.
if (LineTable.Prologue.Version != 2 ||
LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT ||
- LineTable.Prologue.LineBase != -5 || LineTable.Prologue.LineRange != 14 ||
- LineTable.Prologue.OpcodeBase != 13)
+ LineTable.Prologue.OpcodeBase > 13)
reportWarning("line table paramters mismatch. Cannot emit.");
- else
- Streamer->emitLineTableForUnit(LineData.slice(StmtList + 4, PrologueEnd),
+ else {
+ MCDwarfLineTableParams Params;
+ Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
+ Params.DWARF2LineBase = LineTable.Prologue.LineBase;
+ Params.DWARF2LineRange = LineTable.Prologue.LineRange;
+ Streamer->emitLineTableForUnit(Params,
+ LineData.slice(StmtList + 4, PrologueEnd),
LineTable.Prologue.MinInstLength, NewRows,
Unit.getOrigUnit().getAddressByteSize());
+ }
}
void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
bool DwarfLinker::link(const DebugMap &Map) {
- if (Map.begin() == Map.end()) {
- errs() << "Empty debug map.\n";
- return false;
- }
-
if (!createStreamer(Map.getTriple(), OutputFilename))
return false;
}
}
+/// \brief Get the offset of string \p S in the string table. This
+/// can insert a new element or return the offset of a preexisitng
+/// one.
+uint32_t NonRelocatableStringpool::getStringOffset(StringRef S) {
+ if (S.empty() && !Strings.empty())
+ return 0;
+
+ std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
+ MapTy::iterator It;
+ bool Inserted;
+
+ // A non-empty string can't be at offset 0, so if we have an entry
+ // with a 0 offset, it must be a previously interned string.
+ std::tie(It, Inserted) = Strings.insert(std::make_pair(S, Entry));
+ if (Inserted || It->getValue().first == 0) {
+ // Set offset and chain at the end of the entries list.
+ It->getValue().first = CurrentEndOffset;
+ CurrentEndOffset += S.size() + 1; // +1 for the '\0'.
+ Last->getValue().second = &*It;
+ Last = &*It;
+ }
+ return It->getValue().first;
+}
+
+/// \brief Put \p S into the StringMap so that it gets permanent
+/// storage, but do not actually link it in the chain of elements
+/// that go into the output section. A latter call to
+/// getStringOffset() with the same string will chain it though.
+StringRef NonRelocatableStringpool::internString(StringRef S) {
+ std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
+ auto InsertResult = Strings.insert(std::make_pair(S, Entry));
+ return InsertResult.first->getKey();
+}
+
+void warn(const Twine &Warning, const Twine &Context) {
+ errs() << Twine("while processing ") + Context + ":\n";
+ errs() << Twine("warning: ") + Warning + "\n";
+}
+
+bool error(const Twine &Error, const Twine &Context) {
+ errs() << Twine("while processing ") + Context + ":\n";
+ errs() << Twine("error: ") + Error + "\n";
+ return false;
+}
+
bool linkDwarf(StringRef OutputFilename, const DebugMap &DM,
const LinkOptions &Options) {
DwarfLinker Linker(OutputFilename, Options);