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, ®s); // 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; }