www.mikrocontroller.net

Forum: Compiler & IDEs Adress-Analyse von Objekten in der bss-Sektion


Autor: rw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sollte alles im Mapfile drinstehen.

Aber ich habe noch nicht verstanden, wozu man das braucht - ausser für's 
Debugging.

Autor: rw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Evtl. das Debugging-Format des erzeugten Binaries analysieren. Da steht 
sowas drin.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
obj_file="$(sed -n 's/^ *file *\([^ ]\+\) *$/\1/p' gdb-macros)"
in
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:
#!/bin/bash

usage(){
    echo "\
usage: $pname [-s] regexp
Function: display addresses around regexp, sorted by address
          Matches on any symbol (not only variables).
opts:
  -s  display size too"
    exit
}

while getopts sSh-: argv; do
    case "$argv" in
        s|S) opt_s=S;;
        *) usage;;
    esac
done
shift $((OPTIND-1))

obj_file="$(sed -n 's/^ *file *\([^ ]\+\) *$/\1/p' gdb-macros)"

[[ $1 =~ [0-9a-fA-F] ]] && iopt="-i"
avr-nm -anl$opt_s "$obj_file" \
| while IFS= read line; do
    if [[ "$line" =~ ^(.*)\     .*/([^/]+:[0-9]+)$ ]] ; then
        line="${BASH_REMATCH[1]}        ${BASH_REMATCH[2]}"
    fi
    echo "$line"
  done \
| sort --key=1 \
| 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.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
% avr-gcc -g -S -o struct_test_c.s struct_test_c.c
% pstruct struct_test_c.s
struct inner {
  int                inner.xyzzy                0       2
}

struct test_struct {
  char               test_struct.bar            0       1
  int                test_struct.baz            1       2
  struct inner       test_struct.sub            3       2
    int              test_struct.sub.xyzzy      3       2
}


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

Autor: rw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
(gdb) info symbol 0x0804957b
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

Autor: rw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
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
print &variable
die jeweiligen Adressen zuordnen und sie so weiterverarbeiten.

Vielen Dank für's Mitdenken.
Richard

Autor: Roberto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine weitere Möglichkeit ist

avr-readelf -wi test.elf

damit wird die komplette Symboltabelle ausgegeben, aus der sich alle 
Informationen zusammenbauen lassen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.