// Compute the size and offset of a DIE. The offset is relative to start of the // CU. It returns the offset after laying out the DIE. unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) { // Record the abbreviation. assignAbbrevNumber(Die.getAbbrev()); // Get the abbreviation for this DIE. const DIEAbbrev &Abbrev = Die.getAbbrev(); // Set DIE offset Die.setOffset(Offset); // Start the size with the size of abbreviation code. Offset += getULEB128Size(Die.getAbbrevNumber()); const SmallVectorImpl<DIEValue *> &Values = Die.getValues(); const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); // Get the children. const auto &Children = Die.getChildren(); // Size the DIE children if any. if (!Children.empty()) { assert(Abbrev.hasChildren() && "Children flag not set"); for (auto &Child : Children) Offset = computeSizeAndOffset(*Child, Offset); // End of children marker. Offset += sizeof(int8_t); } Die.setSize(Offset - Die.getOffset()); return Offset; }
void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params, StringRef PrologueBytes, unsigned MinInstLength, std::vector<DWARFDebugLine::Row> &Rows, unsigned PointerSize) { // Switch to the section where the table will be emitted into. MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection()); MCSymbol *LineStartSym = MC->createTempSymbol(); MCSymbol *LineEndSym = MC->createTempSymbol(); // The first 4 bytes is the total length of the information for this // compilation unit (not including these 4 bytes for the length). Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4); Asm->OutStreamer->EmitLabel(LineStartSym); // Copy Prologue. MS->EmitBytes(PrologueBytes); LineSectionSize += PrologueBytes.size() + 4; SmallString<128> EncodingBuffer; raw_svector_ostream EncodingOS(EncodingBuffer); if (Rows.empty()) { // We only have the dummy entry, dsymutil emits an entry with a 0 // address in that case. MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); MS->EmitLabel(LineEndSym); return; } // Line table state machine fields unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; unsigned IsStatement = 1; unsigned Isa = 0; uint64_t Address = -1ULL; unsigned RowsSinceLastSequence = 0; for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) { auto &Row = Rows[Idx]; int64_t AddressDelta; if (Address == -1ULL) { MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MS->EmitULEB128IntValue(PointerSize + 1); MS->EmitIntValue(dwarf::DW_LNE_set_address, 1); MS->EmitIntValue(Row.Address, PointerSize); LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1); AddressDelta = 0; } else { AddressDelta = (Row.Address - Address) / MinInstLength; } // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. // We should find a way to share this code, but the current compatibility // requirement with classic dsymutil makes it hard. Revisit that once this // requirement is dropped. if (FileNum != Row.File) { FileNum = Row.File; MS->EmitIntValue(dwarf::DW_LNS_set_file, 1); MS->EmitULEB128IntValue(FileNum); LineSectionSize += 1 + getULEB128Size(FileNum); } if (Column != Row.Column) { Column = Row.Column; MS->EmitIntValue(dwarf::DW_LNS_set_column, 1); MS->EmitULEB128IntValue(Column); LineSectionSize += 1 + getULEB128Size(Column); } // FIXME: We should handle the discriminator here, but dsymutil doesn't // consider it, thus ignore it for now. if (Isa != Row.Isa) { Isa = Row.Isa; MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); MS->EmitULEB128IntValue(Isa); LineSectionSize += 1 + getULEB128Size(Isa); } if (IsStatement != Row.IsStmt) { IsStatement = Row.IsStmt; MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); LineSectionSize += 1; } if (Row.BasicBlock) { MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); LineSectionSize += 1; } if (Row.PrologueEnd) { MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); LineSectionSize += 1; } if (Row.EpilogueBegin) { MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); LineSectionSize += 1; } int64_t LineDelta = int64_t(Row.Line) - LastLine; if (!Row.EndSequence) { MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); Address = Row.Address; LastLine = Row.Line; RowsSinceLastSequence++; } else { if (LineDelta) { MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1); MS->EmitSLEB128IntValue(LineDelta); LineSectionSize += 1 + getSLEB128Size(LineDelta); } if (AddressDelta) { MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1); MS->EmitULEB128IntValue(AddressDelta); LineSectionSize += 1 + getULEB128Size(AddressDelta); } MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); Address = -1ULL; LastLine = FileNum = IsStatement = 1; RowsSinceLastSequence = Column = Isa = 0; } } if (RowsSinceLastSequence) { MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); } MS->EmitLabel(LineEndSym); }