Forum: Compiler & IDEs Sektionen im Linker Script


von Arne Maximilian R. (arnemaximilian_r)


Lesenswert?

Moin zusammen,

ich spiele momentan mit ein paar ARM Mikrocontrollern rum und bin dabei 
über das Linker Script gestolpert. Die Aufgabe des Script's ist mir 
durchaus klar und nach ein paar Seiten Dokumentation und Tutorials 
verstehe ich soweit auch die grundlegende Syntax und Funktionsweise. 
Womit ich aber aktuell sehr stark kämpfen muss ist die Auswahl der 
Sektionen und den Zusammenhang mit einigen Code Teilen.
Ich nutze z.B. Yagarto von Michael Fischer. Tolle Toolchain funktioniert 
alles soweit super und er hat auch ein paar Beispiele zur Verfügung 
gestellt. Top. Aber woher bezieht der Herr seine Informationen für seine 
Linker Script's?
Er verwendet z.B. eine .fastrun Sektion. Diese habe ich aber in keinen 
anderen Beispiel gefunden (egal ob Code Sourcery oder andere). Das es 
sich dabei um eine Sektion handelt, die für Code reserviert ist, der 
danach aus dem RAM ausgeführt werden soll ist mir klar. Doch irgendwo im 
Compiler muss ja festgelegt sein, dass der Compiler diese Sektionen 
erstellt (für die einzelnen Objektdateien). Dazu kommt der Punkt, dass 
der Compiler irgendwo her wissen muss, dass dieser Code vom RAM aus 
ausgeführt werden soll.
Bisher habe ich dazu aber noch nichts gefunden.

Verlässt man die "einfache" Umgebung der Yagarto Beispiele wird es noch 
viel schlimmer. Dort haben mich Sektionen wie glue_7, init, 
vfp11_veneer, ARM.attributes und so weiter erwartet. Bei den Meisten 
konnte ich bisher mittels Google zumindest eine Funktion heraus finden. 
Aber z.B. die beiden letzten Erwähnten sind mir noch ein Rätsel.
Daher nun die wichtige Hauptfrage: Wie finde ich raus, welche Sektionen 
es alles (für meine HW) geben kann und welche Funktionen haben die 
einzelnen Sektionen dann?

Ich möchte am Ende in der Lage sein ein Linker Script zusammen zu 
stellen, bei dem ich Bewusst die Sektionen ausgewählt habe und zumindest 
darauf verweisen kann, was die Sektion macht.

Ich würde mich über eine Antwort sehr freuen (aber bitte keine Google 
Antwort <- da habe ich schon mehr als 6 Stunden verbracht und wenn es da 
zu finden ist suche ich definitiv nach dem Falschen).

MfG
Arne

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Arne Maximilian R. schrieb:
> Moin zusammen,
>
> ich spiele momentan mit ein paar ARM Mikrocontrollern rum und bin dabei
> über das Linker Script gestolpert. Die Aufgabe des Script's ist mir
> durchaus klar und nach ein paar Seiten Dokumentation und Tutorials
> verstehe ich soweit auch die grundlegende Syntax und Funktionsweise.
> Womit ich aber aktuell sehr stark kämpfen muss ist die Auswahl der
> Sektionen und den Zusammenhang mit einigen Code Teilen.
> Ich nutze z.B. Yagarto von Michael Fischer. Tolle Toolchain funktioniert
> alles soweit super und er hat auch ein paar Beispiele zur Verfügung
> gestellt. Top. Aber woher bezieht der Herr seine Informationen für seine
> Linker Script's?
> Er verwendet z.B. eine .fastrun Sektion. Diese habe ich aber in keinen
> anderen Beispiel gefunden (egal ob Code Sourcery oder andere).

".fastrun" ist einfach nur ein Name einer input-section. Woanders hat 
man vielleicht ramrun, runfromram oder ramfunc verwendet. Es gibt dafür 
meines Wissens keine Vorgaben in Dokumenten von ARM. Das "fast" ist auch 
nur dann schnell wenn die Ausführung aus dem RAM schnell ist, muss nicht 
unbedingt bei allen Controllern der Fall sein.

