1LLVM-DEBUGINFO-ANALYZER(1) LLVM LLVM-DEBUGINFO-ANALYZER(1)
2
3
4
6 llvm-debuginfo-analyzer - Print a logical representation of low-level
7 debug information.
8
9 • SYNOPSIS
10
11 • DESCRIPTION
12
13 • OPTIONS
14
15 • GENERAL
16
17 • ATTRIBUTES
18
19 • PRINT
20
21 • OUTPUT
22
23 • REPORT
24
25 • SELECTION
26
27 • ELEMENTS
28
29 • LINES
30
31 • SCOPES
32
33 • SYMBOLS
34
35 • TYPES
36
37 • COMPARE
38
39 • WARNING
40
41 • INTERNAL
42
43 • EXAMPLES
44
45 • TEST CASE 1 - GENERAL OPTIONS
46
47 • PRINTING MODE
48
49 • BASIC DETAILS
50
51 • SELECT LOGICAL ELEMENTS
52
53 • COMPARISON MODE
54
55 • LOGICAL VIEW
56
57 • LOGICAL ELEMENTS
58
59 • TEST CASE 2 - ASSEMBLER INSTRUCTIONS
60
61 • CodeView - Clang (Windows)
62
63 • CodeView - MSVC (Windows)
64
65 • DWARF - Clang (Linux)
66
67 • DWARF - GCC (Linux)
68
69 • TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF
70
71 • CodeView - Clang (Windows)
72
73 • CodeView - MSVC (Windows)
74
75 • DWARF - Clang (Linux)
76
77 • DWARF - GCC (Linux)
78
79 • TEST CASE 4 - MISSING NESTED ENUMERATIONS
80
81 • CodeView - Clang (Windows)
82
83 • CodeView - MSVC (Windows)
84
85 • DWARF - Clang (Linux)
86
87 • DWARF - GCC (Linux)
88
89 • TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLE
90
91 • CODEVIEW - Clang (Windows)
92
93 • CODEVIEW - MSVC (Windows)
94
95 • DWARF - Clang (Linux)
96
97 • DWARF - GCC (Linux)
98
99 • TEST CASE 6 - FULL LOGICAL VIEW
100
101 • EXIT STATUS
102
103 • SEE ALSO
104
106 llvm-debuginfo-analyzer [options] [filename ...]
107
109 llvm-debuginfo-analyzer parses debug and text sections in binary object
110 files and prints their contents in a logical view, which is a human
111 readable representation that closely matches the structure of the orig‐
112 inal user source code. Supported object file formats include ELF,
113 Mach-O, PDB and COFF.
114
115 The logical view abstracts the complexity associated with the different
116 low-level representations of the debugging information that is embedded
117 in the object file. llvm-debuginfo-analyzer produces a canonical view
118 of the debug information regardless of how it is formatted. The same
119 logical view will be seen regardless of object file format, assuming
120 the debug information correctly represents the same original source
121 code.
122
123 The logical view includes the following logical elements: type, scope,
124 symbol and line, which are the basic software elements used in the
125 C/C++ programming language. Each logical element has a set of at‐
126 tributes, such as types, classes, functions, variables, parameters,
127 etc. The --attribute can be used to specify which attributes to include
128 when printing a logical element. A logical element may have a kind that
129 describes specific types of elements. For instance, a scope could have
130 a kind value of function, class, namespace.
131
132 llvm-debuginfo-analyzer defaults to print a pre-defined layout of logi‐
133 cal elements and attributes. The command line options can be used to
134 control the printed elements (--print), using a specific layout (‐
135 --report), matching a given pattern (--select, --select-offsets). Also,
136 the output can be limited to specified logical elements using (‐
137 --select-lines, --select-scopes, --select-symbols, --select-types).
138
139 llvm-debuginfo-analyzer can also compare a set of logical views (‐
140 --compare), to find differences and identify possible debug information
141 syntax issues (--warning) in any object file.
142
144 llvm-debuginfo-analyzer options are separated into several categories,
145 each tailored to a different purpose:
146
147 • GENERAL - Standard LLVM options to display help, version, etc.
148
149 • ATTRIBUTES - Describe how to include different details when print‐
150 ing an element.
151
152 • PRINT - Specify which elements will be included when printing the
153 view.
154
155 • OUTPUT - Describe the supported formats when printing the view.
156
157 • REPORT - Describe the format layouts for view printing.
158
159 • SELECTION - Allows to use specific criteria or conditions to se‐
160 lect which elements to print.
161
162 • COMPARE - Compare logical views and print missing and/or added el‐
163 ements.
164
165 • WARNING - Print the warnings detected during the creation of the
166 view.
167
168 • INTERNAL - Internal analysis of the logical view.
169
170 GENERAL
171 This section describes the standard help options, used to display the
172 usage, version, response files, etc.
173
174 -h, --help
175 Show help and usage for this command. (--help-hidden for more).
176
177 --help-list
178 Show help and usage for this command without grouping the op‐
179 tions into categories (--help-list-hidden for more).
180
181 --help-hidden
182 Display all available options.
183
184 --print-all-options
185 Print all option values after command line parsing.
186
187 --print-options
188 Print non-default options after command line parsing
189
190 --version
191 Display the version of the tool.
192
193 @<FILE>
194 Read command-line options from <FILE>.
195
196 If no input file is specified, llvm-debuginfo-analyzer defaults to read
197 a.out and return an error when no input file is found.
198
199 If - is used as the input file, llvm-debuginfo-analyzer reads the input
200 from its standard input stream.
201
202 ATTRIBUTES
203 The following options enable attributes given for the printed elements.
204 The attributes are divided in categories based on the type of data be‐
205 ing added, such as: internal offsets in the binary file, location de‐
206 scriptors, register names, user source filenames, additional element
207 transformations, toolchain name, binary file format, etc.
208
209 --attribute=<value[,value,...]>
210 With value being one of the options in the following lists.
211
212 =all: Include all the below attributes.
213 =extended: Add low-level attributes.
214 =standard: Add standard high-level attributes.
215
216 The following attributes describe the most common information
217 for a logical element. They help to identify the lexical scope
218 level; the element visibility across modules (global, local);
219 the toolchain name that produced the binary file.
220
221 =global: Element referenced across Compile Units.
222 =format: Object file format name.
223 =level: Lexical scope level (File=0, Compile Unit=1).
224 =local: Element referenced only in the Compile Unit.
225 =producer: Toolchain identification name.
226
227 The following attributes describe files and directory names from
228 the user source code, where the elements are declared or de‐
229 fined; functions with public visibility across modules. These
230 options allow to map the elements to their user code location,
231 for cross references purposes.
232
233 =directories: Directories referenced in the debug information.
234 =filename: Filename where the element is defined.
235 =files: Files referenced in the debug information.
236 =pathname: Pathname where the object is defined.
237 =publics: Function names that are public.
238
239 The following attributes describe additional logical element
240 source transformations, in order to display built-in types (int,
241 bool, etc.); parameters and arguments used during template in‐
242 stantiation; parent name hierarchy; array dimensions informa‐
243 tion; compiler generated elements and the underlying types asso‐
244 ciated with the types aliases.
245
246 =argument: Template parameters replaced by its arguments.
247 =base: Base types (int, bool, etc.).
248 =generated: Compiler generated elements.
249 =encoded: Template arguments encoded in the template name.
250 =qualified: The element type include parents in its name.
251 =reference: Element declaration and definition references.
252 =subrange: Subrange encoding information for arrays.
253 =typename: Template parameters.
254 =underlying: Underlying type for type definitions.
255
256 The following attributes describe the debug location information
257 for a symbol or scope. It includes the symbol percentage cover‐
258 age and any gaps within the location layout; ranges determining
259 the code sections attached to a function. When descriptors are
260 used, the target processor registers are displayed.
261
262 =coverage: Symbol location coverage.
263 =gaps: Missing debug location (gaps).
264 =location: Symbol debug location.
265 =range: Debug location ranges.
266 =register: Processor register names.
267
268 The following attributes are associated with low level details,
269 such as: offsets in the binary file; discriminators added to the
270 lines of inlined functions in order to distinguish specific in‐
271 stances; debug lines state machine registers; elements discarded
272 by the compiler (inlining) or by the linker optimizations
273 (dead-stripping); system compile units generated by the MS
274 toolchain in PDBs.
275
276 =discarded: Discarded elements by the linker.
277 =discriminator: Discriminators for inlined function instances.
278 =inserted: Generated inlined abstract references.
279 =linkage: Object file linkage name.
280 =offset: Debug information offset.
281 =qualifier: Line qualifiers (Newstatement, BasicBlock, etc).
282 =zero: Zero line numbers.
283
284 The following attribute described specific information for the
285 PE/COFF file format. It includes MS runtime types.
286
287 =system: Display PDB's MS system elements.
288
289 The above attributes are grouped into standard and extended cat‐
290 egories that can be enabled.
291
292 The standard group, contains those attributes that add suffi‐
293 cient information to describe a logical element and that can
294 cover the normal situations while dealing with debug informa‐
295 tion.
296
297 =base
298 =coverage
299 =directories
300 =discriminator
301 =filename
302 =files
303 =format
304 =level
305 =producer
306 =publics
307 =range
308 =reference
309 =zero
310
311 The extended group, contains those attributes that require a
312 more extended knowledge about debug information. They are in‐
313 tended when a lower level of detail is required.
314
315 =argument
316 =discarded
317 =encoded
318 =gaps
319 =generated
320 =global
321 =inserted
322 =linkage
323 =local
324 =location
325 =offset
326 =operation
327 =pathname
328 =qualified
329 =qualifier
330 =register
331 =subrange
332 =system
333 =typename
334
335 PRINT
336 The following options describe the elements to print. The layout used
337 is determined by the --report. In the tree layout, all the elements
338 have their enclosing lexical scopes printed, even when not explicitly
339 specified.
340
341 --print=<value[,value,...]>
342 With value being one of the options in the following lists.
343
344 =all: Include all the below attributes.
345
346 The following options print the requested elements; in the case
347 of any given select conditions (--select), only those elements
348 that match them, will be printed. The elements value is a conve‐
349 nient way to specify instructions, lines, scopes, symbols and
350 types all at once.
351
352 =elements: Instructions, lines, scopes, symbols and types.
353 =instructions: Assembler instructions for code sections.
354 =lines: Source lines referenced in the debug information.
355 =scopes: Lexical blocks (function, class, namespace, etc).
356 =symbols: Symbols (variable, member, parameter, etc).
357 =types: Types (pointer, reference, type alias, etc).
358
359 The following options print information, collected during the
360 creation of the elements, such as: scope contributions to the
361 debug information; summary of elements created, printed or
362 matched (--select); warnings produced during the view creation.
363
364 =sizes: Debug Information scopes contributions.
365 =summary: Summary of elements allocated, selected or printed.
366 =warnings: Warnings detected.
367
368 Note: The --print=sizes option is ELF specific.
369
370 OUTPUT
371 The following options describe how to control the output generated when
372 printing the logical elements.
373
374 --output-file=<path>
375 Redirect the output to a file specified by <path>, where - is
376 the standard output stream.
377
378 llvm-debuginfo-analyzer has the concept of split view. When redirect‐
379 ing the output from a complex binary format, it is divided into indi‐
380 vidual files, each one containing the logical view output for a single
381 compilation unit.
382
383 --output-folder=<name>
384 The folder to write a file per compilation unit when --out‐
385 put=split is specified.
386
387 --output-level=<level>
388 Only print elements up to the given lexical level value. The in‐
389 put file is at lexical level zero and a compilation unit is at
390 lexical level one.
391
392 --output=<value[,value,...]>
393 With value being one of the options in the following lists.
394
395 =all: Include all the below outputs.
396
397 =json: Use JSON as the output format (Not implemented).
398 =split: Split the output by Compile Units.
399 =text: Use a free form text output.
400
401 --output-sort=<key>
402 Primary key when ordering the elements in the output (default:
403 line). Sorting by logical element kind, requires be familiarity
404 with the element kind selection options (--select-lines,
405 --select-scopes, --select-symbols, --select-types), as those op‐
406 tions describe the different logical element kinds.
407
408 =kind: Sort by element kind.
409 =line: Sort by element line number.
410 =name: Sort by element name.
411 =offset: Sort by element offset.
412
413 REPORT
414 Depending on the task being executed (print, compare, select), several
415 layouts are supported to display the elements in a more suitable way,
416 to make the output easier to understand.
417
418 --report=<value[,value,...]>
419 With value being one of the options in the following list.
420
421 =all: Include all the below reports.
422
423 =children: Elements and children are displayed in a tree format.
424 =list: Elements are displayed in a tabular format.
425 =parents: Elements and parents are displayed in a tree format.
426 =view: Elements, parents and children are displayed in a tree format.
427
428 The list layout presents the logical elements in a tabular form without
429 any parent-child relationship. This may be the preferred way to display
430 elements that match specific conditions when comparing logical views,
431 making it easier to find differences.
432
433 The children, parents and view layout displays the elements in a tree
434 format, with the scopes representing their nodes, and types, symbols,
435 lines and other scopes representing the children. The layout shows the
436 lexical scoping relationship between elements, with the binary file be‐
437 ing the tree root (level 0) and each compilation unit being a child
438 (level 1).
439
440 The children layout includes the elements that match any given criteria
441 (--select) or (--compare) and its children.
442
443 The parents layout includes the elements that match any given criteria
444 (--select) or (--compare) and its parents.
445
446 The combined view layout includes the elements that match any given
447 criteria (--select) or (--compare), its parents and children.
448
449 Notes:
450
451 1. When a selection criteria (--select) is specified with no report op‐
452 tion, the list layout is selected.
453
454 2. The comparison mode always uses the view layout.
455
456 SELECTION
457 When printing an element, different data can be included and it varies
458 (--attribute) from data directly associated with the binary file (off‐
459 set) to high level details such as coverage, lexical scope level, loca‐
460 tion. As the printed output can reach a considerable size, several se‐
461 lection options, enable printing of specific elements.
462
463 The pattern matching can ignore the case (--select-nocase) and be ex‐
464 tended to use regular expressions (--select-regex).
465
466 ELEMENTS
467 The following options allow printing of elements that match the given
468 <pattern>, offset <value> or an element <condition>.
469
470 --select=<pattern>
471 Print all elements whose name or line number matches the given
472 <pattern>.
473
474 --select-offsets=<value[,value,...]>
475 Print all elements whose offset matches the given values. See
476 --attribute option.
477
478 --select-elements=<condition[,condition,...]>
479 Print all elements that satisfy the given <condition>. With con‐
480 dition being one of the options in the following list.
481
482 =discarded: Discarded elements by the linker.
483 =global: Element referenced across Compile Units.
484 =optimized: Optimized inlined abstract references.
485
486 --select-nocase
487 Pattern matching is case-insensitive when using --select.
488
489 --select-regex
490 Treat any <pattern> strings as regular expressions when select‐
491 ing with --select option. If --select-nocase is specified, the
492 regular expression becomes case-insensitive.
493
494 If the <pattern> criteria is too general, a more selective option can
495 be specified to target a particular category of elements: lines (‐
496 --select-lines), scopes (--select-scopes), symbols (--select-symbols)
497 and types (--select-types). These options require knowledge of the de‐
498 bug information format (DWARF, CodeView, COFF), as the given kind de‐
499 scribes a very specific type of element.
500
501 LINES
502 The following options allow printing of lines that match the given
503 <kind>. The given criteria describes the debug line state machine reg‐
504 isters.
505
506 --select-lines=<kind[,kind,...]>
507 With kind being one of the options in the following list.
508
509 =AlwaysStepInto: marks an always step into.
510 =BasicBlock: Marks a new basic block.
511 =Discriminator: Line that has a discriminator.
512 =EndSequence: Marks the end in the sequence of lines.
513 =EpilogueBegin: Marks the start of a function epilogue.
514 =LineDebug: Lines that correspond to debug lines.
515 =LineAssembler: Lines that correspond to disassembly text.
516 =NeverStepInto: marks a never step into.
517 =NewStatement: Marks a new statement.
518 =PrologueEnd: Marks the end of a function prologue.
519
520 SCOPES
521 The following options allow printing of scopes that match the given
522 <kind>.
523
524 --select-scopes=<kind[,kind,...]>
525 With kind being one of the options in the following list.
526
527 =Aggregate: A class, structure or union.
528 =Array: An array.
529 =Block: A generic block (lexical block or exception block).
530 =CallSite: A call site.
531 =CatchBlock: An exception block.
532 =Class: A class.
533 =CompileUnit: A compile unit.
534 =EntryPoint: A subroutine entry point.
535 =Enumeration: An enumeration.
536 =Function: A function.
537 =FunctionType: A function pointer.
538 =InlinedFunction: An inlined function.
539 =Label: A label.
540 =LexicalBlock: A lexical block.
541 =Namespace: A namespace.
542 =Root: The element representing the main scope.
543 =Structure: A structure.
544 =Subprogram: A subprogram.
545 =Template: A template definition.
546 =TemplateAlias: A template alias.
547 =TemplatePack: A template pack.
548 =TryBlock: An exception try block.
549 =Union: A union.
550
551 SYMBOLS
552 The following options allow printing of symbols that match the given
553 <kind>.
554
555 --select-symbols=<kind[,kind,...]>
556 With kind being one of the options in the following list.
557
558 =CallSiteParameter: A call site parameter.
559 =Constant: A constant symbol.
560 =Inheritance: A base class.
561 =Member: A member class.
562 =Parameter: A parameter to function.
563 =Unspecified: Unspecified parameters to function.
564 =Variable: A variable.
565
566 TYPES
567 The following options allow printing of types that match the given
568 <kind>.
569
570 --select-types=<kind[,kind,...]>
571 With kind being one of the options in the following list.
572
573 =Base: Base type (integer, boolean, etc).
574 =Const: Constant specifier.
575 =Enumerator: Enumerator.
576 =Import: Import declaration.
577 =ImportDeclaration: Import declaration.
578 =ImportModule: Import module.
579 =Pointer: Pointer type.
580 =PointerMember: Pointer to member function.
581 =Reference: Reference type.
582 =Restrict: Restrict specifier.
583 =RvalueReference: R-value reference.
584 =Subrange: Array subrange.
585 =TemplateParam: Template parameter.
586 =TemplateTemplateParam: Template template parameter.
587 =TemplateTypeParam: Template type parameter.
588 =TemplateValueParam: Template value parameter.
589 =Typedef: Type definition.
590 =Unspecified: Unspecified type.
591 =Volatile: Volatile specifier.
592
593 COMPARE
594 When dealing with debug information, there are situations when the
595 printing of the elements is not the correct approach. That is the case,
596 when we are interested in the effects caused by different versions of
597 the same toolchain, or the impact of specific compiler optimizations.
598
599 For those cases, we are looking to see which elements have been added
600 or removed. Due to the complicated debug information format, it is very
601 difficult to use a regular diff tool to find those elements; even im‐
602 possible when dealing with different debug formats.
603
604 llvm-debuginfo-analyzer supports a logical element comparison, allowing
605 to find semantic differences between logical views, produced by differ‐
606 ent toolchain versions or even debug information formats.
607
608 When comparing logical views created from different debug formats, its
609 accuracy depends on how close the debug information represents the user
610 code. For instance, a logical view created from a binary file with
611 DWARF debug information may include more detailed data than a logical
612 view created from a binary file with CodeView/COFF debug information.
613
614 The following options describe the elements to compare.
615
616 --compare=<value[,value,...]>
617 With value being one of the options in the following list.
618
619 =all: Include all the below elements.
620
621 =lines: Include lines.
622 =scopes: Include scopes.
623 =symbols: Include symbols.
624 =types: Include types.
625
626 llvm-debuginfo-analyzer takes the first binary file on the command line
627 as the reference and the second one as the target. To get a more de‐
628 scriptive report, the comparison is done twice. The reference and tar‐
629 get views are swapped, in order to produce those missing elements from
630 the target view and those added elements to the reference view.
631
632 See --report options on how to describe the comparison reports.
633
634 WARNING
635 When reading the input object files, llvm-debuginfo-analyzer can detect
636 issues in the raw debug information. These may not be considered fatal
637 to the purpose of printing a logical view but they can give an indica‐
638 tion about the quality and potentially expose issues with the generated
639 debug information.
640
641 The following options describe the warnings to be recorded for later
642 printing, if they are requested by --print.
643
644 --warning=<value[,value,...]>
645 With value being one of the options in the following list.
646
647 =all: Include all the below warnings.
648
649 The following options collect additional information during the
650 creation of the logical view, to include invalid coverage values
651 and locations for symbols; invalid code ranges; lines that are
652 zero.
653
654 =coverages: Invalid symbol coverages values.
655 =lines: Debug lines that are zero.
656 =locations: Invalid symbol locations.
657 =ranges: Invalid code ranges.
658
659 INTERNAL
660 For a better understanding of the logical view, access to more de‐
661 tailed internal information could be needed. Such data would help to
662 identify debug information processed or incorrect logical element
663 management. Typically these kind of options are available only in
664 debug builds.
665
666 llvm-debuginfo-analyzer supports these advanced options in both re‐
667 lease and debug builds, with the exception of the unique ID that is
668 generated only in debug builds.
669
670 --internal=<value[,value,...]>
671 With value being one of the options in the following list.
672
673 =all: Include all the below options.
674
675 The following options allow to check the integrity of the logi‐
676 cal view; collect the debug tags that are processed or not im‐
677 plemented; ignore the logical element line number, to facilitate
678 the logical view comparison when using external comparison
679 tools; print the command line options used to invoke llvm-debug‐
680 info-analyzer.
681
682 =id: Print unique element ID.
683 =cmdline: Print command line.
684 =integrity: Check elements integrity.
685 =none: Ignore element line number.
686 =tag: Debug information tags.
687
688 Note: For ELF format, the collected tags represent the debug
689 tags that are not processed. For PE/COFF format, they represent
690 the tags that are processed.
691
693 This section includes some real binary files to show how to use
694 llvm-debuginfo-analyzer to print a logical view and to diagnose possi‐
695 ble debug information issues.
696
697 TEST CASE 1 - GENERAL OPTIONS
698 The below example is used to show different output generated by
699 llvm-debuginfo-analyzer. We compiled the example for an X86 ELF target
700 with Clang (-O0 -g):
701
702 1 using INTPTR = const int *;
703 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
704 3 if (ParamBool) {
705 4 typedef int INTEGER;
706 5 const INTEGER CONSTANT = 7;
707 6 return CONSTANT;
708 7 }
709 8 return ParamUnsigned;
710 9 }
711
712 PRINTING MODE
713 In this mode llvm-debuginfo-analyzer prints the logical view or por‐
714 tions of it, based on criteria patterns (including regular expressions)
715 to select the kind of logical elements to be included in the output.
716
717 BASIC DETAILS
718 The following command prints basic details for all the logical elements
719 sorted by the debug information internal offset; it includes its lexi‐
720 cal level and debug info format.
721
722 llvm-debuginfo-analyzer --attribute=level,format
723 --output-sort=offset
724 --print=scopes,symbols,types,lines,instructions
725 test-dwarf-clang.o
726
727 or
728
729 llvm-debuginfo-analyzer --attribute=level,format
730 --output-sort=offset
731 --print=elements
732 test-dwarf-clang.o
733
734 Each row represents an element that is present within the debug infor‐
735 mation. The first column represents the scope level, followed by the
736 associated line number (if any), and finally the description of the el‐
737 ement.
738
739 Logical View:
740 [000] {File} 'test-dwarf-clang.o' -> elf64-x86-64
741
742 [001] {CompileUnit} 'test.cpp'
743 [002] 2 {Function} extern not_inlined 'foo' -> 'int'
744 [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
745 [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
746 [003] 2 {Parameter} 'ParamBool' -> 'bool'
747 [003] {Block}
748 [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
749 [004] 5 {Line}
750 [004] {Code} 'movl $0x7, -0x1c(%rbp)'
751 [004] 6 {Line}
752 [004] {Code} 'movl $0x7, -0x4(%rbp)'
753 [004] {Code} 'jmp 0x6'
754 [004] 8 {Line}
755 [004] {Code} 'movl -0x14(%rbp), %eax'
756 [003] 4 {TypeAlias} 'INTEGER' -> 'int'
757 [003] 2 {Line}
758 [003] {Code} 'pushq %rbp'
759 [003] {Code} 'movq %rsp, %rbp'
760 [003] {Code} 'movb %dl, %al'
761 [003] {Code} 'movq %rdi, -0x10(%rbp)'
762 [003] {Code} 'movl %esi, -0x14(%rbp)'
763 [003] {Code} 'andb $0x1, %al'
764 [003] {Code} 'movb %al, -0x15(%rbp)'
765 [003] 3 {Line}
766 [003] {Code} 'testb $0x1, -0x15(%rbp)'
767 [003] {Code} 'je 0x13'
768 [003] 8 {Line}
769 [003] {Code} 'movl %eax, -0x4(%rbp)'
770 [003] 9 {Line}
771 [003] {Code} 'movl -0x4(%rbp), %eax'
772 [003] {Code} 'popq %rbp'
773 [003] {Code} 'retq'
774 [003] 9 {Line}
775 [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
776
777 On closer inspection, we can see what could be a potential debug issue:
778
779 [003] {Block}
780 [003] 4 {TypeAlias} 'INTEGER' -> 'int'
781
782 The 'INTEGER' definition is at level [003], the same lexical scope as
783 the anonymous {Block} ('true' branch for the 'if' statement) whereas in
784 the original source code the typedef statement is clearly inside that
785 block, so the 'INTEGER' definition should also be at level [004] inside
786 the block.
787
788 SELECT LOGICAL ELEMENTS
789 The following prints all instructions, symbols and types that contain
790 'inte' or 'movl' in their names or types, using a tab layout and given
791 the number of matches.
792
793 llvm-debuginfo-analyzer --attribute=level
794 --select-nocase --select-regex
795 --select=INTe --select=movl
796 --report=list
797 --print=symbols,types,instructions,summary
798 test-dwarf-clang.o
799
800 Logical View:
801 [000] {File} 'test-dwarf-clang.o'
802
803 [001] {CompileUnit} 'test.cpp'
804 [003] {Code} 'movl $0x7, -0x1c(%rbp)'
805 [003] {Code} 'movl $0x7, -0x4(%rbp)'
806 [003] {Code} 'movl %eax, -0x4(%rbp)'
807 [003] {Code} 'movl %esi, -0x14(%rbp)'
808 [003] {Code} 'movl -0x14(%rbp), %eax'
809 [003] {Code} 'movl -0x4(%rbp), %eax'
810 [003] 4 {TypeAlias} 'INTEGER' -> 'int'
811 [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
812
813 -----------------------------
814 Element Total Found
815 -----------------------------
816 Scopes 3 0
817 Symbols 4 1
818 Types 2 1
819 Lines 17 6
820 -----------------------------
821 Total 26 8
822
823 COMPARISON MODE
824 In this mode llvm-debuginfo-analyzer compares logical views to produce
825 a report with the logical elements that are missing or added. This a
826 very powerful aid in finding semantic differences in the debug informa‐
827 tion produced by different toolchain versions or even completely dif‐
828 ferent toolchains altogether (For example a compiler producing DWARF
829 can be directly compared against a completely different compiler that
830 produces CodeView).
831
832 Given the previous example we found the above debug information issue
833 (related to the previous invalid scope location for the 'typedef int
834 INTEGER') by comparing against another compiler.
835
836 Using GCC to generate test-dwarf-gcc.o, we can apply a selection pat‐
837 tern with the printing mode to obtain the following logical view out‐
838 put.
839
840 llvm-debuginfo-analyzer --attribute=level
841 --select-regex --select-nocase --select=INTe
842 --report=list
843 --print=symbols,types
844 test-dwarf-clang.o test-dwarf-gcc.o
845
846 Logical View:
847 [000] {File} 'test-dwarf-clang.o'
848
849 [001] {CompileUnit} 'test.cpp'
850 [003] 4 {TypeAlias} 'INTEGER' -> 'int'
851 [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
852
853 Logical View:
854 [000] {File} 'test-dwarf-gcc.o'
855
856 [001] {CompileUnit} 'test.cpp'
857 [004] 4 {TypeAlias} 'INTEGER' -> 'int'
858 [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
859
860 The output shows that both objects contain the same elements. But the
861 'typedef INTEGER' is located at different scope level. The GCC gener‐
862 ated object, shows '4', which is the correct value.
863
864 Note that there is no requirement that GCC must produce identical or
865 similar DWARF to Clang to allow the comparison. We're only comparing
866 the semantics. The same case when comparing CodeView debug information
867 generated by MSVC and Clang.
868
869 There are 2 comparison methods: logical view and logical elements.
870
871 LOGICAL VIEW
872 It compares the logical view as a whole unit; for a match, each com‐
873 pared logical element must have the same parents and children.
874
875 Using the llvm-debuginfo-analyzer comparison functionality, that issue
876 can be seen in a more global context, that can include the logical
877 view.
878
879 The output shows in view form the missing (-), added (+) elements, giv‐
880 ing more context by swapping the reference and target object files.
881
882 llvm-debuginfo-analyzer --attribute=level
883 --compare=types
884 --report=view
885 --print=symbols,types
886 test-dwarf-clang.o test-dwarf-gcc.o
887
888 Reference: 'test-dwarf-clang.o'
889 Target: 'test-dwarf-gcc.o'
890
891 Logical View:
892 [000] {File} 'test-dwarf-clang.o'
893
894 [001] {CompileUnit} 'test.cpp'
895 [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
896 [002] 2 {Function} extern not_inlined 'foo' -> 'int'
897 [003] {Block}
898 [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
899 +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
900 [003] 2 {Parameter} 'ParamBool' -> 'bool'
901 [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
902 [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
903 -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
904
905 The output shows the merging view path (reference and target) with the
906 missing and added elements.
907
908 LOGICAL ELEMENTS
909 It compares individual logical elements without considering if their
910 parents are the same. For both comparison methods, the equal criteria
911 includes the name, source code location, type, lexical scope level.
912
913 llvm-debuginfo-analyzer --attribute=level
914 --compare=types
915 --report=list
916 --print=symbols,types,summary
917 test-dwarf-clang.o test-dwarf-gcc.o
918
919 Reference: 'test-dwarf-clang.o'
920 Target: 'test-dwarf-gcc.o'
921
922 (1) Missing Types:
923 -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
924
925 (1) Added Types:
926 +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
927
928 ----------------------------------------
929 Element Expected Missing Added
930 ----------------------------------------
931 Scopes 4 0 0
932 Symbols 0 0 0
933 Types 2 1 1
934 Lines 0 0 0
935 ----------------------------------------
936 Total 6 1 1
937
938 Changing the Reference and Target order:
939
940 llvm-debuginfo-analyzer --attribute=level
941 --compare=types
942 --report=list
943 --print=symbols,types,summary
944 test-dwarf-gcc.o test-dwarf-clang.o
945
946 Reference: 'test-dwarf-gcc.o'
947 Target: 'test-dwarf-clang.o'
948
949 (1) Missing Types:
950 -[004] 4 {TypeAlias} 'INTEGER' -> 'int'
951
952 (1) Added Types:
953 +[003] 4 {TypeAlias} 'INTEGER' -> 'int'
954
955 ----------------------------------------
956 Element Expected Missing Added
957 ----------------------------------------
958 Scopes 4 0 0
959 Symbols 0 0 0
960 Types 2 1 1
961 Lines 0 0 0
962 ----------------------------------------
963 Total 6 1 1
964
965 As the Reference and Target are switched, the Added Types from the
966 first case now are listed as Missing Types.
967
968 TEST CASE 2 - ASSEMBLER INSTRUCTIONS
969 The below example is used to show different output generated by
970 llvm-debuginfo-analyzer. We compiled the example for an X86 Codeview
971 and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g)
972 for Windows and Linux.
973
974 1 extern int printf(const char * format, ... );
975 2
976 3 int main()
977 4 {
978 5 printf("Hello, World\n");
979 6 return 0;
980 7 }
981
982 These are the logical views that llvm-debuginfo-analyzer generates for
983 3 different compilers (MSVC, Clang and GCC), emitting different debug
984 information formats (CodeView, DWARF) on Windows and Linux.
985
986 llvm-debuginfo-analyzer --attribute=level,format,producer
987 --print=lines,instructions
988 hello-world-codeview-clang.o
989 hello-world-codeview-msvc.o
990 hello-world-dwarf-clang.o
991 hello-world-dwarf-gcc.o
992
993 CodeView - Clang (Windows)
994 Logical View:
995 [000] {File} 'hello-world-codeview-clang.o' -> COFF-x86-64
996
997 [001] {CompileUnit} 'hello-world.cpp'
998 [002] {Producer} 'clang version 14.0.0'
999 [002] {Function} extern not_inlined 'main' -> 'int'
1000 [003] 4 {Line}
1001 [003] {Code} 'subq $0x28, %rsp'
1002 [003] {Code} 'movl $0x0, 0x24(%rsp)'
1003 [003] 5 {Line}
1004 [003] {Code} 'leaq (%rip), %rcx'
1005 [003] {Code} 'callq 0x0'
1006 [003] 6 {Line}
1007 [003] {Code} 'xorl %eax, %eax'
1008 [003] {Code} 'addq $0x28, %rsp'
1009 [003] {Code} 'retq'
1010
1011 CodeView - MSVC (Windows)
1012 Logical View:
1013 [000] {File} 'hello-world-codeview-msvc.o' -> COFF-i386
1014
1015 [001] {CompileUnit} 'hello-world.cpp'
1016 [002] {Producer} 'Microsoft (R) Optimizing Compiler'
1017 [002] {Function} extern not_inlined 'main' -> 'int'
1018 [003] 4 {Line}
1019 [003] {Code} 'pushl %ebp'
1020 [003] {Code} 'movl %esp, %ebp'
1021 [003] 5 {Line}
1022 [003] {Code} 'pushl $0x0'
1023 [003] {Code} 'calll 0x0'
1024 [003] {Code} 'addl $0x4, %esp'
1025 [003] 6 {Line}
1026 [003] {Code} 'xorl %eax, %eax'
1027 [003] 7 {Line}
1028 [003] {Code} 'popl %ebp'
1029 [003] {Code} 'retl'
1030
1031 DWARF - Clang (Linux)
1032 Logical View:
1033 [000] {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64
1034
1035 [001] {CompileUnit} 'hello-world.cpp'
1036 [002] {Producer} 'clang version 14.0.0'
1037 [002] 3 {Function} extern not_inlined 'main' -> 'int'
1038 [003] 4 {Line}
1039 [003] {Code} 'pushq %rbp'
1040 [003] {Code} 'movq %rsp, %rbp'
1041 [003] {Code} 'subq $0x10, %rsp'
1042 [003] {Code} 'movl $0x0, -0x4(%rbp)'
1043 [003] 5 {Line}
1044 [003] {Code} 'movabsq $0x0, %rdi'
1045 [003] {Code} 'movb $0x0, %al'
1046 [003] {Code} 'callq 0x0'
1047 [003] 6 {Line}
1048 [003] {Code} 'xorl %eax, %eax'
1049 [003] {Code} 'addq $0x10, %rsp'
1050 [003] {Code} 'popq %rbp'
1051 [003] {Code} 'retq'
1052 [003] 6 {Line}
1053
1054 DWARF - GCC (Linux)
1055 Logical View:
1056 [000] {File} 'hello-world-dwarf-gcc.o' -> elf64-x86-64
1057
1058 [001] {CompileUnit} 'hello-world.cpp'
1059 [002] {Producer} 'GNU C++14 9.3.0'
1060 [002] 3 {Function} extern not_inlined 'main' -> 'int'
1061 [003] 4 {Line}
1062 [003] {Code} 'endbr64'
1063 [003] {Code} 'pushq %rbp'
1064 [003] {Code} 'movq %rsp, %rbp'
1065 [003] 5 {Line}
1066 [003] {Code} 'leaq (%rip), %rdi'
1067 [003] {Code} 'movl $0x0, %eax'
1068 [003] {Code} 'callq 0x0'
1069 [003] 6 {Line}
1070 [003] {Code} 'movl $0x0, %eax'
1071 [003] 7 {Line}
1072 [003] {Code} 'popq %rbp'
1073 [003] {Code} 'retq'
1074 [003] 7 {Line}
1075
1076 The logical views shows the intermixed lines and assembler instruc‐
1077 tions, allowing to compare the code generated by the different
1078 toolchains.
1079
1080 TEST CASE 3 - INCORRECT LEXICAL SCOPE FOR TYPEDEF
1081 The below example is used to show different output generated by
1082 llvm-debuginfo-analyzer. We compiled the example for an X86 Codeview
1083 and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).
1084
1085 1 int bar(float Input) { return (int)Input; }
1086 2
1087 3 unsigned foo(char Param) {
1088 4 typedef int INT; // ** Definition for INT **
1089 5 INT Value = Param;
1090 6 {
1091 7 typedef float FLOAT; // ** Definition for FLOAT **
1092 8 {
1093 9 FLOAT Added = Value + Param;
1094 10 Value = bar(Added);
1095 11 }
1096 12 }
1097 13 return Value + Param;
1098 14 }
1099
1100 The above test is used to illustrate a scope issue found in the Clang
1101 compiler: PR44884 (Bugs LLVM) / PR44229 (GitHub LLVM)
1102
1103 The lines 4 and 7 contains 2 typedefs, defined at different lexical
1104 scopes.
1105
1106 4 typedef int INT;
1107 7 typedef float FLOAT;
1108
1109 These are the logical views that llvm-debuginfo-analyzer generates for
1110 3 different compilers (MSVC, Clang and GCC), emitting different debug
1111 information formats (CodeView, DWARF) on different platforms.
1112
1113 llvm-debuginfo-analyzer --attribute=level,format,producer
1114 --print=symbols,types,lines
1115 --output-sort=kind
1116 pr-44884-codeview-clang.o
1117 pr-44884-codeview-msvc.o
1118 pr-44884-dwarf-clang.o
1119 pr-44884-dwarf-gcc.o
1120
1121 CodeView - Clang (Windows)
1122 Logical View:
1123 [000] {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
1124
1125 [001] {CompileUnit} 'pr-44884.cpp'
1126 [002] {Producer} 'clang version 14.0.0'
1127 [002] {Function} extern not_inlined 'bar' -> 'int'
1128 [003] {Parameter} 'Input' -> 'float'
1129 [003] 1 {Line}
1130 [002] {Function} extern not_inlined 'foo' -> 'unsigned'
1131 [003] {Block}
1132 [004] {Variable} 'Added' -> 'float'
1133 [004] 9 {Line}
1134 [004] 10 {Line}
1135 [003] {Parameter} 'Param' -> 'char'
1136 [003] {TypeAlias} 'FLOAT' -> 'float'
1137 [003] {TypeAlias} 'INT' -> 'int'
1138 [003] {Variable} 'Value' -> 'int'
1139 [003] 3 {Line}
1140 [003] 5 {Line}
1141 [003] 13 {Line}
1142
1143 CodeView - MSVC (Windows)
1144 Logical View:
1145 [000] {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
1146
1147 [001] {CompileUnit} 'pr-44884.cpp'
1148 [002] {Producer} 'Microsoft (R) Optimizing Compiler'
1149 [002] {Function} extern not_inlined 'bar' -> 'int'
1150 [003] {Variable} 'Input' -> 'float'
1151 [003] 1 {Line}
1152 [002] {Function} extern not_inlined 'foo' -> 'unsigned'
1153 [003] {Block}
1154 [004] {Block}
1155 [005] {Variable} 'Added' -> 'float'
1156 [004] {TypeAlias} 'FLOAT' -> 'float'
1157 [004] 9 {Line}
1158 [004] 10 {Line}
1159 [003] {TypeAlias} 'INT' -> 'int'
1160 [003] {Variable} 'Param' -> 'char'
1161 [003] {Variable} 'Value' -> 'int'
1162 [003] 3 {Line}
1163 [003] 5 {Line}
1164 [003] 13 {Line}
1165 [003] 14 {Line}
1166
1167 DWARF - Clang (Linux)
1168 Logical View:
1169 [000] {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
1170
1171 [001] {CompileUnit} 'pr-44884.cpp'
1172 [002] {Producer} 'clang version 14.0.0'
1173 [002] 1 {Function} extern not_inlined 'bar' -> 'int'
1174 [003] 1 {Parameter} 'Input' -> 'float'
1175 [003] 1 {Line}
1176 [003] 1 {Line}
1177 [003] 1 {Line}
1178 [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
1179 [003] {Block}
1180 [004] 9 {Variable} 'Added' -> 'FLOAT'
1181 [004] 9 {Line}
1182 [004] 9 {Line}
1183 [004] 9 {Line}
1184 [004] 9 {Line}
1185 [004] 9 {Line}
1186 [004] 10 {Line}
1187 [004] 10 {Line}
1188 [004] 10 {Line}
1189 [004] 13 {Line}
1190 [003] 3 {Parameter} 'Param' -> 'char'
1191 [003] 7 {TypeAlias} 'FLOAT' -> 'float'
1192 [003] 4 {TypeAlias} 'INT' -> 'int'
1193 [003] 5 {Variable} 'Value' -> 'INT'
1194 [003] 3 {Line}
1195 [003] 5 {Line}
1196 [003] 5 {Line}
1197 [003] 13 {Line}
1198 [003] 13 {Line}
1199 [003] 13 {Line}
1200 [003] 13 {Line}
1201
1202 DWARF - GCC (Linux)
1203 Logical View:
1204 [000] {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
1205
1206 [001] {CompileUnit} 'pr-44884.cpp'
1207 [002] {Producer} 'GNU C++14 10.2.1 20201103'
1208 [002] 1 {Function} extern not_inlined 'bar' -> 'int'
1209 [003] 1 {Parameter} 'Input' -> 'float'
1210 [003] 1 {Line}
1211 [003] 1 {Line}
1212 [003] 1 {Line}
1213 [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
1214 [003] {Block}
1215 [004] {Block}
1216 [005] 9 {Variable} 'Added' -> 'FLOAT'
1217 [005] 9 {Line}
1218 [005] 9 {Line}
1219 [005] 9 {Line}
1220 [005] 10 {Line}
1221 [005] 13 {Line}
1222 [004] 7 {TypeAlias} 'FLOAT' -> 'float'
1223 [003] 3 {Parameter} 'Param' -> 'char'
1224 [003] 4 {TypeAlias} 'INT' -> 'int'
1225 [003] 5 {Variable} 'Value' -> 'INT'
1226 [003] 3 {Line}
1227 [003] 5 {Line}
1228 [003] 13 {Line}
1229 [003] 14 {Line}
1230 [003] 14 {Line}
1231
1232 From the previous logical views, we can see that the Clang compiler
1233 emits both typedefs at the same lexical scope (3), which is wrong. GCC
1234 and MSVC emit correct lexical scope for both typedefs.
1235
1236 Using the llvm-debuginfo-analyzer selection facilities, we can produce
1237 a simple tabular output showing just the logical types that are Type‐
1238 def.
1239
1240 llvm-debuginfo-analyzer --attribute=level,format
1241 --output-sort=name
1242 --select-types=Typedef
1243 --report=list
1244 --print=types
1245 pr-44884-*.o
1246
1247 Logical View:
1248 [000] {File} 'pr-44884-codeview-clang.o' -> COFF-x86-64
1249
1250 [001] {CompileUnit} 'pr_44884.cpp'
1251 [003] {TypeAlias} 'FLOAT' -> 'float'
1252 [003] {TypeAlias} 'INT' -> 'int'
1253
1254 Logical View:
1255 [000] {File} 'pr-44884-codeview-msvc.o' -> COFF-i386
1256
1257 [001] {CompileUnit} 'pr_44884.cpp'
1258 [004] {TypeAlias} 'FLOAT' -> 'float'
1259 [003] {TypeAlias} 'INT' -> 'int'
1260
1261 Logical View:
1262 [000] {File} 'pr-44884-dwarf-clang.o' -> elf64-x86-64
1263
1264 [001] {CompileUnit} 'pr_44884.cpp'
1265 [003] 7 {TypeAlias} 'FLOAT' -> 'float'
1266 [003] 4 {TypeAlias} 'INT' -> 'int'
1267
1268 Logical View:
1269 [000] {File} 'pr-44884-dwarf-gcc.o' -> elf32-littlearm
1270
1271 [001] {CompileUnit} 'pr_44884.cpp'
1272 [004] 7 {TypeAlias} 'FLOAT' -> 'float'
1273 [003] 4 {TypeAlias} 'INT' -> 'int'
1274
1275 It also shows, that the CodeView debug information does not generate
1276 source code line numbers for the those logical types. The logical view
1277 is sorted by the types name.
1278
1279 TEST CASE 4 - MISSING NESTED ENUMERATIONS
1280 The below example is used to show different output generated by
1281 llvm-debuginfo-analyzer. We compiled the example for an X86 Codeview
1282 and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).
1283
1284 1 struct Struct {
1285 2 union Union {
1286 3 enum NestedEnum { RED, BLUE };
1287 4 };
1288 5 Union U;
1289 6 };
1290 7
1291 8 Struct S;
1292 9 int test() {
1293 10 return S.U.BLUE;
1294 11 }
1295
1296 The above test is used to illustrate a scope issue found in the Clang
1297 compiler: PR46466 (Bugs LLVM) / PR45811 (GitHub LLVM)
1298
1299 These are the logical views that llvm-debuginfo-analyzer generates for
1300 3 different compilers (MSVC, Clang and GCC), emitting different debug
1301 information formats (CodeView, DWARF) on different platforms.
1302
1303 llvm-debuginfo-analyzer --attribute=level,format,producer
1304 --output-sort=name
1305 --print=symbols,types
1306 pr-46466-codeview-clang.o
1307 pr-46466-codeview-msvc.o
1308 pr-46466-dwarf-clang.o
1309 pr-46466-dwarf-gcc.o
1310
1311 CodeView - Clang (Windows)
1312 Logical View:
1313 [000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
1314
1315 [001] {CompileUnit} 'pr-46466.cpp'
1316 [002] {Producer} 'clang version 14.0.0'
1317 [002] {Variable} extern 'S' -> 'Struct'
1318 [002] 1 {Struct} 'Struct'
1319 [003] {Member} public 'U' -> 'Union'
1320 [003] 2 {Union} 'Union'
1321 [004] 3 {Enumeration} 'NestedEnum' -> 'int'
1322 [005] {Enumerator} 'BLUE' = '0x1'
1323 [005] {Enumerator} 'RED' = '0x0'
1324
1325 CodeView - MSVC (Windows)
1326 Logical View:
1327 [000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
1328
1329 [001] {CompileUnit} 'pr-46466.cpp'
1330 [002] {Producer} 'Microsoft (R) Optimizing Compiler'
1331 [002] {Variable} extern 'S' -> 'Struct'
1332 [002] 1 {Struct} 'Struct'
1333 [003] {Member} public 'U' -> 'Union'
1334 [003] 2 {Union} 'Union'
1335 [004] 3 {Enumeration} 'NestedEnum' -> 'int'
1336 [005] {Enumerator} 'BLUE' = '0x1'
1337 [005] {Enumerator} 'RED' = '0x0'
1338
1339 DWARF - Clang (Linux)
1340 Logical View:
1341 [000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
1342
1343 [001] {CompileUnit} 'pr-46466.cpp'
1344 [002] {Producer} 'clang version 14.0.0'
1345 [002] 8 {Variable} extern 'S' -> 'Struct'
1346 [002] 1 {Struct} 'Struct'
1347 [003] 5 {Member} public 'U' -> 'Union'
1348
1349 DWARF - GCC (Linux)
1350 Logical View:
1351 [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
1352
1353 [001] {CompileUnit} 'pr-46466.cpp'
1354 [002] {Producer} 'GNU C++14 9.3.0'
1355 [002] 8 {Variable} extern 'S' -> 'Struct'
1356 [002] 1 {Struct} 'Struct'
1357 [003] 5 {Member} public 'U' -> 'Union'
1358 [003] 2 {Union} 'Union'
1359 [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
1360 [005] {Enumerator} 'BLUE' = '0x1'
1361 [005] {Enumerator} 'RED' = '0x0'
1362
1363 From the previous logical views, we can see that the DWARF debug infor‐
1364 mation generated by the Clang compiler does not include any references
1365 to the enumerators RED and BLUE. The DWARF generated by GCC, CodeView
1366 generated by Clang and MSVC, they do include such references.
1367
1368 Using the llvm-debuginfo-analyzer selection facilities, we can produce
1369 a logical view showing just the logical types that are Enumerator and
1370 its parents. The logical view is sorted by the types name.
1371
1372 llvm-debuginfo-analyzer --attribute=format,level
1373 --output-sort=name
1374 --select-types=Enumerator
1375 --report=parents
1376 --print=types
1377 pr-46466-*.o
1378
1379 Logical View:
1380 [000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
1381
1382 [001] {CompileUnit} 'pr-46466.cpp'
1383 [002] 1 {Struct} 'Struct'
1384 [003] 2 {Union} 'Union'
1385 [004] 3 {Enumeration} 'NestedEnum' -> 'int'
1386 [005] {Enumerator} 'BLUE' = '0x1'
1387 [005] {Enumerator} 'RED' = '0x0'
1388
1389 Logical View:
1390 [000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
1391
1392 [001] {CompileUnit} 'pr-46466.cpp'
1393 [002] 1 {Struct} 'Struct'
1394 [003] 2 {Union} 'Union'
1395 [004] 3 {Enumeration} 'NestedEnum' -> 'int'
1396 [005] {Enumerator} 'BLUE' = '0x1'
1397 [005] {Enumerator} 'RED' = '0x0'
1398
1399 Logical View:
1400 [000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
1401
1402 [001] {CompileUnit} 'pr-46466.cpp'
1403
1404 Logical View:
1405 [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
1406
1407 [001] {CompileUnit} 'pr-46466.cpp'
1408 [002] 1 {Struct} 'Struct'
1409 [003] 2 {Union} 'Union'
1410 [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
1411 [005] {Enumerator} 'BLUE' = '0x1'
1412 [005] {Enumerator} 'RED' = '0x0'
1413
1414 Using the llvm-debuginfo-analyzer selection facilities, we can produce
1415 a simple tabular output including a summary for the logical types that
1416 are Enumerator. The logical view is sorted by the types name.
1417
1418 llvm-debuginfo-analyzer --attribute=format,level
1419 --output-sort=name
1420 --select-types=Enumerator
1421 --print=types,summary
1422 pr-46466-*.o
1423
1424 Logical View:
1425 [000] {File} 'pr-46466-codeview-clang.o' -> COFF-x86-64
1426
1427 [001] {CompileUnit} 'pr-46466.cpp'
1428 [005] {Enumerator} 'BLUE' = '0x1'
1429 [005] {Enumerator} 'RED' = '0x0'
1430
1431 -----------------------------
1432 Element Total Found
1433 -----------------------------
1434 Scopes 5 0
1435 Symbols 2 0
1436 Types 6 2
1437 Lines 0 0
1438 -----------------------------
1439 Total 13 2
1440
1441 Logical View:
1442 [000] {File} 'pr-46466-codeview-msvc.o' -> COFF-i386
1443
1444 [001] {CompileUnit} 'pr-46466.cpp'
1445 [005] {Enumerator} 'BLUE' = '0x1'
1446 [005] {Enumerator} 'RED' = '0x0'
1447
1448 -----------------------------
1449 Element Total Found
1450 -----------------------------
1451 Scopes 5 0
1452 Symbols 2 0
1453 Types 7 2
1454 Lines 0 0
1455 -----------------------------
1456 Total 14 2
1457
1458 Logical View:
1459 [000] {File} 'pr-46466-dwarf-clang.o' -> elf64-x86-64
1460
1461 [001] {CompileUnit} 'pr-46466.cpp'
1462
1463 -----------------------------
1464 Element Total Found
1465 -----------------------------
1466 Scopes 4 0
1467 Symbols 0 0
1468 Types 0 0
1469 Lines 0 0
1470 -----------------------------
1471 Total 4 0
1472
1473 Logical View:
1474 [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
1475
1476 [001] {CompileUnit} 'pr-46466.cpp'
1477 [005] {Enumerator} 'BLUE' = '0x1'
1478 [005] {Enumerator} 'RED' = '0x0'
1479
1480 -----------------------------
1481 Element Total Found
1482 -----------------------------
1483 Scopes 5 0
1484 Symbols 0 0
1485 Types 2 2
1486 Lines 0 0
1487 -----------------------------
1488 Total 7 2
1489
1490 From the values printed under the Found column, we can see that no
1491 Types were found in the DWARF debug information generated by Clang.
1492
1493 TEST CASE 5 - INCORRECT LEXICAL SCOPE FOR VARIABLE
1494 The below example is used to show different output generated by
1495 llvm-debuginfo-analyzer. We compiled the example for an X86 Codeview
1496 and ELF targets with recent versions of Clang, GCC and MSVC (-O0 -g).
1497
1498 // definitions.h
1499 #ifdef _MSC_VER
1500 #define forceinline __forceinline
1501 #elif defined(__clang__)
1502 #if __has_attribute(__always_inline__)
1503 #define forceinline inline __attribute__((__always_inline__))
1504 #else
1505 #define forceinline inline
1506 #endif
1507 #elif defined(__GNUC__)
1508 #define forceinline inline __attribute__((__always_inline__))
1509 #else
1510 #define forceinline inline
1511 #error
1512 #endif
1513
1514 As the test is dependent on inline compiler options, the above header
1515 file defines forceinline.
1516
1517 #include "definitions.h"
1518
1519 1 #include "definitions.h"
1520 2 forceinline int InlineFunction(int Param) {
1521 3 int Var_1 = Param;
1522 4 {
1523 5 int Var_2 = Param + Var_1;
1524 6 Var_1 = Var_2;
1525 7 }
1526 8 return Var_1;
1527 9 }
1528 10
1529 11 int test(int Param_1, int Param_2) {
1530 12 int A = Param_1;
1531 13 A += InlineFunction(Param_2);
1532 14 return A;
1533 15 }
1534
1535 The above test is used to illustrate a variable issue found in the
1536 Clang compiler: PR43860 (Bugs LLVM) / PR43205 (GitHub)
1537
1538 These are the logical views that llvm-debuginfo-analyzer generates for
1539 3 different compilers (MSVC, Clang and GCC), emitting different debug
1540 information formats (CodeView, DWARF) on different platforms.
1541
1542 llvm-debuginfo-analyzer --attribute=level,format,producer
1543 --output-sort=name
1544 --print=symbols
1545 pr-43860-codeview-clang.o
1546 pr-43860-codeview-msvc.o
1547 pr-43860-dwarf-clang.o
1548 pr-43860-dwarf-gcc.o
1549
1550 CODEVIEW - Clang (Windows)
1551 Logical View:
1552 [000] {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
1553
1554 [001] {CompileUnit} 'pr-43860.cpp'
1555 [002] {Producer} 'clang version 14.0.0'
1556 [002] 2 {Function} inlined 'InlineFunction' -> 'int'
1557 [003] {Parameter} '' -> 'int'
1558 [002] {Function} extern not_inlined 'test' -> 'int'
1559 [003] {Variable} 'A' -> 'int'
1560 [003] {InlinedFunction} inlined 'InlineFunction' -> 'int'
1561 [004] {Parameter} 'Param' -> 'int'
1562 [004] {Variable} 'Var_1' -> 'int'
1563 [004] {Variable} 'Var_2' -> 'int'
1564 [003] {Parameter} 'Param_1' -> 'int'
1565 [003] {Parameter} 'Param_2' -> 'int'
1566
1567 CODEVIEW - MSVC (Windows)
1568 Logical View:
1569 [000] {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
1570
1571 [001] {CompileUnit} 'pr-43860.cpp'
1572 [002] {Producer} 'Microsoft (R) Optimizing Compiler'
1573 [002] {Function} extern not_inlined 'InlineFunction' -> 'int'
1574 [003] {Block}
1575 [004] {Variable} 'Var_2' -> 'int'
1576 [003] {Variable} 'Param' -> 'int'
1577 [003] {Variable} 'Var_1' -> 'int'
1578 [002] {Function} extern not_inlined 'test' -> 'int'
1579 [003] {Variable} 'A' -> 'int'
1580 [003] {Variable} 'Param_1' -> 'int'
1581 [003] {Variable} 'Param_2' -> 'int'
1582
1583 DWARF - Clang (Linux)
1584 Logical View:
1585 [000] {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
1586
1587 [001] {CompileUnit} 'pr-43860.cpp'
1588 [002] {Producer} 'clang version 14.0.0'
1589 [002] 2 {Function} extern inlined 'InlineFunction' -> 'int'
1590 [003] {Block}
1591 [004] 5 {Variable} 'Var_2' -> 'int'
1592 [003] 2 {Parameter} 'Param' -> 'int'
1593 [003] 3 {Variable} 'Var_1' -> 'int'
1594 [002] 11 {Function} extern not_inlined 'test' -> 'int'
1595 [003] 12 {Variable} 'A' -> 'int'
1596 [003] 14 {InlinedFunction} inlined 'InlineFunction' -> 'int'
1597 [004] {Block}
1598 [005] {Variable} 'Var_2' -> 'int'
1599 [004] {Parameter} 'Param' -> 'int'
1600 [004] {Variable} 'Var_1' -> 'int'
1601 [003] 11 {Parameter} 'Param_1' -> 'int'
1602 [003] 11 {Parameter} 'Param_2' -> 'int'
1603
1604 DWARF - GCC (Linux)
1605 Logical View:
1606 [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
1607
1608 [001] {CompileUnit} 'pr-43860.cpp'
1609 [002] {Producer} 'GNU C++14 9.3.0'
1610 [002] 2 {Function} extern declared_inlined 'InlineFunction' -> 'int'
1611 [003] {Block}
1612 [004] 5 {Variable} 'Var_2' -> 'int'
1613 [003] 2 {Parameter} 'Param' -> 'int'
1614 [003] 3 {Variable} 'Var_1' -> 'int'
1615 [002] 11 {Function} extern not_inlined 'test' -> 'int'
1616 [003] 12 {Variable} 'A' -> 'int'
1617 [003] 13 {InlinedFunction} declared_inlined 'InlineFunction' -> 'int'
1618 [004] {Block}
1619 [005] {Variable} 'Var_2' -> 'int'
1620 [004] {Parameter} 'Param' -> 'int'
1621 [004] {Variable} 'Var_1' -> 'int'
1622 [003] 11 {Parameter} 'Param_1' -> 'int'
1623 [003] 11 {Parameter} 'Param_2' -> 'int'
1624
1625 From the previous logical views, we can see that the CodeView debug in‐
1626 formation generated by the Clang compiler shows the variables Var_1 and
1627 Var_2 are at the same lexical scope (4) in the function InlineFuction.
1628 The DWARF generated by GCC/Clang and CodeView generated by MSVC, show
1629 those variables at the correct lexical scope: 3 and 4 respectively.
1630
1631 Using the llvm-debuginfo-analyzer selection facilities, we can produce
1632 a simple tabular output showing just the logical elements that have in
1633 their name the var pattern. The logical view is sorted by the variables
1634 name.
1635
1636 llvm-debuginfo-analyzer --attribute=level,format
1637 --output-sort=name
1638 --select-regex --select-nocase --select=Var
1639 --report=list
1640 --print=symbols
1641 pr-43860-*.o
1642
1643 Logical View:
1644 [000] {File} 'pr-43860-codeview-clang.o' -> COFF-x86-64
1645
1646 [001] {CompileUnit} 'pr-43860.cpp'
1647 [004] {Variable} 'Var_1' -> 'int'
1648 [004] {Variable} 'Var_2' -> 'int'
1649
1650 Logical View:
1651 [000] {File} 'pr-43860-codeview-msvc.o' -> COFF-i386
1652
1653 [001] {CompileUnit} 'pr-43860.cpp'
1654 [003] {Variable} 'Var_1' -> 'int'
1655 [004] {Variable} 'Var_2' -> 'int'
1656
1657 Logical View:
1658 [000] {File} 'pr-43860-dwarf-clang.o' -> elf64-x86-64
1659
1660 [001] {CompileUnit} 'pr-43860.cpp'
1661 [004] {Variable} 'Var_1' -> 'int'
1662 [003] 3 {Variable} 'Var_1' -> 'int'
1663 [005] {Variable} 'Var_2' -> 'int'
1664 [004] 5 {Variable} 'Var_2' -> 'int'
1665
1666 Logical View:
1667 [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
1668
1669 [001] {CompileUnit} 'pr-43860.cpp'
1670 [004] {Variable} 'Var_1' -> 'int'
1671 [003] 3 {Variable} 'Var_1' -> 'int'
1672 [005] {Variable} 'Var_2' -> 'int'
1673 [004] 5 {Variable} 'Var_2' -> 'int'
1674
1675 It also shows, that the CodeView debug information does not generate
1676 source code line numbers for the those logical symbols. The logical
1677 view is sorted by the types name.
1678
1679 TEST CASE 6 - FULL LOGICAL VIEW
1680 For advanced users, llvm-debuginfo-analyzer can display low level in‐
1681 formation that includes offsets within the debug information section,
1682 debug location operands, linkage names, etc.
1683
1684 llvm-debuginfo-analyzer --attribute=all
1685 --print=all
1686 test-dwarf-clang.o
1687
1688 Logical View:
1689 [0x0000000000][000] {File} 'test-dwarf-clang.o' -> elf64-x86-64
1690
1691 [0x000000000b][001] {CompileUnit} 'test.cpp'
1692 [0x000000000b][002] {Producer} 'clang version 12.0.0'
1693 {Directory} ''
1694 {File} 'test.cpp'
1695 {Public} 'foo' [0x0000000000:0x000000003a]
1696 [0x000000000b][002] {Range} Lines 2:9 [0x0000000000:0x000000003a]
1697 [0x00000000bc][002] {BaseType} 'bool'
1698 [0x0000000099][002] {BaseType} 'int'
1699 [0x00000000b5][002] {BaseType} 'unsigned int'
1700
1701 [0x00000000a0][002] {Source} '/test.cpp'
1702 [0x00000000a0][002] 1 {TypeAlias} 'INTPTR' -> [0x00000000ab]'* const int'
1703 [0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
1704 [0x000000002a][003] {Range} Lines 2:9 [0x0000000000:0x000000003a]
1705 [0x000000002a][003] {Linkage} 0x2 '_Z3fooPKijb'
1706 [0x0000000071][003] {Block}
1707 [0x0000000071][004] {Range} Lines 5:8 [0x000000001c:0x000000002f]
1708 [0x000000007e][004] 5 {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
1709 [0x000000007e][005] {Coverage} 100.00%
1710 [0x000000007f][005] {Location}
1711 [0x000000007f][006] {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
1712 [0x000000001c][004] 5 {Line} {NewStatement} '/test.cpp'
1713 [0x000000001c][004] {Code} 'movl $0x7, -0x1c(%rbp)'
1714 [0x0000000023][004] 6 {Line} {NewStatement} '/test.cpp'
1715 [0x0000000023][004] {Code} 'movl $0x7, -0x4(%rbp)'
1716 [0x000000002a][004] {Code} 'jmp 0x6'
1717 [0x000000002f][004] 8 {Line} {NewStatement} '/test.cpp'
1718 [0x000000002f][004] {Code} 'movl -0x14(%rbp), %eax'
1719 [0x0000000063][003] 2 {Parameter} 'ParamBool' -> [0x00000000bc]'bool'
1720 [0x0000000063][004] {Coverage} 100.00%
1721 [0x0000000064][004] {Location}
1722 [0x0000000064][005] {Entry} Stack Offset: -21 (0xffffffffffffffeb) [DW_OP_fbreg]
1723 [0x0000000047][003] 2 {Parameter} 'ParamPtr' -> [0x00000000a0]'INTPTR'
1724 [0x0000000047][004] {Coverage} 100.00%
1725 [0x0000000048][004] {Location}
1726 [0x0000000048][005] {Entry} Stack Offset: -16 (0xfffffffffffffff0) [DW_OP_fbreg]
1727 [0x0000000055][003] 2 {Parameter} 'ParamUnsigned' -> [0x00000000b5]'unsigned int'
1728 [0x0000000055][004] {Coverage} 100.00%
1729 [0x0000000056][004] {Location}
1730 [0x0000000056][005] {Entry} Stack Offset: -20 (0xffffffffffffffec) [DW_OP_fbreg]
1731 [0x000000008d][003] 4 {TypeAlias} 'INTEGER' -> [0x0000000099]'int'
1732 [0x0000000000][003] 2 {Line} {NewStatement} '/test.cpp'
1733 [0x0000000000][003] {Code} 'pushq %rbp'
1734 [0x0000000001][003] {Code} 'movq %rsp, %rbp'
1735 [0x0000000004][003] {Code} 'movb %dl, %al'
1736 [0x0000000006][003] {Code} 'movq %rdi, -0x10(%rbp)'
1737 [0x000000000a][003] {Code} 'movl %esi, -0x14(%rbp)'
1738 [0x000000000d][003] {Code} 'andb $0x1, %al'
1739 [0x000000000f][003] {Code} 'movb %al, -0x15(%rbp)'
1740 [0x0000000012][003] 3 {Line} {NewStatement} {PrologueEnd} '/test.cpp'
1741 [0x0000000012][003] {Code} 'testb $0x1, -0x15(%rbp)'
1742 [0x0000000016][003] {Code} 'je 0x13'
1743 [0x0000000032][003] 8 {Line} '/test.cpp'
1744 [0x0000000032][003] {Code} 'movl %eax, -0x4(%rbp)'
1745 [0x0000000035][003] 9 {Line} {NewStatement} '/test.cpp'
1746 [0x0000000035][003] {Code} 'movl -0x4(%rbp), %eax'
1747 [0x0000000038][003] {Code} 'popq %rbp'
1748 [0x0000000039][003] {Code} 'retq'
1749 [0x000000003a][003] 9 {Line} {NewStatement} {EndSequence} '/test.cpp'
1750
1751 -----------------------------
1752 Element Total Printed
1753 -----------------------------
1754 Scopes 3 3
1755 Symbols 4 4
1756 Types 5 5
1757 Lines 25 25
1758 -----------------------------
1759 Total 37 37
1760
1761 Scope Sizes:
1762 189 (100.00%) : [0x000000000b][001] {CompileUnit} 'test.cpp'
1763 110 ( 58.20%) : [0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
1764 27 ( 14.29%) : [0x0000000071][003] {Block}
1765
1766 Totals by lexical level:
1767 [001]: 189 (100.00%)
1768 [002]: 110 ( 58.20%)
1769 [003]: 27 ( 14.29%)
1770
1771 The Scope Sizes table shows the contribution in bytes to the debug in‐
1772 formation by each scope, which can be used to determine unexpected size
1773 changes in the DWARF sections between different versions of the same
1774 toolchain.
1775
1776 [0x000000002a][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000099]'int'
1777 [0x000000002a][003] {Range} Lines 2:9 [0x0000000000:0x000000003a]
1778 [0x000000002a][003] {Linkage} 0x2 '_Z3fooPKijb'
1779 [0x0000000071][003] {Block}
1780 [0x0000000071][004] {Range} Lines 5:8 [0x000000001c:0x000000002f]
1781 [0x000000007e][004] 5 {Variable} 'CONSTANT' -> [0x00000000c3]'const INTEGER'
1782 [0x000000007e][005] {Coverage} 100.00%
1783 [0x000000007f][005] {Location}
1784 [0x000000007f][006] {Entry} Stack Offset: -28 (0xffffffffffffffe4) [DW_OP_fbreg]
1785
1786 The {Range} attribute describe the line ranges for a logical scope.
1787 For this case, the function foo is within the lines 2 and 9.
1788
1789 The {Coverage} and {Location} attributes describe the debug location
1790 and coverage for logical symbols. For optimized code, the coverage
1791 value decreases and it affects the program debuggability.
1792
1794 llvm-debuginfo-analyzer returns 0 if the input files were parsed and
1795 printed successfully. Otherwise, it returns 1.
1796
1798 llvm-dwarfdump
1799
1801 Maintained by the LLVM Team (https://llvm.org/).
1802
1804 2003-2023, LLVM Project
1805
1806
1807
1808
180916 2023-07-20 LLVM-DEBUGINFO-ANALYZER(1)