Hi,

I've "stock" Ubuntu 14.04.1 running under an aarch64-qemu (built from
mainline git) in full-system emulation [1]. Everything worked fine until
I tried to find a bug in an application built for aarch64 (that bug most
likely being not the fault of qemu but the app itself). When I started
debugging, strange things happened: breakpoints in gdb did not behave as
they should. First, together with gdb developers, we speculated that
it's a bug in gdb (which still may hold, at least partially) [2], but
then I traced back the problem to a point where it has led out of gdb.
It seems that PTRACE_SINGLESTEP is not working as it should, it does not
stop the execution of the child after a step but lets it run
indefinitely. I validated the problem with a pair of simple programs
(attached: executing ezptrace on x86_64 prints 93010 steps before end,
but inside the aarch64 emulation all I get is "step 0 / 56 / end".)

I'm still not sure that it's a qemu problem but I already figured out
that the aarch64 kernel does support single stepping [3]. I'd thank for
any hints.

Best regards,
Akos

[1]
http://webkit.sed.hu/blog/20140816/quickndirty-set-aarch64-ubuntu-1404-vm-qemu
[2] https://sourceware.org/bugzilla/show_bug.cgi?id=17280
[3]
https://github.com/torvalds/linux/blob/e1a08b855f56d6528e7f85aae9ca8123f4c3ae04/arch/arm64/include/asm/ptrace.h#L114

-- 
Ákos Kiss, PhD
assistant professor

Department of Software Engineering, University of Szeged
Dugonics tér 13., 6720 Szeged, Hungary
Phone: +36-62-544143
Fax: +36-62-546723
ak...@inf.u-szeged.hu

// ezptrace.c
// source: 
http://stackoverflow.com/questions/7697344/why-doesnt-ptrace-singlestep-work-properly

#include <sys/user.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t child;
    child = fork();
    if (child == 0) {
        char *argv[] = { "ezptraceme", NULL };
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execv(argv[0], argv);
    }
    else {

        int status;
        wait(&status);
//        struct user_regs_struct regs;
        int stepno = 0;
        while (1) {
//            ptrace(PTRACE_GETREGS, child, NULL, &regs);
//            printf("eip: %x\n", (unsigned int) regs.eip);
            printf("step %d\n", stepno++);
            ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
            waitpid(child, &status, 0);
            if(WIFEXITED(status)) break;
        }
        printf("end\n");
    }
    return 0;
}
#include <stdio.h>
int main() {
    int sum = 1;
    int i;
    for (i = 1; i <= 10; i++)
        sum += i;
    printf("%d\n", sum);
    return 0;
}

Reply via email to