qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Devin Hussey <husseydevin@gmail.com>
To: qemu-devel@nongnu.org
Subject: Issues with modifying pc in a sigaction handler
Date: Tue, 13 Apr 2021 18:03:52 -0400	[thread overview]
Message-ID: <CAEtFKsuPfRS1_exHPBNE-BLthbXoudUOcX6ND80FA=JqV8LrzA@mail.gmail.com> (raw)

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;
}

int main(void)
{
    // Set up the signal handler
    struct sigaction sa, osa;
    sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigaction(SIGILL, &sa, &osa);
    sigaction(SIGTRAP, &sa, &osa);

    // Throw a SIGILL, which we do a runtime patch to call hello().
    // Make sure we mark the caller saved registers.
    __asm__ ("udf #0" ::: "r0", "r1", "r2", "r3", "r12", "lr", "memory");
    printf(" world!\n");
}
---
Compile with:
clang -O2 -march=armv7-a -mthumb file.c -static

(The same should happen with GCC).

On hardware (specifically, a Snapdragon 730g in Termux on Android 11),
the code prints "Hello, world!" and exits normally.

However, qemu-arm will get tripped up by the pc being odd, and execute this:

---
... snip
----------------
IN: main
0x00010288:  4c05       ldr      r4, [pc, #0x14]
0x0001028a:  de00       udf      #0

----------------
IN: handler
0x000102a4:  4804       ldr      r0, [pc, #0x10]
0x000102a6:  6dd1       ldr      r1, [r2, #0x5c]
0x000102a8:  4478       add      r0, pc
0x000102aa:  3102       adds     r1, #2
0x000102ac:  f041 0101  orr      r1, r1, #1
0x000102b0:  e9c2 1016  strd     r1, r0, [r2, #0x58]
0x000102b4:  4770       bx       lr

----------------
IN: __restore_rt
0x0004c36c:  e3a070ad  mov      r7, #0xad
0x0004c370:  ef000000  svc      #0

----------------
IN: hello
0x000102bd:  7848       ldrb     r0, [r1, #1]
0x000102bf:  0644       lsls     r4, r0, #0x19
0x000102c1:  5cf0       ldrb     r0, [r6, r3]
0x000102c3:  06bb       lsls     r3, r7, #0x1a
0x000102c5:  053e       lsls     r6, r7, #0x14
0x000102c7:  f000 89b5  beq.w    #0x90635

qemu: uncaught target signal 11 (Segmentation fault) - core dumped

---

Note the odd addresses in hello().

It should be interpreted as so, which happens when you manually clear
the Thumb bit:

---
0x000102b8:  4801       ldr      r0, [pc, #4]
                         0x000102ba:  4478       add      r0, pc
                                                  0x000102bc:  f006
bb5c  b.w      #0x16978 (printf)
---


             reply	other threads:[~2021-04-13 22:44 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-13 22:03 Devin Hussey [this message]
2021-04-14  9:49 ` Issues with modifying pc in a sigaction handler Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAEtFKsuPfRS1_exHPBNE-BLthbXoudUOcX6ND80FA=JqV8LrzA@mail.gmail.com' \
    --to=husseydevin@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).