arrow-left

All pages
gitbookPowered by GitBook
1 of 5

Loading...

Loading...

Loading...

Loading...

Loading...

GDB Debugging

Debug Linux kernel with GDB

hashtag
Compile a correct Linux kernel

Clone a Linux tree and run make ARCH=arm defconfig to make a generic kernel configuration suited for qemu. Now edit the kernel configuration (.config) and add the following lines at the bottom:

Now run make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) to compile the kernel. If you get asked about anything, just press enter to use the standard value.

Copy the output zImage (arch/arm/boot/zImage) to efi/boot/bootarm.efi on your EFI partition folder in your qemu directory.

hashtag
Prepare GDB for debugging

hashtag
Install

Run sudo apt-get install gdb-multiarch to install GDB on Ubuntu. gdb-mutliarch is required because normal gdb package doesn't have support for ARM.

hashtag
Run

Open up the terminal you want GDB to run in, and change directory to your Linux compilation directory. Then run gdb-multiarch vmlinux., it will open GDB you and you can now connect to a target with target remote localhost:1234. At this point GDB will wait for qemu to start. After that you can now debug with qemu, there are tutorials online to show you how to do this.

hashtag
Run qemu

Go to the directory where your qemu files are located, start qemu as described in , only change is that you need to add a -s parameter, this lets qemu know that it starts a GDB server.

CONFIG_DEBUG_INFO=y
CONFIG_GDB_SCRIPTS=y
Qemu emulation

VSCode integration

Debug Linux kernel within Visual Studio Code

hashtag
Create configuration files

The following steps have to be performed in your Linux source directory.

hashtag
Create tasks.json

Create a file called tasks.json in the directory .vscode and paste the following contents into it:

circle-info

You may want to change line 26 and 34, as they point to the directory where your qemu files are located.

See for the documentation about the tasks.json format

hashtag
Create launch.json

Create a file called launch.json in the directory .vscode and paste the following contents into it: Use IntelliSense to learn about possible attributes. Hover to view descriptions of existing attributes. For more information, visit:

hashtag
Create c_cpp_properties.json

Create a file called c_cpp_properties.json in the directory .vscode and paste the following contents into it:

hashtag
Debug

Press F5 to start debugging. The following steps will be performed:

  • Compile Kernel

  • Copy zImage to qemu EFI partition

  • Launch qemu

The following keys are important:

  • F9 for creating a breakpoint

  • F10 for going a step forward

  • F11 for stepping into a function

Start GDB debugging

F12 to step out of a function

https://go.microsoft.com/fwlink/?LinkId=733558arrow-up-right
https://go.microsoft.com/fwlink/?linkid=830387arrow-up-right
tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build Kernel for ARM",
      "type": "shell",
      "command": "make",
      "args": [
          "ARCH=arm",
          "CROSS_COMPILE=arm-linux-gnueabihf-",
          "-j6"
      ],
      "group": {
          "kind": "build",
          "isDefault": true
      },
      "problemMatcher": [
          "$gcc"
      ]
    },
    {
      "label": "Copy zImage",
      "command": "cp",
      "args": [
        "arch/arm/boot/zImage",
        "../emulation/boot/efi/boot/bootarm.efi"
      ],
      "dependsOn":["Build Kernel for ARM"]
    },
    {
      "label": "Run qemu",
      "command": "/usr/bin/qemu-system-arm -m 1024 -cpu cortex-a15 -M virt -pflash flash0.img -pflash flash1.img -nographic -drive file=fat:rw:boot/ -smp '4' -s",
      "options": {
        "cwd": "${workspaceFolder}/../emulation"
      },
      "type": "shell",
      "isBackground": true,
      "problemMatcher": [
        {
          "pattern": [
            {
              "regexp": ".",
              "file": 1,
              "location": 2,
              "message": 3
          }
          ],
          "background": {
            "activeOnStart": true,
            "beginsPattern": ".",
            "endsPattern": ".",
          }
        }
      ],
      "dependsOn":["Copy zImage"]
    },
    {
      "label": "Terminate All Tasks",
      "command": "echo ${input:terminate}",
      "type": "shell",
      "problemMatcher": []
    }
  ],
  "inputs": [
    {
      "id": "terminate",
      "type": "command",
      "command": "workbench.action.tasks.terminate",
      "args": "terminateAll"
    }
  ]
} 
launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Run",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceRoot}/vmlinux",
            "miDebuggerServerAddress": "localhost:1234",
            "miDebuggerPath": "/usr/bin/gdb-multiarch",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "targetArchitecture": "arm",
            "preLaunchTask": "Run qemu",
            "postDebugTask": "Terminate All Tasks",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}
