[英]How to print exact value of the program counter in C
I want to write a C program which would print the contents of the program counter PC
.我想写一个 C 程序来打印程序计数器
PC
的内容。 Can this be done from user space, or assembly, or some specific kernel routines are used?这可以从用户空间、程序集或使用某些特定的 kernel 例程来完成吗?
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).您应该能够通过使用 ARM 编译器工具链中的
__current_pc()
内在__current_pc()
来确定 PC(ARM 编译器支持许多与 GCC 相同的扩展)。 * This is particular to ARM: *这是 ARM 特有的:
int main () {
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
return 0;
}
* Thanks to FrankH.
* 感谢 FrankH。 for pointing out the presence of
__current_pc()
用于指出
__current_pc()
的存在
In general, the PC gets saved as the return address in a function call.通常,PC 被保存为函数调用中的返回地址。 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.在带有 GCC 的非 ARM linux系统上,您可以调用
__builtin_return_address(0)
来获取当前函数调用上下文的返回地址。 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.以这种方式获取程序计数器会导致添加函数调用的惩罚,但它避免了内联汇编,因此该技术可移植到 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:当我在
x86
系统上运行上述程序时,它会产生输出:
0x8048432
0x8048447
0x804845c
When disassembled in gdb
:在
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.
On ARM, you can use:在 ARM 上,您可以使用:
static __inline__ void * get_pc(void) {
void *pc;
asm("mov %0, pc" : "=r"(pc));
return pc;
}
Or this one should work as well:或者这个也应该工作:
static __inline__ void * get_pc(void) {
register void * pc __asm__("pc");
__asm__("" : "=r"(pc));
return pc;
}
The forced inlining is important here, because that ensures you retrieve PC
as per the call site.强制内联在这里很重要,因为这可确保您根据调用站点检索
PC
。
Edit: just remembered, __current_pc()
ARM intrinsic .编辑:只记得,
__current_pc()
ARM 内在的。 GCC should have this as well. GCC 也应该有这个。
Well I think you can get the information by inserting assembly blocks inside your C code.好吧,我认为您可以通过在 C 代码中插入汇编块来获取信息。 This will totally depend on your compiler and the register set of your platform.
这将完全取决于您的编译器和您平台的寄存器集。 I did it like this:
我是这样做的:
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 4004ce
4004e1 4004e1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.