c - 如何在 C 中打印程序计数器的精确值

标签 c linux assembly linux-kernel arm

我想编写一个 C 程序来打印程序计数器 PC 的内容。这可以从用户空间、程序集或使用某些特定的内核例程来完成吗?

最佳答案

您应该能够使用 __current_pc() intrinsic 确定 PC在 ARM 编译器工具链中(ARM 编译器支持许多与 GCC 相同的扩展)。* 这是 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()

一般来说,PC 被保存为函数调用中的返回地址。在非 ARM 上 在带有 GCC 的系统中,可以调用 __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.

关于c - 如何在 C 中打印程序计数器的精确值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18350021/

相关文章:

linux - 增加 Linux 中 TCP/IP 连接的最大数量

c - 标准缓冲区在系统()调用之前没有被清除

c - 关于 AT&T 汇编语法 (%esp,1)

c - 当我打开二进制文件时,fwrite() 和 fread() 如何工作

Java Class.isAssignableFrom 总是返回 false ... 仅在 IDE 之外

c - Makefile -o,为什么需要.o

linux - 尝试将地址复制到结构时出现段错误?

linux - GCC:内联汇编中的 putchar(char)

c - 什么是看门狗?

c - C语言中将变量放入数组中