Wie lassen sich schwache Links mit GCC zum Laufen bringen?

Lesezeit: 7 Minuten

Es scheint 3 Möglichkeiten zu geben, GCC anzuweisen, ein Symbol schwach zu verknüpfen:

  • __attribute__((weak_import))
  • __attribute__((weak))
  • #pragma weak symbol_name

Keines davon funktioniert bei mir:

#pragma weak asdf
extern void asdf(void) __attribute__((weak_import, weak));
...
{
    if(asdf != NULL) asdf();
}

Ich bekomme immer einen Link-Fehler wie diesen:

Undefined symbols:
  "_asdf", referenced from:
      _asdf$non_lazy_ptr in ccFA05kN.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Ich verwende GCC 4.0.1 unter OS X 10.5.5. Was mache ich falsch?

  • int __attribute__((weak)) main() { ... } funktioniert gut für mich mit gcc/Mac OS X, kann aber nicht mit gcc/MinGW kompiliert werden. 🙁

    – Mcandre

    12. September 2012 um 21:13 Uhr

Ich habe mir das gerade angesehen und dachte, einige andere könnten an meinen Ergebnissen interessiert sein.

Schwaches Linken mit schwachem_import funktioniert wirklich nur mit dynamischen Bibliotheken gut. Sie können es mit statischem Linken zum Laufen bringen (indem Sie -undefined dynamic_lookup wie oben vorgeschlagen angeben), aber das ist keine so heiße Idee. Das bedeutet, dass bis zur Laufzeit keine undefinierten Symbole erkannt werden. Dies würde ich persönlich im Produktionscode vermeiden.

Hier ist eine Mac OS X Terminal-Sitzung, die zeigt, wie es funktioniert:

Hier ist FC

int f(int n)
{
    return n * 7;
}

Hier ist whatnof.c

#include <stdio.h>
#include <stdlib.h>

extern int f (int) __attribute__((weak_import));

int main() {
    if(f == NULL)
        printf("what, no f?\n");
    else
        printf("f(8) is %d\n", f(8));
    exit(0);
}

Erstellen Sie eine dynamische Bibliothek aus fc:

$ cc -dynamiclib -o f.dylib f.c

Kompilieren und verknüpfen Sie mit der dynamischen Bibliothek, listen Sie dynamische Bibliotheken auf.

$ cc -o whatnof whatnof.c f.dylib
$ otool -L whatnof
whatnof:
       f.dylib (compatibility version 0.0.0, current version 0.0.0)
       /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Führen Sie whatnof aus, um zu sehen, was passiert:

$ whatnof
f(8) is 56

Ersetzen Sie nun f.dylib durch eine leere Bibliothek (keine Symbole):

$ mv f.dylib f.dylib.real
$ touch null.c
$ cc -dynamiclib -o f.dylib null.c

Führen Sie dasselbe whatnof aus, um zu sehen, was passiert:

$ whatnof
what, no f?

Die Grundidee (oder “Anwendungsfall”) für schwach_import besteht darin, dass Sie mit einer Reihe dynamischer (gemeinsam genutzter) Bibliotheken verknüpfen können, aber dann denselben Code mit früheren Versionen derselben Bibliotheken ausführen können. Sie können Funktionen gegen NULL prüfen, um festzustellen, ob sie in der bestimmten dynamischen Bibliothek unterstützt werden, für die der Code derzeit ausgeführt wird. Dies scheint Teil des grundlegenden Entwicklungsmodells zu sein, das von Xcode unterstützt wird. Ich hoffe, dieses Beispiel ist nützlich; es hat mir geholfen, mich in Bezug auf diesen Teil des Xcode-Designs zu beruhigen.

Hinzufügen -Wl,-flat_namespace,-undefined,dynamic_lookup zur gcc-Compilerzeile, die Sie für den endgültigen Link verwenden.

  • Wenn ich gcc/MinGW verwende, heißt es cc1.exe: error: unrecognized command line option "-flat_namespace,-undefined,dynamic_lookup".

    – Mcandre

    12. September 2012 um 21:12 Uhr

Minimales lauffähiges Linux-Beispiel

Haupt c

#include <stdio.h>

int my_weak_var __attribute__((weak)) = 1;

int main(void) {
    printf("%d\n", my_weak_var);
}

notmain.c

int my_weak_var = 2;

Kompilieren und mit beiden Objekten ausführen:

gcc -c -std=c99 -Wall -Wextra -pedantic -o main.o main.c
gcc -c -std=c99 -Wall -Wextra -pedantic -o notmain.o notmain.c
gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.o notmain.o
./main.out

Ausgabe:

2

Kompilieren und ohne ausführen notmain.o:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.o
./main.out

Ausgabe:

1

GitHub-Upstream.

Wir sehen das also, wenn es weiter gegeben wird notmain.odann hat das nicht schwache Symbol wie erwartet Vorrang.

Wir können die ELF-Objektdateisymbole analysieren mit:

nm main.o notmain.o

was ergibt:

main.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
0000000000000000 V my_weak_var
                 U printf

notmain.o:
0000000000000000 D my_weak_var

und dann:

man nm

enthält:

Der Symboltyp. Mindestens die folgenden Typen werden verwendet; andere hängen ebenfalls vom Objektdateiformat ab. Bei Kleinbuchstaben ist das Symbol normalerweise lokal; bei Großbuchstaben ist das Symbol global (extern). Es gibt jedoch einige Kleinbuchstaben, die für spezielle globale Symbole (“u”, “v” und “w”) angezeigt werden.

