Chan Kim
Chan Kim

Reputation: 5989

How to run arm64 baremetal hello world program on qemu?

Often a question leads me into another question.
While trying to debug an inline assembly code, I met with another basic problem.
To make long story short, I want to run arm64 baremetal hello world program on qemu.

#include <stdio.h>

int main()
{
printf("Hello World!\n");
}

I compile it like this : aarch64-none-elf-gcc -g test.c

I get undefined reference errors for _exit _sbrk _write _close _lseek _read _fstat and _isatty. I learned in the past the -specs=rdimon.specs compile options removes this errors. So I ran

aarch64-none-elf-gcc -g test.c -specs=rdimon.specs

and it compiles ok with a.out file.
Now I run qemu baremetal program to debug the code.

qemu-system-aarch64 -machine virt,gic-version=max,secure=true,virtualization=true -cpu cortex-a72 -kernel a.out -m 2048M -nographic -s -S

and here is the gdb run result.

ckim@ckim-ubuntu:~/testdir/testinlinedebugprint$ aarch64-none-elf-gdb a.out
GNU gdb (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16)) 10.1.90.20201028-git
Copyright (C) 2020 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 "--host=x86_64-pc-linux-gnu --target=aarch64-none-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://bugs.linaro.org/>.
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"...
Reading symbols from a.out...
(gdb) set architecture aarch64
The target architecture is set to "aarch64".
(gdb) set serial baud 115200
(gdb) target remote :1234
Remote debugging using :1234
_start ()
    at /tmp/dgboter/bbs/build02--cen7x86_64/buildbot/cen7x86_64--aarch64-none-elf/build/src/newlib-cygwin/libgloss/aarch64/crt0.S:90
90  /tmp/dgboter/bbs/build02--cen7x86_64/buildbot/cen7x86_64--aarch64-none-elf/build/src/newlib-cygwin/libgloss/aarch64/crt0.S: No such file or directory.
(gdb) b main
Breakpoint 1 at 0x4002f8: file test.c, line 26.
(gdb) 
(gdb) r
The "remote" target does not support "run".  Try "help target" or "continue".
(gdb) c
Continuing.

It doesn't break and hangs.
What am I doing wrong? and how can I solve the /tmp/dgboter/bbs/build02--cen7x86_64/buildbot/cen7x86_64--aarch64-none-elf/build/src/newlib-cygwin/libgloss/aarch64/crt0.S: No such file or directory. problem? Any help will be really appreciated. Thanks!

ADD :
I realized I have asked the same question (How to compile baremetal hello_world.c and run it on qemu-system-aarch64?) before (Ah! my memory..) I realized I need all the stuff like start.S crt0.S and the linker script, . . .I stupidly thought the baremetal compiler will take care of it automatically when actually I have to fill the really low level things. I've worked on baremetal programs in some cases but it was after someone else had already set up those initial environment(sometimes I even modified them many times!). In baremetal, you have to privide all the things. There isn't anything you can take for granted because it's "bare metal". I realized this basic thing so late..

Upvotes: 0

Views: 1978

Answers (1)

Peter Maydell
Peter Maydell

Reputation: 11493

When you build a program for "bare metal" that means that you need to configure your toolchain to produce a binary that works on the specific piece of bare metal that you try to run it on. For instance, the binary must:

  • put its code somewhere in the machine's memory map where there is either ROM or RAM
  • put its data where there is RAM
  • make sure that on startup the stack pointer is correctly initialized to point into RAM
  • if it wants to print output, include routines which access a suitable device on that machine. This is likely a serial port, and serial ports are often entirely different devices, located at different addresses, on different machines

If any of these things are wrong or don't match the actual machine you run on, the result is typically exactly what you see -- the program crashes without output.

More specifically, rdimon.specs tells the compiler to build in C library functions which do some of this via the "semihosting" debugger ABI (which has support for "print string" and some other things). Your QEMU command line doesn't enable implementation of semihosting (you can turn it on with the -semihosting option), so that won't work at all. But there are probably other problems you're also hitting.

Upvotes: 2

Related Questions