mikrocontroller.net

Forum: Compiler & IDEs arm-elf-ld Freuden (Linker-Probleme)


Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Bisher haben meine Versuche gescheitert, dieses Beispiel von Miro Samek 
(http://en.mikrocontroller.net/topic/113459) mit WinARM zu kompilieren.
Ich habe das Proejkt dann "geringfügig" umgemodelt.

Dieses Ummodeln bestand hauptsächlich im Ändern des Linkerscripts:
http://web3.veesi.de/ARM/AT91SAM7S64-ROM-TOBI.ld
Ich habe den AT91SAM7S64-ROM.ld von Martin Thomas als Vorbild genommen, 
und und zumindest versucht um die Funktionen des Samek-Scripts zu 
erweitern.
Dabei trat das Problem auf, dass in der .data section, die ja im RAM vom 
Startupcode platziert werden soll, aber im ROM gespeichert werden soll, 
die Loadadresse nicht generiert wurde (obwohl das genau gleich 
formuliert war wie für .fastcode).
Ich habe einfach je eine Section gemacht, einmal im RAM und einmal im 
ROM.
Kann ich das so machen? / Ist das gut so?
Ist der Linkerscript allgemein benutzbar?
Diese Linkerscriptgeschichte finde ich am schlimmsten, weil einem keiner 
so richtig weiterhelfen kann. Viele Beispiele sind zwar gut, aber ein 
gutes Tutorial ersetzen sie leider auch nicht.

Soweit so gut.
D:\dat-loc-tobi\Programming\ARM\Projects\std-code-try1>make all

.compiling
arm-elf-gcc -I./ -c -fno-common -O0 -g main.c

/*[...]*/
/*Kompiliert und assembliert sourcen ohne mullen und knullen*/
/*[...]*/

..linking
arm-elf-ld -v -Map main.map -TAT91SAM7S64-ROM-TOBI.ld -o main.out main.o startup.o lowlevelinit.o is
r.o arm_exc.o  C:/WinARM/arm-elf/lib/libm.a C:/WinARM/lib/gcc/arm-elf/4.1.1/libgcc.a C:/WinARM/arm-e
lf/lib/libc.a

GNU ld version 060606 20060606

C:/WinARM/arm-elf/lib/libc.a(init.o): In function `__libc_fini_array':
init.c:(.text+0x3c): undefined reference to `_fini'

C:/WinARM/arm-elf/lib/libc.a(init.o): In function `__libc_init_array':
init.c:(.text+0x80): undefined reference to `_init'

make: *** [main.out] Error 1

Diese beiden Fehlermeldungen spuckt der Linker jetzt noch aus. An was 
kann das liegen?
Ich hab mal bei google gesucht, da hieß es irgendwo, es gäbe einen 
Fehler in der Lib...
Glaub ich jetzt aber ned. Muss irgendwie am Linkerscript liegen?

Falls ihr euch das ganze Projekt anschauen wollt:
http://web3.veesi.de/ARM/std-code-try1.zip

Ich weis nicht. Bin ich einfach nur zu blöd oder ist das wirklich so 
schwer? - Wohl ersteres ;)

Danke schonmal,
Tobi

