2017-04-03 2 views
0

Ich benutze LLVM api, um Bitcodedateien zu parsen. Ich habe das folgende Snippet und ich verwende diesen Befehl, um den Bitcode $CC -emit-llvm -c -g source.c zu erzeugen, in dem CC auf den Pfad clang gesetzt ist. einen numerischen Wert haben, basierend auf dem Typ des ParametersLLVMs Bitcode falsche Erkennung von Funktionsparametern

#include <stdio.h> 

struct Point { 
    int a; 
    int b; 
}; 

int func_0(struct Point p, int x) { 
    return 0; 
} 

The TypeID soll. Sowohl für die ganze Zahl x als auch für die Struktur Point erhalte ich den Wert 10, der als TokenTyID bezeichnet wird. Also entschied ich mich, die Funktionen isIntegerTy() bzw. isStructTy() zu verwenden, um zu sehen, ob ich zumindest in diesem Fall das richtige Ergebnis erhalte. Diese Lösung funktioniert für den Ganzzahlparameter x, aber nicht für die Struktur. Wie kann ich Strukturen korrekt identifizieren und ihre Felder lesen?

Just, auf Vollständigkeit die Bitcode ich diesen Code verwenden, um zu analysieren:

using namespace llvm; 

int main(int argc, char** argv) { 
    LLVMContext context; 
    OwningPtr<MemoryBuffer> mb; 
    MemoryBuffer::getFile(FileName, mb); 
    Module *m = ParseBitcodeFile(mb.get(), context); 

    for (Module::const_iterator i = m->getFunctionList().begin(), e = m->getFunctionList().end(); i != e; ++i) { 
     if (i->isDeclaration() || i->getName().str() == "main") 
      continue; 

     std::cout << i->getName().str() << std::endl; 

     Type* ret_type = i->getReturnType(); 
     std::cout << "\t(ret) " << ret_type->getTypeID() << std::endl; 

     Function::const_arg_iterator ai; 
     Function::const_arg_iterator ae; 

     for (ai = i->arg_begin(), ae = i->arg_end(); ai != ae; ++ai) { 
      Type* t = ai->getType(); 

      std::cout << "\t" << ai->getName().str() << " " << t->getTypeID() 
         << "(" << t->getFunctionNumParams() << ")" 
         << " is struct? " << (t->isStructTy() ? "Y" : "N") 
         << " is int? " << (t->isIntegerTy() ? "Y" : "N") 
         << "\n"; 
     } 
    } 

    return 0; 
} 

ich diesen Beitrag Why does Clang coerce struct parameters to ints über die von klirren mit den Strukturen durchgeführt Übersetzung lesen, und ich bin mir ziemlich sicher, dass mein gleiches Problem .

+0

Versucht, LLVM IR mit 'clang -S -emit-llvm' zu entladen? – arrowd

+0

Ja, es funktioniert nicht so gut. Wenn ich den IR-Code mit der Option "-S" erzeuge und dann den Bitcode mit "llvm-as" erzeuge, ist das Problem das gleiche. – Surcle

+0

Ich meine, versuchen Sie, generierte IR zu sehen und herauszufinden, in was Ihre Struktur verwandelt wird. – arrowd

Antwort

0

Da clang die Funktionssignatur im IR ändert, müssen Sie diese Informationen mithilfe der Debug-Informationen abrufen. Hier ist ein grober Code:

DITypeIdentifierMap TypeIdentifierMap; 

DIType* getLowestDINode(DIType* Ty) { 
    if (Ty->getTag() == dwarf::DW_TAG_pointer_type || 
     Ty->getTag() == dwarf::DW_TAG_member) { 
    DIType *baseTy = 
     dyn_cast<DIDerivedType>(Ty)->getBaseType().resolve(TypeIdentifierMap); 
    if (!baseTy) { 
     errs() << "Type : NULL - Nothing more to do\n"; 
     return NULL; 
    } 

    //Skip all the DINodes with DW_TAG_typedef tag 
    while ((baseTy->getTag() == dwarf::DW_TAG_typedef || baseTy->getTag() == dwarf::DW_TAG_const_type 
      || baseTy->getTag() == dwarf::DW_TAG_pointer_type)) { 
     if (DITypeRef temp = dyn_cast<DIDerivedType>(baseTy)->getBaseType()) 
     baseTy = temp.resolve(TypeIdentifierMap); 
     else 
     break; 
    } 
    return baseTy; 
    } 
    return Ty; 
} 

int main(int argc, char** argv) { 
    LLVMContext context; 
    OwningPtr<MemoryBuffer> mb; 
    MemoryBuffer::getFile(FileName, mb); 
    Module *m = ParseBitcodeFile(mb.get(), context); 
    if (NamedMDNode *CU_Nodes = m.getNamedMetadata("llvm.dbg.cu")) { 
    TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); 
    } 
    SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; 
    F.getAllMetadata(MDs); 
    for (auto &MD : MDs) { 
    if (MDNode *N = MD.second) { 
     if (auto *subRoutine = dyn_cast<DISubprogram>(N)->getType()) { 
     if (!subRoutine->getTypeArray()[0]) { 
      errs() << "return type \"void\" for Function : " << F.getName().str() 
      << "\n"; 
     } 

     const auto &TypeRef = subRoutine->getTypeArray(); 
     for (int i=0; i<TypeRef.size(); i++) { 
      // Resolve the type 
      DIType *Ty = ArgTypeRef.resolve(TypeIdentifierMap); 
      DIType* baseTy = getLowestDINode(Ty); 
      if (!baseTy) 
      return; 
      // If that pointer is a struct 
      if (baseTy->getTag() == dwarf::DW_TAG_structure_type) { 
      std::cout << "structure type name: " << baseTy->getName().str() << std::endl(); 
      } 
     } 
     } 
    } 
    } 
} 

Ich weiß, es sieht hässlich aus, aber mit Debug-Informationen ist nicht einfach.

+0

Vielen Dank für Ihre Antwort. Können Sie mir den ganzen Code der vorherigen Aussagen geben? – Surcle

+0

Sicher, hier ist ein Link zum Code: https://github.com/jiten-thakkar/DataStructureAnalysis/blob/dsa_llvm3.8/lib/dsaGenerator/DSAGenerator.cpp Ich habe daran für ein anderes Projekt gearbeitet – deLta