@@ -182,6 +182,7 @@ void CodeViewDebug::endModule() {
182
182
assert (Asm != nullptr );
183
183
Asm->OutStreamer ->SwitchSection (
184
184
Asm->getObjFileLowering ().getCOFFDebugSymbolsSection ());
185
+ Asm->OutStreamer ->AddComment (" Debug section magic" );
185
186
Asm->EmitInt32 (COFF::DEBUG_SECTION_MAGIC);
186
187
187
188
// The COFF .debug$S section consists of several subsections, each starting
@@ -207,14 +208,11 @@ void CodeViewDebug::endModule() {
207
208
clear ();
208
209
}
209
210
210
- template <typename T> static void emitRecord (MCStreamer &OS, const T &Rec) {
211
- OS.EmitBytes (StringRef (reinterpret_cast <const char *>(&Rec), sizeof (Rec)));
212
- }
213
-
214
211
void CodeViewDebug::emitTypeInformation () {
215
212
// Start the .debug$T section with 0x4.
216
213
Asm->OutStreamer ->SwitchSection (
217
214
Asm->getObjFileLowering ().getCOFFDebugTypesSection ());
215
+ Asm->OutStreamer ->AddComment (" Debug section magic" );
218
216
Asm->EmitInt32 (COFF::DEBUG_SECTION_MAGIC);
219
217
220
218
NamedMDNode *CU_Nodes =
@@ -226,34 +224,49 @@ void CodeViewDebug::emitTypeInformation() {
226
224
// frame info. All functions are assigned a simple 'void ()' type. Emit that
227
225
// type here.
228
226
TypeIndex ArgListIdx = getNextTypeIndex ();
227
+ Asm->OutStreamer ->AddComment (" Type record length" );
229
228
Asm->EmitInt16 (2 + sizeof (ArgList));
229
+ Asm->OutStreamer ->AddComment (" Leaf type: LF_ARGLIST" );
230
230
Asm->EmitInt16 (LF_ARGLIST);
231
+ Asm->OutStreamer ->AddComment (" Number of arguments" );
231
232
Asm->EmitInt32 (0 );
232
233
233
234
TypeIndex VoidProcIdx = getNextTypeIndex ();
235
+ Asm->OutStreamer ->AddComment (" Type record length" );
234
236
Asm->EmitInt16 (2 + sizeof (ProcedureType));
237
+ Asm->OutStreamer ->AddComment (" Leaf type: LF_PROCEDURE" );
235
238
Asm->EmitInt16 (LF_PROCEDURE);
236
- ProcedureType Proc{}; // Zero initialize.
237
- Proc.ReturnType = TypeIndex::Void ();
238
- Proc.CallConv = CallingConvention::NearC;
239
- Proc.Options = FunctionOptions::None;
240
- Proc.NumParameters = 0 ;
241
- Proc.ArgListType = ArgListIdx;
242
- emitRecord (*Asm->OutStreamer , Proc);
239
+ Asm->OutStreamer ->AddComment (" Return type index" );
240
+ Asm->EmitInt32 (TypeIndex::Void ().getIndex ());
241
+ Asm->OutStreamer ->AddComment (" Calling convention" );
242
+ Asm->EmitInt8 (char (CallingConvention::NearC));
243
+ Asm->OutStreamer ->AddComment (" Function options" );
244
+ Asm->EmitInt8 (char (FunctionOptions::None));
245
+ Asm->OutStreamer ->AddComment (" # of parameters" );
246
+ Asm->EmitInt16 (0 );
247
+ Asm->OutStreamer ->AddComment (" Argument list type index" );
248
+ Asm->EmitInt32 (ArgListIdx.getIndex ());
243
249
244
250
for (MDNode *N : CU_Nodes->operands ()) {
245
251
auto *CUNode = cast<DICompileUnit>(N);
246
252
for (auto *SP : CUNode->getSubprograms ()) {
247
253
StringRef DisplayName = SP->getDisplayName ();
254
+ Asm->OutStreamer ->AddComment (" Type record length" );
248
255
Asm->EmitInt16 (2 + sizeof (FuncId) + DisplayName.size () + 1 );
256
+ Asm->OutStreamer ->AddComment (" Leaf type: LF_FUNC_ID" );
249
257
Asm->EmitInt16 (LF_FUNC_ID);
250
258
251
- FuncId Func{}; // Zero initialize.
252
- Func.ParentScope = TypeIndex ();
253
- Func.FunctionType = VoidProcIdx;
254
- emitRecord (*Asm->OutStreamer , Func);
255
- Asm->OutStreamer ->EmitBytes (DisplayName);
256
- Asm->EmitInt8 (0 );
259
+ Asm->OutStreamer ->AddComment (" Scope type index" );
260
+ Asm->EmitInt32 (TypeIndex ().getIndex ());
261
+ Asm->OutStreamer ->AddComment (" Function type" );
262
+ Asm->EmitInt32 (VoidProcIdx.getIndex ());
263
+ {
264
+ SmallString<32 > NullTerminatedString (DisplayName);
265
+ if (NullTerminatedString.empty () || NullTerminatedString.back () != ' \0 ' )
266
+ NullTerminatedString.push_back (' \0 ' );
267
+ Asm->OutStreamer ->AddComment (" Function name" );
268
+ Asm->OutStreamer ->EmitBytes (NullTerminatedString);
269
+ }
257
270
258
271
TypeIndex FuncIdIdx = getNextTypeIndex ();
259
272
SubprogramToFuncId.insert (std::make_pair (SP, FuncIdIdx));
@@ -271,23 +284,30 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
271
284
272
285
OS.AddComment (" Inlinee lines subsection" );
273
286
OS.EmitIntValue (unsigned (ModuleSubstreamKind::InlineeLines), 4 );
287
+ OS.AddComment (" Subsection size" );
274
288
OS.emitAbsoluteSymbolDiff (InlineEnd, InlineBegin, 4 );
275
289
OS.EmitLabel (InlineBegin);
276
290
277
291
// We don't provide any extra file info.
278
292
// FIXME: Find out if debuggers use this info.
293
+ OS.AddComment (" Inlinee lines signature" );
279
294
OS.EmitIntValue (unsigned (InlineeLinesSignature::Normal), 4 );
280
295
281
296
for (const DISubprogram *SP : InlinedSubprograms) {
297
+ OS.AddBlankLine ();
282
298
TypeIndex TypeId = SubprogramToFuncId[SP];
283
299
unsigned FileId = maybeRecordFile (SP->getFile ());
284
300
OS.AddComment (" Inlined function " + SP->getDisplayName () + " starts at " +
285
301
SP->getFilename () + Twine (' :' ) + Twine (SP->getLine ()));
302
+ OS.AddBlankLine ();
286
303
// The filechecksum table uses 8 byte entries for now, and file ids start at
287
304
// 1.
288
305
unsigned FileOffset = (FileId - 1 ) * 8 ;
306
+ OS.AddComment (" Type index of inlined function" );
289
307
OS.EmitIntValue (TypeId.getIndex (), 4 );
308
+ OS.AddComment (" Offset into filechecksum table" );
290
309
OS.EmitIntValue (FileOffset, 4 );
310
+ OS.AddComment (" Starting line number" );
291
311
OS.EmitIntValue (SP->getLine (), 4 );
292
312
}
293
313
@@ -330,14 +350,18 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
330
350
TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee ];
331
351
332
352
// SymbolRecord
353
+ Asm->OutStreamer ->AddComment (" Record length" );
333
354
EmitLabelDiff (OS, InlineBegin, InlineEnd, 2 ); // RecordLength
334
355
OS.EmitLabel (InlineBegin);
356
+ Asm->OutStreamer ->AddComment (" Record kind: S_INLINESITE" );
335
357
Asm->EmitInt16 (SymbolRecordKind::S_INLINESITE); // RecordKind
336
358
337
- InlineSiteSym SiteBytes{};
338
- SiteBytes.Inlinee = InlineeIdx;
339
- Asm->OutStreamer ->EmitBytes (
340
- StringRef (reinterpret_cast <const char *>(&SiteBytes), sizeof (SiteBytes)));
359
+ Asm->OutStreamer ->AddComment (" PtrParent" );
360
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
361
+ Asm->OutStreamer ->AddComment (" PtrEnd" );
362
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
363
+ Asm->OutStreamer ->AddComment (" Inlinee type index" );
364
+ Asm->EmitInt32 (InlineeIdx.getIndex ());
341
365
342
366
unsigned FileId = maybeRecordFile (Site.Inlinee ->getFile ());
343
367
unsigned StartLineNum = Site.Inlinee ->getLine ();
@@ -358,7 +382,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
358
382
}
359
383
360
384
// Close the scope.
385
+ Asm->OutStreamer ->AddComment (" Record length" );
361
386
Asm->EmitInt16 (2 ); // RecordLength
387
+ Asm->OutStreamer ->AddComment (" Record kind: S_INLINESITE_END" );
362
388
Asm->EmitInt16 (SymbolRecordKind::S_INLINESITE_END); // RecordKind
363
389
}
364
390
@@ -382,30 +408,51 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
382
408
*SymbolsEnd = Asm->MMI ->getContext ().createTempSymbol ();
383
409
Asm->OutStreamer ->AddComment (" Symbol subsection for " + Twine (FuncName));
384
410
Asm->EmitInt32 (unsigned (ModuleSubstreamKind::Symbols));
411
+ Asm->OutStreamer ->AddComment (" Subsection size" );
385
412
EmitLabelDiff (*Asm->OutStreamer , SymbolsBegin, SymbolsEnd);
386
413
Asm->OutStreamer ->EmitLabel (SymbolsBegin);
387
414
{
388
- MCSymbol *ProcSegmentBegin = Asm->MMI ->getContext ().createTempSymbol (),
389
- *ProcSegmentEnd = Asm->MMI ->getContext ().createTempSymbol ();
390
- EmitLabelDiff (*Asm->OutStreamer , ProcSegmentBegin, ProcSegmentEnd, 2 );
391
- Asm->OutStreamer ->EmitLabel (ProcSegmentBegin);
415
+ MCSymbol *ProcRecordBegin = Asm->MMI ->getContext ().createTempSymbol (),
416
+ *ProcRecordEnd = Asm->MMI ->getContext ().createTempSymbol ();
417
+ Asm->OutStreamer ->AddComment (" Record length" );
418
+ EmitLabelDiff (*Asm->OutStreamer , ProcRecordBegin, ProcRecordEnd, 2 );
419
+ Asm->OutStreamer ->EmitLabel (ProcRecordBegin);
392
420
421
+ Asm->OutStreamer ->AddComment (" Record kind: S_GPROC32_ID" );
393
422
Asm->EmitInt16 (unsigned (SymbolRecordKind::S_GPROC32_ID));
394
423
395
- // Some bytes of this segment don't seem to be required for basic debugging,
396
- // so just fill them with zeroes.
397
- Asm->OutStreamer ->EmitFill (12 , 0 );
424
+ // These fields are filled in by tools like CVPACK which run after the fact.
425
+ Asm->OutStreamer ->AddComment (" PtrParent" );
426
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
427
+ Asm->OutStreamer ->AddComment (" PtrEnd" );
428
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
429
+ Asm->OutStreamer ->AddComment (" PtrNext" );
430
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
398
431
// This is the important bit that tells the debugger where the function
399
432
// code is located and what's its size:
433
+ Asm->OutStreamer ->AddComment (" Code size" );
400
434
EmitLabelDiff (*Asm->OutStreamer , Fn, FI.End );
401
- Asm->OutStreamer ->EmitFill (12 , 0 );
435
+ Asm->OutStreamer ->AddComment (" Offset after prologue" );
436
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
437
+ Asm->OutStreamer ->AddComment (" Offset before epilogue" );
438
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
439
+ Asm->OutStreamer ->AddComment (" Function type index" );
440
+ Asm->OutStreamer ->EmitIntValue (0 , 4 );
441
+ Asm->OutStreamer ->AddComment (" Function section relative address" );
402
442
Asm->OutStreamer ->EmitCOFFSecRel32 (Fn);
443
+ Asm->OutStreamer ->AddComment (" Function section index" );
403
444
Asm->OutStreamer ->EmitCOFFSectionIndex (Fn);
445
+ Asm->OutStreamer ->AddComment (" Flags" );
404
446
Asm->EmitInt8 (0 );
405
447
// Emit the function display name as a null-terminated string.
406
- Asm->OutStreamer ->EmitBytes (FuncName);
407
- Asm->EmitInt8 (0 );
408
- Asm->OutStreamer ->EmitLabel (ProcSegmentEnd);
448
+ Asm->OutStreamer ->AddComment (" Function name" );
449
+ {
450
+ SmallString<32 > NullTerminatedString (FuncName);
451
+ if (NullTerminatedString.empty () || NullTerminatedString.back () != ' \0 ' )
452
+ NullTerminatedString.push_back (' \0 ' );
453
+ Asm->OutStreamer ->EmitBytes (NullTerminatedString);
454
+ }
455
+ Asm->OutStreamer ->EmitLabel (ProcRecordEnd);
409
456
410
457
// Emit inlined call site information. Only emit functions inlined directly
411
458
// into the parent function. We'll emit the other sites recursively as part
@@ -417,7 +464,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
417
464
}
418
465
419
466
// We're done with this function.
467
+ Asm->OutStreamer ->AddComment (" Record length" );
420
468
Asm->EmitInt16 (0x0002 );
469
+ Asm->OutStreamer ->AddComment (" Record kind: S_PROC_ID_END" );
421
470
Asm->EmitInt16 (unsigned (SymbolRecordKind::S_PROC_ID_END));
422
471
}
423
472
Asm->OutStreamer ->EmitLabel (SymbolsEnd);
0 commit comments