Newer
Older
collectVariableInfo();
// Begin accumulating function debug information.
MMI->BeginFunction(MF);
Bill Wendling
committed
// Assumes in correct section after the entry point.
EmitLabel("func_begin", ++SubprogramCount);
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
unsigned LabelID = 0;
DISubprogram SP = getDISubprogram(DLT.Scope);
if (!SP.isNull())
LabelID = recordSourceLine(SP.getLineNumber(), 0, DLT.Scope);
else
LabelID = recordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
Asm->printLabel(LabelID);
O << '\n';
}
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
if (DbgScopeMap.empty())
return;
Devang Patel
committed
// 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 abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI)
constructScopeDIE(*AI);
constructScopeDIE(CurrentFnDbgScope);
Devang Patel
committed
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
// Clear debug info
if (CurrentFnDbgScope) {
CurrentFnDbgScope = NULL;
Devang Patel
committed
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
ConcreteScopes.clear();
AbstractScopesList.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;
//===----------------------------------------------------------------------===//
// 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()) 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());
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->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;
}
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");
/// emitDebugInfo / emitDebugInfoPerCU - Emit the debug info section.
void DwarfDebug::emitDebugInfoPerCU(CompileUnit *Unit) {
DIE *Die = Unit->getCUDie();
// 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());
emitDebugInfoPerCU(ModuleCU);
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
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());
emitDebugPubNamesPerCU(ModuleCU);
/// 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());
/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
Asm->OutStreamer.SwitchSection(LineInfo);
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");
EmitLabel("debug_inlined_begin", 1);
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
// for (ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
// I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
MDNode *Node = *I;
ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
= InlineInfo.find(Node);
SmallVector<InlineInfoLabels, 4> &Labels = II->second;
const char *LName = SP.getLinkageName();
const char *Name = SP.getName();
Asm->EmitString(Name);
else {
// Skip special LLVM prefix that is used to inform the asm printer to not
// emit usual symbol prefix before the symbol name. This happens for
// Objective-C symbol names and symbol whose name is replaced using GCC's
// __asm__ attribute.
if (LName[0] == 1)
LName = &LName[1];
// Asm->EmitString(LName);
EmitSectionOffset("string", "section_str",
StringPool.idFor(LName), false, true);
Asm->EOL("MIPS linkage name");
EmitSectionOffset("string", "section_str",
StringPool.idFor(Name), false, true);
Asm->EOL("Function name");
Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
if (TD->getPointerSize() == sizeof(int32_t))
O << MAI->getData32bitsDirective();
O << MAI->getData64bitsDirective();
PrintLabelName("label", LI->first); Asm->EOL("low_pc");
EmitLabel("debug_inlined_end", 1);
Asm->EOL();