1

For unit testing purposes, I want to be able to run a bare-metal binary with qemu and capture it's output.

Sample file:

#include <stdio.h>
#include <stdint.h>

static void qemu_exit() {
  register uint32_t r0 __asm__("r0");
  r0 = 0x18;
  register uint32_t r1 __asm__("r1");
  r1 = 0x20026;
  __asm__ volatile("bkpt #0xAB");
}

int main(void) {
  puts("This is some example text that I want to capture");

  qemu_exit();

  return 0;
}

Running with:

qemu-system-gnuarmeclipse --nographic --no-reboot \
  --board STM32F4-Discovery --mcu STM32F429ZI \
  --semihosting-config enable=on,target=native \
  --image <binary>

Displayed to the console is:

QEMU 2.8.0-13 monitor - type 'help' for more information
(qemu) This is some example text that I want to capture

This 'example text' is generated within QEMU and so redirecting stdout to a file does not capture it (only: QEMU 2.8.0-13 monitor - type 'help' for more information (qemu)). Looking at the available qemu logging options -d help does not offer anything as far as I can see.

EDIT

A hacky solution is to use script to capture terminal session: script --quiet --command <qemu-shell-script-wrapper>

1 Answers1

1

That's not an upstream QEMU, and 2.8 is also quite old, but hopefully the same things that work with upstream QEMU will work there.

Firstly, assuming you're not actually using the monitor, you can get rid of that part of the output by dropping '--nographic' and instead using '-display none'. (--nographic does a lot of things all at once, including both "no graphical display" and also "default serial output to the terminal, add a QEMU monitor and multiplex the monitor and the serial", among other things. It's convenient if that's what you want but sometimes it's less confusing to specify everything separately.)

Secondly, you say you're using semihosting output but is the guest's stdlib definitely using semihosting for its puts() string output and not serial port (UART) output? The output will come out on the terminal either way but how you tell QEMU to redirect it somewhere else will differ. (I suspect it may be using UART output, because if it were using semihosting output then the redirection of stdout that you tried should have worked.)

If the output from the guest is via the serial port then you can control where it goes using the '-serial' option (most simply, "-serial stdio" to send to stdout, but you can also do more complicated things like sending to files, pipes or TCP sockets.). If it's via semihosting then you can control where it goes using the 'chardev=id' suboption of -semihosting-config.

Peter Maydell
  • 9,707
  • 1
  • 19
  • 25
  • For xPack QEMU UART is not supported for Cortex-M devices, so I assume it is actual semihosting. When adding `-display none` I still get the board image popping up. Also with `--chardev file,id=c0,path=/dev/stdout --semihosting-config enable=on,target=native,chardev=c0` I get invalid parameter 'chardev'. Is this because my qemu is old or is my command invocation wrong? I would like to use a more modern qemu, but I wish to emulate a cortex-m4. – Edward Chamberlain Dec 15 '21 at 21:43
  • Sounds like the chardev= suboption may not be in that QEMU fork. I'm not sure what a "board image" is here, again that may be specific to that fork. Upstream QEMU supports the Cortex-M4, we have the netduinoplus2 and mps2-an386 board models that use it. – Peter Maydell Dec 16 '21 at 13:59