簡體   English   中英

如何在 C 中打印程序計數器的精確值

[英]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 系統上,您可以調用__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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM