如何在LLVM中获取原始源代码和行号?
我从LLVM源代码树的Hello.cpp修改了以下代码。代码当前打印函数、指令和操作数 我还想打印所访问的函数、指令和变量的源文件名和行号。有人能告诉我怎么做吗如何在LLVM中获取原始源代码和行号?,llvm,Llvm,我从LLVM源代码树的Hello.cpp修改了以下代码。代码当前打印函数、指令和操作数 我还想打印所访问的函数、指令和变量的源文件名和行号。有人能告诉我怎么做吗 $ cat Hello.cpp /* vim: set noexpandtab tabstop=2: */ #include "llvm/ADT/Statistic.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" #include "llvm/Pass
$ cat Hello.cpp
/* vim: set noexpandtab tabstop=2: */
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "hello"
STATISTIC(HelloCounter, "Counts number of functions greeted");
namespace {
// Hello - The first implementation, without getAnalysisUsage.
struct Hello : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
Hello() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
++HelloCounter;
errs() << "Hello: ";
errs().write_escaped(F.getName()) << '\n';
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
errs() << "I:" << *I << "\n";
for (Use &U : I->operands()) {
Value *v = U.get();
errs() << "v:" << *v << "\n";
}
}
return false;
}
};
}
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass");
$ ./main.sh ;./opt.sh
Hello: main
I: %1 = alloca i32, align 4
v:i32 1
I: store i32 0, i32* %1, align 4
v:i32 0
v: %1 = alloca i32, align 4
I: call void (...) bitcast (void ()* @f to void (...)*)()
v:void (...)* bitcast (void ()* @f to void (...)*)
I: ret i32 0
v:i32 0
Hello: f
I: %1 = load i32, i32* @U, align 4
v:@U = common dso_local global i32 0, align 4
I: %2 = add nsw i32 %1, 1
v: %1 = load i32, i32* @U, align 4
v:i32 1
I: store i32 %2, i32* @U, align 4
v: %2 = add nsw i32 %1, 1
v:@U = common dso_local global i32 0, align 4
I: ret void
==> main.sh <==
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:
compile=(
c++
-I"$HOME"/opt/llvm/include
-std=c++11 -Wall -pedantic
-g -fPIC
-fno-rtti
-o Hello.cpp.o -c Hello.cpp
)
"${compile[@]}"
link=(
c++
-Wl,-flat_namespace -Wl,-undefined -Wl,suppress
-o x.so
Hello.cpp.o
)
"${link[@]}"
==> opt.sh <==
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:
cmd=(
~/opt/llvm/bin/opt
-load x.so
-hello
)
"${cmd[@]}" < hello.bc > /dev/null
==> hello.c <==
/* vim: set noexpandtab tabstop=2: */
#include <stdio.h>
int U;
void f();
int main() {
f();
return 0;
}
==> f.c <==
/* vim: set noexpandtab tabstop=2: */
#include <stdio.h>
extern int U;
void f() {
++U;
}
$cat Hello.cpp
/*vim:设置noexpandtab tabstop=2:*/
#包括“llvm/ADT/Statistic.h”
#包括“llvm/IR/Function.h”
#包括“llvm/IR/InstIterator.h”
#包括“llvm/Pass.h”
#包括“llvm/Support/raw_ostream.h”
使用名称空间llvm;
#定义调试类型“hello”
统计(HelloCounter,“统计函数的数量”);
名称空间{
//Hello-第一个实现,没有getAnalysisUsage。
struct Hello:public FunctionPass{
静态字符ID;//传递标识,替换typeid
Hello():FunctionPass(ID){}
bool runOnFunction(功能和F)覆盖{
++HelloCounter;
errs()您需要将这些值强制转换为指令
,然后可以通过DebugLoc
类访问调试信息:
Value *v = U.get();
Instruction *instruction = dyn_cast<Instruction>(v);
const llvm::DebugLoc &debugInfo = instruction->getDebugLoc();
std::string directory = debugInfo->getDirectory();
std::string filePath = debugInfo->getFilename();
int line = debugInfo->getLine();
int column = debugInfo->getColumn();
Value*v=U.get();
指令*指令=动态转换(v);
const llvm::DebugLoc&debugInfo=指令->getDebugLoc();
std::string directory=debugInfo->getDirectory();
std::string filePath=debugInfo->getFilename();
int line=debugInfo->getLine();
int column=debugInfo->getColumn();
UPD:确保包含所需的头文件:
#include <llvm/IR/DebugLoc.h>
#include <llvm/IR/DebugInfoMetadata.h>
#包括
#包括
请注意,只有在启用调试信息的情况下编译源文件时,这才可能。这些信息看起来像文件末尾的许多行,如!39186=!DILocation(行:481,作用域:!39143)
(以及其他一些DIfoobar),以及一些IR指令上的一些标记,如!dbg!39186
。您需要从开始。我遇到了以下错误。您知道怎么回事吗?Hello.cpp:32:39:错误:成员访问不完整的类型“llvm::DILocation”std::string directory=debugInfo->getDirectory()/Users/pengy/opt/llvm/include/llvm/IR/Metadata.def:83:42:注意:转发声明'llvm::DILocation'
@user1424739您需要包含标题文件包含这些类的定义:我将更新答案。我遇到了分段错误。您能帮助尝试编码并查看有什么问题?I:%1=alloca i32,对齐4堆栈转储:……14 opt 0x000000010f41d201 llvm::legacy::PassManager::run(llvm::Module&)+33 15 opt 0x000000010c80c234 main+28116 16 libdyld.dylib 0x00007fff569f0015 start+1./opt.sh:第12行:80208分段错误:11“${cmd[@]}“…
指令可能没有调试信息。调用debugInfo->getDirectory()
相当于debugInfo.get()->getDirectory()
,其中
返回指向DILocation
的指针,在本例中可能是空指针。添加更多错误处理。不确定如何执行。我尝试了此操作。但它仍然会产生分段错误。请尝试该程序,看看有什么问题吗?谢谢。auto di=debugInfo.get();if(di==null){errs()getFilename();int line=di->getLine();int column=di->getColumn();errs()