guest schrieb:
> Oder mittels objcopy in .o Dateien verwandeln und einfach dazu linken:
Das lässt sich noch etwas verbessern:
1. Man konvertiert die Datei erst mit "ld". Der Witz daran ist, dass
"ld" automatisch die richtige Architektur auswählt, während man die bei
"objcopy" noch mit "-B" umständlich angeben muss, was für portable
Makefiles problematisch ist:
1 | ld -r -b binary -o blob.pre.o blob.txt
|
2. Man verarbeitet die Datei mit "objcopy", um die Section-Einstellungen
zu ändern:
1 | objcopy --set-section-alignment" ".data=4" "--set-section-flags" ".data=alloc,load,readonly,data" "--rename-section" ".data=.rodata.myblob" "blob.pre.o" "blob.o"
|
Die seit Binutils 2.33 verfügbare Option "--set-section-aligment" (von
mir implementiert :) ) setzt die Ausrichtung des Datenblocks im
Speicher. Das ist insbesondere wichtig wenn man die Daten auf µC danach
per DMA o.ä. verarbeiten möchte. Die gezeigte "--set-section-flags"
Option sorgt dafür dass der Datenblock im schreibgeschützten
Speicherbereich landet (also typischerweise Flash). Mit
"--rename-section" bekommt die Section noch einen sprechenderen Namen.
3. Man linkt die erzeugte "blob.o" dazu, und nutzt dann wie im o.g. Link
gezeigt im C-Code die Symbole "_binary_blob_txt_start" /
"_binary_blob_txt_end" / "_binary_blob_txt_size". Man kann da noch einen
Wrapper für bauen:
1 | #include <string_view>
|
2 |
|
3 | #define OS_BINSECT2(start,end) (std::string_view { []() -> char* { extern char start; return &start; }(), []() -> std::size_t { extern char start, end; return &end - &start; }()})
|
4 |
|
5 | #define OS_BINSECT(name) OS_BINSECT2(_binary_ ## name ## _start, _binary_ ## name ## _end)
|
Wenn man dann im Code irgendwo "OS_BINSECT(blob_txt)" schreibt wird dies
automatisch zu einem std::string_view, welcher die gewünschten
Binärdaten enthält.
Der Vorteil dieses Vorgehens ist dass so beliebig (große) binäre
Datenblöcke schnell eingebunden werden können, egal was die für
(Sonder)zeichen enthalten, ohne C(++)-Code generieren zu müssen und die
Daten escapen zu müssen. Indem man das richtige ld & objcopy benutzt
(also z.B. arm-none-eabi-ld/objcopy) ist die ELF-Datei automatisch
richtig für die gewünschte Plattform.
Der Nachteil ist dass man eben aktuelle binutils braucht und das im
Makefile etwas umständlich ist.
Beim Erzeugen von C(++) Code muss man auch auf Trigraphs acht geben und
das Übersetzen großer solcher Datenblöcke dauert je nach Darstellung
recht lange. Daher bevorzuge ich die ld+objcopy Variante.