qemu-system-arm semihosting always calls exit(0)

Bug #1216845 reported by Liviu Ionescu
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
QEMU
Fix Released
Undecided
Unassigned

Bug Description

In my embedded ARM project I have a bunch of unit tests that I run in a POSIX synthetic environment, and, as usual for POSIX processes, these tests return 0 for success and !=0 for error.

Now I expanded the testing environment to run some of these tests compiled for ARM, under QEMU, with the tracing messages forwarded via the semihosting API.

Up to now everything is fine with the emulation.

However I have a problem with passing the failure code back to the operating system, to drive the continuous integration framework.

I checked the arm-semi.c code and for SYS_EXIT and I discovered that the parameter passed is ignored and it always calls exit(0):

    case SYS_EXIT:
        gdb_exit(env, 0);
        exit(0);

To solve my problem I temporarily made a patch, and for cases that should return non zero codes, I call an unsupported BKPT instruction, which makes QEMU abort, and pass an non zero code (1) back to the operating system.

    qemu: Unsupported SemiHosting SWI 0xf1

This kludge is more or less functional, but is quite inconvenient.

After checking the ARM manuals, I discovered that SYS_EXIT is not standard, and the 0x18 code used for it originally was used for angel_SWIreason_ReportException, which has a slightly different purpose.

Now the question:

Would it be possible to no longer ignore the code passed to 0x18, and if it is non zero, to call exit() with a different value?

The suggested rule would be:

if (code ==0 || code == 0x20026)
  exit(0);
elif (code < 256)
  exit(code);
else
  exit(1);

The value 0x20026 means ADP_Stopped_ApplicationExit, and, if I understood it right, it means that the program terminated successfully. If this is not true, it can be removed from the first conditional statement.

What do you think? Can this be added to arm-semi.c?

Regards,

Liviu

Tags: arm
Revision history for this message
Karl Zimmerman (karl-erik-zimmerman) wrote :

Had a similar problem with my emulation environment. However, I did some inspection of the assembly code generated by newlib for ARM semi-hosting. While it initially appears that exit() and _exit() discard the status code, upon careful inspection one finds that it is pushed on the stack, with the SP pointing right to it at the point at which the SWI is executed.

Thus, if the code passed to 0x18 is 0x20026, you can fetch the status code passed to exit() from the stack.

Revision history for this message
Liviu Ionescu (ilg) wrote :

thank you for your suggestion.

as semihosting servers I use the j-link gdb server, openocd and qemu. if I got it right, you suggest to modify all these servers to retrieve the exit code from a specific location. as long as this is not documented in the ARM manuals, I cannot recommend such a solution.

in the GNU ARM Eclipse project templates I fixed the problem by using my own semihosting routines, where exit returns different values for 0 and non zero, so I no longer depend on the newlib support for semihosting.

Revision history for this message
Peter Maydell (pmaydell) wrote : Re: [Qemu-devel] [Bug 1216845] Re: qemu-system-arm semihosting always calls exit(0)

On 4 February 2015 at 15:56, Karl Zimmerman
<email address hidden> wrote:
> Had a similar problem with my emulation environment. However, I did
> some inspection of the assembly code generated by newlib for ARM semi-
> hosting. While it initially appears that exit() and _exit() discard the
> status code, upon careful inspection one finds that it is pushed on the
> stack, with the SP pointing right to it at the point at which the SWI is
> executed.
>
> Thus, if the code passed to 0x18 is 0x20026, you can fetch the status
> code passed to exit() from the stack.

Yes, but this is an internal implementation detail of newlib,
not a part of the semihosting ABI. It might well change
in different versions of newlib and we can't rely on it.

-- PMM

Revision history for this message
Peter Maydell (pmaydell) wrote :

With the new 2.0 ARM semihosting ABI, there is an optional extension SYS_EXIT_EXTENDED which can be used to implement returning a non-zero exit code for 32-bit ARM programs:

https://developer.arm.com/docs/100863/latest/semihosting-operations/sys_exit_extended-0x20#sh-ext-exit-extended

QEMU should implement this.

Changed in qemu:
status: New → Confirmed
tags: added: arm
Revision history for this message
Peter Maydell (pmaydell) wrote :

https://<email address hidden>/ is a patchset which adds semihosting v2 support to QEMU. With those patches and a guest binary which understands semihosting v2 and knows how to probe for the existence of the EXIT_EXTENDED extension, arm guest binaries will be able to pass a non-zero exit status.

Changed in qemu:
status: Confirmed → In Progress
Revision history for this message
Peter Maydell (pmaydell) wrote :

The semihosting v2 support went into QEMU in the 4.2 release, but I forgot to close this bug...

Changed in qemu:
status: In Progress → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.