Author: Jonas Devlieghere Date: 2022-01-27T19:35:28-08:00 New Revision: 4a64955c37570ef5f98db705d290d75adbeaf442
URL: https://github.com/llvm/llvm-project/commit/4a64955c37570ef5f98db705d290d75adbeaf442 DIFF: https://github.com/llvm/llvm-project/commit/4a64955c37570ef5f98db705d290d75adbeaf442.diff LOG: [lldb] Remove reproducers documentation Added: Modified: lldb/docs/index.rst Removed: lldb/docs/design/reproducers.rst ################################################################################ diff --git a/lldb/docs/design/reproducers.rst b/lldb/docs/design/reproducers.rst deleted file mode 100644 index cac8721196d3e..0000000000000 --- a/lldb/docs/design/reproducers.rst +++ /dev/null @@ -1,205 +0,0 @@ -Reproducers -=========== - -As unbelievable as it may sound, the debugger has bugs. These bugs might -manifest themselves as errors, missing results or even a crash. Quite often -these bugs don't reproduce in simple, isolated scenarios. The debugger deals -with a lot of moving parts and subtle diff erences can easily add up. - -Reproducers in LLDB improve the experience for both the users encountering bugs -and the developers working on resolving them. The general idea consists of -*capturing* all the information necessary to later *replay* a debug session -while debugging the debugger. - -.. contents:: - :local: - -Usage ------ - -Reproducers are a generic concept in LLDB and are not inherently coupled with -the command line driver. The functionality can be used for anything that uses -the SB API and the driver is just one example. However, because it's probably -the most common way users interact with lldb, that's the workflow described in -this section. - -Capture -``````` - -Until reproducer capture is enabled by default, you need to launch LLDB in -capture mode. For the command line driver, this means passing ``--capture``. -You cannot enable reproducer capture from within LLDB, as this would be too -late to capture initialization of the debugger. - -.. code-block:: bash - - $ lldb --capture - -In capture mode, LLDB will keep track of all the information it needs to replay -the current debug session. Most data is captured lazily to limit the impact on -performance. To create the reproducer, use the ``reproducer generate`` -sub-command. It's always possible to check the status of the reproducers with -the ``reproducer status`` sub-command. Note that generating the reproducer -terminates the debug session. - -.. code-block:: none - - (lldb) reproducer status - Reproducer is in capture mode. - (lldb) reproducer generate - Reproducer written to '/path/to/reproducer' - Please have a look at the directory to assess if you're willing to share the contained information. - - -The resulting reproducer is a directory. It was a conscious decision to not -compress and archive it automatically. The reproducer can contain potentially -sensitive information like object and symbol files, their paths on disk, debug -information, memory excerpts of the inferior process, etc. - -Replay -`````` - -It is strongly recommended to replay the reproducer locally to ensure it -actually reproduces the expected behavior. If the reproducer doesn't behave -correctly locally, it means there's a bug in the reproducer implementation that -should be addressed. - -To replay a reproducer, simply pass its path to LLDB through the ``--replay`` -flag. It is unnecessary to pass any other command line flags. The flags that -were passed to LLDB during capture are already part of the reproducer. - -.. code-block:: bash - - $ lldb --replay /path/to/reproducer - - -During replay LLDB will behave similar to batch mode. The session should be -identical to the recorded debug session. The only expected diff erences are that -the binary being debugged doesn't actually run during replay. That means that -you won't see any of its side effects, like things being printed to the -terminal. Another expected diff erence is the behavior of the ``reproducer -generate`` command, which becomes a NOOP during replay. - -Augmenting a Bug Report with a Reproducer -````````````````````````````````````````` - -A reproducer can significantly improve a bug report, but it in itself is not -sufficient. Always describe the expected and unexpected behavior. Just like the -debugger can have bugs, the reproducer can have bugs too. - - -Design ------- - - -Replay -`````` - -Reproducers support two replay modes. The main and most common mode is active -replay. It's called active, because it's LLDB that is driving replay by calling -the captured SB API functions one after each other. The second mode is passive -replay. In this mode, LLDB sits idle until an SB API function is called, for -example from Python, and then replays just this individual call. - -Active Replay -^^^^^^^^^^^^^ - -No matter how a reproducer was captured, they can always be replayed with the -command line driver. When a reproducer is passed with the ``--replay`` flag, the -driver short-circuits and passes off control to the reproducer infrastructure, -effectively bypassing its normal operation. This works because the driver is -implemented using the SB API and is therefore nothing more than a sequence of -SB API calls. - -Replay is driven by the ``Registry::Replay``. As long as there's data in the -buffer holding the API data, the next SB API function call is deserialized. -Once the function is known, the registry can retrieve its signature, and use -that to deserialize its arguments. The function can then be invoked, most -commonly through the synthesized default replayer, or potentially using a -custom defined replay function. This process continues, until more data is -available or a replay error is encountered. - -During replay only a function's side effects matter. The result returned by the -replayed function is ignored because it cannot be observed beyond the driver. -This is sound, because anything that is passed into a subsequent API call will -have been serialized as an input argument. This also works for SB API objects -because the reproducers know about every object that has crossed the API -boundary, which is true by definition for object return values. - - -Passive Replay -^^^^^^^^^^^^^^ - -Passive replay exists to support running the API test suite against a -reproducer. The API test suite is written in Python and tests the debugger by -calling into its API from Python. To make this work, the API must transparently -replay itself when called. This is what makes passive replay diff erent from -driver replay, where it is lldb itself that's driving replay. For passive -replay, the driving factor is external. - -In order to replay API calls, the reproducers need a way to intercept them. -Every API call is already instrumented with an ``LLDB_RECORD_*`` macro that -captures its input arguments. Furthermore, it also contains the necessary logic -to detect which calls cross the API boundary and should be intercepted. We were -able to reuse all of this to implement passive replay. - -During passive replay is enabled, nothing happens until an SB API is called. -Inside that API function, the macro detects whether this call should be -replayed (i.e. crossed the API boundary). If the answer is yes, the next -function is deserialized from the SB API data and compared to the current -function. If the signature matches, we deserialize its input arguments and -reinvoke the current function with the deserialized arguments. We don't need to -do anything special to prevent us from recursively calling the replayed version -again, as the API boundary crossing logic knows that we're still behind the API -boundary when we re-invoked the current function. - -Another big diff erence with driver replay is the return value. While this -didn't matter for driver replay, it's key for passive replay, because that's -what gets checked by the test suite. Luckily, the ``LLDB_RECORD_*`` macros -contained sufficient type information to derive the result type. - -Testing -------- - -Reproducers are tested in the following ways: - - - Unit tests to cover the reproducer infrastructure. There are tests for the - provider, loader and for the reproducer instrumentation. - - Feature specific end-to-end test cases in the ``test/Shell/Reproducer`` - directory. These tests serve as integration and regression tests for the - reproducers infrastructure, as well as doing some sanity checking for basic - debugger functionality. - - The API and shell tests can be run against a replayed reproducer. The - ``check-lldb-reproducers`` target will run the API and shell test suite - twice: first running the test normally while capturing a reproducer and then - a second time using the replayed session as the test input. For the shell - tests this use a little shim (``lldb-repro``) that uses the arguments and - current working directory to transparently generate or replay a reproducer. - For the API tests an extra argument with the reproducer path is passed to - ``dotest.py`` which initializes the debugger in the appropriate mode. - Certain tests do not fit this paradigm (for example test that check the - output of the binary being debugged) and are skipped by marking them as - unsupported by adding ``UNSUPPORTED: lldb-repro`` to the top of the shell - test or adding the ``skipIfReproducer`` decorator for the API tests. - -Knows Issues ------------- - -The reproducers are still a work in progress. Here's a non-exhaustive list of -outstanding work, limitations and known issues. - - - The VFS cannot deal with more than one current working directory. Changing - the current working directory during the debug session will break relative - paths. - - Not all SB APIs are properly instrumented. We need customer serialization - for APIs that take buffers and lengths. - - We leak memory during replay because the reproducer doesn't capture the end - of an object's life time. We need to add instrumentation to the destructor - of SB API objects. - - The reproducer includes every file opened by LLDB. This is overkill. For - example we do not need to capture source files for code listings. There's - currently no way to say that some file shouldn't be included in the - reproducer. - - We do not yet automatically generate a reproducer on a crash. The reason is - that generating the reproducer is too expensive to do in a signal handler. - We should re-invoke lldb after a crash and do the heavy lifting. diff --git a/lldb/docs/index.rst b/lldb/docs/index.rst index 24643ce8bc024..e189c432c4fef 100644 --- a/lldb/docs/index.rst +++ b/lldb/docs/index.rst @@ -158,7 +158,6 @@ interesting areas to contribute to lldb. :caption: Design design/overview - design/reproducers design/sbapi .. toctree:: _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits