J'ai une passe LLVM utilisée pour renommer des fonctions. Étant donné un fichier source file.cc
, je génère le bitcode LLVM comme suit:Comment manipuler puis démembrer une fonction pendant un passage LLVM?
.
Je voudrais lancer un LLVM passer au-dessus foo.bc
et renomme tous les GLOBALS, les fonctions et les alias afin que je puisse sortir le code binaire transformé en un nouveau fichier file_renamed.bc
, puis lien file.bc
et file_renamed.bc
en un seul fichier, file_linked.bc
.
Un de mes questions que je rencontrais est que tout simplement faire F.setName(F.getName() + "_renamed")
, ajoutera le suffixe après le nom mutilée retourné par F.getName()
.
Une autre question: J'ai une fonction demangle(const std::string &Name)
en dessous demangles avec succès Name
, mais je vais avoir du mal à re-mutiler ce nom. S'il existe une meilleure façon de renommer les identifiants dans le bitcode LLVM, ou de lier deux instances du même bitcode tout en étant capable d'identifier de manière unique les fonctions et les variables globales dans chaque version, n'hésitez pas à le suggérer dans votre réponse .
Voici ma passe LLVM. Notez que j'utilise LLVM 3.4 (il est une dépendance pour le projet sur lequel je travaille.)
têtes
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cxxabi.h>
#include <memory>
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/Mangler.h"
code
using namespace llvm;
namespace {
struct FunctionRename : public ModulePass {
static char ID; // Pass identification
FunctionRename() : ModulePass(ID) {}
bool runOnModule(Module &M) override {
// Rename all globals and references to them
for (auto it = M.global_begin(); it != M.global_end(); ++it)
{...}
// Rename all aliases and references to them
for (auto it = M.alias_begin(); it != M.alias_end(); ++it)
{...}
// Rename all functions and references to them
for (auto &F : M)
{
StringRef Name = F.getName();
if (F.isDeclaration())
continue;
std::string demangled_name = demangle(Name.str());
std::string new_name = rename(demangled_name);
F.setName(mangle(new_name, &F));
F.setLinkage(GlobalValue::WeakAnyLinkage);
}
return true;
}
std::string demangle(const std::string &Name)
{
int status;
char* demangled_name = NULL;
char* cstr_name = new char[Name.length() + 1];
strcpy(cstr_name, Name.c_str());
demangled_name = __cxxabiv1::__cxa_demangle(cstr_name, NULL, NULL, &status);
if (status != 0)
{
errs() << "Demangling operation failed:\n";
switch (status)
{...}
exit(-1);
}
std::string s(demangled_name);
return s;
}
std::string rename(std::string &Name)
{
std::string search_str = std::string("(");
std::string suffix_str = std::string("_renamed");
size_t i = Name.find_first_of(search_str);
if (i == std::string::npos)
Name.append(suffix_str);
else
Name.insert(i, suffix_str);
return Name;
}
/* PROBLEMATIC FUNCTION */
std::string mangle(const std::string &Name, const GlobalValue *GV)
{
SmallString<256> MangledName(StringRef(Name));
Mangler m;
m.getNameWithPrefix((SmallVectorImpl<char>&) MangledName, GV, false, true);
Twine T;
StringRef S = T.toStringRef((SmallVectorImpl<char>&) MangledName);
return S.str();
}
};
}
// Register Pass
char FunctionRename::ID = 0;
static RegisterPass<FunctionRename> X("functionrename", "Function Rename Pass");
Je pense que votre fonction 'démangle' est également incorrecte. Il démange en utilisant la bibliothèque ABI C++ LLVM a été compilé, et bitcode peut être produit par le compilateur avec différents ABI C++. – arrowd
Si je me souviens bien le "Mangler" inclus dans LLVM n'est pas un mangler C++ mais un mangler C qui ajoute typiquement un "_" aux noms de symboles pour distinguer les symboles C des symboles d'assemblage, si vous voulez lien vers les bibliothèques clang correspondant au clang que vous avez utilisé pour générer le bitcode. – PaulR