mikrocontroller.net

Forum: Compiler & IDEs GDB findet Sourcecode nicht


Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich versuche, mit GDB/openOCD ein Projekt zu debuggen. Grösstenteils 
funktioniert alles bestens, jedoch in einem File, task.c von FreeRTOS 
(oder zumindest in bestimmten Funktionen innerhalb dieses Files) findet 
GDB den Source nicht. Er meint dann z.B. beim steppen:
"No line number information available for address"

Wenn ich task.o mit Objdump anschaue, sehe ich den Sourcecode, auch die 
Funktionen, die GDB nicht findet.

info sources sagt mir, dass task.c eingebunden ist.

Hat jemand von Euch auch schon ein ähnliches Problem gehabt?

BTW - Wo steht eigentlich die "line number information?" Sprich - wo 
steht, in welchem File und auf welcher Zeile der Source code für einen 
bestimmten Maschinencode steht? Das müsste nach meiner Logik ja auch im 
Object-File drin stehen, oder?



Gruss & danke
Simon

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
„No line number information available“ bedeutet normalerweise, dass ohne 
-g übersetzt wurde.  Dazu passt allerdings nicht, dass mit objdump der 
Source da ist.  Wurde task.o danach mit [avr-]strip behandelt?  Das 
würde dann wieder passen.

Simon Huwyler schrieb:
> Sprich - wo
> steht, in welchem File und auf welcher Zeile der Source code für einen
> bestimmten Maschinencode steht?

Das steht in einer eigenen Section im .o und .elf.

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmmm.... ich sehe gerade etwas sehr verdächtiges:

