[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issues with modifying pc in a sigaction handler

From: Peter Maydell
Subject: Re: Issues with modifying pc in a sigaction handler
Date: Wed, 14 Apr 2021 10:49:39 +0100

On Tue, 13 Apr 2021 at 23:44, Devin Hussey <husseydevin@gmail.com> wrote:
> In a toy project I was doing
> (https://github.com/easyaspi314/ThumbGolf), I found that qemu will
> incorrectly handle modifying pc in a handler.
> Specifically, on platforms with instruction alignment requirements
> (most notably ARM), if you set the pc to an odd address, QEMU will
> start reading unaligned instructions.
> Naturally, this is frustrating when dealing with ARM Thumb functions
> which have the lowest bit set when referenced, as you must manually
> clear the Thumb bit instead of it being implicit on hardware.
> The following code exhibits this bug for ARM:
> ---
> #include <signal.h>
> #include <ucontext.h>
> #include <stdio.h>
> static void hello(void)
> {
>     printf("Hello,");
> }
> static void handler(int signo, siginfo_t *si, void *data)
> {
>     ucontext_t *uc = (ucontext_t *)data;
>     // Effectively bl hello although we assume thumb state
>     uc->uc_mcontext.arm_lr = uc->uc_mcontext.arm_pc + 2 | 1;
>     uc->uc_mcontext.arm_pc = (unsigned long)&hello;

This is setting the arm_pc field to an odd number (because
the compiler/linker for Thumb will treat "take the address
of a thumb mode function" as a request for the value with the
LSB set to indicate Thumb mode. However, the ABI for the
uc_mcontext fields is that the arm_pc field should be the actual
required value of the PC -- if you want to go to somewhere in
Thumb mode you need to set the arm_pc field to the true PC
(with the LSB clear) and also set the T bit in the CPSR field
of the uc_mcontext.

So your code is doing something it shouldn't and has thus
wandered off into a corner case where QEMU behaves differently
from the hardware...

-- PMM

reply via email to

[Prev in Thread] Current Thread [Next in Thread]