Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
void DwarfDebug::ConstructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
DICompositeType *CTy) {
Buffer.setTag(dwarf::DW_TAG_array_type);
if (CTy->getTag() == dwarf::DW_TAG_vector_type)
AddUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1);
// Emit derived type.
AddType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom());
DIArray Elements = CTy->getTypeArray();
// Construct an anonymous type for index type.
DIE IdxBuffer(dwarf::DW_TAG_base_type);
AddUInt(&IdxBuffer, dwarf::DW_AT_byte_size, 0, sizeof(int32_t));
AddUInt(&IdxBuffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
dwarf::DW_ATE_signed);
DIE *IndexTy = DW_Unit->AddDie(IdxBuffer);
// Add subranges to array type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
if (Element.getTag() == dwarf::DW_TAG_subrange_type)
ConstructSubrangeDIE(Buffer, DISubrange(Element.getNode()), IndexTy);
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
}
}
/// ConstructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator);
std::string Name;
ETy->getName(Name);
AddString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
int64_t Value = ETy->getEnumValue();
AddSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value);
return Enumerator;
}
/// CreateGlobalVariableDIE - Create new DIE using GV.
DIE *DwarfDebug::CreateGlobalVariableDIE(CompileUnit *DW_Unit,
const DIGlobalVariable &GV) {
DIE *GVDie = new DIE(dwarf::DW_TAG_variable);
std::string Name;
GV.getDisplayName(Name);
AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
std::string LinkageName;
GV.getLinkageName(LinkageName);
if (!LinkageName.empty()) {
// 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 (LinkageName[0] == 1)
LinkageName = &LinkageName[1];
AddString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
if (!GV.isLocalToUnit())
AddUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
AddSourceLine(GVDie, &GV);
return GVDie;
}
/// CreateMemberDIE - Create new member DIE.
DIE *DwarfDebug::CreateMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
DIE *MemberDie = new DIE(DT.getTag());
std::string Name;
DT.getName(Name);
if (!Name.empty())
AddString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
AddType(DW_Unit, MemberDie, DT.getTypeDerivedFrom());
AddSourceLine(MemberDie, &DT);
uint64_t Size = DT.getSizeInBits();
uint64_t FieldSize = DT.getOriginalTypeSize();
if (Size != FieldSize) {
// Handle bitfield.
AddUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3);
AddUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits());
uint64_t Offset = DT.getOffsetInBits();
uint64_t FieldOffset = Offset;
uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
uint64_t HiMark = (Offset + FieldSize) & AlignMask;
FieldOffset = (HiMark - FieldSize);
Offset -= FieldOffset;
// Maybe we need to work from the other end.
if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
AddUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset);
}
DIEBlock *Block = new DIEBlock();
AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
AddUInt(Block, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3);
AddBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, Block);
if (DT.isProtected())
AddUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
dwarf::DW_ACCESS_protected);
else if (DT.isPrivate())
AddUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
dwarf::DW_ACCESS_private);
return MemberDie;
}
/// CreateSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit,
const DISubprogram &SP,
Bill Wendling
committed
bool IsConstructor,
bool IsInlined) {
DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram);
std::string Name;
SP.getName(Name);
AddString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
std::string LinkageName;
SP.getLinkageName(LinkageName);
if (!LinkageName.empty()) {
// 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 (LinkageName[0] == 1)
LinkageName = &LinkageName[1];
AddString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
AddSourceLine(SPDie, &SP);
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
// Add prototyped tag, if C or ObjC.
unsigned Lang = SP.getCompileUnit().getLanguage();
if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 ||
Lang == dwarf::DW_LANG_ObjC)
AddUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
// Add Return Type.
unsigned SPTag = SPTy.getTag();
if (!IsConstructor) {
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
AddType(DW_Unit, SPDie, SPTy);
else
AddType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
}
if (!SP.isDefinition()) {
AddUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// Add arguments. Do not add arguments for subprogram definition. They will
// be handled through RecordVariable.
if (SPTag == dwarf::DW_TAG_subroutine_type)
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
AddType(DW_Unit, Arg, DIType(Args.getElement(i).getNode()));
AddUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
SPDie->AddChild(Arg);
}
}
Bill Wendling
committed
if (!SP.isLocalToUnit() && !IsInlined)
AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// DW_TAG_inlined_subroutine may refer to this DIE.
Slot = SPDie;
return SPDie;
}
/// FindCompileUnit - Get the compile unit for the given descriptor.
///
CompileUnit &DwarfDebug::FindCompileUnit(DICompileUnit Unit) const {
DenseMap<Value *, CompileUnit *>::const_iterator I =
assert(I != CompileUnitMap.end() && "Missing compile unit.");
return *I->second;
}
Bill Wendling
committed
/// CreateDbgScopeVariable - Create a new scope variable.
Bill Wendling
committed
DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
// Get the descriptor.
const DIVariable &VD = DV->getVariable();
// Translate tag to proper Dwarf tag. The result variable is dropped for
// now.
unsigned Tag;
switch (VD.getTag()) {
case dwarf::DW_TAG_return_variable:
return NULL;
case dwarf::DW_TAG_arg_variable:
Tag = dwarf::DW_TAG_formal_parameter;
break;
case dwarf::DW_TAG_auto_variable: // fall thru
default:
Tag = dwarf::DW_TAG_variable;
break;
}
// Define variable debug information entry.
DIE *VariableDie = new DIE(Tag);
std::string Name;
VD.getName(Name);
AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
// Add source line info if available.
AddSourceLine(VariableDie, &VD);
// Add variable type.
Caroline Tice
committed
if (VD.isBlockByrefVariable())
AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
else
AddType(Unit, VariableDie, VD.getType());
// Add variable address.
if (!DV->isInlinedFnVar()) {
// Variables for abstract instances of inlined functions don't get a
// location.
MachineLocation Location;
Location.set(RI->getFrameRegister(*MF),
RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
Caroline Tice
committed
if (VD.isBlockByrefVariable())
AddBlockByrefAddress (DV, VariableDie, dwarf::DW_AT_location, Location);
else
AddAddress(VariableDie, dwarf::DW_AT_location, Location);
}
return VariableDie;
}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
///
DbgScope *DwarfDebug::getOrCreateScope(MDNode *N) {
DbgScope *&Slot = DbgScopeMap[N];
if (Slot) return Slot;
DbgScope *Parent = NULL;
// Don't create a new scope if we already created one for an inlined function.
DenseMap<const MDNode *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(N);
if (II != AbstractInstanceRootMap.end())
return LexicalScopeStack.back();
if (!Block.isNull()) {
DIDescriptor ParentDesc = Block.getContext();
Parent =
ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getNode());
if (Parent)
Parent->AddScope(Slot);
else
// First function is top level function.
FunctionDbgScope = Slot;
return Slot;
}
/// ConstructDbgScope - Construct the components of a scope.
///
void DwarfDebug::ConstructDbgScope(DbgScope *ParentScope,
unsigned ParentStartID,
unsigned ParentEndID,
DIE *ParentDie, CompileUnit *Unit) {
// Add variables to scope.
SmallVector<DbgVariable *, 8> &Variables = ParentScope->getVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
Bill Wendling
committed
DIE *VariableDie = CreateDbgScopeVariable(Variables[i], Unit);
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
if (VariableDie) ParentDie->AddChild(VariableDie);
}
// Add concrete instances to scope.
SmallVector<DbgConcreteScope *, 8> &ConcreteInsts =
ParentScope->getConcreteInsts();
for (unsigned i = 0, N = ConcreteInsts.size(); i < N; ++i) {
DbgConcreteScope *ConcreteInst = ConcreteInsts[i];
DIE *Die = ConcreteInst->getDie();
unsigned StartID = ConcreteInst->getStartLabelID();
unsigned EndID = ConcreteInst->getEndLabelID();
// Add the scope bounds.
if (StartID)
AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("label", StartID));
else
AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
if (EndID)
AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("label", EndID));
else
AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
ParentDie->AddChild(Die);
}
// Add nested scopes.
SmallVector<DbgScope *, 4> &Scopes = ParentScope->getScopes();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
// Define the Scope debug information entry.
DbgScope *Scope = Scopes[j];
unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
// Ignore empty scopes.
if (StartID == EndID && StartID != 0) continue;
// Do not ignore inlined scopes even if they don't have any variables or
// scopes.
if (Scope->getScopes().empty() && Scope->getVariables().empty() &&
Scope->getConcreteInsts().empty())
continue;
if (StartID == ParentStartID && EndID == ParentEndID) {
// Just add stuff to the parent scope.
ConstructDbgScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit);
} else {
DIE *ScopeDie = new DIE(dwarf::DW_TAG_lexical_block);
// Add the scope bounds.
if (StartID)
AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("label", StartID));
else
AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
if (EndID)
AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("label", EndID));
else
AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
// Add the scope's contents.
ConstructDbgScope(Scope, StartID, EndID, ScopeDie, Unit);
ParentDie->AddChild(ScopeDie);
}
}
}
/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
///
void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope,
bool AbstractScope) {
// Exit if there is no root scope.
if (!RootScope) return;
DIDescriptor Desc = RootScope->getDesc();
if (Desc.isNull())
return;
// Get the subprogram debug information entry.
// Get the subprogram die.
assert(SPDie && "Missing subprogram descriptor");
if (!AbstractScope) {
// Add the function bounds.
AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
MachineLocation Location(RI->getFrameRegister(*MF));
AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
}
ConstructDbgScope(RootScope, 0, 0, SPDie, ModuleCU);
}
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
///
void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
StringMap<DIE*>::iterator GI = Globals.find(MF->getFunction()->getName());
if (GI != Globals.end()) {
DIE *SPDie = GI->second;
// Add the function bounds.
AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
DWLabel("func_begin", SubprogramCount));
AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
DWLabel("func_end", SubprogramCount));
MachineLocation Location(RI->getFrameRegister(*MF));
AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
}
}
/// GetOrCreateSourceID - 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) {
unsigned DId;
StringMap<unsigned>::iterator DI = DirectoryIdMap.find(DirName);
if (DI != DirectoryIdMap.end()) {
DId = DI->getValue();
} else {
DId = DirectoryNames.size() + 1;
DirectoryIdMap[DirName] = DId;
DirectoryNames.push_back(DirName);
unsigned FId;
StringMap<unsigned>::iterator FI = SourceFileIdMap.find(FileName);
if (FI != SourceFileIdMap.end()) {
FId = FI->getValue();
} else {
FId = SourceFileNames.size() + 1;
SourceFileIdMap[FileName] = FId;
SourceFileNames.push_back(FileName);
DenseMap<std::pair<unsigned, unsigned>, unsigned>::iterator SI =
SourceIdMap.find(std::make_pair(DId, FId));
if (SI != SourceIdMap.end())
return SI->second;
unsigned SrcId = SourceIds.size() + 1; // DW_AT_decl_file cannot be 0.
SourceIdMap[std::make_pair(DId, FId)] = SrcId;
SourceIds.push_back(std::make_pair(DId, FId));
void DwarfDebug::ConstructCompileUnit(MDNode *N) {
DICompileUnit DIUnit(N);
std::string Dir, FN, Prod;
unsigned ID = GetOrCreateSourceID(DIUnit.getDirectory(Dir),
DIUnit.getFilename(FN));
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
AddSectionOffset(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
DWLabel("section_line", 0), DWLabel("section_line", 0),
false);
AddString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
DIUnit.getProducer(Prod));
AddUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
DIUnit.getLanguage());
AddString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
if (!Dir.empty())
AddString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
if (DIUnit.isOptimized())
AddUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
std::string Flags;
DIUnit.getFlags(Flags);
if (!Flags.empty())
AddString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
unsigned RVer = DIUnit.getRunTimeVersion();
if (RVer)
AddUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
CompileUnit *Unit = new CompileUnit(ID, Die);
// Use first compile unit marked as isMain as the compile unit
// for this module.
CompileUnits.push_back(Unit);
void DwarfDebug::ConstructGlobalVariableDIE(MDNode *N) {
DIGlobalVariable DI_GV(N);
// If debug information is malformed then ignore it.
if (DI_GV.Verify() == false)
return;
// Check for pre-existence.
DIE *&Slot = ModuleCU->getDieMapSlotFor(DI_GV.getNode());
DIE *VariableDie = CreateGlobalVariableDIE(ModuleCU, DI_GV);
// Add address.
DIEBlock *Block = new DIEBlock();
AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
AddObjectLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getMangledName(DI_GV.getGlobal()));
AddBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
// Add to map.
Slot = VariableDie;
// Expose as global. FIXME - need to check external flag.
std::string Name;
ModuleCU->AddGlobal(DI_GV.getName(Name), VariableDie);
void DwarfDebug::ConstructSubprogram(MDNode *N) {
DISubprogram SP(N);
Bill Wendling
committed
// Check for pre-existence.
if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing
// class type.
Bill Wendling
committed
DIE *SubprogramDie = CreateSubprogramDIE(ModuleCU, SP);
Bill Wendling
committed
// Add to map.
Slot = SubprogramDie;
// Expose as global.
std::string Name;
ModuleCU->AddGlobal(SP.getName(Name), SubprogramDie);
/// BeginModule - Emit all Dwarf sections that should come prior to the
/// content. Create global DIEs and emit initial debug info sections.
/// This is inovked by the target AsmPrinter.
void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) {
this->M = M;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
// Create all the compile unit DIEs.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I)
if (CompileUnits.empty()) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
// If main compile unit for this module is not seen than randomly
// select first compile unit.
// If there is not any debug info available for any global variables and any
// subprograms then there is not any debug info to emit.
if (DbgFinder.global_variable_count() == 0
&& DbgFinder.subprogram_count() == 0) {
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return;
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
E = DbgFinder.global_variable_end(); I != E; ++I)
ConstructGlobalVariableDIE(*I);
// Create DIEs for each of the externally visible subprograms.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
MMI = mmi;
shouldEmit = true;
MMI->setDebugInfoAvailability(true);
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
// Print out .file directives to specify files for .loc directives. These are
// printed out early so that they precede any .loc directives.
if (MAI->hasDotLocAndDotFile()) {
for (unsigned i = 1, e = getNumSourceIds()+1; i != e; ++i) {
// Remember source id starts at 1.
std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(i);
sys::Path FullPath(getSourceDirectoryName(Id.first));
bool AppendOk =
FullPath.appendComponent(getSourceFileName(Id.second));
assert(AppendOk && "Could not append filename to directory!");
AppendOk = false;
Asm->EmitFile(i, FullPath.str());
// Emit initial sections
EmitInitial();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
/// EndModule - Emit all Dwarf sections that should come after the content.
///
void DwarfDebug::EndModule() {
if (!ShouldEmitDwarfDebug())
return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->OutStreamer.SwitchSection(SectionMap[i]);
EmitLabel("section_end", i);
}
// Emit common frame information.
EmitCommonDebugFrame();
// Emit function debug frame information
for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
E = DebugFrames.end(); I != E; ++I)
EmitFunctionDebugFrame(*I);
// Compute DIE offsets and sizes.
SizeAndOffsets();
// Emit all the DIEs into a debug info section
EmitDebugInfo();
// Corresponding abbreviations into a abbrev section.
EmitAbbreviations();
// Emit source line correspondence into a debug line section.
EmitDebugLines();
// Emit info into a debug pubnames section.
EmitDebugPubNames();
// Emit info into a debug str section.
EmitDebugStr();
// Emit info into a debug loc section.
EmitDebugLoc();
// Emit info into a debug aranges section.
EmitDebugARanges();
// Emit info into a debug ranges section.
EmitDebugRanges();
// Emit info into a debug macinfo section.
EmitDebugMacInfo();
// Emit inline info.
EmitDebugInlineInfo();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
/// BeginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::BeginFunction(MachineFunction *MF) {
this->MF = MF;
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
// 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 = RecordSourceLine(DLT.Line, DLT.Col,
DICompileUnit(DLT.CompileUnit));
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();
// 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();
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(Value *V, unsigned Line, unsigned Col) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
CompileUnit *Unit = CompileUnitMap[V];
assert(Unit && "Unable to find CompileUnit");
unsigned ID = MMI->NextLabelID();
Lines.push_back(SrcLineInfo(Line, Col, Unit->getID(), ID));
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,
DICompileUnit CU) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
std::string Dir, Fn;
unsigned Src = GetOrCreateSourceID(CU.getDirectory(Dir),
CU.getFilename(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, FileName);
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.
DenseMap<MDNode *, DbgScope *>::iterator
I = DbgAbstractScopeMap.find(SP.getNode());
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.
DenseMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
SI = DbgConcreteScopeMap.find(Node);
Bill Wendling
committed
if (SI == DbgConcreteScopeMap.end())
else
SI->second.push_back(ConcreteScope);
Bill Wendling
committed
// Track the start label for this inlined function.
DenseMap<MDNode *, SmallVector<unsigned, 4> >::iterator
I = InlineInfo.find(Node);
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())