Aus:

  /* Allocate the memory required by the TCB and stack for the new task,
  checking that the allocation was successful. */
  pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );

  if( pxNewTCB != NULL )
  {
    portSTACK_TYPE *pxTopOfStack;

    #if( portUSING_MPU_WRAPPERS == 1 )
      /* Should the task be created in privileged mode? */
      portBASE_TYPE xRunPrivileged;
      if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 )
      {
        xRunPrivileged = pdTRUE;
      }
      else
      {
        xRunPrivileged = pdFALSE;
      }
      uxPriority &= ~portPRIVILEGE_BIT;
    #endif /* portUSING_MPU_WRAPPERS == 1 */

    /* Calculate the top of stack address.  This depends on whether the
    stack grows from high memory to low (as per the 80x86) or visa 
versa.
    portSTACK_GROWTH is used to make the result positive or negative as
    required by the port. */
    #if( portSTACK_GROWTH < 0 )
    {




macht der:




/* Allocate the memory required by the TCB and stack for the new task,
  checking that the allocation was successful. */
  pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
  10:  f8bd 300e   ldrh.w  r3, [sp, #14]
  14:  4618        mov  r0, r3
  16:  990e        ldr  r1, [sp, #56]  ; 0x38
  18:  f7ff fffe   bl  0 <xTaskGenericCreate>
  1c:  4603        mov  r3, r0
  1e:  9308        str  r3, [sp, #32]

  if( pxNewTCB != NULL )
  20:  9b08        ldr  r3, [sp, #32]
  22:  2b00        cmp  r3, #0
  24:  f000 80b1   beq.w  18a <xTaskGenericCreate+0x18a>
    stack grows from high memory to low (as per the 80x86) or visa 
versa.
    portSTACK_GROWTH is used to make the result positive or negative as
    required by the port. */
    #if( portSTACK_GROWTH < 0 )
    {
      pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
  28:  9b08        ldr  r3, [sp, #32]
  2a:  6b1a        ldr  r2, [r3, #48]  ; 0x30




Der Stinker hat 'ne Zeile vergessen! (das #if statement ist false - aber 
unten, da fehlt eine Kommentarzeile) Wie kann denn das passieren? 
Nochmals meine Frage: Hat jemand von Euch schon mit so was gekämpft?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde sagen, da hat der Präprozessor das #if wegrationalisiert.

EDIT:  das hast Du gesehen.  Dass Kommentarzeilen nicht vollständig 
sind, hat nichts zu sagen.  Es ist ja der zusammengemischte Mix, den 
objdump -d hinterher erzeugt und nichts, was der Compiler sieht.  Die 
Kommentarzeilen und der C-Source sind nur für Dich zur Information.

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank schon mal für die Antwort! Nö Strip habe ich ich nicht 
verwendet.

Habe auch gerade gesehen, dass er bei den "intakten" Files ebenfalls 
Teile der Kommentare weglässt.

Wie kann ich die Source-Info aus dem elf-File rausholen?

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
> Es ist ja der zusammengemischte Mix, den
> objdump -d hinterher erzeugt und nichts, was der Compiler sieht.

Dazu noch 'ne Frage: Woher hat denn eigentlich objdump die Information? 
Steht der Sourcecode vollständig im objectfile, wenn ich mit -g 
compiliere? Oder holt sich objdump den aus den Sources? Und wenn ja, 
woher weiss es, aus welchen Sources?

Oder anders: Findet Objdump und gcc den Sourcecode auf die selbe Weise? 
Oder werden da ganz andere Prinzipien angewandt?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
avr-objdump -Sl *.elf sollte Dir u.a. die Zeilennummern zeigen, etwa so:
incrementalCleanup():
/U/minni-hcz/Projekte/108/tank-main.c:392
...

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Huwyler schrieb:
> Dazu noch 'ne Frage: Woher hat denn eigentlich objdump die Information?
> Steht der Sourcecode vollständig im objectfile, wenn ich mit -g
> compiliere? Oder holt sich objdump den aus den Sources? Und wenn ja,
> woher weiss es, aus welchen Sources?

Er holt sich's aus den Sourcen.  Woher er die weiß:  siehe einen Artikel 
drüber.  (Damit er denselben auf verschiedenen Maschinen findet, ist der 
Pfad übrigens dort ein NFS-Automount (/U).)

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank!

Ich habe das mal probiert - und siehe da:

void vTaskStartScheduler()
{
 8001c1c:  b500        push  {lr}
 8001c1e:  b087        sub  sp, #28
/home/simon/PLH/PLH1/FreeRTOS/Source/task.c:1054
portBASE_TYPE xReturn;


task.c existiert genau an dieser Stelle, und auf Zeile 1054 steht die 
erste Instruktion von vTaskStartScheduler().

Compiler und Linker scheinen also alles richtig gemacht zu haben. Warum 
zum Geier findet GDB diesen Code nicht, anderen Code, dessen Sources im 
selben Verzeichnis sind, jedoch schon?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der Pfad stimmt (also der Source nicht nur im gleichen Verzeichnis 
steht, sondern auch dort übersetzt wurde) und das der objdump des .elf 
war, bin ich leider auch mit meinem Latein am Ende.

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wollte nur kurz mitteilen, dass es inzwischen geklappt hat mit dem 
GDB.

Einerseits bin ich sehr zufrieden, andererseits verwirrter denn je.

Das von mir benutzte Makefile-Template (von Martin Thomas) aktiviert die 
GCC-Switches -ffunction-sections und -fdata-sections. Als ich die mal 
rausgenommen hatte, passierte etwas SEHR merkwürdiges: Beim Rebuild 
mooste der Linker, er fände ein Symbol nicht. Es war irgendwas in der 
Umgebung der Syscalls, weiss nicht mehr genau, welches. Aber - und das 
ist jetzt wirklich strange - ich sah, dass er es tatsächlich nicht 
finden KONNTE! Weil es schlicht nicht existierte (durch #ifdef 
ausgeblendet - ist ein Inline-Assembler Stub, und folglich 
compilerabhängig).

Deswegen meine Verwirrung:

- Wie zum Geier konnte der vorher linken??? Das Programm liess sich zwar 
teilweise (betraf eine gaaaaanz andere Funktion) nicht debuggen, aber es 
funktionierte bestens!

- Was zum Geier hat das mit obigen Compiler-Switches zu tun???

Aber eben: Eigentlich bin ich nur froh, dass es läuft. Und ich dachte, 
das interessiert zumindest Hc Zimmerer - auch wenn mein Latein nie und 
nimmer ausreicht, zu erklären, wie obiges Phänomen zustande kam. :-)

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-ffunction-section und -fdata-sections sorgt dafür, dass jeder Funktion 
und jeder Variable vom Compiler eine eigene Input-Section zugewiesen 
wird. Damit hat der Linker bei aktivierter Option --gc-sections die 
Möglichkeit, Input-Sections zu verwerfen (=nicht in output-sections 
aufzunehmen), die nicht genutzt werden. Es könnte sein, dass eine 
Funktion vom Compiler "geinlined" wurde. Wenn eine "extern" sichtbare 
Fassung der Funktion nicht benötigt wird, konnte diese wg. --gc-sections 
entsorgt wurden. Da nicht mehr vorhanden, gab es keine Linker-Fehler. 
Dann wäre es aber so, das die "geinlinete"-Variante aus irgend einem 
Grund eine Abhängigkeit nicht aufweisen würde, die bei der "sichtbaren" 
Variante vorhanden ist. Ist nur eine wenig fundierte Vermutung. Man 
bräuchte ein minimales aber funktionsfähiges Beispiel, um dieser Sache 
etwas nachgehen zu können. Was passiert, wenn -ffunction-sections 
aktiviert bleibt und Linker-Option --gc-sections entfernt wird?

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, da ist er ja, der Martin! :-)

Gleich zu begin: Vielen Dank für Deine umfangreichen Templates und 
Projekte!! Hast (wohl nicht nur) mir viel Arbeit erspart! Builden tu ich 
nur noch mit Deinen Templates, und am Wochenende habe ich gerade "Dein" 
FAT (Deine Implementation für Cortex) in Betrieb genommen!

Ja, irgendwie in diese Richtung stelle ich mir das auch vor. Habe gerade 
beim Mittagessen darüber nachgedacht und mit Kollegen darüber geredet 
(allerdings handelt es sich in diesem Fall um ein Hobby-Projekt).

Ich könnte mal diesen Schritt wieder rückgängig machen und schauen, 
welche Funktionen denn von dem Fehler betroffen sind. Und dann mal 
schauen, wohin diese Funktionen gelinkt werden. Vielleicht entsteht 
irgendwie irgendwo ein Mismatch, ausgelöst durch eine nicht aufgelöste 
(und vielleicht wie von Dir gesagt auch nicht benötigte) Referenz, der 
sich dann auf nachfolgend eingelinkte Funktionen fortpflanzt.
Wenn ich mal Zeit habe, werde ich das machen.

Gruäss
Simon

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmals,

ich habe zwar die Untersuchungen, die ich vorhatte, mangels Zeit nicht 
gemacht, jedoch habe ich im Buch

The Definitive Guide to GCC von William Von Hagen

gelesen, dass sich -fdata-sections und -g tatsächlich beissen. Die 
sollte man wohl nicht zusammen verwenden.

Ich nehme das jetzt einfach so zur Kenntnis. Stört ja nicht. Solange ich 
debugge, ist jegliche Optimierung ja eh zweitrangig resp. unerwünscht.

Gruäss
Simon

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.