Я хочу извлечь каждую структуру в файл битового кода (.b c) и сохранить его на карте. Для каждой структуры я создаю отдельный объект StructDescriptor, в котором хранится информация о каждом члене структуры, в частности о членах-указателях функций. Однако, когда я запускаю программу, она возвращает отсутствие идентифицированных структур (Module->getIdentifiedStructTypes()
).
Меня удивляет то, что тот же код работает при вставке его в класс CallGraph
LLVM и выполнении opt
в том же файле битового кода.
Parser. cpp:
#include <string>
#include <vector>
#include <set>
#include <stdexcept>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Constants.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/SourceMgr.h>
#include <CallGraph.h>
#include <ModuleContext.h>
#include <StructDescriptor.h>
#include <InstructionUtils.h>
using namespace llvm;
/*
* Command line arguments. See docs/CommandLine.rst for more information.
*/
static cl::list<std::string>
LLVMIRFiles(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore);
/*
* LLVM Module list for all LLVM IR files passed in the command line.
*/
static std::vector<std::pair<Module *, StringRef>> LLVMModules;
int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
SMDiagnostic Err;
outs() << "Parsing " << LLVMIRFiles.size() << " LLVM IR file(s)...\n";
for (unsigned i = 0; i < LLVMIRFiles.size(); i++) {
LLVMContext *C = new LLVMContext();
Module *M = parseIRFile(LLVMIRFiles[i], Err, *C).get();
if (M == NULL) {
errs() << "Failed to parse " << LLVMIRFiles[i] << ", skip...\n";
continue;
}
LLVMModules.push_back(std::make_pair(M, LLVMIRFiles[i]));
}
if (LLVMModules.size() != 0) {
errs() << LLVMModules.size() << " modules found.\n";
}
CallGraph *GC = new CallGraph();
for (auto pair : LLVMModules) {
GC->registerStructTypes(pair.first);
}
GC->dumpStructTypes();
}
CallGraph. cpp:
void CallGraph::registerStructTypes(Module *M) {
if (M->getIdentifiedStructTypes().size() == 0) {
errs() << "No identified structs in module.\n";
return;
}
for (StructType *T : M->getIdentifiedStructTypes()) {
StructDescriptor S(T);
for (unsigned N = 0; N < T->getNumElements(); ++N) {
PointerType *P = dyn_cast<PointerType>(T->getElementType(N));
if (!P || !P->isFunctionPtrTy())
continue;
errs() << "Found function pointer at index " << N << ", insert...\n";
S.registerFunctionPointer(N);
}
if (S.hasFunctionPointers())
StructMap[T] = std::make_unique<StructDescriptor>(S);
}
}
void CallGraph::dumpStructTypes() {
errs() << StructMap.size() << " entries found.\n";
auto it = struct_begin();
while (it != struct_end()) {
it->second.get()->print();
it++;
}
}
Эта программа возвращает:
Parsing 1 LLVM IR file(s)...
1 modules found.
No identified structs in module.
0 entries found.
У меня та же функция registerStructTypes
в исходном коде LLVM. Когда я запускаю opt
для того же файла с битовым кодом с параметром --print-callgraph
, вывод выглядит следующим образом (сокращенно):
Found function pointer at index 0, insert...
Почему M->getIdentifiedStructTypes()
пустой список в моей внешней программе C ++, в то время как тот же код работает при вызове opt
? Я использую самостоятельно построенную версию 10.0.0 LLVM / clang.