Autor: Fabian Scheler (rosepeter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Tobias,

ist nur eine Idee, aber ausprobieren kann ja nichts schaden:
 ..linking
 arm-elf-ld -v -Map main.map -TAT91SAM7S64-ROM-TOBI.ld -o main.out main.o
 startup.o lowlevelinit.o isr.o arm_exc.o  C:/WinARM/arm-elf/lib/libm.a
 C:/WinARM/lib/gcc/arm-elf/4.1.1/libgcc.a C:/WinARM/arm-e
 lf/lib/libc.a
 
 GNU ld version 060606 20060606
 
 C:/WinARM/arm-elf/lib/libc.a(init.o): In function `__libc_fini_array':
 init.c:(.text+0x3c): undefined reference to `_fini'
 
 C:/WinARM/arm-elf/lib/libc.a(init.o): In function `__libc_init_array':
 init.c:(.text+0x80): undefined reference to `_init'

die Fehlermeldung besagt ja, dass der Linker ein bestimmtes Symbol nicht 
findet - ich vermute aber, dass du dieses Symbol gar nicht brauchst. Die 
undefinierte Referenz könnte daher kommen, dass du evtl. die Komplette 
Bibliothek libc.a einbindest, nicht nur die Teile, die auch benötigt 
werden. Dabei bin ich mir aber nicht zu 100% sicher, aber mir kommt dein 
ld-Aufruf etwas seltsam vor, ich würde den ld eher so aufrufen:
 arm-elf-ld -v -Map main.map -TAT91SAM7S64-ROM-TOBI.ld -o main.out main.o
 startup.o lowlevelinit.o isr.o arm_exc.o  -lm -lgcc -lc -L C:/WinARM/arm-elf/lib -L C:/WinARM/lib/gcc/arm-elf/4.1.1

Ich weiß, wie bereits gesagt, nicht genau, ob es einen Unterschied 
macht, die Bibliothek direkt als Eingabedatei anzugeben, oder mit '-l'. 
Evtl. müsste man die Pfade mit '-L' auch gar nicht mehr explizit 
angeben, weil es die Standard-Pfade sein müssten, in denen der 
arm-elf-ld sowieso sucht.

Ciao, Fabian

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

Bewertung
0 lesenswert
nicht lesenswert
- Wird das init aus der libc wirklich benötigt? Falls man die 
Initialisierung "von Hand" macht, kann man mit -nostartfiles linken

- Besser über das Compiler-Frontend (arm-elf-gcc) Linken. Dieses "weiss" 
wo die passende libc abgelegt ist, Pfadangaben kann man sich dann 
sparen.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

] (*,) argh
Klar, man könnte das ja auch mal mit -l versuchen... ;)

Problem:
Leider haben weder der von Fabian vorgeschlagene Aufruf
arm-elf-ld -v -Map main.map -TAT91SAM7S64-ROM-TOBI.ld -nostartfiles -o main.out main.o startup.o low
levelinit.o isr.o arm_exc.o  -lm -lgcc -lc -LC:/WinARM/lib/gcc/arm-elf/4.1.1

noch Martins -nostartfiles (der Init wird vom "hauseigenen" Startupcode 
gemacht) zum Erfolg geführt:
D:\dat-loc-tobi\Programming\ARM\Projects\std-code-try1>make all
..linking
arm-elf-ld -v -Map main.map -TAT91SAM7S64-ROM-TOBI.ld -nostartfiles -o main.out main.o startup.o low
levelinit.o isr.o arm_exc.o  -lm -lgcc -lc -LC:/WinARM/lib/gcc/arm-elf/4.1.1

GNU ld version 060606 20060606
c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_fini_array':
init.c:(.text+0x3c): undefined reference to `_fini'
c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_init_array':
init.c:(.text+0x80): undefined reference to `_init'
make: *** [main.out] Error 1

Ich habe nochmal den orginal-Linkerscript blinky.ld benutzt:
http://web3.veesi.de/ARM/blinky.ld
Ergebnis:
GNU ld version 060606 20060606
startup.o: In function `_cstartup':
(.text+0x140): undefined reference to `__data_load'
c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_fini_array':
init.c:(.text+0x3c): undefined reference to `_fini'
c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_init_array':
init.c:(.text+0x80): undefined reference to `_init'
arm-elf-ld: BFD 060606 20060606 internal error, aborting at c:/winarms/binutils-060606/bfd/elflink.c
 line 6509 in elf_link_output_extsym

arm-elf-ld: Please report this bug.

__data_load wird im Linkerscript in Zeile 110 deklariert.
__data_load wird dann im Startupcode verwendet (startup.s, Z. 100) 
(siehe Link zum Projekt):
[...]
/* Relocate the .data section (copy from ROM to RAM) */
    LDR     r0,=__data_load
    LDR     r1,=__data_start
[...]

Aber warum ist es eine "undefined reference"? Ich meine es wird ja auch 
die .fastcode Sektion im ">RAM AT>ROM" abgelegt und da wird die 
Loadadresse definiert, und da klappts ja wunderbar.

