libc/libgloss/arm/_kill.c
Tamar Christina 430b529111 Fix AArch32 semihosting SYS_EXIT call on semihosting v1.
The current SYS_EXIT has a bug that when making the call it always uses
the v2 calling convention.  This is undefined behavior according to the
semihosting specification:
https://developer.arm.com/docs/100863/latest/semihosting-operations/sys_exit-0x18

This patch fixes it by making sure v1 passes the argument directly in the register instead
of in a block. And for v2 it does the same if the v2 extension isn't supported.

The sequence generated now is

   12424:       ebfffecd        bl      11f60 <_has_ext_exit_extended>
   12428:       e3500000        cmp     r0, #0
   1242c:       11a0500d        movne   r5, sp
   12430:       059d5000        ldreq   r5, [sp]
   12434:       e1a00004        mov     r0, r4
   12438:       e1a01005        mov     r1, r5
   1243c:       ef00f000        svc     0x0000f000

Signed-off-by: Tamar Christina <tamar.christina@arm.com>
2018-07-11 17:18:04 +02:00

53 lines
823 B
C

#include <_ansi.h>
#include <signal.h>
#include "swi.h"
int _kill (int, int);
int
_kill (int pid, int sig)
{
(void) pid; (void) sig;
#ifdef ARM_RDI_MONITOR
/* Note: The pid argument is thrown away. */
int block[2];
block[1] = sig;
int insn;
#if SEMIHOST_V2
if (_has_ext_exit_extended ())
{
insn = AngelSWI_Reason_ReportExceptionExtended;
}
else
#endif
{
insn = AngelSWI_Reason_ReportException;
}
switch (sig)
{
case SIGABRT:
{
block[0] = ADP_Stopped_RunTimeError;
break;
}
default:
{
block[0] = ADP_Stopped_ApplicationExit;
break;
}
}
#if SEMIHOST_V2
if (_has_ext_exit_extended ())
return do_AngelSWI (insn, block);
else
#endif
return do_AngelSWI (insn, (void*)block[0]);
#else
asm ("swi %a0" :: "i" (SWI_Exit));
#endif
}