2025-10-20
今天在npc上实现itrace的时候碰到了一个很坑的问题,当然这也可能是我知识不丰富的原因。
NEMU的实现itrace的时候要用到反汇编相关函数,实现的方法是在一个disasm.c中定义了disassemble函数,这个函数会用到capstone动态链接库的内容。让我卡了一段时间的错误有两个,一个是这个动态链接库怎么处理,另一个是这个反汇编函数的初始化函数init_disasm一直报错。
第一个问题其实比较简单,NEMU中是用了dlopen打开动态链接库然后加载函数句柄来调用动态链接库里的内容的,所以这部分不需要处理,在c代码中指定好库的位置即可。
第二个问题有点坑,原先的init_disasm函数是这样的
void init_disasm() {
void *dl_handle;
dl_handle = dlopen("tools/capstone/repo/libcapstone.so.5", RTLD_LAZY);
assert(dl_handle);
cs_err (*cs_open_dl)(cs_arch arch, cs_mode mode, csh *handle) = NULL;
cs_open_dl = dlsym(dl_handle, "cs_open");
assert(cs_open_dl);
cs_disasm_dl = dlsym(dl_handle, "cs_disasm");
assert(cs_disasm_dl);
cs_free_dl = dlsym(dl_handle, "cs_free");
assert(cs_free_dl);
...
在NPC下编译的时候会报这种错误
invalid conversion from 'void*' to 'cs_err (*)(cs_arch,cs_mode,csh*)
dlsym的作用是在打开的库中寻找匹配的函数并返回函数指针,在NEMU中这样是没问题的,因为NEMU都是按照C语言来编译的,C语言允许这种隐式的类型转换,但是NPC是用Verilator编译的,是按照CPP编译的,而C++是不允许这种写法的,所以需要显示得指出函数类型转换,最终代码如下
void init_disasm() {
void *dl_handle;
dl_handle = dlopen("lib/libcapstone.so.5", RTLD_LAZY);
assert(dl_handle);
cs_err (*cs_open_dl)(cs_arch arch, cs_mode mode, csh *handle) = NULL;
//cs_open_dl = (cs_err (*)(cs_arch,cs_mode,csh*))dlsym(dl_handle, "cs_open");
cs_open_dl = dlsym(dl_handle, "cs_open");
assert(cs_open_dl);
//cs_err (*cs_disasm_dl)(cs_arch arch, cs_mode mode, csh *handle) = NULL;
cs_disasm_dl = (size_t(*)(csh,const uint8_t*,size_t,uint64_t,size_t,cs_insn**))dlsym(dl_handle, "cs_disasm");
assert(cs_disasm_dl);
//cs_err (*cs_free_dl)(cs_arch arch, cs_mode mode, csh *handle) = NULL;
cs_free_dl = (void(*)(cs_insn*,size_t))dlsym(dl_handle, "cs_free");
assert(cs_free_dl);
...
只是个简单的问题,但是因为前置知识缺乏,这个问题研究了好久