[英]How to print exact value of the program counter in C
我想写一个 C 程序来打印程序计数器PC
的内容。 这可以从用户空间、程序集或使用某些特定的 kernel 例程来完成吗?
您应该能够通过使用 ARM 编译器工具链中的__current_pc()
内在__current_pc()
来确定 PC(ARM 编译器支持许多与 GCC 相同的扩展)。 *这是 ARM 特有的:
int main () {
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
return 0;
}
* 感谢 FrankH。 用于指出
__current_pc()
的存在
通常,PC 被保存为函数调用中的返回地址。 在带有 GCC 的非 ARM linux系统上,您可以调用__builtin_return_address(0)
来获取当前函数调用上下文的返回地址。 以这种方式获取程序计数器会导致添加函数调用的惩罚,但它避免了内联汇编,因此该技术可移植到 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;
}
当我在x86
系统上运行上述程序时,它会产生输出:
0x8048432
0x8048447
0x804845c
在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.
在 ARM 上,您可以使用:
static __inline__ void * get_pc(void) {
void *pc;
asm("mov %0, pc" : "=r"(pc));
return pc;
}
或者这个也应该工作:
static __inline__ void * get_pc(void) {
register void * pc __asm__("pc");
__asm__("" : "=r"(pc));
return pc;
}
强制内联在这里很重要,因为这可确保您根据调用站点检索PC
。
编辑:只记得, __current_pc()
ARM 内在的。 GCC 也应该有这个。
好吧,我认为您可以通过在 C 代码中插入汇编块来获取信息。 这将完全取决于您的编译器和您平台的寄存器集。 我是这样做的:
int get_counter1()
{
__asm__ ("lea (%rip), %eax ") ;
}
int get_counter2()
{
int x = 0;
__asm__ ("lea (%rip), %eax") ;
}
int main()
{
printf("%x\n",get_counter1());
printf("%x\n",get_counter2());
return 0;
}
4004ce
4004e1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.