Anzahl der Zugriffe auf eine Speicheradresse messen



  • Ich habe hier ein Problem über das ich seit einiger Zeit grüble - vielleicht könnt ihr mir da mit ein paar Ideen helfen.

    Für ein Uni-Projekt habe ich hier C-Code, der aus einem Tool für modellbasierte SW-Entwicklung generiert wurde. Ich soll nun untersuchen, ob und wie oft eine Variable xy gelesen bzw. geschrieben wird - das heißt, wie oft auf die Speicheradresse von xy zugegriffen wird. Ich kann die C-Files kompilieren und mir auch den Assembler-Code dazu anschauen.

    Nun dachte ich zuerst an eine Art Parser, der halt den C-Code nach der Variablen xy durchsucht und entsprechend feststellt, ob Lese- oder Schreibzugriffe stattfinden. Bei Zugriffen über Zeiger, z.B. bei lustigen verschachtelten Funktionsaufrufen, bei Arrays oder bei Klassen wird das spätestens hässlich aber imo immer noch machbar. Wirklich hässlich wirds aber dann, wenn auf die zu untersuchende Speicheradresse über Berechnungen zugegriffen wird, die erst zur Laufzeit feststehen, z.B.

    memcpy(blablubb+1000, &ziel, 1);
    

    Also wenn da blablubb zufällig auf (&xy-1000) zeigt, kann ich den Zugriff auf xy erst zur Laufzeit feststellen. Ich hoffe das stimmt so?

    Aaaalso... Wäre es evtl einfacher, ein Assembler-File zu parsen? Damit gehe ich allerdings dem o.g. Problem auch nicht aus dem Weg. Oder was könnte ich sonst noch tun? Vielleicht mit dem Object-File arbeiten? Oder.... sonst irgendwelche Ideen? Fällt evtl irgendwem sogar noch ein (weiterer) Grund ein, warum mein Vorhaben evtl garnicht funktionieren kann?

    Danke für's Lesen soweit.



  • Über eventuelle Debugging Features musst du dich in der Dokumentation der verwendeten Hardwareplattform informieren. Ein evtl. vorhandenes Betriebssystem hat hier in der Regel dann auch ein Wörtchen mitzureden.



  • Hi,

    danke für deine Antwort. Leider hab ich keine Informationen über die Hardware, die wird noch entwickelt bzw. die Architektur ist noch nicht so ganz klar... Also mir ist natürlich klar, dass das zur Laufzeit eine Rolle spielt, aber ich will meine Prüfung ja vor der Übersetzung durchführen.

    Wieso hat da das OS noch mitzureden? Ich meine, der Code wird doch so ausgeführt wie er da steht? Oder beziehst du dich auf Speicherverwaltungsmaßnahmen vom OS?

    Mir gehts jetzt auch garnicht um die Laufzeit - ich würde die Prüfung, ob und wie oft auf eine Variable zugegriffen wird, halt gern vor der Kompilierung an Hand von Quelltext (C, ASM) o.ä. nachvollziehen und frage, ob ein Parser hier die einzige Lösung ist bzw. ob ein Parser überhaupt eine Lösung sein kann. Dann müsste man sich Gedanken machen, ob man evtl was mit den Object files nach der Kompilierung anfangen kann. Debugging bzw. generell Überprüfungen zur Laufzeit sind wohl ohne Simulator und ohne Hardware erstmal nicht drin...



  • Warum nicht so?

    static int counter = 0;
    int _ziel = 200;
    
    int ziel()
    {
        counter++;
        return _ziel;
    }
    

    Einziges Problem wäre wohl, dass die meisten Compiler das einfach wegoptimieren...



  • Ja über sowas habe ich auch schon nachgedacht. Leider wird - wie gesagt - der Quelltext aus einem Tool generiert. Änderungen am Codegenerator wären da wohl zu umfangreich für den Nutzen, den die Analyse bringen soll. Und deine Methode funktioniert ja auch wieder nur zur Laufzeit...



  • Wenn du die Zugriffe partout nicht zur Laufzeit untersuchen willst (was ich noch nicht ganz nachvollziehen kann, da das IMHO mit Abstand die eleganteste Loesung waere - entweder per Debugging-Features der Plattform oder Simulation), bleibt dir wohl nichts anderes uebrig, als einen Parser auf die Quellcodes loszulassen. Mir faellt kein Grund ein, warum das prinzipiell nicht funktionieren sollte.
    Allerdings waere ein C++-Parser wahrscheinlich deutlich komplizierter als einer fuer Assembler oder den Maschinencode in den Objekt-Dateien (um den zu bekommen, muesste doch aber schon zumindest der Befehlssatz der Zielarchitektur feststehen..?). ...und bei einem Parser fuer den Maschinencode waerst du ohnehin schon wieder sehr nahe an einer VM. Da schliesst sich der Kreis... 😉



  • Danke für deine Antwort.

    Die Laufzeitprüfung funktioniert aber auch nur dann, wenn man alle Programmpfade abdeckt. Und das ist bei komplexer Software durchaus schwierig, man kann nicht oder nur schwer garantieren, durch Simulation alle möglichen Programmpfade abzulaufen. Das sehe ich da als Problem.

    Außerdem... wie kann ich denn, ohne den erzeugten Quellcode zu ändern, über einen Debugger automatisch(!) prüfen, ob eiin Speicherbereich gelesen wurde? Ich meine, schreiben ist nicht das Problem, wenn der Wert im speicher geändert wurde... Aber lesen?

    Zurück zum Thema Parser: Also ASM-Files parsen wäre hier der wohl beste Ansatz?



  • Vielleicht solltest du zunaechst mal genau definieren, was du ueberhaupt zaehlen willst... irgendwie wird das noch nicht so ganz klar, finde ich.

    Einige Plattformen bieten Debuging-Funktionen, idR. auch in Hardware, die bei beliebigem Speicherzugriff an festgelegten Adressen unterbrechen und damit die Moeglichkeit bieten, festgelegte Aktionen auszufuehren (zB. Zaehler erhoehen). In einer VM koenntest du sogar beliebige Konditionen einbauen, um Aktionen auszufuehren. Beide Loesungen kommen im Wesentlichen ohne Aenderungen am zu untersuchenden Code aus (von Code zum Initialisieren von Hardware-Debuging-Funktionen mal abgesehen).


Log in to reply