> Das es
> sich dabei um eine Sektion handelt, die für Code reserviert ist, der
> danach aus dem RAM ausgeführt werden soll ist mir klar. Doch irgendwo im
> Compiler muss ja festgelegt sein, dass der Compiler diese Sektionen
> erstellt (für die einzelnen Objektdateien).

Binutils ld-Dokumentation gelesen? Unteschied zwischen input- und 
output-sections verstanden? gcc-Dokumentation Abschnitte Attributes for 
functions und for data gelesen?

Dem Compiler wird per Funktionsattribut im Quellcode mitgeteilt, das 
diese Funktion einer input-section mit dem gewählten Namen zugeordnet 
wird.

> Dazu kommt der Punkt, dass
> der Compiler irgendwo her wissen muss, dass dieser Code vom RAM aus
> ausgeführt werden soll.

Der Compiler "weiss" das auch nicht. Es ist Aufgabe des Linkers die 
Adressen (LMA und VMA, siehe LD-Dokumentation) zuzuweisen. Am 
Einfachsten ist es, eine input-section wie .ramrun/.fastrun in die 
output-section .data mit aufzunehmen (siehe vorliegendes Linker-script). 
Damit wird der Binärcode der Funktionen im Startup-Code mit allen 
anderen Werten in .data (z.B. Initialwerte gloabler Variablen) von 
ROM/Flash (LMA) ins RAM kopiert (VMA, vgl. vorliegenden startup-code).

> Bisher habe ich dazu aber noch nichts gefunden.

Im Speziellen mglw. nicht. Das Prinzip wurde aber wohl beim Studium der 
Compiler- und Binutils-Dokumentation überlesen.

> Verlässt man die "einfache" Umgebung der Yagarto Beispiele wird es noch
> viel schlimmer. Dort haben mich Sektionen wie glue_7, init,
> vfp11_veneer, ARM.attributes und so weiter erwartet.

Wer erwartet? Die stehen vielleicht im Linker-Script und der Linker kann 
somit Adressen zuweisen, wenn eine solche input-section nicht leer ist. 
Einige input-sections können aber einfach leer sein.

> Bei den Meisten
> konnte ich bisher mittels Google zumindest eine Funktion heraus finden.
> Aber z.B. die beiden letzten Erwähnten sind mir noch ein Rätsel.

vfp11 bezieht sich auf Floating-Point. Wie z.B. bei den glue-Funktionen 
erzeugt der Compiler intern Hilfsfunktionen in input-sections, die per 
Linkerscript in output-sections aufgenommen werden.

> Daher nun die wichtige Hauptfrage: Wie finde ich raus, welche Sektionen
> es alles (für meine HW) geben kann und welche Funktionen haben die
> einzelnen Sektionen dann?

"Geben kann": den Linker mit Option --verbose aufrufen. Dann erscheint 
das default linker-script, darin sollten alle mgl. input-sections 
enthalten sein. Einige können durchaus leer sein (z.B. Interwork 
glue-Funktionen bei Controllern, die kein Interwork unterstützen).
"Funktion": gcc-Dokumentation, binutils-Dokumentation, ARM Infocenter. 
Ob dort dann alle möglichen Sections beschrieben sind, weiss ich nicht, 
alle kenne ich auch nicht.

> Ich möchte am Ende in der Lage sein ein Linker Script zusammen zu
> stellen, bei dem ich Bewusst die Sektionen ausgewählt habe und zumindest
> darauf verweisen kann, was die Sektion macht.

Vorschlag Lernziel 1: Zusammenhang input- und output-sections, Map-Files 
lesen lernen (ist nicht wild).

So sehr viel ist im 'üblichen' Geschäft nicht zu "wählen", .text, .data, 
.bss input macht der Compiler schon. Spannend wird es eher bei quirligem 
Speicherlayout (Bootloader, verschieden schnelle Speicher, 
Speicherbereiche mit eingeschränkten Funktionen oder Sonderfunktionen, 
Interruptvektoren in mehreren Ausführungen,...)

> Ich würde mich über eine Antwort sehr freuen (aber bitte keine Google
> Antwort <- da habe ich schon mehr als 6 Stunden verbracht und wenn es da
> zu finden ist suche ich definitiv nach dem Falschen).

