Newer
Older
O << '\n';
#endif
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// EndFunction - Gather and emit post-function debug information.
///
void DwarfDebug::EndFunction(MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
if (DbgScopeMap.empty())
return;
#endif
// Define end label for subprogram.
EmitLabel("func_end", SubprogramCount);
// Get function line info.
if (!Lines.empty()) {
// Get section line info.
Chris Lattner
committed
unsigned ID = SectionMap.insert(Asm->getCurrentSection());
if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
// Append the function info to section info.
SectionLineInfos.insert(SectionLineInfos.end(),
Lines.begin(), Lines.end());
}
// Construct the DbgScope for abstract instances.
for (SmallVector<DbgScope *, 32>::iterator
I = AbstractInstanceRootList.begin(),
E = AbstractInstanceRootList.end(); I != E; ++I)
ConstructFunctionDbgScope(*I);
// Construct scopes for subprogram.
if (FunctionDbgScope)
ConstructFunctionDbgScope(FunctionDbgScope);
else
// FIXME: This is wrong. We are essentially getting past a problem with
// debug information not being able to handle unreachable blocks that have
// debug information in them. In particular, those unreachable blocks that
// have "region end" info in them. That situation results in the "root
// scope" not being created. If that's the case, then emit a "default"
// scope, i.e., one that encompasses the whole function. This isn't
// desirable. And a better way of handling this (and all of the debugging
// information) needs to be explored.
ConstructDefaultDbgScope(MF);
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
// Clear debug info
if (FunctionDbgScope) {
delete FunctionDbgScope;
DbgScopeMap.clear();
Devang Patel
committed
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
DbgAbstractScopeMap.clear();
DbgConcreteScopeMap.clear();
FunctionDbgScope = NULL;
LexicalScopeStack.clear();
AbstractInstanceRootList.clear();
AbstractInstanceRootMap.clear();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// RecordSourceLine - Records location information and associates it with a
/// label. Returns a unique label ID used to generate a label and provide
/// correspondence to the source line list.
unsigned DwarfDebug::RecordSourceLine(unsigned Line, unsigned Col,
MDNode *S) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
const char *Dir = NULL;
const char *Fn = NULL;
DIDescriptor Scope(S);
if (Scope.isCompileUnit()) {
DICompileUnit CU(S);
Dir = CU.getDirectory();
Fn = CU.getFilename();
} else if (Scope.isSubprogram()) {
DISubprogram SP(S);
Dir = SP.getDirectory();
Fn = SP.getFilename();
} else if (Scope.isLexicalBlock()) {
DILexicalBlock DB(S);
Dir = DB.getDirectory();
Fn = DB.getFilename();
} else
assert (0 && "Unexpected scope info");
unsigned Src = GetOrCreateSourceID(Dir, Fn);
unsigned ID = MMI->NextLabelID();
Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
/// timed. Look up the source id with the given directory and source file
/// names. If none currently exists, create a new id and insert it in the
/// SourceIds map. This can update DirectoryNames and SourceFileNames maps as
/// well.
unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
const std::string &FileName) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return SrcId;
/// RecordRegionStart - Indicate the start of a region.
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned ID = MMI->NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
LexicalScopeStack.push_back(Scope);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// RecordRegionEnd - Indicate the end of a region.
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned ID = MMI->NextLabelID();
Scope->setEndLabelID(ID);
Devang Patel
committed
// FIXME : region.end() may not be in the last basic block.
// For now, do not pop last lexical scope because next basic
// block may start new inlined function's body.
unsigned LSSize = LexicalScopeStack.size();
if (LSSize != 0 && LSSize != 1)
LexicalScopeStack.pop_back();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// RecordVariable - Indicate the declaration of a local variable.
void DwarfDebug::RecordVariable(MDNode *N, unsigned FrameIndex) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
DbgScope *Scope = NULL;
bool InlinedFnVar = false;
if (Desc.getTag() == dwarf::DW_TAG_variable)
Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode());
else {
bool InlinedVar = false;
MDNode *Context = DIVariable(N).getContext().getNode();
DISubprogram SP(Context);
if (!SP.isNull()) {
// SP is inserted into DbgAbstractScopeMap when inlined function
// start was recorded by RecordInlineFnStart.
Devang Patel
committed
ValueMap<MDNode *, DbgScope *>::iterator
if (I != DbgAbstractScopeMap.end()) {
InlinedVar = true;
Scope = I->second;
}
}
assert(Scope && "Unable to find the variable's scope");
DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex, InlinedFnVar);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
unsigned Line, unsigned Col) {
unsigned LabelID = MMI->NextLabelID();
if (!MAI->doesDwarfUsesInlineInfoSection())
if (TimePassesIsEnabled)
DebugTimer->startTimer();
MDNode *Node = SP.getNode();
DenseMap<const MDNode *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(Node);
if (II == AbstractInstanceRootMap.end()) {
// Create an abstract instance entry for this inlined function if it doesn't
// already exist.
DbgScope *Scope = new DbgScope(NULL, DIDescriptor(Node));
Bill Wendling
committed
// Get the compile unit context.
SPDie = CreateSubprogramDIE(ModuleCU, SP, false, true);
// Mark as being inlined. This makes this subprogram entry an abstract
// instance root.
// FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
// that it's defined. That probably won't change in the future. However,
// this could be more elegant.
AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
Bill Wendling
committed
// Keep track of the abstract scope for this function.
Bill Wendling
committed
AbstractInstanceRootList.push_back(Scope);
}
Bill Wendling
committed
// Create a concrete inlined instance for this inlined function.
DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(Node));
DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, Origin);
AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
Bill Wendling
committed
ConcreteScope->setDie(ScopeDie);
ConcreteScope->setStartLabelID(LabelID);
MMI->RecordUsedDbgLabel(LabelID);
LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
// Keep track of the concrete scope that's inlined into this function.
Devang Patel
committed
ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
Bill Wendling
committed
if (SI == DbgConcreteScopeMap.end())
else
SI->second.push_back(ConcreteScope);
Bill Wendling
committed
// Track the start label for this inlined function.
Devang Patel
committed
ValueMap<MDNode *, SmallVector<unsigned, 4> >::iterator
Bill Wendling
committed
if (I == InlineInfo.end())
else
I->second.push_back(LabelID);
Bill Wendling
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
if (!MAI->doesDwarfUsesInlineInfoSection())
if (TimePassesIsEnabled)
DebugTimer->startTimer();
Devang Patel
committed
ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
if (I == DbgConcreteScopeMap.end()) {
// FIXME: Can this situation actually happen? And if so, should it?
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
Bill Wendling
committed
SmallVector<DbgScope *, 8> &Scopes = I->second;
if (Scopes.empty()) {
// Returned ID is 0 if this is unbalanced "end of inlined
// scope". This could happen if optimizer eats dbg intrinsics
// or "beginning of inlined scope" is not recoginized due to
// missing location info. In such cases, ignore this region.end.
return 0;
}
DbgScope *Scope = Scopes.back(); Scopes.pop_back();
unsigned ID = MMI->NextLabelID();
MMI->RecordUsedDbgLabel(ID);
Scope->setEndLabelID(ID);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return ID;
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
/// SizeAndOffsetDie - Compute the size and offset of a DIE.
///
unsigned DwarfDebug::SizeAndOffsetDie(DIE *Die, unsigned Offset, bool Last) {
// Get the children.
const std::vector<DIE *> &Children = Die->getChildren();
// If not last sibling and has children then add sibling offset attribute.
if (!Last && !Children.empty()) Die->AddSiblingOffset();
// Record the abbreviation.
AssignAbbrevNumber(Die->getAbbrev());
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
// Set DIE offset
Die->setOffset(Offset);
// Start the size with the size of abbreviation code.
Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);
const SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &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(TD, AbbrevData[i].getForm());
// Size the DIE children if any.
if (!Children.empty()) {
assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
"Children flag not set");
for (unsigned j = 0, M = Children.size(); j < M; ++j)
Offset = SizeAndOffsetDie(Children[j], Offset, (j + 1) == M);
// End of children marker.
Offset += sizeof(int8_t);
}
Die->setSize(Offset - Die->getOffset());
return Offset;
/// SizeAndOffsets - Compute the size and offset of all the DIEs.
///
void DwarfDebug::SizeAndOffsets() {
// Compute size of compile unit header.
static unsigned Offset =
sizeof(int32_t) + // Length of Compilation Unit Info
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
SizeAndOffsetDie(ModuleCU->getDie(), Offset, true);
CompileUnitOffsets[ModuleCU] = 0;
/// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc
/// tools to recognize the object file contains Dwarf information.
void DwarfDebug::EmitInitial() {
// Check to see if we already emitted intial headers.
if (didInitial) return;
didInitial = true;
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
// Dwarf sections base addresses.
if (MAI->doesDwarfRequireFrameSection()) {
Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection());
EmitLabel("section_debug_frame", 0);
}
Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
EmitLabel("section_info", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
EmitLabel("section_abbrev", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
EmitLabel("section_aranges", 0);
if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
Asm->OutStreamer.SwitchSection(LineInfoDirective);
EmitLabel("section_macinfo", 0);
}
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
EmitLabel("section_line", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
EmitLabel("section_loc", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
EmitLabel("section_pubnames", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
EmitLabel("section_str", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
EmitLabel("section_ranges", 0);
Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
EmitLabel("text_begin", 0);
Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
EmitLabel("data_begin", 0);
Bill Wendling
committed
}
/// EmitDIE - Recusively Emits a debug information entry.
///
void DwarfDebug::EmitDIE(DIE *Die) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
Bill Wendling
committed
Bill Wendling
committed
// Emit the code (index) for the abbreviation.
Asm->EmitULEB128Bytes(AbbrevNumber);
Bill Wendling
committed
if (Asm->isVerbose())
Asm->EOL(std::string("Abbrev [" +
utostr(AbbrevNumber) +
"] 0x" + utohexstr(Die->getOffset()) +
":0x" + utohexstr(Die->getSize()) + " " +
dwarf::TagString(Abbrev->getTag())));
else
Asm->EOL();
Bill Wendling
committed
SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
unsigned Attr = AbbrevData[i].getAttribute();
unsigned Form = AbbrevData[i].getForm();
assert(Form && "Too many attributes for DIE (check abbreviation)");
switch (Attr) {
case dwarf::DW_AT_sibling:
Asm->EmitInt32(Die->SiblingOffset());
break;
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr =
CompileUnitOffsets[Die->getAbstractCompileUnit()] +
Origin->getOffset();
Asm->EmitInt32(Addr);
break;
}
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(this, Form);
break;
}
Asm->EOL(dwarf::AttributeString(Attr));
}
// Emit the DIE children if any.
if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
const std::vector<DIE *> &Children = Die->getChildren();
for (unsigned j = 0, M = Children.size(); j < M; ++j)
EmitDIE(Children[j]);
Asm->EmitInt8(0); Asm->EOL("End Of Children Mark");
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
/// EmitDebugInfo / EmitDebugInfoPerCU - Emit the debug info section.
///
void DwarfDebug::EmitDebugInfoPerCU(CompileUnit *Unit) {
DIE *Die = Unit->getDie();
// Emit the compile units header.
EmitLabel("info_begin", Unit->getID());
// Emit size of content not including length itself
unsigned ContentSize = Die->getSize() +
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t) + // Pointer Size (in bytes)
sizeof(int32_t); // FIXME - extra pad for gdb bug.
Asm->EmitInt32(ContentSize); Asm->EOL("Length of Compilation Unit Info");
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
EmitSectionOffset("abbrev_begin", "section_abbrev", 0, 0, true, false);
Asm->EOL("Offset Into Abbrev. Section");
Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
EmitDIE(Die);
// FIXME - extra padding for gdb bug.
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
EmitLabel("info_end", Unit->getID());
Asm->EOL();
}
void DwarfDebug::EmitDebugInfo() {
// Start debug info section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfInfoSection());
Bill Wendling
committed
}
/// EmitAbbreviations - Emit the abbreviation section.
Bill Wendling
committed
///
void DwarfDebug::EmitAbbreviations() const {
// Check to see if it is worth the effort.
if (!Abbreviations.empty()) {
// Start the debug abbrev section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAbbrevSection());
EmitLabel("abbrev_begin", 0);
// For each abbrevation.
for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
// Get abbreviation data
const DIEAbbrev *Abbrev = Abbreviations[i];
// Emit the abbrevations code (base 1 index.)
Asm->EmitULEB128Bytes(Abbrev->getNumber());
Asm->EOL("Abbreviation Code");
// Emit the abbreviations data.
Abbrev->Emit(Asm);
// Mark end of abbreviations.
Asm->EmitULEB128Bytes(0); Asm->EOL("EOM(3)");
EmitLabel("abbrev_end", 0);
Asm->EOL();
}
}
/// EmitEndOfLineMatrix - Emit the last address of the section and the end of
/// the line matrix.
///
void DwarfDebug::EmitEndOfLineMatrix(unsigned SectionEnd) {
// Define last address of section.
Asm->EmitInt8(0); Asm->EOL("Extended Op");
Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
EmitReference("section_end", SectionEnd); Asm->EOL("Section end label");
// Mark end of matrix.
Asm->EmitInt8(0); Asm->EOL("DW_LNE_end_sequence");
Asm->EmitULEB128Bytes(1); Asm->EOL();
Asm->EmitInt8(1); Asm->EOL();
}
/// EmitDebugLines - Emit source line information.
///
void DwarfDebug::EmitDebugLines() {
// If the target is using .loc/.file, the assembler will be emitting the
// .debug_line table automatically.
if (MAI->hasDotLocAndDotFile())
// Minimum line delta, thus ranging from -10..(255-10).
const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1);
// Maximum line delta, thus ranging from -10..(255-10).
const int MaxLineDelta = 255 + MinLineDelta;
// Start the dwarf line section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLineSection());
// Construct the section header.
EmitDifference("line_end", 0, "line_begin", 0, true);
Asm->EOL("Length of Source Line Info");
EmitLabel("line_begin", 0);
Bill Wendling
committed
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF version number");
EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0, true);
Asm->EOL("Prolog Length");
EmitLabel("line_prolog_begin", 0);
Asm->EmitInt8(1); Asm->EOL("Minimum Instruction Length");
Asm->EmitInt8(1); Asm->EOL("Default is_stmt_start flag");
Asm->EmitInt8(MinLineDelta); Asm->EOL("Line Base Value (Special Opcodes)");
Asm->EmitInt8(MaxLineDelta); Asm->EOL("Line Range Value (Special Opcodes)");
Asm->EmitInt8(-MinLineDelta); Asm->EOL("Special Opcode Base");
// Line number standard opcode encodings argument count
Asm->EmitInt8(0); Asm->EOL("DW_LNS_copy arg count");
Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_pc arg count");
Asm->EmitInt8(1); Asm->EOL("DW_LNS_advance_line arg count");
Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_file arg count");
Asm->EmitInt8(1); Asm->EOL("DW_LNS_set_column arg count");
Asm->EmitInt8(0); Asm->EOL("DW_LNS_negate_stmt arg count");
Asm->EmitInt8(0); Asm->EOL("DW_LNS_set_basic_block arg count");
Asm->EmitInt8(0); Asm->EOL("DW_LNS_const_add_pc arg count");
Asm->EmitInt8(1); Asm->EOL("DW_LNS_fixed_advance_pc arg count");
Bill Wendling
committed
// Emit directories.
for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
Asm->EmitString(getSourceDirectoryName(DI));
Asm->EOL("Directory");
}
Asm->EmitInt8(0); Asm->EOL("End of directories");
// Emit files.
for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
// Remember source id starts at 1.
std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
Asm->EmitString(getSourceFileName(Id.second));
Asm->EOL("Source");
Asm->EmitULEB128Bytes(Id.first);
Asm->EOL("Directory #");
Asm->EmitULEB128Bytes(0);
Asm->EOL("Mod date");
Asm->EmitULEB128Bytes(0);
Asm->EOL("File size");
Asm->EmitInt8(0); Asm->EOL("End of files");
EmitLabel("line_prolog_end", 0);
// A sequence for each text section.
unsigned SecSrcLinesSize = SectionSourceLines.size();
for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
// Isolate current sections line info.
const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
Chris Lattner
committed
/*if (Asm->isVerbose()) {
const MCSection *S = SectionMap[j + 1];
O << '\t' << MAI->getCommentString() << " Section"
Chris Lattner
committed
}*/
Asm->EOL();
// Dwarf assumes we start with first line of first source file.
unsigned Source = 1;
unsigned Line = 1;
// Construct rows of the address, source, line, column matrix.
for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
const SrcLineInfo &LineInfo = LineInfos[i];
unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
if (!LabelID) continue;
if (LineInfo.getLine() == 0) continue;
if (!Asm->isVerbose())
Asm->EOL();
else {
std::pair<unsigned, unsigned> SourceID =
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
O << '\t' << MAI->getCommentString() << ' '
<< getSourceDirectoryName(SourceID.first) << ' '
<< getSourceFileName(SourceID.second)
<<" :" << utostr_32(LineInfo.getLine()) << '\n';
}
// Define the line address.
Asm->EmitInt8(0); Asm->EOL("Extended Op");
Asm->EmitInt8(TD->getPointerSize() + 1); Asm->EOL("Op size");
Asm->EmitInt8(dwarf::DW_LNE_set_address); Asm->EOL("DW_LNE_set_address");
EmitReference("label", LabelID); Asm->EOL("Location label");
// If change of source, then switch to the new source.
if (Source != LineInfo.getSourceID()) {
Source = LineInfo.getSourceID();
Asm->EmitInt8(dwarf::DW_LNS_set_file); Asm->EOL("DW_LNS_set_file");
Asm->EmitULEB128Bytes(Source); Asm->EOL("New Source");
}
// If change of line.
if (Line != LineInfo.getLine()) {
// Determine offset.
int Offset = LineInfo.getLine() - Line;
int Delta = Offset - MinLineDelta;
// Update line.
Line = LineInfo.getLine();
// If delta is small enough and in range...
if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
// ... then use fast opcode.
Asm->EmitInt8(Delta - MinLineDelta); Asm->EOL("Line Delta");
} else {
// ... otherwise use long hand.
Asm->EmitInt8(dwarf::DW_LNS_advance_line);
Asm->EOL("DW_LNS_advance_line");
Asm->EmitSLEB128Bytes(Offset); Asm->EOL("Line Offset");
Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
}
} else {
// Copy the previous row (different address or source)
Asm->EmitInt8(dwarf::DW_LNS_copy); Asm->EOL("DW_LNS_copy");
}
}
EmitEndOfLineMatrix(j + 1);
}
if (SecSrcLinesSize == 0)
// Because we're emitting a debug_line section, we still need a line
// table. The linker and friends expect it to exist. If there's nothing to
// put into it, emit an empty table.
EmitEndOfLineMatrix(1);
EmitLabel("line_end", 0);
Asm->EOL();
/// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
///
void DwarfDebug::EmitCommonDebugFrame() {
if (!MAI->doesDwarfRequireFrameSection())
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
TD->getPointerSize() : -TD->getPointerSize();
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
EmitLabel("debug_frame_common", 0);
EmitDifference("debug_frame_common_end", 0,
"debug_frame_common_begin", 0, true);
Asm->EOL("Length of Common Information Entry");
EmitLabel("debug_frame_common_begin", 0);
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
Asm->EOL("CIE Identifier Tag");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
Asm->EOL("CIE Version");
Asm->EmitString("");
Asm->EOL("CIE Augmentation");
Asm->EmitULEB128Bytes(1);
Asm->EOL("CIE Code Alignment Factor");
Asm->EmitSLEB128Bytes(stackGrowth);
Asm->EOL("CIE Data Alignment Factor");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
Asm->EOL("CIE RA Column");
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
EmitFrameMoves(NULL, 0, Moves, false);
Asm->EmitAlignment(2, 0, 0, false);
EmitLabel("debug_frame_common_end", 0);
/// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
/// section.
void
DwarfDebug::EmitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
if (!MAI->doesDwarfRequireFrameSection())
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
EmitDifference("debug_frame_end", DebugFrameInfo.Number,
"debug_frame_begin", DebugFrameInfo.Number, true);
Asm->EOL("Length of Frame Information Entry");
EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
EmitSectionOffset("debug_frame_common", "section_debug_frame",
0, 0, true, false);
Asm->EOL("FDE CIE offset");
EmitReference("func_begin", DebugFrameInfo.Number);
Asm->EOL("FDE initial location");
EmitDifference("func_end", DebugFrameInfo.Number,
"func_begin", DebugFrameInfo.Number);
Asm->EOL("FDE address range");
EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
false);
Asm->EmitAlignment(2, 0, 0, false);
EmitLabel("debug_frame_end", DebugFrameInfo.Number);
void DwarfDebug::EmitDebugPubNamesPerCU(CompileUnit *Unit) {
EmitDifference("pubnames_end", Unit->getID(),
"pubnames_begin", Unit->getID(), true);
Asm->EOL("Length of Public Names Info");
EmitLabel("pubnames_begin", Unit->getID());
Bill Wendling
committed
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
Bill Wendling
committed
EmitSectionOffset("info_begin", "section_info",
Unit->getID(), 0, true, false);
Asm->EOL("Offset of Compilation Unit Info");
Bill Wendling
committed
EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),
true);
Asm->EOL("Compilation Unit Length");
StringMap<DIE*> &Globals = Unit->getGlobals();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
DIE * Entity = GI->second;
Asm->EmitInt32(Entity->getOffset()); Asm->EOL("DIE offset");
Asm->EmitString(Name, strlen(Name)); Asm->EOL("External Name");
Asm->EmitInt32(0); Asm->EOL("End Mark");
EmitLabel("pubnames_end", Unit->getID());
/// EmitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::EmitDebugPubNames() {
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubNamesSection());
/// EmitDebugStr - Emit visible names into a debug str section.
///
void DwarfDebug::EmitDebugStr() {
// Check to see if it is worth the effort.
if (!StringPool.empty()) {
// Start the dwarf str section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfStrSection());
// For each of strings in the string pool.
for (unsigned StringID = 1, N = StringPool.size();
StringID <= N; ++StringID) {
// Emit a label for reference from debug information entries.
EmitLabel("string", StringID);
// Emit the string itself.
const std::string &String = StringPool[StringID];
Asm->EmitString(String); Asm->EOL();
}
/// EmitDebugLoc - Emit visible names into a debug loc section.
///
void DwarfDebug::EmitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
/// EmitDebugARanges - Emit visible names into a debug aranges section.
///
void DwarfDebug::EmitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
// FIXME - Mock up
#if 0
CompileUnit *Unit = GetBaseCompileUnit();
// Don't include size of length
Asm->EmitInt32(0x1c); Asm->EOL("Length of Address Ranges Info");
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
EmitReference("info_begin", Unit->getID());
Asm->EOL("Offset of Compilation Unit Info");
Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Size of Address");
Asm->EmitInt8(0); Asm->EOL("Size of Segment Descriptor");
Asm->EmitInt16(0); Asm->EOL("Pad (1)");
Asm->EmitInt16(0); Asm->EOL("Pad (2)");
// Range 1
EmitReference("text_begin", 0); Asm->EOL("Address");
EmitDifference("text_end", 0, "text_begin", 0, true); Asm->EOL("Length");
Asm->EmitInt32(0); Asm->EOL("EOM (1)");
Asm->EmitInt32(0); Asm->EOL("EOM (2)");
#endif
Bill Wendling
committed
Bill Wendling
committed
}
/// EmitDebugRanges - Emit visible names into a debug ranges section.
///
void DwarfDebug::EmitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
Asm->EOL();
}
/// EmitDebugMacInfo - Emit visible names into a debug macinfo section.
///
void DwarfDebug::EmitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
Asm->OutStreamer.SwitchSection(LineInfo);
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
Asm->EOL();
}
}
/// EmitDebugInlineInfo - Emit inline info using following format.
/// Section Header:
/// 1. length of section
/// 2. Dwarf version number
/// 3. address size.
///
/// Entries (one "entry" for each function that was inlined):
///
/// 1. offset into __debug_str section for MIPS linkage name, if exists;
/// otherwise offset into __debug_str for regular function name.
/// 2. offset into __debug_str section for regular function name.
/// 3. an unsigned LEB128 number indicating the number of distinct inlining
/// instances for the function.
///
/// The rest of the entry consists of a {die_offset, low_pc} pair for each
/// inlined instance; the die_offset points to the inlined_subroutine die in the
/// __debug_info section, and the low_pc is the starting address for the
/// inlining instance.
void DwarfDebug::EmitDebugInlineInfo() {
if (!MAI->doesDwarfUsesInlineInfoSection())
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
Asm->EOL();
EmitDifference("debug_inlined_end", 1,
"debug_inlined_begin", 1, true);
Asm->EOL("Length of Debug Inlined Information Entry");