Testing LLDB using QEMU
=======================

QEMU system mode emulation
--------------------------

QEMU can be used to test LLDB in an emulation environment in the absence of
actual hardware. This page describes instructions to help setup a QEMU emulation
environment for testing LLDB.

The scripts under llvm-project/lldb/scripts/lldb-test-qemu can quickly help
setup a virtual LLDB testing environment using QEMU. The scripts currently work
with Arm or AArch64, but support for other architectures can be added easily.

* **setup.sh** is used to build the Linux kernel image and QEMU system emulation executable(s) from source.
* **rootfs.sh** is used to generate Ubuntu root file system images to be used for QEMU system mode emulation.
* **run-qemu.sh** utilizes QEMU to boot a Linux kernel image with a root file system image.

Once we have booted our kernel we can run lldb-server in emulation environment.
Ubuntu Bionic/Focal x86_64 host was used to test these scripts instructions in this
document. Please update it according to your host distribution/architecture.

.. note::
  Instructions on this page and QEMU helper scripts are verified on a Ubuntu Bionic/Focal (x86_64) host. Moreover, scripts require sudo/root permissions for installing dependencies and setting up QEMU host/guest network.

Given below are some examples of common use-cases of LLDB QEMU testing
helper scripts:

Create Ubuntu root file system image for QEMU system emulation with rootfs.sh
--------------------------------------------------------------------------------

**Example:** generate Ubuntu Bionic (armhf) rootfs image of size 1 GB
::

  $ bash rootfs.sh --arch armhf --distro bionic --size 1G

**Example:** generate Ubuntu Focal (arm64) rootfs image of size 2 GB
::

  $ bash rootfs.sh --arch arm64 --distro focal --size 2G

rootfs.sh has been tested for generating Ubuntu Bionic and Focal images but they can be used to generate rootfs images of other Debian Linux distribution.

rootfs.sh defaults username of generated image to your current username on host computer.


Build QEMU or cross compile Linux kernel from source using setup.sh
-----------------------------------------------------------------------

**Example:** Build QEMU binaries and Arm/AArch64 Linux kernel image
::

$ bash setup.sh --qemu --kernel arm
$ bash setup.sh --qemu --kernel arm64

**Example:** Build Linux kernel image only
::

$ bash setup.sh --kernel arm
$ bash setup.sh --kernel arm64

**Example:** Build qemu-system-arm and qemu-system-aarch64 binaries.
::

$ bash setup.sh --qemu

**Example:** Remove qemu.git, linux.git and linux.build from working directory
::

$ bash setup.sh --clean


Run QEMU Arm or AArch64 system emulation using run-qemu.sh
----------------------------------------------------------
run-qemu.sh has following dependencies:

* Follow https://wiki.qemu.org/Documentation/Networking/NAT and set up bridge
  networking for QEMU.

* Make sure /etc/qemu-ifup script is available with executable permissions.

* QEMU binaries must be built from source using setup.sh or provided via --qemu
  commandline argument.

* Linux kernel image must be built from source using setup.sh or provided via
  --kernel commandline argument.

* linux.build and qemu.git folder must be present in current directory if
  setup.sh was used to build Linux kernel and QEMU binaries.

* --sve option will enable AArch64 SVE mode.

* --sme option will enable AArch64 SME mode (SME requires SVE, so this will also
  be enabled).

* --mte option will enable AArch64 MTE (memory tagging) mode
  (can be used on its own or in addition to --sve).


**Example:** Run QEMU Arm or AArch64 system emulation using run-qemu.sh
::

  $ sudo bash run-qemu.sh --arch arm --rootfs <path of rootfs image>
  $ sudo bash run-qemu.sh --arch arm64 --rootfs <path of rootfs image>

**Example:** Run QEMU with kernel image and qemu binary provided using commandline
::

  $ sudo bash run-qemu.sh --arch arm64 --rootfs <path of rootfs image> \
  --kernel <path of Linux kernel image> --qemu <path of QEMU binary>


Steps for running lldb-server in QEMU system emulation environment
------------------------------------------------------------------

Using Bridge Networking
***********************

* Make sure bridge networking is enabled between host machine and QEMU VM

* Find out ip address assigned to eth0 in emulation environment

* Setup ssh access between host machine and emulation environment

* Login emulation environment and install dependencies

::

  $ sudo apt install python-dev libedit-dev libncurses5-dev libexpat1-dev

* Cross compile LLDB server for AArch64 Linux: Please visit https://lldb.llvm.org/resources/build.html for instructions on how to cross compile LLDB server.

* Transfer LLDB server executable to emulation environment

::

  $ scp lldb-server username@ip-address-of-emulation-environment:/home/username

* Run lldb-server inside QEMU VM

* Try connecting to lldb-server running inside QEMU VM with selected ip:port

Without Bridge Networking
*************************

Without bridge networking you will have to forward individual ports from the VM
to the host (refer to QEMU's manuals for the specific options).

* At least one to connect to the initial ``lldb-server``.
* One more if you want to use ``lldb-server`` in ``platform mode``, and have it
  start a ``gdbserver`` instance for you.

If you are doing either of the latter 2 you should also restrict what ports
``lldb-server tries`` to use, otherwise it will randomly pick one that is almost
certainly not forwarded. An example of this is shown below.

::

  $ lldb-server platform --server --listen 0.0.0.0:54321 --gdbserver-port 49140

The result of this is that:

* ``lldb-server`` platform mode listens externally on port ``54321``.

* When it is asked to start a new gdbserver mode instance, it will use the port
  ``49140``.

Your VM configuration should have ports ``54321`` and ``49140`` forwarded for
this to work.

QEMU user mode emulation
------------------------

Serious testing of LLDB should be done using system mode emulation. The following
is presented for information only and is not a supported testing configuration
supported by the LLDB project.

However, it is possible to run the test suite against user mode QEMU if you just
want to test a specific aspect of ``lldb`` and are ok ignoring a lot of expected
failures. This method can also be adapted for simulators with a qemu-like command
line interface.

(``lldb-server`` cannot be tested using user mode QEMU because that does not
emulate the debugging system calls that ``lldb-server`` tries to make)

Change ``LLDB_TEST_USER_ARGS`` to choose the ``qemu-user`` platform and
configure it for your architecture. The example below is for AArch64 and assumes
that ``qemu-aarch64`` is installed and on your path.

If you need to override how the ``qemu-user`` platform finds the QEMU binary,
look up the rest of the platform's settings in LLDB.

::

  -DLLDB_TEST_USER_ARGS="--platform-name;qemu-user;--setting;platform.plugin.qemu-user.architecture=aarch64;--arch;aarch64"

Also set ``LLDB_TEST_COMPILER`` to something that can target the emulated
architecture. Then you should be able to run ``ninja check-lldb`` and it will
run the tests on QEMU user automatically.

You will see a number of failures compared to a normal test run. Reasons for
this can be, but are not limited to:

* QEMU's built-in debug stub acting differently and supporting different
  features to different extents, when compared to ``lldb-server``. We try to
  be compatible but LLDB is not regularly tested with QEMU user.

* Tests that spawn new processes to attach to. QEMU user only emulates a single
  process.

* Watchpoints. Either these are not emulated or behave differently to real
  hardware. Add ``--skip-category;watchpoint`` to ``-DLLDB_TEST_USER_ARGS`` to
  skip those.

* Lack of memory region information due to QEMU communicating this in the
  GDB server format which LLDB does not use.
