函数轨迹的桩的简单梳理

发布时间 2023-05-05 07:40:17作者: zwlwf

函数轨迹的桩的简单梳理

  1. 可以参考某个Pass,如Passes/DataflowAnalysis.cpp, Passes/DataflowAnalysis.h的文件,在这个文件的基础修改,

  2. runFunction()的实现大致如下,

static int funCnt = 0; // 给每个函数编号
for(BinaryFunction *func : BC) {
  BinaryBasicBlock *entryBB = *func->begin();
  insertPlugin(entryBB);
  BinaryBasisBlock *exitBB = *std::prev(func->end());
  appendPlugin(exitBB);
}
}

void insertPlugin(BB) {
// stp x0, x1, [sp, -16]!
// msr x1, #NZCV
// mov x0, funCnt&0xffff; // funCnt设为uint64_t, 需要分4步进行移动, movk一次可以移动16bit, 2B
// movk x0, (funCnt>>16)&0xffff, lsl 16 
// movk x0, (funCnt>>32)&0xffff, lsl 32
// movk x0, (funCnt>>48)&0xffff, lsl 48
// call recordFunctinEntry(uint64_t); // recordFunctionEntry中,首先需要保存所有寄存器的状态,或者你明确知道会修改的寄存器集合状态
// mrs x1, #NZCV
// ldp x0, x1, [sp], 8
  insert_All_Of_Above_Instructions_before_block();
}

void appendPlugin(BB) {
// stp x0, x1, [sp, -16]!
// msr x1, #NZCV
// mov x0, funCnt&0xffff; // funCnt设为uint64_t, 需要分4步进行移动, movk一次可以移动16bit, 2B
// movk x0, (funCnt>>16)&0xffff, lsl 16 
// movk x0, (funCnt>>32)&0xffff, lsl 32
// movk x0, (funCnt>>48)&0xffff, lsl 48
// call recordFunctinExit(uint64_t); // recordFunctionEntry中,首先需要保存所有寄存器的状态,或者你明确知道会修改的寄存器集合状态
// mrs x1, #NZCV
// ldp x0, x1, [sp], 8
  insert_All_Of_Above_Instructions_before_block();
}
  1. 添加一个instr.cpp, 其中实现recordFunctionEntry和recordFunctionExit函数, 在这两个函数中,需要添加控制开关,以便我们在合适的时机打开水龙头接水。
recordFunctionEntry() {
SAVE_ALL
bl __recordFunctionEntry();
RESTORE_ALL
}

入口/出口函数传入的仅仅是函数的id,需要收集起来,然后写到文件中。

#define MAXLEN 10000
uint64_t g_functionTrace[MAXLEN];
void __recordFunctionEntry(uint64_t id) {
if(!g_probe_switch_on) return;
static uint32_t len = 0;
g_functionTrace[len++] = id;
}
  1. 需要准备一个probe的开始和结束处理函数。
void probe_start() {
   g_probe_switch_on = 1;
}

void probe_end() {
  FILE *fp = fopen("/
}
  1. 若是交互式执行程序,就在自己希望程序开始采集数据的时候手动敲一下probe_start(), 希望结束的时候手动敲一下probe_end(). 若为非交互式程序,就将probe_start放到程序的启动运行中,probe_end()放在程序的结束运行中。