Hallo, ich habe ein mit avr-g++ kompiliertes Programm, welches aus einem globalen Objekt besteht. Dieses Objekt enthält rekursiv verschaltet wiederum viele weitere Objekte. In der main-Funktion wird in eine Methode dieses globalen Objektes gesprungen und so das Programm gestartet. Nun landet dieses globale Objekt mit all seinen Membern in der bss-Sektion hinter den statischen Variablen. Mit Hilfe von avr-objdump -D bekomme ich auch Startadresse heraus, bei der das globale Objekt in der bss-Sektion beginnt. Nun möchte ich gern eine Layout-Übersicht über den gesamten Rest der bss-Sektion bekommen. Die einzige Variante, die mir dazu einfallen würde, wäre, das Gesamtheader-File herzunehmen, zu parsen und alle Offsets der Membervariablen auf deren Namen abzubilden. Dazu müsste ich natürlich auch die Größen aller Klassen bestimmen, also sizeof(). Daraus würden sich dann die Adressen zur Laufzeit berechnen lassen. Hat jemand einen Tipp für mich, ob es für so etwas Werkzeuge gibt? Mein KnowHow ist für solch einen Parser nicht ausreichend. Welche Unterstützung kann mir gcc da bieten? Vielen Dank und Herzliche Grüße Richard
Sollte alles im Mapfile drinstehen. Aber ich habe noch nicht verstanden, wozu man das braucht - ausser für's Debugging.
Danke, aber das Mapfile (wenn du die Memorymap des Linkers meinst), enthält leider nicht die Informationen, die ich benötige. Ich benötige eine Übersicht über die Offsets der einzelnen Member in allen Klassen. Das ganze ist tatsächlich für Debugging-Zwecke gedacht. Wenn ich die Adressen aller global angelegten Objekte kenne, kann ich von außen zum Beispiel zur Laufzeit einzelne Methoden anstoßen und schauen, was passiert. Richard
Evtl. das Debugging-Format des erzeugten Binaries analysieren. Da steht sowas drin.
Nicht ganz das, was Du suchst, aber das folgende Skript gibt alle Symbole, sortiert nach ihren Adressen, aus. Mit einem Argument (Variablenname) gibt es die Umgebung dieser Variablen aus. Du musst folgene Zeile ändern. Angenommen, Dein Object-File heißt pgm.elf:
1 | obj_file="$(sed -n 's/^ *file *\([^ ]\+\) *$/\1/p' gdb-macros)" |
in
1 | obj_file="pgm.elf" |
Das Skript (es sollte (hoffentlich) auch auf der Konsole mit WinAVR laufen; evtl. das #!/bin/bash in #!/bin/sh am Beginn ändern) folgt:
1 | #!/bin/bash
|
2 | |
3 | usage(){
|
4 | echo "\ |
5 | usage: $pname [-s] regexp |
6 | Function: display addresses around regexp, sorted by address
|
7 | Matches on any symbol (not only variables).
|
8 | opts:
|
9 | -s display size too"
|
10 | exit
|
11 | }
|
12 | |
13 | while getopts sSh-: argv; do |
14 | case "$argv" in |
15 | s|S) opt_s=S;; |
16 | *) usage;; |
17 | esac
|
18 | done
|
19 | shift $((OPTIND-1)) |
20 | |
21 | obj_file="$(sed -n 's/^ *file *\([^ ]\+\) *$/\1/p' gdb-macros)" |
22 | |
23 | [[ $1 =~ [0-9a-fA-F] ]] && iopt="-i" |
24 | avr-nm -anl$opt_s "$obj_file" \ |
25 | | while IFS= read line; do |
26 | if [[ "$line" =~ ^(.*)\ .*/([^/]+:[0-9]+)$ ]] ; then |
27 | line="${BASH_REMATCH[1]} ${BASH_REMATCH[2]}" |
28 | fi
|
29 | echo "$line" |
30 | done \ |
31 | | sort --key=1 \ |
32 | | grep -C 4 --color=auto $iopt "$1" |
EDIT: Es läuft nur mit der Bash -- also das, was ich oben zu #!/bin/bash geschrieben habe, gilt nicht. Ist keine Bash vorhanden, kannst Du eventuell etwas aus dem Gerüst übernehmen. Und noch was, was mir aufgefallen ist: zwischen ${BASH_REMATCH[1]} und ${BASH_REMATCH[2]} ist genau 1 Space und 1 Tab. Den Tab scheint die Forensoftware trotz pre../pre zu expandieren.
A. K. schrieb: > Evtl. das Debugging-Format des erzeugten Binaries analysieren. Da steht > sowas drin. Für C-Code gibt es pstruct, das ist bei Perl mit dabei (als Variante von c2ph, womit zu C-Headern automatisch Perl-Module generiert werden können), damit kann aus dem generierten Assemblercode das Layout einer struct extrahiert werden.
1 | % avr-gcc -g -S -o struct_test_c.s struct_test_c.c |
2 | % pstruct struct_test_c.s |
3 | struct inner { |
4 | int inner.xyzzy 0 2 |
5 | } |
6 | |
7 | struct test_struct { |
8 | char test_struct.bar 0 1 |
9 | int test_struct.baz 1 2 |
10 | struct inner test_struct.sub 3 2 |
11 | int test_struct.sub.xyzzy 3 2 |
12 | } |
Erste Zahlen-Spalte ist der Offset, zweite die Grösse des Feldes. Leider kommt das Tool derzeit mit C++-Debuginformationen nicht klar (auch nicht für eine simple struct, wenn g++ verwendet wird), aber vielleicht kann der Code als Ausgangspunkt verwendet werden. Andreas
@mizch: danke erst einmal. Dein Script läuft unter Cygwin, aber ich kann nicht erkennen, was es anderes ausgibt, als eine Auswahl der Symbole nebst ihrer Größe und Ladeadresse die ich auch mit "avr-objdump -t" oder über die Memory-Map des Linkers herausbekommen würde. @aferber: Ja, so etwas wie pstruct bräuchte ich, dass auch mit C++ umgehen kann. Ich habe gerade mal ddd ausprobiert. Damit kann ich mir immerhin schon einmal meine globale Systemvariable mit allen Elementen als grafischen Baum anschauen. Allerdings gibt es mir keine Informationen über die einzelnen Größen/Offsets der Variablen und überhaupt bekomme ich diesen Baum nur als Bild aus ddd exportiert. Ich habe das ELF mal in den gdb geladen. Mit Aufrufen wie "print &globalesObjekt.member.tiefer.undnochTiefer" kann ich mir alle Adressen von beliebigen Membern anzeigen lassen. Jetzt möchte ich das ganze aber umgekehrt machen. Das heißt: Ich möchte eine Adresse eingeben und eine Variable zurück bekommen. Dafür konnte ich aber (noch) keinen Befehl finden.
rw schrieb: > Das heißt: Ich möchte eine Adresse eingeben und eine > Variable zurück bekommen. Dafür konnte ich aber (noch) keinen Befehl > finden.
1 | (gdb) info symbol 0x0804957b |
2 | test_var + 11 in section .bss |
Allerdings erhältst du so keine Informationen darüber, welchen Member du "getroffen" hast, nur den nackten Offset in die Variable. Um die komplette Struct anschliessend auszugeben reicht es aber natürlich. Funktioniert natürlich nur mit statischen Variablen (static storage duration, nicht static linkage). Andreas
Japp. Das habe ich auch gesehen, aber das nützt mir nicht viel. Um zum Ziel zu kommen, habe ich es jetzt folgendermaßen gemacht:
1 | print meinGlobalesObjekt |
gibt mir einen String zurück, welcher den gesamten rekursiven Aufbau von meinGlobalesObjekt mit allen Membern nebst ihren Typen enthält. Da diese Ausgabe wohlstrukturiert ist, kann mir ein kleines Script alle Variablennamen (eines bestimmten Typs) zusammenbauen. Dieser Liste kann ich dann mit
1 | print &variable |
die jeweiligen Adressen zuordnen und sie so weiterverarbeiten. Vielen Dank für's Mitdenken. Richard
Eine weitere Möglichkeit ist avr-readelf -wi test.elf damit wird die komplette Symboltabelle ausgegeben, aus der sich alle Informationen zusammenbauen lassen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.