c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}",
                "${workspaceFolder}/include",
                "${workspaceFolder}/include/uapi",
                "${workspaceFolder}/include/generated",
                "${workspaceFolder}/arch/arm/include",
                "${workspaceFolder}/arch/arm/include/uapi",
                "${workspaceFolder}/arch/arm/include/generated"
            ],
            "defines": [
                "__KERNEL__"
            ],
            "compilerPath": "/usr/bin/arm-linux-gnueabihf-gcc",
            "cStandard": "gnu17",
            "cppStandard": "c++17",
            "intelliSenseMode": "linux-gcc-arm",
            "browse": {
                "path": [
                    "${workspaceFolder}",
                    "${workspaceFolder}/include",
                    "${workspaceFolder}/mm",
                    "${workspaceFolder}/fs",
                    "${workspaceFolder}/kernel"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            }
        }
    ],
    "version": 4
}

Qemu emulation

Run arm32 UEFI in a virtual machine.

Emulating a arm32 UEFI device is useful for developing Linux and debugging it.

In the GDB Debugging page you can find instructions on how to compile Linux for this virtual machine.

circle-info

A premade ZIP with all required files can be found at the bottom.

hashtag
Compile OVMF for qemu

hashtag
Install required packages

Run the following commands to install the required packages.

You will need other stuff too, but that is probably already installed. (e.g. git)

hashtag
Download source

You need the source code of edk2 and acpica.

hashtag
Compile OVMF

Go to your source directory and run the following commands.

Your output OVMF firmware file for qemu is$WORKSPACE/Build/ArmVirtQemu-ARM/RELEASEGCC5/FV/QEMU_EFI.fd

hashtag
Setup qemu files and run it

Create a directory, where you want your files to be in. Put your QEMU_EFI.fd firmware file in this directory, compiled in the previous section. Now run the following commands to create some disk images:

Now create a directory named boot. This will be your EFI partition. You can now easily place your EFI files in there.

hashtag
Run qemu

To start your virtual machine run the following command, and make sure qemu-system-arm is installed.

This will run qemu with 4 virtual CPU cores. They are Coretx-A15 cores. Used because it works.

hashtag
Premade files

The following ZIP includes all files setup in their proper location. In addition its EFI partition folder has a UEFI shell in it. To run it either execute the run.sh file or enter the command described in .

hashtag
References

Links where the above compiling information is from:

Run qemu
file-archive
2MB
arm32-uefi-qemu-setup.zip
archive
arrow-up-right-from-squareOpen
Premade qemu setup
https://developer.arm.com/tools-and-software/open-source-software/firmware/edkii-uefi-firmware/building-edkii-uefi-firmware-for-arm-platformsarrow-up-right
https://designprincipia.com/virtualize-uefi-on-arm-using-qemu/arrow-up-right
sudo apt install python python3 python3-distutils
sudo apt install gcc-arm-none-eabi
sudo apt install uuid-dev
sudo apt install build-essential
sudo apt install bison
sudo apt install flex
# Go to the directory you want to work in
export WORKSPACE=$PWD

# Download edk2 and acpica
git clone https://github.com/acpica/acpica.git
git clone https://github.com/tianocore/edk2.git

# Download submodules
cd edk2
git submodule update --init
cd ..
# Compile acpica tools
make -C $WORKSPACE/acpica -j$(nproc)

# Set environment variables
export GCC5_ARM_PREFIX=arm-none-eabi-
export IASL_PREFIX=$WORKSPACE/acpica/generate/unix/bin/
export PYTHON_COMMAND=/usr/bin/python3

# Configure the edk2 environment
source edk2/edksetup.sh

# Compile edk2 BaseTools
make -C edk2/BaseTools -j$(nproc)

# Compile OVMF
build -a ARM -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc -b RELEASE -j$(nproc)
rm -f flash0.img flash1.img
dd if=/dev/zero bs=1M count=64 of=flash0.img
dd if=/dev/zero bs=1M count=64 of=flash1.img
dd if=QEMU_EFI.fd bs=1M of=flash0.img conv=notrunc
qemu-system-arm \ 
    -m 1024 \
    -cpu cortex-a15 \
    -M virt \
    -pflash flash0.img \
    -pflash flash1.img \
    -nographic \
    -drive \
    file=fat:rw:boot/ \
    -smp '4'

