Newer
Older
Devang Patel
committed
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
// 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;
// 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);
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;
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, MInsn,
ScopeLoc);
DbgVariable *RegVar = new DbgVariable(DV, MInsn, AbsDbgVariable);
Scope->addVariable(RegVar);
}
}
}
/// beginScope - Process beginning of a scope starting at Label.
void DwarfDebug::beginScope(const MachineInstr *MI, MCSymbol *Label) {
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
/// endScope - Process end of a scope.
void DwarfDebug::endScope(const MachineInstr *MI) {
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 (TimePassesIsEnabled)
DebugTimer->startTimer();
if (!extractScopeInformation())
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();
}
}
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
if (DbgScopeMap.empty())
return;
Devang Patel
committed
if (CurrentFnDbgScope) {
// Define end label for subprogram.
Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount));
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
// 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();
ConcreteScopes.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(AbstractScopes);
Jeffrey Yasskin
committed
AbstractVariables.clear();
Devang Patel
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// 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) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
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));
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;
//===----------------------------------------------------------------------===//
// 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*/);
/// 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());
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());
/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {