You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LLVM 13/14中如何检测全局变量是否为字符串?

LLVM/Clang 13-14中检测全局字符串变量的替代方案

早期LLVM/Clang版本里,我靠GlobalVar->getName()判断全局变量名是否以.str结尾来识别字符串变量,但在13、14版本里,全局变量名变成了类似??_C@_0M@LACCCNMM@hello?5world?$AA@的特殊命名,原方法失效。尝试解析这类名称后还是没法判断,想知道有没有合适的LLVM函数能实现这个检测,或者我的操作哪里有问题?

附示例C代码及编译命令:

// compiled with: clang.exe -std=c99 helloCC.c -o helloCC.exe -mllvm -my_get_strings=1 -flegacy-pass-manager

#include <stdio.h>

char *xmy1 = "hello world";

int main(int argc, char *argv[]) {
   printf("%s", xmy1);
   return 0;
}

注:已手动修改LLVM/Clang代码,将自定义Pass添加至PassManagerBuilder.cpp的populateModulePassManager函数中,通过-flegacy-pass-manager参数触发执行。


解决方案

1. 放弃依赖变量名,直接从IR结构判断

LLVM IR中,字符串常量全局变量有明确的类型和初始化特征,不需要靠名称识别:

  • 全局变量的类型是PointerType,指向的是ArrayType,且数组元素为i8(对应C语言的char)
  • 变量的初始化器(Initializer)是ConstantDataArray类型,这类对象专门存储字符串或字节常量

示例代码片段:

if (GlobalVariable *GV = dyn_cast<GlobalVariable>(&I)) {
    // 检查是否为指向i8数组的指针
    if (PointerType *PT = dyn_cast<PointerType>(GV->getType())) {
        if (ArrayType *AT = dyn_cast<ArrayType>(PT->getElementType())) {
            if (AT->getElementType()->isIntegerTy(8)) {
                // 检查是否存在常量初始化器
                if (Constant *Init = GV->getInitializer()) {
                    if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Init)) {
                        // 确认是字符串常量全局变量
                        StringRef rawStr = CDA->getAsString();
                        // 可直接获取字符串内容做后续处理
                    }
                }
            }
        }
    }
}

2. 关于特殊命名的原因

你看到的??_C@_...不是LLVM层面的混淆,是Windows平台下Clang兼容MSVC的字符串池命名规则生成的名称,这类名称是编译器自动生成的,没有通用的解析规则,所以解混淆的思路不可行。

3. Pass执行阶段的注意事项

确保你的自定义Pass在优化Pass之前运行:LLVM的优化阶段可能会对全局变量做合并、重命名或删除操作,晚于优化阶段执行会导致检测结果不准确。你通过-flegacy-pass-manager使用旧版Pass管理器,只要Pass添加到populateModulePassManager的顺序在优化Pass之前,就不会有问题。

内容的提问来源于stack exchange,提问作者m00nic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:01:17