[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / lldb / docs / design / reproducers.rst
blobcac8721196d3e79fec8437152a5e3aebe13841b1
1 Reproducers
2 ===========
4 As unbelievable as it may sound, the debugger has bugs. These bugs might
5 manifest themselves as errors, missing results or even a crash. Quite often
6 these bugs don't reproduce in simple, isolated scenarios. The debugger deals
7 with a lot of moving parts and subtle differences can easily add up.
9 Reproducers in LLDB improve the experience for both the users encountering bugs
10 and the developers working on resolving them. The general idea consists of
11 *capturing* all the information necessary to later *replay* a debug session
12 while debugging the debugger.
14 .. contents::
15    :local:
17 Usage
18 -----
20 Reproducers are a generic concept in LLDB and are not inherently coupled with
21 the command line driver. The functionality can be used for anything that uses
22 the SB API and the driver is just one example. However, because it's probably
23 the most common way users interact with lldb, that's the workflow described in
24 this section.
26 Capture
27 ```````
29 Until reproducer capture is enabled by default, you need to launch LLDB in
30 capture mode. For the command line driver, this means passing ``--capture``.
31 You cannot enable reproducer capture from within LLDB, as this would be too
32 late to capture initialization of the debugger.
34 .. code-block:: bash
36   $ lldb --capture
38 In capture mode, LLDB will keep track of all the information it needs to replay
39 the current debug session. Most data is captured lazily to limit the impact on
40 performance. To create the reproducer, use the ``reproducer generate``
41 sub-command. It's always possible to check the status of the reproducers with
42 the ``reproducer status`` sub-command. Note that generating the reproducer
43 terminates the debug session.
45 .. code-block:: none
47   (lldb) reproducer status
48   Reproducer is in capture mode.
49   (lldb) reproducer generate
50   Reproducer written to '/path/to/reproducer'
51   Please have a look at the directory to assess if you're willing to share the contained information.
54 The resulting reproducer is a directory. It was a conscious decision to not
55 compress and archive it automatically. The reproducer can contain potentially
56 sensitive information like object and symbol files, their paths on disk, debug
57 information, memory excerpts of the inferior process, etc.
59 Replay
60 ``````
62 It is strongly recommended to replay the reproducer locally to ensure it
63 actually reproduces the expected behavior. If the reproducer doesn't behave
64 correctly locally, it means there's a bug in the reproducer implementation that
65 should be addressed.
67 To replay a reproducer, simply pass its path to LLDB through the ``--replay``
68 flag. It is unnecessary to pass any other command line flags. The flags that
69 were passed to LLDB during capture are already part of the reproducer.
71 .. code-block:: bash
73   $ lldb --replay /path/to/reproducer
76 During replay LLDB will behave similar to batch mode. The session should be
77 identical to the recorded debug session. The only expected differences are that
78 the binary being debugged doesn't actually run during replay. That means that
79 you won't see any of its side effects, like things being printed to the
80 terminal. Another expected difference is the behavior of the ``reproducer
81 generate`` command, which becomes a NOOP during replay.
83 Augmenting a Bug Report with a Reproducer
84 `````````````````````````````````````````
86 A reproducer can significantly improve a bug report, but it in itself is not
87 sufficient. Always describe the expected and unexpected behavior. Just like the
88 debugger can have bugs, the reproducer can have bugs too.
91 Design
92 ------
95 Replay
96 ``````
98 Reproducers support two replay modes. The main and most common mode is active
99 replay. It's called active, because it's LLDB that is driving replay by calling
100 the captured SB API functions one after each other. The second mode is passive
101 replay. In this mode, LLDB sits idle until an SB API function is called, for
102 example from Python, and then replays just this individual call.
104 Active Replay
105 ^^^^^^^^^^^^^
107 No matter how a reproducer was captured, they can always be replayed with the
108 command line driver. When a reproducer is passed with the ``--replay`` flag, the
109 driver short-circuits and passes off control to the reproducer infrastructure,
110 effectively bypassing its normal operation. This works because the driver is
111 implemented using the SB API and is therefore nothing more than a sequence of
112 SB API calls.
114 Replay is driven by the ``Registry::Replay``. As long as there's data in the
115 buffer holding the API data, the next SB API function call is deserialized.
116 Once the function is known, the registry can retrieve its signature, and use
117 that to deserialize its arguments. The function can then be invoked, most
118 commonly through the synthesized default replayer, or potentially using a
119 custom defined replay function. This process continues, until more data is
120 available or a replay error is encountered.
122 During replay only a function's side effects matter. The result returned by the
123 replayed function is ignored because it cannot be observed beyond the driver.
124 This is sound, because anything that is passed into a subsequent API call will
125 have been serialized as an input argument. This also works for SB API objects
126 because the reproducers know about every object that has crossed the API
127 boundary, which is true by definition for object return values.
130 Passive Replay
131 ^^^^^^^^^^^^^^
133 Passive replay exists to support running the API test suite against a
134 reproducer. The API test suite is written in Python and tests the debugger by
135 calling into its API from Python. To make this work, the API must transparently
136 replay itself when called. This is what makes passive replay different from
137 driver replay, where it is lldb itself that's driving replay. For passive
138 replay, the driving factor is external.
140 In order to replay API calls, the reproducers need a way to intercept them.
141 Every API call is already instrumented with an ``LLDB_RECORD_*`` macro that
142 captures its input arguments. Furthermore, it also contains the necessary logic
143 to detect which calls cross the API boundary and should be intercepted. We were
144 able to reuse all of this to implement passive replay.
146 During passive replay is enabled, nothing happens until an SB API is called.
147 Inside that API function, the macro detects whether this call should be
148 replayed (i.e. crossed the API boundary). If the answer is yes, the next
149 function is deserialized from the SB API data and compared to the current
150 function. If the signature matches, we deserialize its input arguments and
151 reinvoke the current function with the deserialized arguments. We don't need to
152 do anything special to prevent us from recursively calling the replayed version
153 again, as the API boundary crossing logic knows that we're still behind the API
154 boundary when we re-invoked the current function.
156 Another big difference with driver replay is the return value. While this
157 didn't matter for driver replay, it's key for passive replay, because that's
158 what gets checked by the test suite. Luckily, the ``LLDB_RECORD_*`` macros
159 contained sufficient type information to derive the result type.
161 Testing
162 -------
164 Reproducers are tested in the following ways:
166  - Unit tests to cover the reproducer infrastructure. There are tests for the
167    provider, loader and for the reproducer instrumentation.
168  - Feature specific end-to-end test cases in the ``test/Shell/Reproducer``
169    directory. These tests serve as integration and regression tests for the
170    reproducers infrastructure, as well as doing some sanity checking for basic
171    debugger functionality.
172  - The API and shell tests can be run against a replayed reproducer. The
173    ``check-lldb-reproducers`` target will run the API and shell test suite
174    twice: first running the test normally while capturing a reproducer and then
175    a second time using the replayed session as the test input. For the shell
176    tests this use a little shim (``lldb-repro``) that uses the arguments and
177    current working directory to transparently generate or replay a reproducer.
178    For the API tests an extra argument with the reproducer path is passed to
179    ``dotest.py`` which initializes the debugger in the appropriate mode.
180    Certain tests do not fit this paradigm (for example test that check the
181    output of the binary being debugged) and are skipped by marking them as
182    unsupported by adding ``UNSUPPORTED: lldb-repro`` to the top of the shell
183    test or adding the ``skipIfReproducer`` decorator for the API tests.
185 Knows Issues
186 ------------
188 The reproducers are still a work in progress. Here's a non-exhaustive list of
189 outstanding work, limitations and known issues.
191  - The VFS cannot deal with more than one current working directory. Changing
192    the current working directory during the debug session will break relative
193    paths.
194  - Not all SB APIs are properly instrumented. We need customer serialization
195    for APIs that take buffers and lengths.
196  - We leak memory during replay because the reproducer doesn't capture the end
197    of an object's life time. We need to add instrumentation to the destructor
198    of SB API objects.
199  - The reproducer includes every file opened by LLDB. This is overkill. For
200    example we do not need to capture source files for code listings. There's
201    currently no way to say that some file shouldn't be included in the
202    reproducer.
203  - We do not yet automatically generate a reproducer on a crash. The reason is
204    that generating the reproducer is too expensive to do in a signal handler.
205    We should re-invoke lldb after a crash and do the heavy lifting.