Forum: Compiler & IDEs GDB findet Sourcecode nicht


von Simon H. (simi)


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

von Hc Z. (mizch)


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.

von Simon H. (simi)


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?

von Hc Z. (mizch)


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.

von Simon H. (simi)


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?

von Simon H. (simi)


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?

von Hc Z. (mizch)


Lesenswert?

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

von Hc Z. (mizch)


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).)

von Simon H. (simi)


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?

von Hc Z. (mizch)


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.

von Simon H. (simi)


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. :-)

von Martin T. (mthomas) (Moderator) Benutzerseite


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?

von Simon H. (simi)


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

von Simon H. (simi)


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

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
Noch kein Account? Hier anmelden.