Scheint so. Manchmal muss man halt erst durch viele Seiten 
PDF/bilderlose html. Hier z.B. die GNU Bintuils Linkerdokumentation 
("ld"): http://sourceware.org/binutils/docs/ld/ nicht nur überfliegen, 
ist ein guter Anfang bezügl. Linker, Linkerscripts

von Arne Maximilian R. (arnemaximilian_r)


Lesenswert?

Moin,

ich glaube du hast mein Anliegen und meine Fragen nicht ganz verstanden.

Martin Thomas schrieb:
> ".fastrun" ist einfach nur ein Name einer input-section. Woanders hat
> man vielleicht ramrun, runfromram oder ramfunc verwendet. Es gibt dafür
> meines Wissens keine Vorgaben in Dokumenten von ARM. Das "fast" ist auch
> nur dann schnell wenn die Ausführung aus dem RAM schnell ist, muss nicht
> unbedingt bei allen Controllern der Fall sein.
Das die Input Sektion einen beliebigen Namen haben kann ist mir klar. 
Ich kann auch eigene Input Sektionen definieren. Dies mache ich z.B. für 
mein Interrupt Vector (.isr_vector heißt die Sektion bei mir).
Die Frage hier ist aber WOHER weiß der COMPILER, dass der Code nicht in 
die .text (Input <- zumindest aus Linkersicht) Sektion kommt? Dies muss 
der Compiler wissen, dass der Code in die .fastrun Sektion kommt? Woher 
kann ich die Informationen ziehen, dass der Compiler diese Sektion, mit 
diesem Namen und GENAU dieser Funktion erstellt?