Configs we already tried

This is a place were we put configurations we tried, and didn't work or did work up to a certain point.

hashtag
Surface RT 1

hashtag
@Leander's trial and fail

Note to members of the gitbook: I don't know if it is useful to make this person-specific.

hashtag
#001

This hangs at without supplying device tree with dtb= If device tree is supplied, cpuidle complains at printed. [ 0.000000] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2 [ 0.000000] cfg80211: failed to load regulatory.db

circle-info

Testing without device tree from here on

hashtag
#002

Changed:CONFIG_CFG80211=n [ 0.000000] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2 [ 0.000000] cfg80211: failed to load regulatory.db This is issue doesn't exist anymore, it just freezes at [ 0.000000] Freeing unused kernel memory: 1024K

Note the line, clock should be 100kHz[ 0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns

[ 0.000000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.000000] Warning: unable to open an initial console. It looks like it's using some serial and then is unable to open a console. -> No device tree so it doesn't know /dev/ttyS0 (UART-A)

hashtag
#003

CONFIG_FB_EFI=y CONFIG_CMDLINE="console=ttyS0,115200 console=tty0 earlyprintk initcall_debug sched_debug lpj=10000"

It booted, then disabled uart and printed to the screen. Log only contains print from uart. Stuck at the same line.

hashtag
#004

CONFIG_CMDLINE="console=ttyS0,115200 console=tty0 earlycon earlyprintk initcall_debug sched_debug lpj=10000"

Log should be the same apart from the cmdline. Again, it displayed to display, so log doesn't include that output.

hashtag
#005

CONFIG_CMDLINE="console=ttyS0,115200 earlycon earlyprintk initcall_debug sched_debug lpj=10000"

Screen with a cursor, all output on uart. But because there is no device tree, no console from initrd.

circle-info

Testing with device tree from here on

hashtag
#006

Nothing changed in config. Only added device tree.

Kernel panic: [ 0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000010Has to do with cpuidle. You can also see complaints about a bad device tree.

hashtag
#007

Only device tree edits.

Screen has no cursor anymore, only backlight is turned on. You can't print something on it with echo hello >> /dev/fb0 or echo hello >> /dev/tty0

Successful boot to Buildroot.

Note: Log has a lot of entries two times.

hashtag
#008

CONFIG_VGA_ARB=n CONFIG_TEGRA_HOST1X=n CONFIG_DRM=n

No different screen behaviour.

Log has some commands at the bottom.

hashtag
#009

No config changed. Only device tree edits. Added nodes to it until dtc didn't complain about anything.

Some strange screen behaviour.

[ 0.000000] tegra20-cpufreq tegra20-cpufreq: operating points not found [ 0.000000] tegra20-cpufreq tegra20-cpufreq: please update your device tree Looks like some cpu frequency nodes have to be added to device tree.

hashtag
#010

Only device tree edits.

Screen still doesn't work.

Boots fine to Buildroot. Log has commands at the bottom.

hashtag
#011

CONFIG_CMDLINE="console=ttyS0,115200 console=tty0 earlyprintk initcall_debug sched_debug lpj=10000"

Found out that screen works, but it gets cleared when Busybox (from ramdisk) starts. At least I think at that point it gets cleared, not 100% sure.

hashtag
#012

CONFIG_CMDLINE="console=ttyS0,115200 earlyprintk initcall_debug sched_debug lpj=10000"

Minimal device tree with sd-card+emmc+uart, it includes tegra30.dtsi

No display output with this command line, but you get log output when adding console=tty0, but afterwards it stops around when Busybox takes over.

hashtag
#013

Added a raspberry pi rootfs. Specifying root= option with efi shell

Display stops working after the line [ 251.431349] tegra-devfreq 6000c800.actmon: Failed to get emc clock

Log contains output from rootfs.

circle-info

Config reseted. Started from a new one.

hashtag
#014

CONFIG_EFI_STUB=y CONFIG_EFI=y CONFIG_CMDLINE="console=ttyS0,115200n8 earlyprintk initcall_debug sched_debug lpj=10000 boot_delay=50" CONFIG_CMDLINE_EXTEND=y CONFIG_SMP=n CONFIG_CACHE_L2X0=n CONFIG_EARLY_PRINTK=y CONFIG_DEBUG_TEGRA_UART=y CONFIG_TEGRA_DEBUG_UARTA=y CONFIG_BOOT_PRINTK_DELAY=y

CONFIG_BOOT_PRINTK_DELAY=y and boot_delay=50(cmdline) are necessary so mmc driver gets loaded early enough.

Log contains a few commands from rootfs.

hashtag
#015

I'm not sure what changed.

Working display with booted raspberry pi os!

hashtag
Surface RT 2

EFI linux booting

Booting linux with UEFI boot is now possible.

hashtag
Issues

  • PMIC regulators don't work.

Audio, Wireless, Cameras, Sensors .This is also true for APX boot.

hashtag
TODO

  • Implement ACPI for arm32. This will help in development for all other devices that run Windows RT too. Why? It removes the need for a device tree and enables us to comunicate with the firmware, which will hopefully enable us to use PMIC stuff. Also we can upstream our ACPI Parking Protocol driver, which is needed for SMP.

  • Get Audio, Wireless, Cameras, Sensors.

  • Possibly more, but we don't know about it yet.

file-download
163KB
.config
arrow-up-right-from-squareOpen
#001 .config
file-download
6KB
tegra30-microsoft-surfaceRT-test1.dts
arrow-up-right-from-squareOpen
#001 device tree
file-download
160KB
.config
arrow-up-right-from-squareOpen
#002 .config
file-download
12KB
log.txt
arrow-up-right-from-squareOpen
#002 log
file-download
159KB
.config
arrow-up-right-from-squareOpen
#003 .config
file-download
5KB
log.txt
arrow-up-right-from-squareOpen
#003 log
file-download
160KB
.config
arrow-up-right-from-squareOpen
#004 .config
file-download
5KB
log.txt
arrow-up-right-from-squareOpen
#004 log
file-download
159KB
.config
arrow-up-right-from-squareOpen
#005 .config
file-download
13KB
log.txt
arrow-up-right-from-squareOpen
#005 log
file-download
159KB
.config
arrow-up-right-from-squareOpen
#006 .config
file-download
18KB
log.txt
arrow-up-right-from-squareOpen
#006 log
file-download
2KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#006 device tree
file-download
159KB
.config
arrow-up-right-from-squareOpen
#007 .config
file-download
30KB
log.txt
arrow-up-right-from-squareOpen
#007 log
file-download
2KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#007 device tree
file-download
156KB
.config
arrow-up-right-from-squareOpen
#008 .config
file-download
18KB
log.txt
arrow-up-right-from-squareOpen
#008 log
file-download
2KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#008 device tree
file-download
155KB
.config
arrow-up-right-from-squareOpen
#009 .config
file-download
17KB
log.txt
arrow-up-right-from-squareOpen
#009 log
file-download
5KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#009 device tree
file-download
155KB
.config
arrow-up-right-from-squareOpen
#010 .config
file-download
19KB
log.txt
arrow-up-right-from-squareOpen
#010 log
file-download
6KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#010 device tree
file-download
155KB
.config
arrow-up-right-from-squareOpen
#011 .config
file-download
22KB
log.txt
arrow-up-right-from-squareOpen
#011 log
file-download
6KB
tegra30-microsoft-surfaceRT.dts
arrow-up-right-from-squareOpen
#011 device tree
file-download
155KB
.config
arrow-up-right-from-squareOpen
#012 .config
file-download
25KB
log.txt
arrow-up-right-from-squareOpen
#012 log
file-download
932B
tegra30-microsoft-surfaceRT-test2.dts
arrow-up-right-from-squareOpen
#012 device tree
file-download
155KB
.config
arrow-up-right-from-squareOpen
#013 .config
file-download
29KB
log.txt
arrow-up-right-from-squareOpen
#013 log
file-download
932B
tegra30-microsoft-surfaceRT-test2.dts
arrow-up-right-from-squareOpen
#013 device tree
file-download
166KB
.config
arrow-up-right-from-squareOpen
#014 .config
file-download
36KB
log.txt
arrow-up-right-from-squareOpen
#014 log
file-download
932B
tegra30-microsoft-surfaceRT-test2.dts
arrow-up-right-from-squareOpen
#014 device tree
file-download
166KB
.config
arrow-up-right-from-squareOpen
#015 .config
file-download
47KB
log.txt
arrow-up-right-from-squareOpen
#015 log
file-download
6KB
tegra30-microsoft-surfaceRT-test1.dts
arrow-up-right-from-squareOpen
#015 device tree