7 Stimmen

Identifizierung der Typen aller Variablen in einem C-Projekt

Ich versuche, ein Programm zu schreiben, mit dem ich überprüfen kann, ob ein C-Quellcode mit einer Variablennamenskonvention übereinstimmt. Zu diesem Zweck muss ich den Quellcode analysieren und den Typ aller lokalen und globalen Variablen identifizieren.

Das Endergebnis wird mit ziemlicher Sicherheit ein Python-Programm sein, aber das Werkzeug zur Analyse des Codes könnte entweder ein Python-Modul oder eine Anwendung sein, die einen leicht zu analysierenden Bericht erstellt. Alternativ (mehr dazu weiter unten) könnte es auch eine Möglichkeit sein, Informationen aus dem Compiler zu extrahieren (in Form eines Berichts oder ähnlichem). Falls das hilfreich sein sollte, wird es aller Wahrscheinlichkeit nach der Keil ARM-Compiler.

Ich habe experimentiert mit ctags und das ist sehr nützlich, um alle Typedefs und Makrodefinitionen usw. zu finden, aber es bietet keine direkte Möglichkeit, den Typ von Variablen zu finden, besonders wenn die Definition über mehrere Zeilen verteilt ist (was hoffentlich nicht der Fall sein wird!).

Beispiele hierfür könnten sein:

static volatile u8 var1; // should be flagged as static and volatile and a u8 (typedef of unsigned 8-bit integer)
volatile   /* comments */   
    static /* inserted just to make life */
        u8 /* difficult! */   var2 =
        (u8) 72
           ; // likewise (nasty syntax, but technically valid C)
const uint_16t *pointer1;  // flagged as a pointer to a constant uint_16t
int * const pointer2; // flagged as a constant pointer to an int
const char * const pointer3; // flagged as a constant pointer to a constant char
static MyTypedefTYPE var3; // flagged as a MyTypedefTYPE variable
u8 var4, var5, var6 = 72;
int *array1[SOME_LENGTH]; // flagged as an array of pointers to integers
char array2[FIRST_DIM][72]; // flagged as an array of arrays of type char

usw. usw.

Es muss auch identifizieren, ob sie lokal oder global/Datei-Umfang Variablen (die ctags tun können) und wenn sie lokal sind, würde ich idealerweise wie der Name der Funktion, die sie innerhalb deklariert sind.

Ähnliches möchte ich auch mit Funktionen machen: den Rückgabetyp identifizieren, ob sie statisch sind und den Typ und Namen aller Argumente.

Leider ist dies mit der C-Syntax ziemlich schwierig, da es eine gewisse Flexibilität bei der Reihenfolge der Parameter und viel Flexibilität bei der Menge an Leerzeichen gibt, die zwischen den Parametern erlaubt sind. Ich habe mit der Verwendung einiger ausgefallener regulärer Ausdrücke gespielt, um die Arbeit zu erledigen, aber das ist alles andere als ideal, da es so viele verschiedene Situationen gibt, die angewendet werden können, so dass die regulären Ausdrücke schnell unüberschaubar werden. Ich kann mir nicht helfen, aber ich denke, dass Compiler in der Lage sein müssen, dies zu tun (um zu funktionieren!), also habe ich mich gefragt, ob es möglich ist, diese Informationen zu extrahieren. Der Keil-Compiler scheint eine ".crf"-Datei für jede Quelldatei zu erzeugen, die kompiliert wird, und diese scheint alle in dieser Datei deklarierten Variablen zu enthalten, aber es ist ein binäres Format und ich kann keine Informationen darüber finden, wie man diese Datei parsen kann. Alternativ dazu wäre eine Möglichkeit, die Informationen aus ctags herauszuholen, perfekt.

Für jede Hilfe, die mir jemand anbieten kann, wäre ich dankbar.

Danke,

Al

5voto

Van Gale Punkte 42727

Es gibt eine Reihe von Python-Parser-Paketen, die zur Beschreibung einer Syntax verwendet werden können und dann Python-Code zum Parsen dieser Syntax erzeugen.

Ned Batchelder schrieb eine sehr schöne Zusammenfassung

Davon wurde Ply in einem Projekt namens pycparser das C-Quellcode analysiert. Ich würde empfehlen, mit diesem zu beginnen.

