2017-07-27 4 views
1

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"); 
+1

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

+0

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

Répondre

1

Vous ne pouvez pas facilement mangle les identifiants C++ juste à partir de la chaîne. Vous devez avoir un bon C++ AST. En fait, je ne vois pas pourquoi vous auriez besoin de ce truc de mangle/démembrement. Puisque vous travaillez au niveau IR LLVM, vous ne devriez pas vous soucier des détails de la langue (comme le nom original non-remanié).