Как добавить ассемблерный код в пролог и эпилог всех функций с инструментальным кодом?
Каждый .
Я работаю над проектом C, и мне нужен способ добавления кода сборки в пролог и эпилог каждой функции в исходном коде.
Позвольте привести пример.
Это исходный код:
int main(int argc, char *argv[]){
char buff[20];
int a = 20;
printf("Variable a: %d\n", a);
}
Относительный код сборки таков:
0x0000000000001169 <+0>: endbr64
0x000000000000116d <+4>: push rbp
0x000000000000116e <+5>: mov rbp,rsp
0x0000000000001171 <+8>: sub rsp,0x40
0x0000000000001175 <+12>: mov DWORD PTR [rbp-0x34],edi
0x0000000000001178 <+15>: mov QWORD PTR [rbp-0x40],rsi
0x000000000000117c <+19>: mov rax,QWORD PTR fs:0x28
0x0000000000001185 <+28>: mov QWORD PTR [rbp-0x8],rax
0x0000000000001189 <+32>: xor eax,eax
0x000000000000118b <+34>: mov DWORD PTR [rbp-0x24],0x14
0x0000000000001192 <+41>: mov eax,DWORD PTR [rbp-0x24]
0x0000000000001195 <+44>: mov esi,eax
0x0000000000001197 <+46>: lea rdi,[rip+0xe66] # 0x2004
0x000000000000119e <+53>: mov eax,0x0
0x00000000000011a3 <+58>: call 0x1070 <printf@plt>
0x00000000000011a8 <+63>: mov eax,0x0
0x00000000000011ad <+68>: mov rdx,QWORD PTR [rbp-0x8]
0x00000000000011b1 <+72>: xor rdx,QWORD PTR fs:0x28
0x00000000000011ba <+81>: je 0x11c1 <main+88>
0x00000000000011bc <+83>: call 0x1060 <__stack_chk_fail@plt>
0x00000000000011c1 <+88>: leave
0x00000000000011c2 <+89>: ret
Теперь я хочу найти способ автоматически добавлять мой ассемблерный код в пролог и эпилог, когда я его компилирую. А потом получится такая ситуация:
0x0000000000001169 <+0>: endbr64
0x000000000000116d <+4>: push rbp
0x000000000000116e <+5>: mov rbp,rsp
0x0000000000001171 <+8>: sub rsp,0x40
0x0000000000001175 <+12>: mov DWORD PTR [rbp-0x34],edi
0x0000000000001178 <+15>: mov QWORD PTR [rbp-0x40],rsi
0x000000000000117c <+19>: mov rax,QWORD PTR fs:0x28
0x0000000000001185 <+28>: mov QWORD PTR [rbp-0x8],rax
// instrument code here...
0x0000000000001189 <+32>: xor eax,eax
0x000000000000118b <+34>: mov DWORD PTR [rbp-0x24],0x14
0x0000000000001192 <+41>: mov eax,DWORD PTR [rbp-0x24]
0x0000000000001195 <+44>: mov esi,eax
0x0000000000001197 <+46>: lea rdi,[rip+0xe66] # 0x2004
0x000000000000119e <+53>: mov eax,0x0
0x00000000000011a3 <+58>: call 0x1070 <printf@plt>
0x00000000000011a8 <+63>: mov eax,0x0
// instrument code here...
0x00000000000011ad <+68>: mov rdx,QWORD PTR [rbp-0x8]
0x00000000000011b1 <+72>: xor rdx,QWORD PTR fs:0x28
0x00000000000011ba <+81>: je 0x11c1 <main+88>
0x00000000000011bc <+83>: call 0x1060 <__stack_chk_fail@plt>
0x00000000000011c1 <+88>: leave
0x00000000000011c2 <+89>: ret
Я провел много исследований по этому поводу. И я не мог найти ничего, что объясняло бы, как это сделать.
Я знаю, что компилятор gcc предлагает-finstrument-functions
возможность инструментировать функции, но это не то, что мне нужно. Это потому, что этот вариант включает добавление этих двух функций:
void __cyg_profile_func_enter(void *func, void *callsite);
void __cyg_profile_func_exit(void *func, void *callsite);
что в соответствующей сборке оказываются вызовы этих функций, а это не то, что я хочу.
Я читал, что через плагин gcc, возможно, вы сможете получить такой результат, но документация действительно плохая.
Я также читал кое-что о DynamoRio, но думаю, что мне нужна статическая, а не динамическая измерительная система.
Может ли кто-нибудь указать мне правильное направление? Спасибо всем заранее!