| # 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. |