Martin Thomas schrieb:
> Binutils ld-Dokumentation gelesen? Unteschied zwischen input- und
> output-sections verstanden? gcc-Dokumentation Abschnitte Attributes for
> functions und for data gelesen?
>
> Dem Compiler wird per Funktionsattribut im Quellcode mitgeteilt, das
> diese Funktion einer input-section mit dem gewählten Namen zugeordnet
> wird.
Ja ich habe die Dokumentation gelesen. Dem Linker ist ja aber erst 
einmal egal, welche Sektionen er vorgeworfen bekommt. Er nimmt ja die 
Input Sektionen und ordnet sie seinen vorgesetzten Output Sektionen zu. 
Also dieser Sachstand ist mir soweit klar.
Die GCC Dokumentation habe ich soweit überflogen bzw. versucht zu 
durchsuchen. Ich konnte dort aber nicht die wichtigen Punkte finden. Es 
werden zwar Sektionen erwähnt. Aber Sektionen wie z.B. die fastrun 
Sektion tauchen nicht in der GCC Dokumentation unter dem Function 
Attributes Abschnitt auf (siehe 
http://gcc.gnu.org/onlinedocs/gcc-4.3.2//gcc/Function-Attributes.html ).

Das gewisse Funktionsattribute im Quellcode auftauchen können und nicht 
unbedingt verwendet werden ist mir auch klar. Es gibt aber Sektionen die 
ich nicht explizit angebe, die ich nicht gesondert angebe und die 
wiederum auch nicht zu den Standardsektionen (wie BSS, Data und Text) 
gehören.

Martin Thomas schrieb:
> Der Compiler "weiss" das auch nicht. Es ist Aufgabe des Linkers die
> Adressen (LMA und VMA, siehe LD-Dokumentation) zuzuweisen. Am
> Einfachsten ist es, eine input-section wie .ramrun/.fastrun in die
> output-section .data mit aufzunehmen (siehe vorliegendes Linker-script).
> Damit wird der Binärcode der Funktionen im Startup-Code mit allen
> anderen Werten in .data (z.B. Initialwerte gloabler Variablen) von
> ROM/Flash (LMA) ins RAM kopiert (VMA, vgl. vorliegenden startup-code).
Ja ist mir klar aber irgendwoher muss die Sektion ja kommen.

Martin Thomas schrieb:
> Wer erwartet? Die stehen vielleicht im Linker-Script und der Linker kann
> somit Adressen zuweisen, wenn eine solche input-section nicht leer ist.
> Einige input-sections können aber einfach leer sein.
"Die Sektionen haben mich dort erwartet." Ja mir ist auch klar, dass 
nicht alle Sektionen belegt werden müssen. Z.B. die .jcr Sektion werde 
ich kaum benötigen, da ich nicht mit Java rumspiele und mein Chip es 
meines Wissens nach nicht unterstützt. Es ändert aber nichts daran, dass 
es Sektionen geben kann, dass der Compiler mir Objekt Dateien vorwirft, 
in denen Sektionen drin stecken, die ich unterstützen könnte aber nicht 
tue.

Martin Thomas schrieb:
> vfp11 bezieht sich auf Floating-Point. Wie z.B. bei den glue-Funktionen
> erzeugt der Compiler intern Hilfsfunktionen in input-sections, die per
> Linkerscript in output-sections aufgenommen werden.
Das mit dem vfp11 habe ich auch rausgefunden. Nicht schwer. Was macht 
aber die Sektion und in welchem Zusammenhang kann diese auftauchen?
Die glue Sektion ist hingegen schon klar. Diese Sektion kombiniert ARM 
und Thumb Code. Da ich mit Cortex-Mx Mikrocontrollern arbeite benötige 
ich diese Sektionen zwar nicht aber sie scheinen überall als Legacy 
Produkteingebunden zu sein.
Aber hier wieder die Frage: Aus welcher Dokumentation ziehe ich die 
Informationen für die Sektionen offiziell (und nicht aus einem Forum)?

Martin Thomas schrieb:
> "Geben kann": den Linker mit Option --verbose aufrufen. Dann erscheint
> das default linker-script, darin sollten alle mgl. input-sections
> enthalten sein. Einige können durchaus leer sein (z.B. Interwork
> glue-Funktionen bei Controllern, die kein Interwork unterstützen).
> "Funktion": gcc-Dokumentation, binutils-Dokumentation, ARM Infocenter.
> Ob dort dann alle möglichen Sections beschrieben sind, weiss ich nicht,
> alle kenne ich auch nicht.
Diese Information hat mir tatsächlich ein bisschen geholfen. Das default 
Skript scheint zumindest die Sektionen aufzulisten. Danke, dass hat mir 
zumindest eine genauere Übersicht geliefert.

Martin Thomas schrieb:
> Vorschlag Lernziel 1: Zusammenhang input- und output-sections, Map-Files
> lesen lernen (ist nicht wild).
Done, done und done (leider schon vorher).

Ich möchte mich schon einmal entschuldigen, wenn ich etwas unhöflich 
und/oder undankbar rüber kam. Ich bin durch das Thema nur langsam etwas 
verzweifelt. Ich bin dir auf jeden Fall schon einmal für die Hilfe 
dankbar!
Ich weiß auch nicht, ob ich einen imaginären Heiligen Gral suche, den es 
nicht gibt. Doch ich versuche halt tatsächlich nur eine dokumentierte 
(offizielle) Dokumentation zu finden, in der die Sektionen alle 
auftauchen (und beschrieben werden). Dabei will ich aber nicht aus 
mehreren Linker Script's die Sachen für mein System zusammen schneiden, 
sondern halt bewusst die Sektionen auswählen und auch aufschreiben. Oder 
such ich hier tatsächlich etwas nicht existierendes?

MfG
Arne

von Roland H. (batchman)


Lesenswert?

Arne Maximilian R. schrieb:
> Ich kann auch eigene Input Sektionen definieren. Dies mache ich z.B. für
> mein Interrupt Vector (.isr_vector heißt die Sektion bei mir).

Offensichtlich machst Du das nicht komplett, denn ...

Arne Maximilian R. schrieb:
> Die Frage hier ist aber WOHER weiß der COMPILER, dass der Code nicht in
> die .text (Input <- zumindest aus Linkersicht) Sektion kommt?

... dann hast Du im Quelltext kein __attribute__ stehen, in welchem 
die Sektion angegeben wird, wenn man nicht die Standardsektion haben 
will:
1
void (* const interruptVectors[])(void) __attribute__ ((section(".isr_vector"))) = {

Arne Maximilian R. schrieb:
> Ich möchte mich schon einmal entschuldigen, wenn ich etwas unhöflich
> und/oder undankbar rüber kam.

Ich fand es etwas undankbar.

Arne Maximilian R. schrieb:
> Ich weiß auch nicht, ob ich einen imaginären Heiligen Gral suche, den es
> nicht gibt.

Die Verständnis von Linker-Skripten ist m. E. eine längere Suche wert, 
wenn man nicht nur mit AVRs zu tun hat. Bei AVR kommt man damit nicht in 
Berührung, mit ARMs habe ich begonnen, und es hat für MSP430, PIC32 und 
Renesas RX sehr geholfen (solange man nur mit GCC unterwegs ist).

> Doch ich versuche halt tatsächlich nur eine dokumentierte
> (offizielle) Dokumentation zu finden, in der die Sektionen alle
> auftauchen (und beschrieben werden).

Die "eine" gibt es nicht, da es diese nicht geben kann.

> Dabei will ich aber nicht aus
> mehreren Linker Script's die Sachen für mein System zusammen schneiden,
> sondern halt bewusst die Sektionen auswählen und auch aufschreiben. Oder
> such ich hier tatsächlich etwas nicht existierendes?

Doch :-). Genau das erste wirst Du tun, und mit dem zweiten kombinieren.

M. E. hast Du eine falsche Erwartungshaltung. Es gibt kein "Linker 
scripts for Dummies in 21 days". Das Verständnis von Linker-Skripten ist 
ein längerer Prozess, bei dem im Laufe der Jahre immer wieder neue 
Wissensschnipsel hinzukommen, z. B. für "Run in RAM", FPU, uint64_t etc.

von Arne Maximilian R. (arnemaximilian_r)


Lesenswert?

Moin,

danke schonmal für die Antwort. Ja das bei dem ersten war etwas daneben. 
Ich möchte mich da noch einmal bei Martin Thomas entschuldigen.

Roland H. schrieb:
> M. E. hast Du eine falsche Erwartungshaltung. Es gibt kein "Linker
> scripts for Dummies in 21 days". Das Verständnis von Linker-Skripten ist
> ein längerer Prozess, bei dem im Laufe der Jahre immer wieder neue
> Wissensschnipsel hinzukommen, z. B. für "Run in RAM", FPU, uint64_t etc.
Der grundsätzliche Aufbau der Skripte schien mir nicht ganz so 
kompliziert, doch die Auswahl der passenden Sektionen befriedigt mich 
halt noch nicht.
Aber verstehe ich dich jetzt richtig, dass sich die Auswahl der 
Sektionen nach und nach entwickelt? Sprich je nachdem über was ich im 
Laufe der Zeit stolpere muss ich mein Skript aktualisieren?
Und ich werde auch kein Dokument finden, in dem alle Sektionen 
aufgelistet sind, die der GCC für ein ARM Kern anlegen kann (C und C++)?

MfG
Arne

von Roland H. (batchman)


Lesenswert?

Arne Maximilian R. schrieb:
> Aber verstehe ich dich jetzt richtig, dass sich die Auswahl der
> Sektionen nach und nach entwickelt? Sprich je nachdem über was ich im
> Laufe der Zeit stolpere muss ich mein Skript aktualisieren?

Ja und Ja. Im Zweifel lasse ich allerdings Sektionen drin, und 
aktualisiere den Kommentar, wenn sich das Wissen gemehrt hat ;-)

Das Problem beim Weglassen besteht darin, dass es zunächst funktionieren 
kann. Plötzlich geht es aber nicht mehr, wenn man z. B. ein 
"überflüssiges" ALIGN entfernt hat.

> Und ich werde auch kein Dokument finden, in dem alle Sektionen
> aufgelistet sind, die der GCC für ein ARM Kern anlegen kann (C und C++)?

Vielleicht im ARM Infocenter.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474c/BABEHEDA.html

Da gibt es auch ein "default GNU ld linker script used by armlink".

Dort stehen allerdings die µC-spezifischen Bereiche (z. B. normales RAM 
und CCM-RAM beim stm32f4) nicht drin.

von Arne Maximilian R. (arnemaximilian_r)


Lesenswert?

Ok danke. Es ist zwar nicht die traumhaften Informationen. Aber wie du 
schon beschrieben hast ist es halt ein dauerhafter Lernprozess. 
Zumindest weiß ich jetzt, wie ich vorgehen muss. Danke.

MfG
Arne

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.