“D”
“d” Das Symbol befindet sich im initialisierten Datenabschnitt.

“V”
“v” Das Symbol ist ein schwaches Objekt. Wenn ein schwach definiertes Symbol mit einem normal definierten Symbol verknüpft wird, wird das normal definierte Symbol ohne Fehler verwendet. Wenn ein schwaches undefiniertes Symbol verknüpft und das Symbol nicht definiert ist, wird der Wert des schwachen Symbols fehlerfrei Null. Auf einigen Systemen gibt Großschreibung an, dass ein Standardwert angegeben wurde.

Im Umgang mit .a statische Bibliotheken müssen Sie jedoch möglicherweise verwenden -Wl,--whole-archive wie erklärt unter: Wie mache ich ein starkes gcc-Link-Symbol in der statischen Bibliothek, um ein schwaches Symbol zu überschreiben?

Schwache Symbole können auch undefiniert bleiben, was in Binutils zu “plattformspezifischem Verhalten” führt, siehe: GCC-Verhalten für ungelöste schwache Funktionen

Getestet auf Ubuntu 18.10, GCC 8.2.0.

Sie müssen die Variable MACOSX_DEPLOYMENT_TARGET auf 10.2 oder höher setzen. Sehen Apples Dokumentation und ihre Technote auf schwache Verlinkung.

Aus dem gcc doc Handbuch:

schwach

Das schwache Attribut bewirkt, dass die Deklaration als schwaches Symbol und nicht als globales ausgegeben wird. Dies ist hauptsächlich beim Definieren von Bibliotheksfunktionen nützlich, die im Benutzercode überschrieben werden können, obwohl es auch mit Nicht-Funktionsdeklarationen verwendet werden kann. Schwache Symbole werden für ELF-Ziele und auch für a.out-Ziele unterstützt, wenn der GNU-Assembler und -Linker verwendet werden.

was bedeutet, dass ein Objekt legitimiert ist, ein schwaches Symbol (definiert in einem anderen Objekt/einer anderen Bibliothek) zu überschreiben, ohne dass zur Verbindungszeit Fehler auftreten. Unklar ist, ob Sie die Bibliothek mit der verknüpfen schwach Symbol oder nicht. Es scheint, dass Sie das Symbol nicht definiert haben und die Bibliothek nicht richtig verknüpft ist.

  • Es scheint zwei Verwendungen von schwachen Links zu geben: gcc.gnu.org/ml/gcc/1999-02n/msg01219.html Ich versuche, mit einer alten Version einer Bibliothek zu verknüpfen. Die aktuelle Version definiert Funktionen, die die alte nicht hatte. Ich möchte die neuen Funktionen nutzen können, wenn sie zur Laufzeit verfügbar sind.

    Ben

    8. November 2008 um 15:44 Uhr

  • Dieses Zitat trifft hier nicht zu: „Das Mac OS X Weak Linking Design [comes from the classic Mac OS Code Fragment Manager]. Wenn Sie sich auskennen [ELF]sind Sie möglicherweise an eine andere Bedeutung der Begriffe gewöhnt schwaches Zeichen oder Schwache Verlinkung, wobei ein schwaches Symbol durch ein nicht schwaches Symbol überschrieben werden kann. Die entsprechende Funktion von Mac OS X ist die schwache Definition -sehen „Geltungsbereich und Behandlung von Symboldefinitionen“ für mehr Informationen.”

    – Jeremy W. Sherman

    6. Dezember 2010 um 0:04 Uhr


  • Einverstanden: Apples Dokumentation beschreibt gcc ungenau. Fairerweise bedenkt, dass sich gcc von vornherein nicht richtig beschreibt.

    – März

    5. Oktober 2018 um 20:33 Uhr

  • Es scheint zwei Verwendungen von schwachen Links zu geben: gcc.gnu.org/ml/gcc/1999-02n/msg01219.html Ich versuche, mit einer alten Version einer Bibliothek zu verknüpfen. Die aktuelle Version definiert Funktionen, die die alte nicht hatte. Ich möchte die neuen Funktionen nutzen können, wenn sie zur Laufzeit verfügbar sind.

    Ben

    8. November 2008 um 15:44 Uhr

  • Dieses Zitat trifft hier nicht zu: „Das Mac OS X Weak Linking Design [comes from the classic Mac OS Code Fragment Manager]. Wenn Sie sich auskennen [ELF]sind Sie möglicherweise an eine andere Bedeutung der Begriffe gewöhnt schwaches Zeichen oder Schwache Verlinkung, wobei ein schwaches Symbol durch ein nicht schwaches Symbol überschrieben werden kann. Die entsprechende Funktion von Mac OS X ist die schwache Definition -sehen „Geltungsbereich und Behandlung von Symboldefinitionen“ für mehr Informationen.”

    – Jeremy W. Sherman

    6. Dezember 2010 um 0:04 Uhr


  • Einverstanden: Apples Dokumentation beschreibt gcc ungenau. Fairerweise bedenkt, dass sich gcc von vornherein nicht richtig beschreibt.

    – März

    5. Oktober 2018 um 20:33 Uhr

1368500cookie-checkWie lassen sich schwache Links mit GCC zum Laufen bringen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy