LLVM 对函数参数的位码错误检测
Posted
技术标签:
【中文标题】LLVM 对函数参数的位码错误检测【英文标题】:LLVM's bitcode wrong detections of function's parameters 【发布时间】:2017-04-03 17:41:41 【问题描述】:我正在使用 LLVM api 来解析位码文件。我有以下 sn-p,我正在使用此命令生成位码 $CC -emit-llvm -c -g source.c
,其中 CC 设置为 clang
路径。
#include <stdio.h>
struct Point
int a;
int b;
;
int func_0(struct Point p, int x)
return 0;
TypeID 应该有一个数值,具体取决于参数的类型。但是,对于整数x
和结构Point
,我都获得了10
的值,它被称为TokenTyID
。因此,我决定分别使用函数isIntegerTy()
和isStructTy()
,看看是否至少在这种情况下,我得到了正确的结果。此解决方案适用于整数参数x
,但不适用于结构。 如何正确识别结构并读取其字段?
为了完整起见,为了解析我使用此代码的位码:
using namespace llvm;
int main(int argc, char** argv)
LLVMContext context;
OwningPtr<MemoryBuffer> mb;
MemoryBuffer::getFile(FileName, mb);
Module *m = ParseBitcodeFile(mb.get(), context);
for (Module::const_iterator i = m->getFunctionList().begin(), e = m->getFunctionList().end(); i != e; ++i)
if (i->isDeclaration() || i->getName().str() == "main")
continue;
std::cout << i->getName().str() << std::endl;
Type* ret_type = i->getReturnType();
std::cout << "\t(ret) " << ret_type->getTypeID() << std::endl;
Function::const_arg_iterator ai;
Function::const_arg_iterator ae;
for (ai = i->arg_begin(), ae = i->arg_end(); ai != ae; ++ai)
Type* t = ai->getType();
std::cout << "\t" << ai->getName().str() << " " << t->getTypeID()
<< "(" << t->getFunctionNumParams() << ")"
<< " is struct? " << (t->isStructTy() ? "Y" : "N")
<< " is int? " << (t->isIntegerTy() ? "Y" : "N")
<< "\n";
return 0;
我读了这篇 Why does Clang coerce struct parameters to ints 的帖子,内容是关于 clang 使用结构体执行的翻译,我很确定这也是我的问题。
【问题讨论】:
尝试使用clang -S -emit-llvm
转储 LLVM IR?
是的,它也不起作用。如果我用“-S”选项生成IR码,然后用“llvm-as”生成位码,问题是一样的。
我的意思是,尝试查看生成的 IR 并找出你的结构变成了什么。
生成的IR是一样的。数据结构已被替换,就像我在第一篇文章中解释的那样。
【参考方案1】:
由于 clang 更改了 IR 中的函数签名,因此您必须使用调试信息获取该信息。这是一些粗略的代码:
DITypeIdentifierMap TypeIdentifierMap;
DIType* getLowestDINode(DIType* Ty)
if (Ty->getTag() == dwarf::DW_TAG_pointer_type ||
Ty->getTag() == dwarf::DW_TAG_member)
DIType *baseTy =
dyn_cast<DIDerivedType>(Ty)->getBaseType().resolve(TypeIdentifierMap);
if (!baseTy)
errs() << "Type : NULL - Nothing more to do\n";
return NULL;
//Skip all the DINodes with DW_TAG_typedef tag
while ((baseTy->getTag() == dwarf::DW_TAG_typedef || baseTy->getTag() == dwarf::DW_TAG_const_type
|| baseTy->getTag() == dwarf::DW_TAG_pointer_type))
if (DITypeRef temp = dyn_cast<DIDerivedType>(baseTy)->getBaseType())
baseTy = temp.resolve(TypeIdentifierMap);
else
break;
return baseTy;
return Ty;
int main(int argc, char** argv)
LLVMContext context;
OwningPtr<MemoryBuffer> mb;
MemoryBuffer::getFile(FileName, mb);
Module *m = ParseBitcodeFile(mb.get(), context);
if (NamedMDNode *CU_Nodes = m.getNamedMetadata("llvm.dbg.cu"))
TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
F.getAllMetadata(MDs);
for (auto &MD : MDs)
if (MDNode *N = MD.second)
if (auto *subRoutine = dyn_cast<DISubprogram>(N)->getType())
if (!subRoutine->getTypeArray()[0])
errs() << "return type \"void\" for Function : " << F.getName().str()
<< "\n";
const auto &TypeRef = subRoutine->getTypeArray();
for (int i=0; i<TypeRef.size(); i++)
// Resolve the type
DIType *Ty = ArgTypeRef.resolve(TypeIdentifierMap);
DIType* baseTy = getLowestDINode(Ty);
if (!baseTy)
return;
// If that pointer is a struct
if (baseTy->getTag() == dwarf::DW_TAG_structure_type)
std::cout << "structure type name: " << baseTy->getName().str() << std::endl();
我知道它看起来很难看,但使用调试信息并不容易。
【讨论】:
感谢您的回复。你能把前面语句的全部代码给我吗? 当然,这里有一个代码链接:github.com/jiten-thakkar/DataStructureAnalysis/blob/dsa_llvm3.8/…我一直在为其他一些项目做这个以上是关于LLVM 对函数参数的位码错误检测的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 8.2.1 - 错误:无效的位码版本(生产者:'802.0.41.0_0' 读者:'800.0.42.1_0')
归档基于 Xcode 错误的 Unity 应用程序:无效的位码版本(生产者:'802.0.42.0_0' 读者:'800.0.42.1_0')