Ich habe einen LLVM-Pass verwendet, um Funktionen umzubenennen. Gegeben einige Quelldatei file.cc
, erzeuge ich LLVM Bitcode wie folgt:Wie kann man eine Funktion während des LLVM-Passes verfälschen und dann abmildern?
clang -c -o foo.bc -emit-llvm foo.cc
.
Ich möchte ein LLVM übergehen foo.bc
und benennen Sie alle Globals, Funktionen und Aliase, so dass ich ausgeben kann das transformierte Bitcode in eine neue Datei file_renamed.bc
und dann Link file.bc
und file_renamed.bc
in einer einzigen Datei file_linked.bc
, auszuführen.
Eines meiner Probleme ist mir begegnet, dass einfach F.setName(F.getName() + "_renamed")
tun, wird das Suffix nach dem verstümmelten Namen von F.getName()
zurück hinzufügen.
Ein weiteres Problem: Ich habe eine Funktion demangle(const std::string &Name)
darunter, dass erfolgreich Name
, aber ich habe Probleme, diesen Namen wieder Mangeln.
Wenn es eine bessere Möglichkeit gibt, Kennungen in LLVM-Bitcode umzubenennen oder zwei Instanzen desselben Bitcodes zu verknüpfen, aber die Funktionen und globalen Variablen in jeder Version eindeutig zu identifizieren, können Sie sie in Ihrer Antwort vorschlagen .
Hier ist mein LLVM-Pass. Beachten Sie, dass ich mit LLVM 3.4 (es eine Abhängigkeit für das Projekt arbeite ich an.)
Headers
#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");
Ich denke, Ihre 'Entmagnetisierung'-Funktion ist auch falsch. Es fordert ab, C++ - ABI-Bibliothek zu verwenden, für die LLVM kompiliert wurde, und Bitcode kann von Compiler mit anderem C++ - ABI erzeugt werden. – arrowd
Wenn ich mich richtig erinnere, ist der in LLVM enthaltene "Mangler" kein C++ - Mangler, sondern ein C-Mangler, der den Symbolnamen normalerweise ein "_" hinzufügt, um C-Symbole von Assembly-Symbolen zu unterscheiden, wenn Sie C++ zerlegen möchten Link zu den clang-Bibliotheken, die dem Signal entsprechen, mit dem Sie den Bitcode erzeugt haben. – PaulR