如何打印在C程序计数器的精确值 [英] How to print exact value of the program counter in 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 linux 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屋!