多次调用sigtrap处理程序无法正常工作

时间:2015-09-21 19:59:39

标签: c arm embedded breakpoints

我在ARM上使用C for Linux编写了一个小应用程序,它为SIGTRAP信号设置了一个信号处理程序,并且应该捕获bkpt指令(通过TRAP_HWBKPT代码)并有效地跳过它

处理程序只是在断点地址(这是下一条指令)之后通知断点被引发的位置并使用内联结尾将代码流重定向到4个字节(由于ARM的RISC架构)。我知道应该保留一些寄存器,但现在不是问题。

似乎发生的事情是,对包含断点的函数的第一次调用正常,但第二次调用不再被自定义sigtrap_handler捕获,而是传递给默认处理程序(导致进程)终止):

有谁知道为什么会发生这种情况以及如何解决这个问题,以便我可以实现为每个bkpt指令调用处理程序并继续正常执行的目标?

$ gcc -o break break.c
$ ./break
START
ENTER [0]!
SIGTRAP at 0x856c
EXIT [0]!
ENTER [1]!
Trace/breakpoint trap

这是有问题的代码:

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifndef TRAP_BRANCH
    #define TRAP_BRANCH 3
#endif

#ifndef TRAP_HWBKPT
    #define TRAP_HWBKPT 4
#endif

static void sigtrap_handler(int sig, siginfo_t* siginfo, void* ptr)
{
    switch(siginfo->si_code)
    {
        case TRAP_HWBKPT:
        {
            printf("SIGTRAP at %p\n", (void*)siginfo->si_addr);

            asm volatile("sub sp, r11, #4\n\t"
                         "pop {r11}\n\t"
                         "sub sp, #4\n\t"
                         "mov pc, %0"
                         :
                         : "r" (siginfo->si_addr + 4) // Proceed to instruction directly after breakpoint
                        );
        }break;

        // misc. SIGTRAP codes (fallthrough)
        case TRAP_BRKPT:
        case TRAP_TRACE:
        case TRAP_BRANCH:
        default:
        {
            exit(-1);
        }break;
    }
}

void dummy_routine(int n)
{
    printf("ENTER [%d]!\n", n);

    // Breakpoint
    asm volatile("bkpt");

    printf("EXIT [%d]!\n", n);
    return;
}

int main (int argc, char *argv[])
{
    int i;
    struct sigaction act;

    // Set up sigtrap handler
    memset (&act, 0, sizeof(act));
    act.sa_sigaction = sigtrap_handler;
    act.sa_flags = SA_SIGINFO;

    if (sigaction(SIGTRAP, &act, 0)) {
        perror("Error: sigaction");
        return 1;
    }

    printf("START\n");

    // Trigger routine containing breakpoint multiple times
    for(i = 0; i < 2; i++)
    {
        dummy_routine(i);
    }

    printf("END\n");

    return 0;
}

0 个答案:

没有答案