All Projects → WojciechMigda → how-to-qemu-arm-gdb-gtest

WojciechMigda / how-to-qemu-arm-gdb-gtest

Licence: MIT license
How to run, debug, and unit test ARM code on X86 ubuntu

Programming Languages

C++
36643 projects - #6 most used programming language
shell
77523 projects
c
50402 projects - #5 most used programming language

Projects that are alternatives of or similar to how-to-qemu-arm-gdb-gtest

Platformio Core
PlatformIO is a professional collaborative platform for embedded development 👽 A place where Developers and Teams have true Freedom! No more vendor lock-in!
Stars: ✭ 5,539 (+29052.63%)
Mutual labels:  unit-testing, arm, debug
m3forth
m3forth is a forth cross-compiler for cortex-m3 ARM microcontrollers
Stars: ✭ 16 (-15.79%)
Mutual labels:  arm, gdb, qemu
Shecc
A self-hosting and educational C compiler
Stars: ✭ 286 (+1405.26%)
Mutual labels:  arm, qemu, cross-compiler
Gnu Eprog
Embedded Programming with the GNU Toolchain
Stars: ✭ 230 (+1110.53%)
Mutual labels:  arm, qemu
Peda Arm
GDB plugin peda for arm
Stars: ✭ 110 (+478.95%)
Mutual labels:  arm, gdb
Ataraxia
Simple and lightweight source-based multi-platform Linux distribution with musl libc.
Stars: ✭ 226 (+1089.47%)
Mutual labels:  arm, cross-compiler
Mylinux
myLinux is a small UNIX like OS for embedded systems based on Westermo NetBox
Stars: ✭ 53 (+178.95%)
Mutual labels:  arm, qemu
gdbundle
Minimalist plugin manager for GDB and LLDB
Stars: ✭ 72 (+278.95%)
Mutual labels:  gdb, debug
Qtools
QTools collection of open source tools for embedded systems development on Windows, Linux and MacOS
Stars: ✭ 64 (+236.84%)
Mutual labels:  unit-testing, arm
asm2cfg
Python command-line tool and GDB extension to view and save x86, ARM and objdump assembly files as control-flow graph (CFG) pdf files
Stars: ✭ 42 (+121.05%)
Mutual labels:  arm, gdb
refactoring-for-testability-cpp
Hard-to-test patterns in C++ and how to refactor them
Stars: ✭ 40 (+110.53%)
Mutual labels:  unit-testing, gtest
Nextcloudpi
📦 Build code for NextcloudPi: Raspberry Pi, Odroid, Rock64, Docker, curl installer...
Stars: ✭ 1,340 (+6952.63%)
Mutual labels:  arm, qemu
Daplink
Stars: ✭ 1,162 (+6015.79%)
Mutual labels:  arm, debug
Sos
Home-made almost operating system
Stars: ✭ 57 (+200%)
Mutual labels:  arm, qemu
utest
Lightweight unit testing framework for C/C++ projects. Suitable for embedded devices.
Stars: ✭ 18 (-5.26%)
Mutual labels:  unit-testing, arm
Wasmite
Now WebAssembly has proper testing, unit-testing and debugging 🤗
Stars: ✭ 20 (+5.26%)
Mutual labels:  unit-testing, debug
arm-hard-fault-handler
What to do when Hard fault hits? Debugger and error reporter solution for ARM Cortex M3 and M4.
Stars: ✭ 32 (+68.42%)
Mutual labels:  arm, debug
mdepx
MDEPX — A BSD-style RTOS
Stars: ✭ 17 (-10.53%)
Mutual labels:  arm, qemu
Fasmg Ebc
An EFI Byte Code (EBC) assembler, based on fasmg
Stars: ✭ 17 (-10.53%)
Mutual labels:  arm, qemu
Dockerpi
A Virtualised Raspberry Pi inside a Docker image
Stars: ✭ 1,064 (+5500%)
Mutual labels:  arm, qemu

How to debug and unit test code compiled for ARM on QEmu

Setup

First you need to install few thing, if you haven't already:

$ sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf qemu-system-arm qemu-user gdb-multiarch

(see setup.sh) This will install hard-float gcc cross-compiler & toolchain, qemu, and gdb.

$ arm-linux-gnueabihf-g++ --version
arm-linux-gnueabihf-g++ (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

"Hello ARM!"

Let's compile and run the simplest of examples - "Hello ARM!" program.

#include <stdio.h>

int main()
{
    printf("Hello ARM!\n");
    return 0;
}

(see hello.cpp) Our compiler is arm-linux-gnueabihf-g++ and we will invoke it with from within a simple wrapper (compile.sh), which should yield hello executable. It can be run with qemu-arm to which we also need to pass path to the runtime libraries.

$ qemu-arm -L /usr/arm-linux-gnueabihf ${@}

(see qemu.sh) After running ./qemu.sh ./hello we should be greeted with Hello ARM! on our terminal.

Debugging

To debug our application we will tell qemu-arm to start it in debug mode listening on specified port, e.g.

$ qemu-arm -L /usr/arm-linux-gnueabihf -g 1234 ./hello

(see qemu-gdb.sh) In another terminal we will launch gdb-multiarch:

$ gdb-multiarch
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) file hello
Reading symbols from hello...done.
(gdb) set architecture armv5te
The target architecture is assumed to be armv5teset sysroot /usr/arm-linux-gnueabihf/
(gdb) set sysroot /usr/arm-linux-gnueabihf/
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
Reading symbols from /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3...(no debugging symbols found)...done.
0xf67d6a40 in ?? () from /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3
(gdb) break main
Breakpoint 1 at 0x104dc: file hello.cpp, line 5.
(gdb) continue
Continuing.

Breakpoint 1, main () at hello.cpp:5
5           printf("Hello ARM!\n");
(gdb)

In the above first we had to tell gdb from where to load debug symbols (file), then we have set the hardware architecture (set architecture), followed by specifying location on runtime libraries (set sysroot). Once done with that we connect to qemu started just a while ago (target remote), set the breakpoint, and let the execution to continue.

You can also execute the above in a single command:

gdb-multiarch --ex="set arch armv5te" --ex="set sysroot /usr/arm-linux-gnueabihf/" --ex="target remote localhost:1234" --ex="break main" hello

If you prefer ddd then this is a command for you:

ddd --debugger 'gdb-multiarch --ex="set arch armv5te" --ex="set sysroot /usr/arm-linux-gnueabihf/" --ex="target remote localhost:1234" --ex="break main" hello' --gdb

Unit testing

For unit testing we will use Google Test/Mock combo. We will need native ARM libraries which we will compile ourselves. One thing to note - gtest will be built with threads disabled to remove dependency on pthreads, which we do not have cross-compiled.

$ cmake \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_GTEST=ON -DBUILD_GMOCK=ON \
-Dgtest_disable_pthreads=ON \
-DCMAKE_INSTALL_PREFIX:PATH=../googletest-arm \
-DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ \
../googletest

make -j 4 && make install

(see build-gtest.sh) With that we can compile simple unit testing suite (ut.cpp) and run it just as we did with hello. We should see this after running it:

$ ./qemu.sh ./ut
Running main() from gmock_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from Sqrt
[ RUN      ] Sqrt.gives_some_value_for_positive_input
[       OK ] Sqrt.gives_some_value_for_positive_input (0 ms)
[ RUN      ] Sqrt.gives_none_value_for_negative_input
[       OK ] Sqrt.gives_none_value_for_negative_input (0 ms)
[----------] 2 tests from Sqrt (1 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (3 ms total)
[  PASSED  ] 2 tests.

Tcp server within qemu

We can also launch tcp server within qemu and it will be able to communicate with the outside x86 world. Once we compile attached golf server code (echo_golf.c) we can start it and then connect to it with telnet:

$ ./qemu.sh ./echo_golf 1234 &
$ telnet localhost 1234
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
128
Connection closed by foreign host.

It outputs 128, which is a sum of decimal IPv4 address octet components.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].