Hallo,
ich bin gerade dabei mich ein wenig mit RISC-V zu beschäftigen. Aber ich
denke das Problem das ich gerade habe liegt eher beim GCC.
Folgendes. Ich möchte zur Compilezeit eine Liste auf dem Flash
erstellen. Dazu lege ich Variablen in der rodata-Section an. Ich habe
dort ein start und ein end und dann die Elemente der Liste. Auf die
Elemente der Liste verweise ich im Programmcode aber nicht. Aus dem
Grund werden die leider wegoptimiert. Also dachte ich das wäre genau
etwas für das attribute used.
https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#index-g_t_0040code_007bused_007d-attribute_002e-2641
Nur leider wird das immer noch wegoptmiert... :(
Auch in der Map-File ist leider nichts vorhanden, was auf 1-elements
hinweist. :/ Sobald ich aber auf list verweise funktioniert das... Das
möchte ich aber nicht! ^^
Wie ihr seht, ich nutze die picolibc und probiere das erst einmal in
qemu...
Den gcc nutze ich in folgender Version
Dies ist freie Software; die Kopierbedingungen stehen in den Quellen. Es
5
gibt KEINE Garantie; auch nicht für MARKTGÄNGIGKEIT oder FÜR SPEZIELLE ZWECKE.
Entweder habe ich dort einen Knoten im Kopf und interpretiere die Doc
vom used falsch, oder keine Ahnung. Zumindest benötige ich die Daten in
dieser Section ohne explizit darauf verweisen zu müssen. Für Erklärungen
wäre ich sehr dankbar! ;)
Viele Grüße
sep
Du hast used nur bei list, nicht aber list start und end. Die packst Du
zwar Linker-mäßig vor und nach list, aber der Compiler kann die bereits
wegoptimieren und tut das auch.
Hallo Nop,
Lt Map-File sind list-start/end aber vorhanden. Diese sollten dort
eigentlich nicht wegoptimiert werden. Trotzdem habe ich das einmal
probiert. Und es funktioniert leider nicht.
Sebastian K. schrieb:> Lt Map-File sind list-start/end aber vorhanden.
Du könntest ja mal Mapfile und Linkerfile posten, vieleicht sieht jemand
da ja noch was?
Das bestätigt zumindest mal die Nulldifferenz, weil "list" verworfen
wird.
Was mir aus dem Linkerfile nicht klar wird: Wo kommen eigentlich die
Sections für .rodata.list.xyz her? Funktioniert sowas automatisch mit
alphabetischer Sortierung? Oder muß man sowas deklarieren?
Jo. Im object drin, nach dem Linken nicht mehr. Mir ist nun aufgefallen,
dass ein einziger Verweis auf irgendein Objekt in dem Speicherbereich
komplett reicht. Dann wird die komplette section mit gelinkt. Also hab
ich einmal folgendes probiert...
Ich finde das zwar ein wenig "Würgaround" aber funktionieren tut das
erst einmal. Vielleicht fällt jemandem ja noch was schöneres ein dem
Linker iwie kundzutun bestimmte sections nicht wegzuwerfen.
Ansonsten vielen vielen Dank für die Diskussion. Die hat sehr geholfen
;)
Sebastian K. schrieb:> bestimmte sections nicht wegzuwerfen
Zum Beispiel, indem man einfach auf --gc-sections verzichtet und
stattdessen nur das linkt, was auch benötigt wird?
Jörg W. schrieb:> indem man einfach auf --gc-sections verzichtet
Das wäre auch was und das steht ja in den spec drin... Wobei das ja auch
einige Vorteile hat speziell wenn Daten wirklich mal nicht benötigt
werden.
Sebastian K. schrieb:> Wobei das ja auch einige Vorteile hat
Klar, man kann mehr herum schlampern, der Linker wird es dann schon
richten. ;-)
--gc-sections ist seinerzeit wohl insbesondere hinsichtlich C++
eingeführt worden, weil man dort eben über manche Gebilde (Konstruktoren
/ Destruktoren) nicht im Quelltext selbst entscheiden kann, sondern der
Compiler verpflichtet ist, sie anzulegen. Da hilft es dann, wenn der
Compiler sie in separate sections ablegen kann und der Linker alle die,
die am Ende nicht referenziert werden, entfernt werden.
Also Option für "ich schreibe einfach mal alles hin, was mir einfällt,
egal, ob's am Ende gebraucht wird oder nicht" war es eigentlich nicht
gedacht.
Jörg W. schrieb:> Klar, man kann mehr herum schlampern, der Linker wird es dann schon> richten. ;-)>
*Hust...
Das dachte ich mir auch gerade als ich senden geklickt habe! :D
Der Compiler ist aber unter anderem für solche Optimierungen da. Wäre ja
zu schön, wenn man sich um alles selber kümmern müsste. ;)
Ich denke zu totem Code kommt man schnell und nicht immer direkt
sichtbar. Der Compiler kann das besser analysieren und den toten Code
dann raushauen. Zusätzlich dann auch die Sections, welche nicht
dazugehören. Immerhin ist der Compiler bei sowas um einiges
zuverlässiger als der Mansch. :) Viel mit "rumschlampen" hat das dann
nicht zu tun.
Sebastian K. schrieb:> Ich denke zu totem Code kommt man schnell und nicht immer direkt> sichtbar.
Naja, ist ein Qualitätsmerkmal der Softwareentwicklung.
Es ist ja nicht nur der eingesparte Platz. Der tote Code verrottet
unbemerkt, da er ja nicht benutzt wird. Zwei Jahre später braucht mal
jemand die Funktionalität, die der tote Code verspricht zu
implementieren, benutzt die Funktion wieder – und sucht sich einen Wolf,
warum das nicht (mehr) klappt, bis er dann begreift, dass der Code schon
ewig nicht mehr benutzt worden war zuvor.
Bei uns ist sowas jedenfalls im Codereview rausgeflogen. Die History zu
erhalten ist Aufgabe des VCS.
Sebastian K. schrieb:> Vielleicht fällt jemandem ja noch was schöneres ein dem> Linker iwie kundzutun bestimmte sections nicht wegzuwerfen.
Indem man sie im Linkerfile mit KEEP aufführt, das wäre mein Ansatz
(siehe oben).
Jörg W. schrieb:> Naja, ist ein Qualitätsmerkmal der Softwareentwicklung.
Oftamals ja. Aber wenn Du Libraries hast, die man projektübergreifend
nutzt und pflegt, dann ist es normal, daß sowohl Code als auch Daten
nicht in jedem Projekt komplett genutzt werden. Könnte man alternativ
natürlich mit einem Zoo an #ifdefs in den Griff kriegen.
Aber wie kamst Du eigentlich darauf, als Lösung --gcsections
wegzulassen? In den Compiler-Aufrufen sehe ich das ohnehin nicht?
Nop schrieb:> Aber wenn Du Libraries hast, die man projektübergreifend> nutzt und pflegt, dann ist es normal, daß sowohl Code als auch Daten> nicht in jedem Projekt komplett genutzt werden. Könnte man alternativ> natürlich mit einem Zoo an #ifdefs in den Griff kriegen.
Oder richtige Libraries draus machen: eine Funktion (oder eine wirklich
zusammen gehörige Gruppe von Funktionen) pro Objektmodul, und dann den
Archivar benutzen.
Der Linker pickt sich dann nur die Module, die er braucht.
> Aber wie kamst Du eigentlich darauf, als Lösung --gcsections> wegzulassen?
Weil es ja offensichtlich das Problem verursacht (hat).
> In den Compiler-Aufrufen sehe ich das ohnehin nicht?
Steht im .specs File, welches oben auch gepostet worden ist.
Danke euch beiden auf alle Fälle!
Nop schrieb:> Indem man sie im Linkerfile mit KEEP aufführt, das wäre mein Ansatz> (siehe oben).
Das ist mir auch noch als Idee gekommen als ich darüber ein wenig weiter
sinniert habe. Nun ist ja aber die Sache, dass ich nicht das komplette
ld-script kopieren wollen würde. Da habe ich dann auch was zu gefunden.
http://sourceware.org/binutils/docs/ld/Miscellaneous-Commands.html#Miscellaneous-Commands
Wenn ich mir nun dort einmal das Bsp für Insert [AFTER|BEFORE] anschaue
und das für mich adaptiere erstelle ich mir folgendes:
1
$ cat main.ld
2
SECTIONS
3
{
4
.rodata.list :
5
{
6
*(.list*)
7
}
8
}
9
INSERT AFTER .rodata;
Leider mag das aber nicht. .rodata ist aber auf alle Fälle vorhanden.
Kann mir jmd dort sagen warum?
Sebastian K. schrieb:> .rodata ist aber auf alle Fälle vorhanden
Wenn das da oben dein kompletter Linkerscript ist – nö, da ist kein
.rodata drin. Auch sonst nicht viel.
Du musst den Linkerscript schon, wenn du ihn anpassen willst, komplett
selbst schreiben und pflegen.
Sry. Wollte das nun nicht kommentarlos posten. Also die picolibc.ld ist
dort als Linkerscript mit angegeben. Dann sollte ja auch die rodata
vorhanden sein... Ich schau mir das noch einmal an wie das bei x86
ausschaut...
Hey,
Also ich hab ein paar neue Erkenntnisse, es läuft aber noch nicht so wie
ich das will... ... Also der Fehler kommt immer noch, wenn ich das via
INSERT AFTER mache.
Ich habe ja h´gesagt, bei x86 funktioniert das alles wenn ich die neue
section hinter .rodata anhänge. Ich habe dann einmal geschaut nach der
Compilerversion, der Binutils-Version und den Aufrufen. Dort konnte ich
leider nichts finden.
Anschließend dachte ich mir ich versuche das einmal mit der AVR
Toolchain. Auch dort bekam ich beim INSERT AFTER .rodata; den selben
Fehler. Was aber funktioniert ist INSERT AFTER .data;.
Nun bin ich in LD-Scripte schreiben nun nicht so die Leuchte. Da muss
ich mich erst einmal einlesen. Aber vielleicht hat ja hier jmd. ein
guten Tipp, wie ich das vielleicht hin bekomme?
Ich denke wenn wir dort was hinbekommen werde ich auch bei der picolib
ein PR aufmachen dazu. Denn dynamischer ist ja immer schöner ;)
Hallo,
Also so ganz verstehe ich das nicht. Generell werden Output-Sections
doch in dem SECTIONS-Command definiert. Dort dann:
1
SECTIONS {
2
.outputname : {
3
.inputname
4
}
5
}
Das würde heißen, dass .text in der picolibc ja eine output-section ist.
Aber auch dort kann ich nicht das INSERT nutzen. Zum Ersten hätte ich
dort vorgehabt das .text in .text und .data aufzutrennen. Aber jede
Section, welche ich definiere wird von dem INSERT nicht erkannt.
Ich dachte schon, dass liegt an den PHDRS aber diese definieren ja nur
die Header. Bei dem Linker-script vom AVR funktioniert das ja auch.
Jedoch fällt mir dort bei vielen "ersten" Blicken kein bedeutender
Unterschied auf... ...
Hat jemand dort eine Erklärung?
Danke und Viele Grüße
Sebastian K. schrieb:> Das würde heißen, dass .text in der picolibc ja eine output-section ist.
Die heißt allerdings .text, nicht .rodata.
> das .text in .text und .data aufzutrennen
Vorsicht: .data wird sowohl im RAM als auch im Flash benötigt; letzteres
sind die Initialwerte, die vom Startup-Code in den RAM kopiert werden.
eingebe auch der Fehler kommt, das die .text section nicht vorhanden
ist. Diese sollte doch aber da sein. Laut dem linker-Script von der
picolibc.
Oder verstehe ich dort etwas falsch?
Sebastian K. schrieb:> Oder verstehe ich dort etwas falsch?
Sorry, ich habe mit diesem INSERT auch keine Ahnung.
Kannst noch Mapfiles vergleichen, aber da die relevanten Unterschiede zu
finden hat was von Nadel im Heuhaufen.