如何在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()
一般来说,PC 被保存为函数调用中的返回地址.在带有 GCC 的非 ARM linux 系统上,您可以调用 __builtin_return_address(0)
获取当前函数调用上下文的返回地址.以这种方式获取程序计数器会产生添加函数调用的惩罚,但它避免了内联汇编,因此该技术可移植到任何 GCC 支持的系统.
__attribute__ ((__noinline__))void * get_pc () { return __builtin_return_address(0);}int主(){printf("%p\n", get_pc());printf("%p\n", get_pc());printf("%p\n", get_pc());返回0;}
当我在我的 x86
系统上运行上述程序时,它产生输出:
0x80484320x80484470x804845c
在gdb
中反汇编时:
转储函数 main 的汇编代码:0x08048424 <+0>:推%ebp0x08048425 <+1>: mov %esp,%ebp0x08048427 <+3>: 和 $0xfffffff0,%esp0x0804842a <+6>: sub $0x10,%esp0x0804842d <+9>:调用 0x804841c <get_pc>0x08048432 <+14>: mov %eax,0x4(%esp)0x08048436 <+18>: movl $0x8048510,(%esp)0x0804843d <+25>:调用 0x80482f0 <printf@plt>0x08048442 <+30>:调用 0x804841c <get_pc>0x08048447 <+35>: mov %eax,0x4(%esp)0x0804844b <+39>: movl $0x8048510,(%esp)0x08048452 <+46>:调用 0x80482f0 <printf@plt>0x08048457 <+51>:调用 0x804841c <get_pc>0x0804845c <+56>: mov %eax,0x4(%esp)0x08048460 <+60>: movl $0x8048510,(%esp)0x08048467 <+67>:调用 0x80482f0 <printf@plt>0x0804846c <+72>: mov $0x0,%eax0x08048471 <+77>:离开0x08048472 <+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.
__attribute__ ((__noinline__))
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屋!