LLVM: нет выявленных структур - PullRequest
2 голосов
/ 08 января 2020

Я хочу извлечь каждую структуру в файл битового кода (.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.

...