2013-08-21 2 views
5

Я хочу написать программу на C, которая будет печатать содержимое счетчика программ PC. Можно ли это сделать из пользовательского пространства или сборки или использовать некоторые определенные подпрограммы ядра?Как напечатать точное значение счетчика программ в C

+0

Код отладчика контролирует/получает доступ к ПК, поэтому я должен использовать способ построения встроенной сборки. –

+0

@GrijeshChauhan: Как вы думаете, может быть расширение GCC для счетчика программ? –

+1

Да, я не очень уверен, но я чувствую, что над этим примечанием должен быть какой-то способ: если в коде у вас есть 'lable:', то вы можете распечатать его адрес, используя '& lable' (это заставляет меня сказать« да »). Очень задний код (законный) использует этот вид инструкций, но часто использует код вредоносного кода, поэтому его хорошая функция. –

ответ

11

Вы должны быть в состоянии определить компьютер с помощью __current_pc() intrinsic в инструментарии, ARM компилятор (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()

В общем, компьютер будет сохранен как обратный адрес в вызове функции. В системах без ARM с GCC вы можете позвонить __builtin_return_address(0), чтобы получить обратный адрес текущего контекста вызова функции. Таким образом, получение счетчика программы приводит к штрафу за добавление вызова функции, но оно позволяет избежать встроенной сборки, поэтому этот метод переносится на любую систему, поддерживаемую GCC.

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 <[email protected]> 
    0x08048442 <+30>: call 0x804841c <get_pc> 
    0x08048447 <+35>: mov %eax,0x4(%esp) 
    0x0804844b <+39>: movl $0x8048510,(%esp) 
    0x08048452 <+46>: call 0x80482f0 <[email protected]> 
    0x08048457 <+51>: call 0x804841c <get_pc> 
    0x0804845c <+56>: mov %eax,0x4(%esp) 
    0x08048460 <+60>: movl $0x8048510,(%esp) 
    0x08048467 <+67>: call 0x80482f0 <[email protected]> 
    0x0804846c <+72>: mov $0x0,%eax 
    0x08048471 <+77>: leave 
    0x08048472 <+78>: ret  
End of assembler dump. 
+1

Обратный адрес и ПК ('EIP' /' RIP') _не_ то же самое. –

+0

извинения, в ARM Я должен сказать, что обратный адрес ('LR') и' PC' - это то же самое. –

+0

И еще ... причина, по которой вы работаете, - это то, что вы используете функцию call_ (что делает 'LR' в вашей функции' PC' сайта вызова). Это необязательно неэффективно. –

2

Ну, я думаю, вы можете получить информацию, вставив сборочные блоки в свой код 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

5

На 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 intrinsic. GCC также должен иметь это.

Смежные вопросы