[llvm] [llvm-debuginfo-analyzer] Add support for WebAssembly binary format. (PR #82588)
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 11 21:47:26 PDT 2024
================
@@ -1952,6 +1953,315 @@ The **{Coverage}** and **{Location}** attributes describe the debug
location and coverage for logical symbols. For optimized code, the
coverage value decreases and it affects the program debuggability.
+WEBASSEMBLY SUPPORT
+~~~~~~~~~~~~~~~~~~~
+The below example is used to show the WebAssembly output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for a
+WebAssembly 32-bit target with Clang (-O0 -g --target=wasm32):
+
+.. code-block:: c++
+
+ 1 using INTPTR = const int *;
+ 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+ 3 if (ParamBool) {
+ 4 typedef int INTEGER;
+ 5 const INTEGER CONSTANT = 7;
+ 6 return CONSTANT;
+ 7 }
+ 8 return ParamUnsigned;
+ 9 }
+
+PRINT BASIC DETAILS
+^^^^^^^^^^^^^^^^^^^
+The following command prints basic details for all the logical elements
+sorted by the debug information internal offset; it includes its lexical
+level and debug info format.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level,format
+ --output-sort=offset
+ --print=scopes,symbols,types,lines,instructions
+ test-clang.wasm
+
+or
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level,format
+ --output-sort=offset
+ --print=elements
+ test-clang.wasm
+
+Each row represents an element that is present within the debug
+information. The first column represents the scope level, followed by
+the associated line number (if any), and finally the description of
+the element.
+
+.. code-block:: none
+
+ Logical View:
+ [000] {File} 'test-clang.wasm' -> WASM
+
+ [001] {CompileUnit} 'test.cpp'
+ [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+ [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+ [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+ [003] 2 {Parameter} 'ParamBool' -> 'bool'
+ [003] {Block}
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+ [004] 5 {Line}
+ [004] {Code} 'i32.const 7'
+ [004] {Code} 'local.set 10'
+ [004] {Code} 'local.get 5'
+ [004] {Code} 'local.get 10'
+ [004] {Code} 'i32.store 12'
+ [004] 6 {Line}
+ [004] {Code} 'i32.const 7'
+ [004] {Code} 'local.set 11'
+ [004] {Code} 'local.get 5'
+ [004] {Code} 'local.get 11'
+ [004] {Code} 'i32.store 28'
+ [004] {Code} 'br 1'
+ [004] - {Line}
+ [004] {Code} 'end'
+ [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [003] 2 {Line}
+ [003] {Code} 'nop'
+ [003] {Code} 'end'
+ [003] {Code} 'i64.div_s'
+ [003] {Code} 'global.get 0'
+ [003] {Code} 'local.set 3'
+ [003] {Code} 'i32.const 32'
+ [003] {Code} 'local.set 4'
+ [003] {Code} 'local.get 3'
+ [003] {Code} 'local.get 4'
+ [003] {Code} 'i32.sub'
+ [003] {Code} 'local.set 5'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 0'
+ [003] {Code} 'i32.store 24'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 1'
+ [003] {Code} 'i32.store 20'
+ [003] {Code} 'local.get 2'
+ [003] {Code} 'local.set 6'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 6'
+ [003] {Code} 'i32.store8 19'
+ [003] 3 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load8_u 19'
+ [003] {Code} 'local.set 7'
+ [003] 3 {Line}
+ [003] {Code} 'i32.const 1'
+ [003] {Code} 'local.set 8'
+ [003] {Code} 'local.get 7'
+ [003] {Code} 'local.get 8'
+ [003] {Code} 'i32.and'
+ [003] {Code} 'local.set 9'
+ [003] {Code} 'block'
+ [003] {Code} 'block'
+ [003] {Code} 'local.get 9'
+ [003] {Code} 'i32.eqz'
+ [003] {Code} 'br_if 0'
+ [003] 8 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load 20'
+ [003] {Code} 'local.set 12'
+ [003] 8 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 12'
+ [003] {Code} 'i32.store 28'
+ [003] - {Line}
+ [003] {Code} 'end'
+ [003] 9 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load 28'
+ [003] {Code} 'local.set 13'
+ [003] {Code} 'local.get 13'
+ [003] {Code} 'return'
+ [003] {Code} 'end'
+ [003] 9 {Line}
+ [003] {Code} 'unreachable'
+ [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
+
+SELECT LOGICAL ELEMENTS
+^^^^^^^^^^^^^^^^^^^^^^^
+The following prints all *instructions*, *symbols* and *types* that
+contain **'block'** or **'.store'** in their names or types, using a tab
+layout and given the number of matches.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --select-nocase --select-regex
+ --select=BLOCK --select=.store
+ --report=list
+ --print=symbols,types,instructions,summary
+ test-clang.wasm
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [003] {Code} 'block'
+ [003] {Code} 'block'
+ [004] {Code} 'i32.store 12'
+ [003] {Code} 'i32.store 20'
+ [003] {Code} 'i32.store 24'
+ [004] {Code} 'i32.store 28'
+ [003] {Code} 'i32.store 28'
+ [003] {Code} 'i32.store8 19'
+
+ -----------------------------
+ Element Total Printed
+ -----------------------------
+ Scopes 3 0
+ Symbols 4 0
+ Types 2 0
+ Lines 62 8
+ -----------------------------
+ Total 71 8
+
+COMPARISON MODE
+^^^^^^^^^^^^^^^
+Given the previous example we found the above debug information issue
+(related to the previous invalid scope location for the **'typedef int
+INTEGER'**) by comparing against another compiler.
+
+Using GCC to generate test-dwarf-gcc.o, we can apply a selection pattern
+with the printing mode to obtain the following logical view output.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --select-regex --select-nocase --select=INTe
+ --report=list
+ --print=symbols,types
+ test-clang.wasm test-dwarf-gcc.o
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+
+ Logical View:
+ [000] {File} 'test-dwarf-gcc.o'
+
+ [001] {CompileUnit} 'test.cpp'
+ [004] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+
+The output shows that both objects contain the same elements. But the
+**'typedef INTEGER'** is located at different scope level. The GCC
+generated object, shows **'4'**, which is the correct value.
+
+There are 2 comparison methods: logical view and logical elements.
+
+LOGICAL VIEW
+""""""""""""
+It compares the logical view as a whole unit; for a match, each compared
+logical element must have the same parents and children.
+
+The output shows in view form the **missing (-), added (+)** elements,
+giving more context by swapping the reference and target object files.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=view
+ --print=symbols,types
+ test-clang.wasm test-dwarf-gcc.o
+
+ Reference: 'test-clang.wasm'
+ Target: 'test-dwarf-gcc.o'
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
+ [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+ [003] {Block}
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+ +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [003] 2 {Parameter} 'ParamBool' -> 'bool'
+ [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+ [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+ -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+The output shows the merging view path (reference and target) with the
+missing and added elements.
+
+LOGICAL ELEMENTS
+""""""""""""""""
+It compares individual logical elements without considering if their
+parents are the same. For both comparison methods, the equal criteria
+includes the name, source code location, type, lexical scope level.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=list
+ --print=symbols,types,summary
+ test-clang.wasm test-dwarf-gcc.o
+
+ Reference: 'test-clang.wasm'
+ Target: 'test-dwarf-gcc.o'
+
+ (1) Missing Types:
+ -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ (1) Added Types:
+ +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ ----------------------------------------
+ Element Expected Missing Added
+ ----------------------------------------
+ Scopes 4 0 0
+ Symbols 0 0 0
+ Types 2 1 1
+ Lines 0 0 0
+ ----------------------------------------
+ Total 6 1 1
+
+Changing the *Reference* and *Target* order:
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=list
+ --print=symbols,types,summary
+ test-dwarf-gcc.o test-clang.wasm
+
+ Reference: 'test-dwarf-gcc.o'
+ Target: 'test-clang.wasm'
+
+ (1) Missing Types:
+ -[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ (1) Added Types:
+ +[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ ----------------------------------------
+ Element Expected Missing Added
+ ----------------------------------------
+ Scopes 4 0 0
+ Symbols 0 0 0
+ Types 2 1 1
+ Lines 0 0 0
+ ----------------------------------------
+ Total 6 1 1
----------------
aheejin wrote:
The table looks the same as the previous one after the reference and the target switched. Is that correct?
https://github.com/llvm/llvm-project/pull/82588
More information about the llvm-commits
mailing list