Ich habe die Verwendung des Attributs gcc __section__
gesehen (besonders in Linux-Kernel), um Daten (normalerweise Funktionszeiger) in benutzerdefinierten ELF-Abschnitten zu sammeln. Wie wird das "Zeug", das in diese benutzerdefinierten Abschnitte eingefügt wird, abgerufen und verwendet?
Solange der Abschnittsname zu einem gültigen C-Variablennamen führt, erzeugt gcc
( ld
, eher) zwei magische Variablen: __start_SECTION
und __stop_SECTION
. Diese können verwendet werden, um die Start- und Endadressen eines Abschnitts wie folgt abzurufen:
Ich konnte keine formale Dokumentation für dieses Feature finden, nur ein paar obskure Mailinglistenreferenzen. Wenn Sie wissen, wo sich die Dokumente befinden, hinterlassen Sie einen Kommentar!
Wenn Sie Ihr eigenes Linker-Skript verwenden (wie es der Linux-Kernel tut), müssen Sie die magischen Variablen selbst hinzufügen (siehe vmlinux.lds.[Sh]
und diese SO-Antwort ).
Siehe hier für ein anderes Beispiel Verwenden benutzerdefinierter ELF-Abschnitte.
Linker kann die im Code definierten Symbole verwenden und ihre Anfangswerte zuweisen, wenn Sie den genauen Namen im Linkerskript verwenden:
%Vor%Definieren Sie einfach eine Variable im C-Code:
%Vor%Und dann können Sie als reguläre Variable darauf zugreifen.
%Vor% Sammeln Sie die Informationen zusammen aus verschiedenen Antworten, hier ist ein funktionierendes Beispiel, wie Sie Informationen in einem benutzerdefinierten Linker-Abschnitt sammeln und dann die Informationen aus diesem Abschnitt mit den magischen Variablen __start_SECTION
und __stop_SECTION
in Ihrem C-Programm lesen können. Dabei ist SECTION
der Name des Abschnitts in der Verknüpfungszuordnung.
Die Variablen __start_SECTION
und __stop_SECTION
werden vom Linker zur Verfügung gestellt, so dass explizite extern
Referenzen für diese Variablen erstellt werden müssen, wenn sie aus C-Code verwendet werden.
Es gibt auch einige Probleme, wenn die vom Compiler zum Berechnen von Pointer / Array-Offsets verwendete Ausrichtung sich von der Ausrichtung der Objekte unterscheidet, die in jedem Abschnitt vom Linker gepackt werden. Eine Lösung (in diesem Beispiel verwendet) besteht darin, nur einen Zeiger auf die Daten im Linkerabschnitt zu speichern.
%Vor% Die obige Antwort, __start_SECTION
und __stop_SECTION
, wird funktionieren. Damit das Programm jedoch die Informationen aus dem Linker verwenden kann, müssen Sie diese Variablen als extern char* __start_SECTION
deklarieren. Viel Spaß!