Danke für eure Hilfe, ich hab echt keine Ahnung mehr...
Viele Grüße,
Tobi

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für das konkrete Problem mit .data testweise mal im Code zwei globale 
Veriablen anlegen:
volatile int dummy1 = 123; // sollte in .bss
volatile int dummy2;       // sollte in .data

//dann irgendwo am Anfang von main
...
dummy2 = dummy1;
dummy1 = dummy1;
...
Dann im Map-File nachsehen, an welchen Addressen die beiden Symbole 
angelegt werden und ob die .bss und .data Start-/Ende-Addressen, die im 
Startup für's bss "ausnullen" und .data kopieren genutzt werden, die 
Symboladdressen der dummys "einschliessen". Gab/Gibt beim linker 
manchmal Probleme, wenn .data leer ist. Mit den Ansatz sollte man das 
analysieren können.

Die Beispiele aus der embedded.com Artikelserie sind für eine GNU 
arm-eabi toolchain vorbereitet. Mein WinARM-Packet und Michael Fischers 
Yagarto enthalten in den momentan "offizellen" Versionen arm-elf 
toolchains. Es gibt zwar eine WinARM Testversion mit arm-eabi Toolchain 
aber das ist wirklich nur eine Testversion. Nicht alle enthaltenen 
Beispiele funktionieren, vgl. Thread auf en.mikrocontroller.net. Es gibt 
da ein paar Unterschiede zwischen arm-eabi und arm-elf. Bin selbst noch 
dabei, alle Unterschiede zu analysieren aber grade zu wenig Zeit dafür.

Falls man den Beispielcode zur Artikelserie nachvollziehen will und 
nicht gleich viel an Linker-Skript und Startup-Code herumbasteln will, 
dürfte es am Einfachsten sein, die vorkompilierte "bare-metal"-Toolchain 
von Codesourcery zu verwenden. Die Lite-Version gibt's kostenlos zum 
Download und man kann diese problemlos neben WinARM oder Yagarto 
installiert. Lite heisst nur, dass man kein vorkonfiguriertes Eclipse 
und keinen Support von Codesourcery bekommt (o.k, man kann auf "gratis" 
Antworten in deren Forum hoffen), es gibt keine Beschränkung im Hinblick 
auf die Codegröße.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich... ich...
...bin Sprachlos.
...und (fast) glücklich.

Das war der Fehler! Der Linker meckert jetzt "nur" noch an "_fini" und 
"_init".
Unglaublich.
Die Variablen werden auch laut map-file genau da abgelegt, wo sie hin 
sollen:
.data           0x00200248        0x4 load address 0x00100898
                0x00300ae0                __data_load = LOADADDR (.data)
                0x00200248                __data_start = .
 *(.jcr)
 *(.got.plt)
 *(.got)
 *(.shdata)
 *(.data .data.* .gnu.linkonce.d.*)
 .data          0x00200248        0x4 main.o
                0x00200248                foo1 //Hier...
 .data          0x0020024c        0x0 startup.o
 .data          0x0020024c        0x0 lowlevelinit.o
 .data          0x0020024c        0x0 isr.o
 .data          0x0020024c        0x0 arm_exc.o
 .data          0x0020024c        0x0 c:\winarm\bin\../arm-elf/lib\libc.a(init.o)
                0x0020024c                . = ALIGN (0x4)
                0x0020024c                _edata = .

Und dann in .bss:
.bss            0x0020024c        0xc
                0x0020024c                __bss_start__ = .
 *(.shbss)
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0020024c        0x4 main.o
                0x0020024c                foo2 //...und hier.
 .bss           0x00200250        0x0 startup.o
 .bss           0x00200250        0x0 lowlevelinit.o
 .bss           0x00200250        0x4 isr.o
 .bss           0x00200254        0x0 arm_exc.o
 .bss           0x00200254        0x0 c:\winarm\bin\../arm-elf/lib\libc.a(init.o)
 *(COMMON)
                0x00200258                . = ALIGN (0x8)
 *fill*         0x00200254        0x4 00
                0x00200258                __bss_end__ = .

Mei da wär ich nie drauf gekommen. Es ist immer das, was man nie 
vermuten würde.

