如何打印在C程序计数器的精确值 [英] How to print exact value of the program counter in C

查看:198
本文介绍了如何打印在C程序计数器的精确值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个C程序,将打印程序计数器 PC 的内容。这可以从用户空间,或组装,或某些特定的内核程序被用来做什么?


解决方案

您应该能够使用的 __ current_pc() ARM编译器工具链的内在(ARM编译器支持许多相同的扩展为GCC) * 这是特别ARM:

  INT的main(){
    的printf(%#x的\\ n,__current_pc());
    的printf(%#x的\\ n,__current_pc());
    的printf(%#x的\\ n,__current_pc());
    返回0;
}


  

<子> *感谢FrankH。您指出的__ current_pc的presence()


在一般情况下,个人电脑被保存在一个函数调用的返回地址。在非ARM 的Linux系统的问题,你可以叫 __ builtin_return_address(0)来获得当前函数调用的上下文的返回地址。获得这样的程序计数器即被添加一个函数调用的罚款,但它避免内汇编,所以这种技术是移植到GCC所支持的任何系统。

 无效* get_pc(){返回__builtin_return_address(0); }
诠释主(){
    的printf(%P \\ N,get_pc());
    的printf(%P \\ N,get_pc());
    的printf(%P \\ N,get_pc());
    返回0;
}

当我运行我的 86 系统上面的程序,它产生的输出:

  0x8048432
0x8048447
0x804845c

GDB 拆解:

 汇编code的转储为主要功能:
   0x08048424 1 + 0计算值:推%EBP
   0x08048425 1 + 1&GT ;: MOV%ESP,EBP%
   0x08048427 1 + 3计算值:和$ 0xfffffff0,%尤
   0x0804842a 1 + 6个;:子$为0x10,%尤
   0x0804842d 1 + 9计算值:调用0x804841c&所述; get_pc&GT;
   0x08048432 1 + 14计算值:MOV%eax中,为0x4(%尤)
   0x08048436 1 + 18计算值:MOVL $ 0x8048510,(%尤)
   0x0804843d 1 + 25计算值:调用0x80482f0&下; printf的@ PLT&GT;
   0x08048442 1 + 30计算值:调用0x804841c&所述; get_pc&GT;
   0x08048447 1 + 35计算值:MOV%eax中,为0x4(%尤)
   0x0804844b 1 + 39计算值:MOVL $ 0x8048510,(%尤)
   0x08048452 1 + 46计算值:调用0x80482f0&下; printf的@ PLT&GT;
   0x08048457 1 + 51计算值:调用0x804841c&所述; get_pc&GT;
   0x0804845c 1 + 56计算值:MOV%eax中,为0x4(%尤)
   0x08048460 1 + 60计算值:MOVL $ 0x8048510,(%尤)
   0x08048467 1 + 67计算值:调用0x80482f0&下; printf的@ PLT&GT;
   0x0804846c 1 + 72计算值:MOV $为0x0,%eax中
   0x08048471 1 + 77计算值:离开
   0x08048472 1 + 78计算值:保留
汇编转储结束。

I want to write a C program which would print the contents of the program counter PC. Can this be done from user space, or assembly, or some specific kernel routines are used?

解决方案

You should be able to determine the PC by using the __current_pc() intrinsic in the ARM compiler toolchain (the ARM compiler supports many of the same extensions as GCC).* This is particular to ARM:

int main () {
    printf("%#x\n", __current_pc());
    printf("%#x\n", __current_pc());
    printf("%#x\n", __current_pc());
    return 0;
}

* Thanks to FrankH. for pointing out the presence of __current_pc()

In general, the PC gets saved as the return address in a function call. On non-ARM systems with GCC, you can call __builtin_return_address(0) to obtain the return address of the current function call context. Obtaining the program counter in this way incurs the penalty of adding a function call, but it avoids inline assembly, so this technique is portable to any system supported by GCC.

void * get_pc () { return __builtin_return_address(0); }
int main () {
    printf("%p\n", get_pc());
    printf("%p\n", get_pc());
    printf("%p\n", get_pc());
    return 0;
}

When I run the above program on my x86 system, it produces the output:

0x8048432
0x8048447
0x804845c

When disassembled in gdb:

Dump of assembler code for function main:
   0x08048424 <+0>: push   %ebp
   0x08048425 <+1>: mov    %esp,%ebp
   0x08048427 <+3>: and    $0xfffffff0,%esp
   0x0804842a <+6>: sub    $0x10,%esp
   0x0804842d <+9>: call   0x804841c <get_pc>
   0x08048432 <+14>:    mov    %eax,0x4(%esp)
   0x08048436 <+18>:    movl   $0x8048510,(%esp)
   0x0804843d <+25>:    call   0x80482f0 <printf@plt>
   0x08048442 <+30>:    call   0x804841c <get_pc>
   0x08048447 <+35>:    mov    %eax,0x4(%esp)
   0x0804844b <+39>:    movl   $0x8048510,(%esp)
   0x08048452 <+46>:    call   0x80482f0 <printf@plt>
   0x08048457 <+51>:    call   0x804841c <get_pc>
   0x0804845c <+56>:    mov    %eax,0x4(%esp)
   0x08048460 <+60>:    movl   $0x8048510,(%esp)
   0x08048467 <+67>:    call   0x80482f0 <printf@plt>
   0x0804846c <+72>:    mov    $0x0,%eax
   0x08048471 <+77>:    leave  
   0x08048472 <+78>:    ret    
End of assembler dump.

这篇关于如何打印在C程序计数器的精确值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