Newer
Older
Jeffrey Yasskin
committed
DbgVariable *RegVar = new DbgVariable(DV, VP.first, AbsDbgVariable);
Scope->addVariable(RegVar);
}
Devang Patel
committed
// Collect variable information from DBG_VALUE machine instructions;
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
if (MInsn->getOpcode() != TargetOpcode::DBG_VALUE)
continue;
Devang Patel
committed
Devang Patel
committed
// FIXME : Lift this restriction.
if (MInsn->getNumOperands() != 3)
continue;
DIVariable DV((MDNode*)(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata()));
if (DV.getTag() == dwarf::DW_TAG_arg_variable) {
// FIXME Handle inlined subroutine arguments.
DbgVariable *ArgVar = new DbgVariable(DV, MInsn, NULL);
CurrentFnDbgScope->addVariable(ArgVar);
Devang Patel
committed
DbgValueStartMap[MInsn] = ArgVar;
Devang Patel
committed
continue;
}
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
DILocation ScopeLoc = MF->getDILocation(DL);
DbgScope *Scope =
ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode());
if (!Scope)
Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode());
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
Devang Patel
committed
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, MInsn, ScopeLoc);
Devang Patel
committed
DbgVariable *RegVar = new DbgVariable(DV, MInsn, AbsDbgVariable);
Devang Patel
committed
DbgValueStartMap[MInsn] = RegVar;
Devang Patel
committed
Scope->addVariable(RegVar);
}
}
}
Devang Patel
committed
/// beginScope - Process beginning of a scope.
void DwarfDebug::beginScope(const MachineInstr *MI) {
// Check location.
DebugLoc DL = MI->getDebugLoc();
if (DL.isUnknown())
return;
DILocation DILoc = MF->getDILocation(DL);
if (!DILoc.getScope().Verify())
return;
// Check and update last known location info.
if(DILoc.getNode() == PrevDILoc)
return;
PrevDILoc = DILoc.getNode();
Devang Patel
committed
// DBG_VALUE instruction establishes new value.
if (MI->getOpcode() == TargetOpcode::DBG_VALUE) {
DenseMap<const MachineInstr *, DbgVariable *>::iterator DI
= DbgValueStartMap.find(MI);
if (DI != DbgValueStartMap.end()) {
MCSymbol *Label = recordSourceLine(DILoc.getLineNumber(),
DILoc.getColumnNumber(),
DILoc.getScope().getNode());
DI->second->setDbgValueLabel(Label);
}
}
Devang Patel
committed
// Emit a label to indicate location change. This is used for line
// table even if this instruction does start a new scope.
MCSymbol *Label = recordSourceLine(DILoc.getLineNumber(),
DILoc.getColumnNumber(),
DILoc.getScope().getNode());
// update DbgScope if this instruction starts a new scope.
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
Devang Patel
committed
for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
/// endScope - Process end of a scope.
void DwarfDebug::endScope(const MachineInstr *MI) {
Devang Patel
committed
// Ignore DBG_VALUE instruction.
if (MI->getOpcode() == TargetOpcode::DBG_VALUE)
return;
// Check location.
DebugLoc DL = MI->getDebugLoc();
if (DL.isUnknown())
return;
DILocation DILoc = MF->getDILocation(DL);
if (!DILoc.getScope().Verify())
return;
// Emit a label and update DbgScope if this instruction ends a scope.
InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(Label);
SmallVector<DbgScope*, 2> &SD = I->second;
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
(*SDI)->setEndLabel(Label);
return;
}
/// createDbgScope - Create DbgScope for the scope.
void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
if (!InlinedAt) {
DbgScope *WScope = DbgScopeMap.lookup(Scope);
if (WScope)
return;
WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
DbgScopeMap.insert(std::make_pair(Scope, WScope));
createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL);
return;
}
DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
if (WScope)
return;
WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
DILocation DL(InlinedAt);
createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
/// extractScopeInformation - Scan machine instructions in this function
Devang Patel
committed
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool DwarfDebug::extractScopeInformation() {
Devang Patel
committed
// If scope information was extracted using .dbg intrinsics then there is not
// any need to extract these information by scanning each instruction.
if (!DbgScopeMap.empty())
return false;
DenseMap<const MachineInstr *, unsigned> MIIndexMap;
unsigned MIIndex = 0;
// Scan each instruction and create scopes. First build working set of scopes.
Devang Patel
committed
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
Devang Patel
committed
// FIXME : Remove DBG_VALUE check.
if (MInsn->getOpcode() == TargetOpcode::DBG_VALUE) continue;
MIIndexMap[MInsn] = MIIndex++;
Devang Patel
committed
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
Devang Patel
committed
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
Devang Patel
committed
// into a scope DIE at the end.
if (DLTScope.isCompileUnit()) continue;
createDbgScope(DLTScope.getNode(), DLT.getOrigLocation().getNode());
}
}
// Build scope hierarchy using working set of scopes.
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
Devang Patel
committed
// FIXME : Remove DBG_VALUE check.
if (MInsn->getOpcode() == TargetOpcode::DBG_VALUE) continue;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
if (DLTScope.isCompileUnit()) continue;
DbgScope *Scope = getUpdatedDbgScope(DLTScope.getNode(), MInsn,
DLT.getOrigLocation().getNode());
Scope->setLastInsn(MInsn);
Devang Patel
committed
}
}
if (!CurrentFnDbgScope)
return false;
CurrentFnDbgScope->fixInstructionMarkers(MIIndexMap);
Devang Patel
committed
// Each scope has first instruction and last instruction to mark beginning
// and end of a scope respectively. Create an inverse map that list scopes
// starts (and ends) with an instruction. One instruction may start (or end)
Devang Patel
committed
// multiple scopes. Ignore scopes that are not reachable.
SmallVector<DbgScope *, 4> WorkList;
WorkList.push_back(CurrentFnDbgScope);
while (!WorkList.empty()) {
DbgScope *S = WorkList.back(); WorkList.pop_back();
Jeffrey Yasskin
committed
const SmallVector<DbgScope *, 4> &Children = S->getScopes();
Devang Patel
committed
if (!Children.empty())
Jeffrey Yasskin
committed
for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
Devang Patel
committed
SE = Children.end(); SI != SE; ++SI)
WorkList.push_back(*SI);
if (S->isAbstractScope())
continue;
Devang Patel
committed
const MachineInstr *MI = S->getFirstInsn();
assert (MI && "DbgScope does not have first instruction!");
InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
if (IDI != DbgScopeBeginMap.end())
IDI->second.push_back(S);
else
DbgScopeBeginMap[MI].push_back(S);
Devang Patel
committed
MI = S->getLastInsn();
assert (MI && "DbgScope does not have last instruction!");
IDI = DbgScopeEndMap.find(MI);
if (IDI != DbgScopeEndMap.end())
IDI->second.push_back(S);
else
DbgScopeEndMap[MI].push_back(S);
Devang Patel
committed
}
return !DbgScopeMap.empty();
}
/// beginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (!extractScopeInformation())
TimeRegion Timer(DebugTimer);
collectVariableInfo();
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount));
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
DILocation DLT = MF->getDILocation(FDL);
DISubprogram SP = getDISubprogram(DLT.getScope().getNode());
unsigned Line, Col;
if (SP.Verify()) {
Line = SP.getLineNumber();
Col = 0;
} else {
Line = DLT.getLineNumber();
Col = DLT.getColumnNumber();
}
}
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (DbgScopeMap.empty()) return;
TimeRegion Timer(DebugTimer);
Devang Patel
committed
if (CurrentFnDbgScope) {
// Define end label for subprogram.
Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount));
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
// Get function line info.
if (!Lines.empty()) {
// Get section line info.
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 abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI)
constructScopeDIE(*AI);
constructScopeDIE(CurrentFnDbgScope);
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
Jeffrey Yasskin
committed
DeleteContainerSeconds(DbgScopeMap);
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
Devang Patel
committed
DbgValueStartMap.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(AbstractScopes);
Jeffrey Yasskin
committed
AbstractVariables.clear();
/// recordSourceLine - Register a source line with debug info. Returns the
/// unique label that was emitted and which provides correspondence to
/// the source line list.
MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, MDNode *S) {
TimeRegion Timer(DebugTimer);
StringRef Dir;
StringRef Fn;
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
unsigned Src = GetOrCreateSourceID(Dir, Fn);
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Lines.push_back(SrcLineInfo(Line, Col, Src, Label));
/// 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) {
TimeRegion Timer(DebugTimer);
return GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
/// computeSizeAndOffset - Compute the size and offset of a DIE.
unsigned
DwarfDebug::computeSizeAndOffset(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())
DIEValues.push_back(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 = computeSizeAndOffset(Children[j], Offset, (j + 1) == M);
// End of children marker.
Offset += sizeof(int8_t);
}
Die->setSize(Offset - Die->getOffset());
return Offset;
/// computeSizeAndOffsets - Compute the size and offset of all the DIEs.
void DwarfDebug::computeSizeAndOffsets() {
// 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)
computeSizeAndOffset(ModuleCU->getCUDie(), Offset, true);
/// 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());
Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_info"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges"));
if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
Asm->OutStreamer.SwitchSection(LineInfoDirective);
Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_line"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_loc"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_str"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges"));
Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
Asm->OutStreamer.EmitLabel(getTempLabel("text_begin"));
Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
Asm->OutStreamer.EmitLabel(getTempLabel("data_begin"));
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
// Emit the code (index) for the abbreviation.
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
Twine::utohexstr(Die->getOffset()) + ":0x" +
Twine::utohexstr(Die->getSize()) + " " +
dwarf::TagString(Abbrev->getTag()));
EmitULEB128(AbbrevNumber);
Bill Wendling
committed
const 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)");
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
switch (Attr) {
case dwarf::DW_AT_sibling:
Asm->EmitInt32(Die->getSiblingOffset());
break;
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
Asm->EmitInt32(Addr);
break;
}
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(this, Form);
break;
}
}
// 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]);
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("End Of Children Mark");
Asm->EmitInt8(0);
/// emitDebugInfo - Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
// Start debug info section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfInfoSection());
DIE *Die = ModuleCU->getCUDie();
// Emit the compile units header.
Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->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->OutStreamer.AddComment("Length of Compilation Unit Info");
Asm->EmitInt32(ContentSize);
Asm->OutStreamer.AddComment("DWARF version number");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
Devang Patel
committed
EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
true);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(TD->getPointerSize());
emitDIE(Die);
// FIXME - extra padding for gdb bug.
Asm->OutStreamer.AddComment("4 extra padding bytes for GDB");
Asm->EmitInt8(0);
Asm->EmitInt8(0);
Asm->EmitInt8(0);
Asm->EmitInt8(0);
Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->getID()));
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());
Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_begin"));
// 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.)
EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
// Emit the abbreviations data.
Abbrev->Emit(this);
// Mark end of abbreviations.
EmitULEB128(0, "EOM(3)");
Asm->OutStreamer.EmitLabel(getTempLabel("abbrev_end"));
/// 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->OutStreamer.AddComment("Extended Op");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("Op size");
Asm->EmitInt8(TD->getPointerSize() + 1);
Asm->OutStreamer.AddComment("DW_LNE_set_address");
Asm->EmitInt8(dwarf::DW_LNE_set_address);
Asm->OutStreamer.AddComment("Section end label");
Asm->OutStreamer.EmitSymbolValue(getDWLabel("section_end", SectionEnd),
TD->getPointerSize(), 0/*AddrSpace*/);
Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
Asm->EmitInt8(0);
Asm->EmitInt8(1);
/// 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.
Asm->OutStreamer.AddComment("Length of Source Line Info");
EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true);
Asm->OutStreamer.EmitLabel(getTempLabel("line_begin"));
Bill Wendling
committed
Asm->OutStreamer.AddComment("DWARF version number");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Prolog Length");
EmitDifference(getTempLabel("line_prolog_end"),
getTempLabel("line_prolog_begin"), true);
Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin"));
Asm->OutStreamer.AddComment("Minimum Instruction Length");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("Default is_stmt_start flag");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("Line Base Value (Special Opcodes)");
Asm->EmitInt8(MinLineDelta);
Asm->OutStreamer.AddComment("Line Range Value (Special Opcodes)");
Asm->EmitInt8(MaxLineDelta);
Asm->OutStreamer.AddComment("Special Opcode Base");
Asm->EmitInt8(-MinLineDelta);
// Line number standard opcode encodings argument count
Asm->OutStreamer.AddComment("DW_LNS_copy arg count");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("DW_LNS_advance_pc arg count");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("DW_LNS_advance_line arg count");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("DW_LNS_set_file arg count");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("DW_LNS_set_column arg count");
Asm->EmitInt8(1);
Asm->OutStreamer.AddComment("DW_LNS_negate_stmt arg count");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("DW_LNS_set_basic_block arg count");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("DW_LNS_const_add_pc arg count");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("DW_LNS_fixed_advance_pc arg count");
Asm->EmitInt8(1);
Bill Wendling
committed
// Emit directories.
for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
const std::string &Dir = getSourceDirectoryName(DI);
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory");
Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
Asm->OutStreamer.AddComment("End of directories");
Asm->EmitInt8(0);
// 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);
const std::string &FN = getSourceFileName(Id.second);
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source");
Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0);
EmitULEB128(Id.first, "Directory #");
EmitULEB128(0, "Mod date");
EmitULEB128(0, "File size");
Asm->OutStreamer.AddComment("End of files");
Asm->EmitInt8(0);
Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end"));
// 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];
// 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];
MCSymbol *Label = LineInfo.getLabel();
if (!Label->isDefined()) continue; // Not emitted, in dead code.
if (LineInfo.getLine() == 0) continue;
if (Asm->isVerbose()) {
std::pair<unsigned, unsigned> SrcID =
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
Asm->OutStreamer.AddComment(Twine(getSourceDirectoryName(SrcID.first)) +
"/" +
Twine(getSourceFileName(SrcID.second)) +
":" + Twine(LineInfo.getLine()));
// Define the line address.
Asm->OutStreamer.AddComment("Extended Op");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("Op size");
Asm->EmitInt8(TD->getPointerSize() + 1);
Asm->OutStreamer.AddComment("DW_LNE_set_address");
Asm->EmitInt8(dwarf::DW_LNE_set_address);
Asm->OutStreamer.AddComment("Location label");
Asm->OutStreamer.EmitSymbolValue(Label, TD->getPointerSize(),
0/*AddrSpace*/);
// If change of source, then switch to the new source.
if (Source != LineInfo.getSourceID()) {
Source = LineInfo.getSourceID();
Asm->OutStreamer.AddComment("DW_LNS_set_file");
Asm->EmitInt8(dwarf::DW_LNS_set_file);
EmitULEB128(Source, "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->OutStreamer.AddComment("Line Delta");
Asm->EmitInt8(Delta - MinLineDelta);
} else {
// ... otherwise use long hand.
Asm->OutStreamer.AddComment("DW_LNS_advance_line");
Asm->EmitInt8(dwarf::DW_LNS_advance_line);
EmitSLEB128(Offset, "Line Offset");
Asm->OutStreamer.AddComment("DW_LNS_copy");
Asm->EmitInt8(dwarf::DW_LNS_copy);
}
} else {
// Copy the previous row (different address or source)
Asm->OutStreamer.AddComment("DW_LNS_copy");
Asm->EmitInt8(dwarf::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);
Asm->OutStreamer.EmitLabel(getTempLabel("line_end"));
/// 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());
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common"));
Asm->OutStreamer.AddComment("Length of Common Information Entry");
EmitDifference(getTempLabel("debug_frame_common_end"),
getTempLabel("debug_frame_common_begin"), true);
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin"));
Asm->OutStreamer.AddComment("CIE Identifier Tag");
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
Asm->OutStreamer.AddComment("CIE Version");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
Asm->OutStreamer.AddComment("CIE Augmentation");
Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
EmitULEB128(1, "CIE Code Alignment Factor");
EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
Asm->OutStreamer.AddComment("CIE RA Column");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
EmitFrameMoves(0, Moves, false);
Asm->EmitAlignment(2, 0, 0, false);
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end"));
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
void DwarfDebug::
emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
if (!MAI->doesDwarfRequireFrameSection())
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
Asm->OutStreamer.AddComment("Length of Frame Information Entry");
MCSymbol *DebugFrameBegin =
getDWLabel("debug_frame_begin", DebugFrameInfo.Number);
MCSymbol *DebugFrameEnd =
getDWLabel("debug_frame_end", DebugFrameInfo.Number);
EmitDifference(DebugFrameEnd, DebugFrameBegin, true);
Asm->OutStreamer.AddComment("FDE CIE offset");
Devang Patel
committed
EmitSectionOffset(getTempLabel("debug_frame_common"),
getTempLabel("section_debug_frame"), true);
Asm->OutStreamer.AddComment("FDE initial location");
MCSymbol *FuncBeginSym = getDWLabel("func_begin", DebugFrameInfo.Number);
Asm->OutStreamer.EmitSymbolValue(FuncBeginSym,
TD->getPointerSize(), 0/*AddrSpace*/);
Asm->OutStreamer.AddComment("FDE address range");
EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number), FuncBeginSym);
EmitFrameMoves(FuncBeginSym, DebugFrameInfo.Moves, false);
Asm->EmitAlignment(2, 0, 0, false);
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames() {
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubNamesSection());
Asm->OutStreamer.AddComment("Length of Public Names Info");
EmitDifference(getDWLabel("pubnames_end", ModuleCU->getID()),
getDWLabel("pubnames_begin", ModuleCU->getID()), true);
Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID()));
Bill Wendling
committed
Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Bill Wendling
committed
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
Devang Patel
committed
getTempLabel("section_info"), true);
Bill Wendling
committed
Asm->OutStreamer.AddComment("Compilation Unit Length");
EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
getDWLabel("info_begin", ModuleCU->getID()),
const StringMap<DIE*> &Globals = ModuleCU->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->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
Asm->OutStreamer.AddComment("End Mark");
Asm->EmitInt32(0);
Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID()));
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubTypesSection());
Asm->OutStreamer.AddComment("Length of Public Types Info");
EmitDifference(getDWLabel("pubtypes_end", ModuleCU->getID()),
getDWLabel("pubtypes_begin", ModuleCU->getID()), true);
Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID()));
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info");
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
Devang Patel
committed
getTempLabel("section_info"), true);
Asm->OutStreamer.AddComment("Compilation ModuleCU Length");
EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
getDWLabel("info_begin", ModuleCU->getID()),
true);
const StringMap<DIE*> &Globals = ModuleCU->getGlobalTypes();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
DIE * Entity = GI->second;
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
Asm->OutStreamer.AddComment("End Mark");
Asm->EmitInt32(0);
Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->getID()));
/// emitDebugStr - Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
// Check to see if it is worth the effort.
if (StringPool.empty()) return;
// Start the dwarf str section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfStrSection());
// Get all of the string pool entries and put them in an array by their ID so
// we can sort them.
SmallVector<std::pair<unsigned,
StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
I = StringPool.begin(), E = StringPool.end(); I != E; ++I)
Entries.push_back(std::make_pair(I->second.second, &*I));
array_pod_sort(Entries.begin(), Entries.end());
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
// Emit a label for reference from debug information entries.
Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
// Emit the string itself.
Asm->OutStreamer.EmitBytes(Entries[i].second->getKey(), 0/*addrspace*/);