首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ARM v7 BKPT指令在Linux2.6.35上不能正常工作

ARM v7 BKPT指令在Linux2.6.35上不能正常工作
EN

Stack Overflow用户
提问于 2011-05-11 12:58:41
回答 1查看 1.6K关注 0票数 3

我在Linux2.6.35上与ARM v7上的BKPT指令有关联。其主要原因是故障指令地址(bkpt)不正确,不符合ARM v7手册。

以下是复制的步骤:

  1. 将OS处理程序重新定义为我的SIGBUS处理程序:void(){ sa.sa_sigaction sa;memset(&sa,0,sizeof(sa));sa.sa_flags = SA_SIGINFO;σ填充集(&sa.sa_mask);sa.sa_sigaction= SigBusHandler;sigaction( SIGBUS,&sa,NULL);}
  2. 使用内联_asm并将"BKPT“指令放入main()函数中的代码中: inline (int,char **argv) { InitSigBusHandler();__asm ( "bkpt\n\t”);返回0;}
  3. ,这里是SIGBUS处理程序:

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)契约->si_addr;memcpy((void *)缓冲区,(void *)MSG_SIGBUS_FAULT_ADDR,strlen(MSG_SIGBUS_FAULT_ADDR) );写(2,(const char *)MSG_SIGBUS_FAULT_ADDR,strlen((const char *)MSG_SIGBUS_FAULT_ADDR );sprintf(缓冲器,"%x\n",faultAddr);

  • 问题是指令的错误入口(bkpt)是错误的,不符合ARM v7规范。以下是程序运行后的控制台输出:

在SIGBUS处理程序中:

故障地址: 86b0

在SIGBUS处理程序中:

故障地址: 86c0

在SIGBUS处理程序中:

故障地址: 86c0

在SIGBUS处理程序中:

故障地址: 86c0

在SIGBUS处理程序中:

故障地址: 86c0

在SIGBUS处理程序中:

故障地址: 86b0

在SIGBUS处理程序中:

故障地址: 86a8

在SIGBUS处理程序中:

故障地址: 86f0

在x86体系结构上,此示例正确工作。在ARM v7体系结构上,这个示例有一个奇怪的行为。

如果我在ARM v7上使用GDB,他会用正确的地址捕获我的BKPT指令。

也许有人知道我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-05-11 15:14:15

假定si_addr是精确的(即故障发生时操作的实际地址)对于断点陷阱来说不一定是真/可移植的。

您确实需要检查保存的寄存器状态,即信号处理程序的第三个参数,该参数可以转换为ucontext_t*。状态在CPU之间是不可移植的,因此泛型接口只传递一个void *;GDB检查它(以便info registers工作),并从那里提取故障的程序计数器,这就是它能够指向断点指令的原因。

您在ARM上遇到的情况与在64位x86上尝试的情况类似:

代码语言:javascript
运行
复制
volatile char *ptr = (char*)0x1234567890abcdef;
char crashme = *ptr;

您希望si_addr中的故障地址是0x1234567890abcdef。情况并非如此,因为access上的这个地址将创建一个#GPF而不是#PF错误,而前者不会在x86上设置故障地址寄存器。如果您查看保存为ucontext_t / struct sigcontext (嵌入在其中)的一部分的程序计数器,您将看到错误指令地址,这将是精确的。

将信号处理程序更改为:

代码语言:javascript
运行
复制
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's what you'll see on ARM */
    ...
}

如前所述,问题在于计算出CPU寄存器状态必然会给您提供依赖CPU的代码。您必须做一些调整/包装才能保持这种可移植性,例如:

代码语言:javascript
运行
复制
#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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5964642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档