Einige dieser anderen Parser-Projekte haben vielleicht auch C-Parser-Beispiele.

Editar : Ich habe gerade festgestellt, dass pycparser sogar ein Python-Beispielskript hat, um einfach C-Typ-Deklarationen parsen wie das alte Programm cdecl.

3voto

RBerteig Punkte 39719

Wie wäre es, wenn Sie die Sache von der anderen Seite her angehen würden? Sie haben bereits einen Parser, der alle Nuancen des C-Typensystems versteht: den Compiler selbst. Kompilieren Sie also das Projekt mit voller Debug-Unterstützung und stöbern Sie in den Debug-Daten.

Für ein System, das auf Formaten basiert, die von binutils Die meisten Details, die Sie benötigen, können Sie mit dem BFD Bibliothek.

Microsofts Debug-Formate werden (in gewissem Maße) durch Bibliotheken und Dokumente bei MSDN unterstützt, aber meine Google-Fähigkeiten sind heute schwach und ich kann die Artikel, von denen ich weiß, dass sie existieren, nicht finden, um sie hier zu verlinken.

Der Keil 8051-Compiler (ich habe ihren ARM-Compiler hier nicht verwendet) verwendet das Intel OMF- oder OMF2-Format und dokumentiert, dass die Debugsymbole für ihren Debugger oder "beliebige Intel-kompatible Emulatoren" sind. Spezifikationen für OMF wie sie von Keil C51 verwendet werden, sind erhältlich bei Keil Ich könnte mir also vorstellen, dass ähnliche Spezifikationen auch für andere Compiler verfügbar sind.

Ein kurzer Blick auf die Website von Keil scheint darauf hinzuweisen, dass sie ihren proprietären ARM-Compiler zugunsten einer Lizenz für den RealView-Compiler von ARM aufgegeben haben, der ELF-Objekte mit Debug-Informationen im DWARF-Format zu verwenden scheint. Dwarf sollte von BFD unterstützt werden und sollte Ihnen alles geben, was Sie wissen müssen, um zu überprüfen, ob die Typen und Namen übereinstimmen.

2voto

Ryan Punkte 4089

Probieren Sie ANTLR aus. Es ist ein Parser-Generator, mit Bindungen für Python. Die ANTLR-Website bietet eine ganze Reihe von Grammatiken für gängige Sprachen, einschließlich C. Sie können die Grammatik für C herunterladen und an den entsprechenden Stellen Aktionen hinzufügen, um die Informationen zu sammeln, an denen Sie interessiert sind. Es gibt sogar ein nettes grafisches Tool zur Erstellung und Fehlersuche in den Grammatiken. (Ich weiß, das klingt kitschig, aber es ist tatsächlich recht praktisch und nicht unangenehm)

Ich habe gerade etwas Ähnliches gemacht, nur dass ich meine Symbolinformationen aus GDB extrahiert habe, um sie zu erhalten.

2voto

user47559 Punkte 1211

Was Sie zu tun versuchen, ist eine leichte Form der statischen Analyse. Vielleicht haben Sie Glück, wenn Sie sich die Werkzeuge ansehen, auf die von ウィキペディア .

Den C-Code selbst zu parsen, scheint mir der falsche Weg zu sein: Das ist der Wahnsinn. Wenn Sie darauf bestehen, dann sind [f]lex und yacc (bison) die Werkzeuge, die wahrscheinlich von Ihren Compiler-Autoren verwendet werden.

Wenn Sie mit ctags oder cscope 80 % des Weges zurücklegen, ist der Quellcode für beide weithin verfügbar. Die letzten 20% sind eine einfache Frage der Programmierung :)

0voto

e.James Punkte 112528

Ich habe etwas Ähnliches für ein Projekt gemacht, an dem ich vor ein paar Jahren gearbeitet habe. Am Ende habe ich die erste Hälfte eines C-Compilers geschrieben. Lassen Sie sich von dieser Aussicht nicht erschrecken. Es ist viel einfacher, als es sich anhört, vor allem, wenn Sie nur nach bestimmten Token (in diesem Fall Variablendefinitionen) suchen.

Suchen Sie online nach einer Dokumentation darüber, wie man C-Quellcode scannt, interessante Token erkennt und die Ergebnisse analysiert. Eine gute Anlaufstelle ist Wikipedia-Artikel zur lexikalischen Analyse .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X