Jetzt bleibt "nur" noch das Problem mit dem Init in den Libraries:
arm-elf-ld -v -Map main.map -Tblinky.ld -nostartfiles -o main.out main.o startup.o lowlevelinit.o is
r.o arm_exc.o  -lm -lgcc -lc -LC:/WinARM/lib/gcc/arm-elf/4.1.1
GNU ld version 060606 20060606

c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_fini_array':
init.c:(.text+0x3c): undefined reference to `_fini'
c:\winarm\bin\../arm-elf/lib\libc.a(init.o): In function `__libc_init_array':
init.c:(.text+0x80): undefined reference to `_init'

Könnten sich da vllt. 2 Libraryversionen in die Quere kommen? Oder der 
Linkerscript ist auf eine eine andere Version abgestimmt oder sowas in 
der Richtung?
Hm.

Danke Martin auf jeden Fall für deine Hilfe, das hat mich Kilometer 
weiter gebracht!

Viele Grüße,
Tobi

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

Bewertung
0 lesenswert
nicht lesenswert
Sind in startup.S noch die folgenden Zeilen?
/* Invoke the static constructors */
LDR     r12,=__libc_init_array
MOV     lr,pc           /* set the return address */
BX      r12             /* the target code can be ARM or THUMB */
Wenn ja, einfach testweise erstmal rauswerfen. Die Funktion braucht man 
nach meinem Verständnis nur zum Aufruf der CTORS von statischen 
C++-Objekten, die es in einem "normalen C"-Projekt ja nicht gibt, und 
hat ein paar Abhängigkeiten, die wohl die Ursache für das 
"Linkergemecker" sind.

Autor: Tobias Schlegel (Firma: none) (tobimc) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
D:\dat-loc-tobi\Programming\ARM\Projects\std-code-try1>make all
.compiling
arm-elf-gcc -I./ -c -fno-common -O0 -g main.c
.assembling
arm-elf-as -ahls -mapcs-32 -o startup.o startup.s > startup.lst
.compiling
arm-elf-gcc -I./ -c -fno-common -O0 -g lowlevelinit.c
.compiling
arm-elf-gcc -I./ -c -fno-common -O0 -g isr.c
.assembling
arm-elf-as -ahls -mapcs-32 -o arm_exc.o arm_exc.s > arm_exc.lst
..linking
arm-elf-ld -v -Map main.map -Tblinky.ld -nostartfiles -o main.out main.o startup.o lowlevelinit.o is
r.o arm_exc.o  -lm -lgcc -lc -LC:/WinARM/lib/gcc/arm-elf/4.1.1
GNU ld version 060606 20060606
...copying
arm-elf-objcopy --output-target=binary main.out main.bin
arm-elf-objdump -x --syms main.out > main.dmp

Vielen, vielen Dank, Martin!

Mensch, wenn man weis, an was es lag, kommt man sich so (unglaublich) 
doof vor, aber ich glaube ich habe den Wald vor lauter Bäumen nichtmehr 
gesehen ;)
Einmal Suchen hätte ja gereicht. . .
Au mann.
Trotzdem Danke!

Jetzt kanns weiter gehen - Mal sehen was noch so auf mich zu kommt...

Viele Grüße, und Danke nochmal!
Tobi

Autor: Le_Q (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich darf mich auch bedanken. Habe ein example Linkerscript und startup 
code verwendet. Im startup file wurde das Symbol __libc_init_array 
angesprungen. Welches er wohl in der libc nicht finden konnte. Ich habe 
jetzt mal die entsprechende Zeile entfernt, und siehe da - er linkt brav 
wie er soll!

Ich hoffe jetzt nur das ich diese Function wirklich nicht benötige, und 
diese wirklich nur für C++ Geschichten verwendet wird.

Ihr habt mir den Tag gerettet. ;) Danke.

Autor: Beneder Roman (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

was genau war beim startup-file oder Linker script der Fehler?
Wir bzw. ich habe das selbe Problem.
Verwende Eclipse + OpenOCD + CodeSourcery Lite "Toolchain" - ist 
eigentlich nur eine Compilersuite - und habe den selben bzw. den 
gleichen Fehler.

Kannst du mir das startup-file + ld skript schicken?

LG,

Roman & Philipp

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.