如何使用调用和分配指令在 llvm 字节码中查找类名

How to locate class name in the llvm bytecode, using call and alloca instructions?

本文关键字:字节 查找 llvm 调用 何使用 分配 指令      更新时间:2023-10-16

我有以下C++代码:

class Date {
public:  
  Date(int, int, int);
private:
  int year; int month; int day;
};
extern "C" int main(int argc, char *argv[])
{
   Date today(1,9,2014);
   //....
   return 0;
}
Date::Date(int d, int m, int y) { day = d; month = m; year =y; }

对应的字节码为:

@_ZN4DateC1Eiii = alias void (%class.Date*, i32, i32, i32)* @_ZN4DateC2Eiii
define i32 @main(i32 %argc, i8** %argv) {
entry:
  %retval = alloca i32, align 4
  %argc.addr = alloca i32, align 4
  %argv.addr = alloca i8**, align 4
  %today = alloca %class.Date, align 4
  store i32 0, i32* %retval
  store i32 %argc, i32* %argc.addr, align 4
  call void @llvm.dbg.declare(metadata !{i32* %argc.addr}, metadata !922), !dbg !923
  store i8** %argv, i8*** %argv.addr, align 4
  call void @llvm.dbg.declare(metadata !{i8*** %argv.addr}, metadata !924), !dbg !923
  call void @llvm.dbg.declare(metadata !{%class.Date* %today}, metadata !925), !dbg !927
  call void @_ZN4DateC1Eiii(%class.Date* %today, i32 1, i32 9, i32 1999), !dbg !927
  //...
  ret i32 0, !dbg !930
}
  //...
define void @_ZN4DateC2Eiii(%class.Date* %this, i32 %d, i32 %m, i32 %y) unnamed_addr nounwind align 2 {
entry:
  //...
}

我正在解析此代码,我需要在此语句中提取类名:% today = alloca% class.Date, align 4 有什么办法可以查看刚刚返回的:class.Date ???

我还需要知道如何从调用开始@ _ZN4DateC2Eiii函数:

call void @ _ZN4DateC1Eiii (class.Date% *% today, i32 1, i32 9, i32 1999)! dbg! 927.

Clang 将使用类名来命名 LLVM 类型,如您在示例中所看到的(它使用 %class.Date 作为类型名称)。但是,获取类型名称的唯一可靠方法是查询调试信息。为此:

  1. 确定您关心alloca

  2. 迭代函数,直到找到对llvm.dbg.declare的调用,其中第一个参数是包装 (1) 中的值的元数据节点。

    • 您可以使用isa<DbgDeclareInst>

  3. 创建一个新的DIVariable实例,将 (2) 中的元数据节点作为构造函数参数传递。

  4. 您可以通过从 (3) 中调用对象上的getType来检索对象的类DIType类型。可以在类型 DIType 的对象上使用 getName 来获取类型名称。