122 lines · plain
1==============2Debugging LLVM3==============4 5This document is a collection of tips and tricks for debugging LLVM6using a source-level debugger. The assumption is that you are trying to7figure out the root cause of a miscompilation in the program that you8are compiling.9 10Extract and rerun the compile command11=====================================12 13Extract the Clang command that produces the buggy code. The way to do14this depends on the build system used by your program.15 16- For Ninja-based build systems, you can pass ``-t commands`` to Ninja17 and filter the output by the targeted source file name. For example:18 ``ninja -t commands myprogram | grep path/to/file.cpp``.19 20- For Bazel-based build systems using Bazel 9 or newer (not released yet21 as of this writing), you can pass ``--output=commands`` to the ``bazel22 aquery`` subcommand for a similar result. For example: ``bazel aquery23 --output=commands 'deps(//myprogram)' | grep path/to/file.cpp``. Build24 commands must generally be run from a subdirectory of the source25 directory named ``bazel-$PROJECTNAME``. Bazel typically makes the target26 paths of ``-o`` and ``-MF`` read-only when running commands outside27 of a build, so it may be necessary to change or remove these flags.28 29- A method that should work with any build system is to build your program30 under `Bear <https://github.com/rizsotto/Bear>`_ and look for the31 compile command in the resulting ``compile_commands.json`` file.32 33Once you have the command you can use the following steps to debug34it. Note that any flags mentioned later in this document are LLVM flags35so they must be prefixed with ``-mllvm`` when passed to the Clang driver,36e.g. ``-mllvm -print-after-all``.37 38Understanding the source of the issue39=====================================40 41If you have a miscompilation introduced by a pass, it is42frequently possible to identify the pass where things go wrong43by searching a pass-by-pass printout, which is enabled using the44``-print-after-all`` flag. Pipe stderr into ``less`` (append ``2>&1 |45less`` to command line) and use text search to move between passes46(e.g. type ``/Dump After<Enter>``, ``n`` to move to next pass,47``N`` to move to previous pass). If the name of the function48containing the buggy IR is known, you can filter the output by passing49``-filter-print-funcs=functionname``. You can sometimes pass ``-debug`` to50get useful details about what passes are doing. See also `PrintPasses.cpp51<https://github.com/llvm/llvm-project/blob/main/llvm/lib/IR/PrintPasses.cpp>`_52for more useful options.53 54Creating a debug build of LLVM55==============================56 57The subsequent debugging steps require a debug build of LLVM. Pass the58``-DCMAKE_BUILD_TYPE=Debug`` to CMake in a separate build tree to create59a debug build.60 61Understanding where an instruction came from62============================================63 64A common debugging task involves understanding which part of the code65introduced a buggy instruction. The pass-by-pass dump is sometimes enough,66but for complex or unfamiliar passes, more information is often required.67 68The first step is to record a run of the debug build of Clang under `rr69<https://rr-project.org>`_ passing the LLVM flag ``-print-inst-addrs``70together with ``-print-after-all`` and any desired filters. This will71cause each instruction printed by LLVM to be suffixed with a comment72showing the address of the ``Instruction`` object. You can then replay73the run of Clang with ``rr replay``. Because ``rr`` is deterministic,74the instruction will receive the same address during the replay, so75you can break on the instruction's construction using a conditional76breakpoint that checks for the address printed by LLVM, with commands77such as the following:78 79.. code-block:: text80 81 b Instruction::Instruction if this == 0x1234567882 83When the breakpoint is hit, you will likely be at the location where84the instruction was created, so you can unwind the stack with ``bt``85to see the stack trace. It is also possible that an instruction was86created multiple times at the same address, so you may need to continue87until reaching the desired location, but in the author's experience this88is unlikely to occur.89 90Identifying the source locations of instructions91================================================92 93To identify the source location that caused a particular instruction94to be created, you can pass the LLVM flag ``-print-inst-debug-locs``95and each instruction printed by LLVM is suffixed with the file and line96number of the instruction according to the debug information. Note that97this requires debug information to be enabled (e.g. pass ``-g`` to Clang).98 99LLDB Data Formatters100====================101 102A handful of `LLDB data formatters103<https://lldb.llvm.org/resources/dataformatters.html>`__ are104provided for some of the core LLVM libraries. To use them, execute the105following (or add it to your ``~/.lldbinit``)::106 107 command script import /path/to/llvm/utils/lldbDataFormatters.py108 109GDB pretty printers110===================111 112A handful of `GDB pretty printers113<https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html>`__ are114provided for some of the core LLVM libraries. To use them, execute the115following (or add it to your ``~/.gdbinit``)::116 117 source /path/to/llvm/utils/gdb-scripts/prettyprinters.py118 119It also might be handy to enable the `print pretty120<https://sourceware.org/gdb/current/onlinedocs/gdb.html/Print-Settings.html>`__121option to avoid data structures being printed as a big block of text.122