2
0

WinCodeViewLineTables.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. //===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- C++ -*--===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains support for writing line tables info into COFF files.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "WinCodeViewLineTables.h"
  14. #include "llvm/MC/MCExpr.h"
  15. #include "llvm/MC/MCSymbol.h"
  16. #include "llvm/Support/COFF.h"
  17. namespace llvm {
  18. StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) {
  19. assert(S);
  20. assert((isa<DICompileUnit>(S) || isa<DIFile>(S) || isa<DISubprogram>(S) ||
  21. isa<DILexicalBlockBase>(S)) &&
  22. "Unexpected scope info");
  23. auto *Scope = cast<DIScope>(S);
  24. StringRef Dir = Scope->getDirectory(),
  25. Filename = Scope->getFilename();
  26. char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)];
  27. if (Result)
  28. return Result;
  29. // Clang emits directory and relative filename info into the IR, but CodeView
  30. // operates on full paths. We could change Clang to emit full paths too, but
  31. // that would increase the IR size and probably not needed for other users.
  32. // For now, just concatenate and canonicalize the path here.
  33. std::string Filepath;
  34. if (Filename.find(':') == 1)
  35. Filepath = Filename;
  36. else
  37. Filepath = (Dir + "\\" + Filename).str();
  38. // Canonicalize the path. We have to do it textually because we may no longer
  39. // have access the file in the filesystem.
  40. // First, replace all slashes with backslashes.
  41. std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
  42. // Remove all "\.\" with "\".
  43. size_t Cursor = 0;
  44. while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
  45. Filepath.erase(Cursor, 2);
  46. // Replace all "\XXX\..\" with "\". Don't try too hard though as the original
  47. // path should be well-formatted, e.g. start with a drive letter, etc.
  48. Cursor = 0;
  49. while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
  50. // Something's wrong if the path starts with "\..\", abort.
  51. if (Cursor == 0)
  52. break;
  53. size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
  54. if (PrevSlash == std::string::npos)
  55. // Something's wrong, abort.
  56. break;
  57. Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
  58. // The next ".." might be following the one we've just erased.
  59. Cursor = PrevSlash;
  60. }
  61. // Remove all duplicate backslashes.
  62. Cursor = 0;
  63. while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
  64. Filepath.erase(Cursor, 1);
  65. Result = strdup(Filepath.c_str());
  66. return StringRef(Result);
  67. }
  68. void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL,
  69. const MachineFunction *MF) {
  70. const MDNode *Scope = DL.getScope();
  71. if (!Scope)
  72. return;
  73. StringRef Filename = getFullFilepath(Scope);
  74. // Skip this instruction if it has the same file:line as the previous one.
  75. assert(CurFn);
  76. if (!CurFn->Instrs.empty()) {
  77. const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()];
  78. if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine())
  79. return;
  80. }
  81. FileNameRegistry.add(Filename);
  82. MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
  83. Asm->OutStreamer->EmitLabel(MCL);
  84. CurFn->Instrs.push_back(MCL);
  85. InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine(), DL.getCol());
  86. }
  87. WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP)
  88. : Asm(nullptr), CurFn(nullptr) {
  89. MachineModuleInfo *MMI = AP->MMI;
  90. // If module doesn't have named metadata anchors or COFF debug section
  91. // is not available, skip any debug info related stuff.
  92. if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
  93. !AP->getObjFileLowering().getCOFFDebugSymbolsSection())
  94. return;
  95. // Tell MMI that we have debug info.
  96. MMI->setDebugInfoAvailability(true);
  97. Asm = AP;
  98. }
  99. void WinCodeViewLineTables::endModule() {
  100. if (FnDebugInfo.empty())
  101. return;
  102. assert(Asm != nullptr);
  103. Asm->OutStreamer->SwitchSection(
  104. Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
  105. Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
  106. // The COFF .debug$S section consists of several subsections, each starting
  107. // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
  108. // of the payload followed by the payload itself. The subsections are 4-byte
  109. // aligned.
  110. // Emit per-function debug information. This code is extracted into a
  111. // separate function for readability.
  112. for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
  113. emitDebugInfoForFunction(VisitedFunctions[I]);
  114. // This subsection holds a file index to offset in string table table.
  115. Asm->OutStreamer->AddComment("File index to string table offset subsection");
  116. Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION);
  117. size_t NumFilenames = FileNameRegistry.Infos.size();
  118. Asm->EmitInt32(8 * NumFilenames);
  119. for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
  120. StringRef Filename = FileNameRegistry.Filenames[I];
  121. // For each unique filename, just write its offset in the string table.
  122. Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
  123. // The function name offset is not followed by any additional data.
  124. Asm->EmitInt32(0);
  125. }
  126. // This subsection holds the string table.
  127. Asm->OutStreamer->AddComment("String table");
  128. Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION);
  129. Asm->EmitInt32(FileNameRegistry.LastOffset);
  130. // The payload starts with a null character.
  131. Asm->EmitInt8(0);
  132. for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
  133. // Just emit unique filenames one by one, separated by a null character.
  134. Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
  135. Asm->EmitInt8(0);
  136. }
  137. // No more subsections. Fill with zeros to align the end of the section by 4.
  138. Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
  139. clear();
  140. }
  141. static void EmitLabelDiff(MCStreamer &Streamer,
  142. const MCSymbol *From, const MCSymbol *To,
  143. unsigned int Size = 4) {
  144. MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
  145. MCContext &Context = Streamer.getContext();
  146. const MCExpr *FromRef = MCSymbolRefExpr::create(From, Variant, Context),
  147. *ToRef = MCSymbolRefExpr::create(To, Variant, Context);
  148. const MCExpr *AddrDelta =
  149. MCBinaryExpr::create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
  150. Streamer.EmitValue(AddrDelta, Size);
  151. }
  152. void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) {
  153. // For each function there is a separate subsection
  154. // which holds the PC to file:line table.
  155. const MCSymbol *Fn = Asm->getSymbol(GV);
  156. assert(Fn);
  157. const FunctionInfo &FI = FnDebugInfo[GV];
  158. if (FI.Instrs.empty())
  159. return;
  160. assert(FI.End && "Don't know where the function ends?");
  161. StringRef GVName = GV->getName();
  162. StringRef FuncName;
  163. if (auto *SP = getDISubprogram(GV))
  164. FuncName = SP->getDisplayName();
  165. // FIXME Clang currently sets DisplayName to "bar" for a C++
  166. // "namespace_foo::bar" function, see PR21528. Luckily, dbghelp.dll is trying
  167. // to demangle display names anyways, so let's just put a mangled name into
  168. // the symbols subsection until Clang gives us what we need.
  169. if (GVName.startswith("\01?"))
  170. FuncName = GVName.substr(1);
  171. // Emit a symbol subsection, required by VS2012+ to find function boundaries.
  172. MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(),
  173. *SymbolsEnd = Asm->MMI->getContext().createTempSymbol();
  174. Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName));
  175. Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION);
  176. EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd);
  177. Asm->OutStreamer->EmitLabel(SymbolsBegin);
  178. {
  179. MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(),
  180. *ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol();
  181. EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2);
  182. Asm->OutStreamer->EmitLabel(ProcSegmentBegin);
  183. Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_START);
  184. // Some bytes of this segment don't seem to be required for basic debugging,
  185. // so just fill them with zeroes.
  186. Asm->OutStreamer->EmitFill(12, 0);
  187. // This is the important bit that tells the debugger where the function
  188. // code is located and what's its size:
  189. EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
  190. Asm->OutStreamer->EmitFill(12, 0);
  191. Asm->OutStreamer->EmitCOFFSecRel32(Fn);
  192. Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
  193. Asm->EmitInt8(0);
  194. // Emit the function display name as a null-terminated string.
  195. Asm->OutStreamer->EmitBytes(FuncName);
  196. Asm->EmitInt8(0);
  197. Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
  198. // We're done with this function.
  199. Asm->EmitInt16(0x0002);
  200. Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_END);
  201. }
  202. Asm->OutStreamer->EmitLabel(SymbolsEnd);
  203. // Every subsection must be aligned to a 4-byte boundary.
  204. Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
  205. // PCs/Instructions are grouped into segments sharing the same filename.
  206. // Pre-calculate the lengths (in instructions) of these segments and store
  207. // them in a map for convenience. Each index in the map is the sequential
  208. // number of the respective instruction that starts a new segment.
  209. DenseMap<size_t, size_t> FilenameSegmentLengths;
  210. size_t LastSegmentEnd = 0;
  211. StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename;
  212. for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
  213. if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename)
  214. continue;
  215. FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
  216. LastSegmentEnd = J;
  217. PrevFilename = InstrInfo[FI.Instrs[J]].Filename;
  218. }
  219. FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
  220. // Emit a line table subsection, requred to do PC-to-file:line lookup.
  221. Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName));
  222. Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION);
  223. MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
  224. *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
  225. EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
  226. Asm->OutStreamer->EmitLabel(LineTableBegin);
  227. // Identify the function this subsection is for.
  228. Asm->OutStreamer->EmitCOFFSecRel32(Fn);
  229. Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
  230. // Insert flags after a 16-bit section index.
  231. Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
  232. // Length of the function's code, in bytes.
  233. EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
  234. // PC-to-linenumber lookup table:
  235. MCSymbol *FileSegmentEnd = nullptr;
  236. // The start of the last segment:
  237. size_t LastSegmentStart = 0;
  238. auto FinishPreviousChunk = [&] {
  239. if (!FileSegmentEnd)
  240. return;
  241. for (size_t ColSegI = LastSegmentStart,
  242. ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
  243. ColSegI != ColSegEnd; ++ColSegI) {
  244. unsigned ColumnNumber = InstrInfo[FI.Instrs[ColSegI]].ColumnNumber;
  245. Asm->EmitInt16(ColumnNumber); // Start column
  246. Asm->EmitInt16(ColumnNumber); // End column
  247. }
  248. Asm->OutStreamer->EmitLabel(FileSegmentEnd);
  249. };
  250. for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
  251. MCSymbol *Instr = FI.Instrs[J];
  252. assert(InstrInfo.count(Instr));
  253. if (FilenameSegmentLengths.count(J)) {
  254. // We came to a beginning of a new filename segment.
  255. FinishPreviousChunk();
  256. StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename;
  257. assert(FileNameRegistry.Infos.count(CurFilename));
  258. size_t IndexInStringTable =
  259. FileNameRegistry.Infos[CurFilename].FilenameID;
  260. // Each segment starts with the offset of the filename
  261. // in the string table.
  262. Asm->OutStreamer->AddComment(
  263. "Segment for file '" + Twine(CurFilename) + "' begins");
  264. MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol();
  265. Asm->OutStreamer->EmitLabel(FileSegmentBegin);
  266. Asm->EmitInt32(8 * IndexInStringTable);
  267. // Number of PC records in the lookup table.
  268. size_t SegmentLength = FilenameSegmentLengths[J];
  269. Asm->EmitInt32(SegmentLength);
  270. // Full size of the segment for this filename, including the prev two
  271. // records.
  272. FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
  273. EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
  274. LastSegmentStart = J;
  275. }
  276. // The first PC with the given linenumber and the linenumber itself.
  277. EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
  278. Asm->EmitInt32(InstrInfo[Instr].LineNumber);
  279. }
  280. FinishPreviousChunk();
  281. Asm->OutStreamer->EmitLabel(LineTableEnd);
  282. }
  283. void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) {
  284. assert(!CurFn && "Can't process two functions at once!");
  285. if (!Asm || !Asm->MMI->hasDebugInfo())
  286. return;
  287. const Function *GV = MF->getFunction();
  288. assert(FnDebugInfo.count(GV) == false);
  289. VisitedFunctions.push_back(GV);
  290. CurFn = &FnDebugInfo[GV];
  291. // Find the end of the function prolog.
  292. // FIXME: is there a simpler a way to do this? Can we just search
  293. // for the first instruction of the function, not the last of the prolog?
  294. DebugLoc PrologEndLoc;
  295. bool EmptyPrologue = true;
  296. for (const auto &MBB : *MF) {
  297. if (PrologEndLoc)
  298. break;
  299. for (const auto &MI : MBB) {
  300. if (MI.isDebugValue())
  301. continue;
  302. // First known non-DBG_VALUE and non-frame setup location marks
  303. // the beginning of the function body.
  304. // FIXME: do we need the first subcondition?
  305. if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) {
  306. PrologEndLoc = MI.getDebugLoc();
  307. break;
  308. }
  309. EmptyPrologue = false;
  310. }
  311. }
  312. // Record beginning of function if we have a non-empty prologue.
  313. if (PrologEndLoc && !EmptyPrologue) {
  314. DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
  315. maybeRecordLocation(FnStartDL, MF);
  316. }
  317. }
  318. void WinCodeViewLineTables::endFunction(const MachineFunction *MF) {
  319. if (!Asm || !CurFn) // We haven't created any debug info for this function.
  320. return;
  321. const Function *GV = MF->getFunction();
  322. assert(FnDebugInfo.count(GV));
  323. assert(CurFn == &FnDebugInfo[GV]);
  324. if (CurFn->Instrs.empty()) {
  325. FnDebugInfo.erase(GV);
  326. VisitedFunctions.pop_back();
  327. } else {
  328. CurFn->End = Asm->getFunctionEnd();
  329. }
  330. CurFn = nullptr;
  331. }
  332. void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) {
  333. // Ignore DBG_VALUE locations and function prologue.
  334. if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
  335. return;
  336. DebugLoc DL = MI->getDebugLoc();
  337. if (DL == PrevInstLoc || !DL)
  338. return;
  339. maybeRecordLocation(DL, Asm->MF);
  340. }
  341. }