ARM v7 BKPT instruction does not work correctly on Linux 2.6.35

I have a problem with the BKPT instruction on ARM v7 on Linux 2.6.35. The main reason is that the failure command address (bkpt) is incorrect and does not comply with the ARM v7 manual.

Here are the steps to play:

  • Override the SIGBUS OS handler for my SIGBUS handler:

    void InitSigBusHandler() {  
        struct sigaction sa;  
        memset(&sa, 0, sizeof(sa));    
        sa.sa_flags = SA_SIGINFO;  
        sigfillset(&sa.sa_mask);  
        sa.sa_sigaction = SigBusHandler;  
        sigaction(SIGBUS, &sa, NULL);
        } 
    
  • Use the built-in _asm and put the "BKPT" statement in the code in main () :

    int main(int argc, char **argv)  
    {
         InitSigBusHandler();
         __asm
         (
              "bkpt\n\t"
         );
    
         return 0;
    }
    
  • Here is my SIGBUS handler:

    void SigBusHandler(    
        int         signum,  
        siginfo_t   *pAct,  
        void        *pOldAct  
        )
    {
        write(2,
             (const char *)MSG_SIGBUS_IN_HANDLER,  
              strlen((const char *)MSG_SIGBUS_IN_HANDLER)  
              );
    
        uint32_t faultAddr = (uint32_t)pAct->si_addr;  
        memcpy((void *)buffer,  
              (void *)MSG_SIGBUS_FAULT_ADDR,  
              strlen(MSG_SIGBUS_FAULT_ADDR)  
              );
    
        write(2,  
             (const char *)MSG_SIGBUS_FAULT_ADDR,  
              strlen((const char *)MSG_SIGBUS_FAULT_ADDR)  
              );  
    
        sprintf(buffer, "%x\n", faultAddr);  
        write(2, buffer, strlen(buffer));
    }   
    
  • The problem is the instruction address (bkpt) is incorrect and does not meet the ARM v7 specification. Here is the console output after running the program:

    SIGBUS:
    : 86b0
    SIGBUS:
    : 86c0
    SIGBUS:
    : 86c0
    SIGBUS:
    : 86c0
    SIGBUS:
    : 86c0
    SIGBUS:
    : 86b0
    SIGBUS:
    : 86a8
    SIGBUS:
    : 86f0

x86 . ARM v7 .

GDB ARM v7, BKPT .

, - , ?

+3
1

, si_addr ( , ) , /.

, .. , ucontext_t*. , , , void *; GDB (, info registers ) , .

, ARM, , 64- x86, :

volatile char *ptr = (char*)0x1234567890abcdef;
char crashme = *ptr;

, si_addr 0x1234567890abcdef. , #GPF not #PF, x86. , ucontext_t/struct sigcontext ( ), , .

:

void SigBusHandler(
     int  signum,  
     siginfo_t  *pAct,  
     void  *context
    )
{
    struct sigcontext *ctx = &(((ucontext_t*)context)->uc_mcontext);
    uintptr_t fault_address = ctx->arm_pc;    /* that what you'll see on ARM */
    ...
}

, , , CPU , . /, , :

#if defined(ARM)
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.arm_pc)
#elsif defined(__i386__)
define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.eip)
#elsif defined(__amd64__)
define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.rip)
#endif

uintptr_t instr_address = GET_PC_FROM_CONTEXT(context);

, !

+4

All Articles