2011-01-14 9 views
6

Gibt es eine Möglichkeit mit GCC und GNU Binutils einige Funktionen zu markieren, so dass sie einen Fehler bei Link-Zeit generieren, wenn verwendet? Meine Situation ist, dass ich einige Bibliotheksfunktionen habe, die ich aus Gründen der Kompatibilität mit vorhandenen Binärdateien nicht entferne, aber ich möchte sicherstellen, dass keine neu kompilierte Binärdatei versucht, die Funktionen zu verwenden. Ich kann nicht einfach Kompilierzeit-gcc-Attribute verwenden, da der störende Code meine Header ignoriert und das Vorhandensein der Funktionen mit einem configure-Skript erkennt und sie selbst prototypisiert. Mein Ziel ist es, einen Link-Zeit Fehler für die schlechten configure Skripte zu generieren, so dass sie aufhören zu erkennen, die Existenz der Funktionen.Generating Link-Time-Fehler für veraltete Funktionen

Edit: Eine Idee .. würde Montage mit dem falschen .type für den Einspeisepunkten angeben mit dem dynamischen Linker kompatibel sein, aber Verbindungsfehler erzeugen, wenn sie versuchen, neue Programme zu verknüpfen?

Antwort

0

Die beste Möglichkeit zum Generieren eines Link-Zeitfehlers für veraltete Funktionen, die nicht von Benutzern verwendet werden sollen, besteht darin, sicherzustellen, dass die veralteten Funktionen nicht in den Bibliotheken vorhanden sind - wodurch sie eine Stufe über "veraltet" hinausgehen.

Möglicherweise können Sie eine Hilfsbibliothek mit der veralteten Funktion darin bereitstellen; die Verworfenen, die nicht aufpassen werden, können sich mit der Hilfsbibliothek verbinden, aber die Leute im Mainstream werden die Hilfsbibliothek nicht benutzen und deshalb die Funktionen nicht benutzen. Es geht jedoch immer noch über das "veraltete" Stadium hinaus.

Es ist schwierig, eine Link-Zeit-Warnung zu erhalten. Offensichtlich macht GCC das für einige Funktionen (mktemp() et al), und Apple hat GCC warnen, wenn Sie ein Programm ausführen, das gets() verwendet. Ich weiß nicht, was sie tun, um das zu erreichen.


Im Lichte der Kommentare, ich glaube, das Problem weg bei der Kompilierung, anstatt zu warten, bis Link Zeit oder zur Laufzeit gehen brauchen.

Die GCC-Attribute sind (von der GCC 4.4.1 Handbuch):

error ("message") 

Wenn dieses Attribut auf einer Funktionsdeklaration und einem Aufruf einer solchen Funktion verwendet wird, wird nicht durch totem Code beseitigt Beseitigung oder andere Optimierungen, ein Fehler , der Nachricht enthält, wird diagnostiziert. Dies ist nützlich für die Kompilierzeit Überprüfung, vor allem zusammen mit __builtin_constant_p und Inline-Funktionen wo Überprüfung der Inline-Funktion Argumente ist nicht möglich durch externe char [(Bedingung)? 1: -1]; Tricks. Während es möglich ist, die Funktion undefiniert zu lassen und somit einen Verbindungsfehler auszulösen, wird bei Verwendung dieses Attributs das Problem früher diagnostiziert und der genaue Standort des Anrufs selbst bei Anwesenheit von Inline-Funktionen oder wenn keine Debugging-Informationen ausgegeben werden.

warning ("message") 

Wenn dieses Attribut auf einer Funktionsdeklaration und ein Aufruf an eine solche Funktion ist nicht durch Beseitigung von totem Code oder andere Optimierungen eliminiert verwendet wird, wird eine Warnung die Nachricht enthalten wird wird diagnostiziert. Dies ist nützlich für die Kompilierzeit Überprüfung, vor allem zusammen mit __builtin_constant_p und Inline-Funktionen. Während es möglich ist, die Funktion mit einer Nachricht in .gnu zu definieren.Warnung * Abschnitt, wenn dieses Attribut wird das Problem früher und mit dem genauen Standort des Anrufs auch in Anwesenheit von Inline-Funktionen oder wenn nicht emittierende Debug-Informationen diagnostiziert.

Wenn die Konfigurationsprogramme die Fehler ignorieren, sind sie einfach fehlerhaft. Das bedeutet, dass neuer Code nicht mit den Funktionen kompiliert werden konnte, aber der vorhandene Code weiterhin die veralteten Funktionen in den Bibliotheken verwenden kann (bis er neu kompiliert werden muss).

+0

Die Warnungen können mit der '.gnu.warning' Note getan werden, aber Ich kenne kein Äquivalent für die Generierung von Fehlern. Während Ihre Lösung die beste ist, erfüllt sie leider nicht meine Anforderungen, sowohl mit einem veralteten ABI als auch mit der Verknüpfung neuer Anwendungen übereinzustimmen. –

+0

@R ..: Fair genug. Ist es fair zu sagen, dass Sie eine Kopie der Bibliotheken installiert haben möchten; Sie möchten, dass vorkompilierte Apps (die die veraltete Schnittstelle verwenden können) weiterhin ausgeführt werden. Sie möchten, dass neu kompilierte Apps, die die veraltete Schnittstelle verwenden, keine Verbindung herstellen können? Wenn ja, und wenn die Konfigurationsdetektoren die veralteten Funktionen erkennen, wie planen Sie, dass Leute Dinge reparieren lassen, damit der Code mit den modernen (nicht veralteten) Schnittstellen verknüpft wird? –

+0

Es gibt keine neue Austauschschnittstelle; Der Versuch, diese veralteten Schnittstellen zu verwenden, ist nur schädlich, und das richtige Verhalten besteht darin, sie überhaupt nicht zu verwenden.Leider habe ich keine Kontrolle über die kaputte Software, die versucht, sie zu verwenden, und während ich die Betreuer wahrscheinlich dazu bringen könnte, neue Versionen zu reparieren, versuchen die Benutzer möglicherweise noch eine Weile alte Versionen zu kompilieren. –

0

Eine Idee könnte sein, eine Stub-Bibliothek zu erzeugen, die diese Symbole hat, aber unerwartete Eigenschaften hat.

  • vielleicht Objekte erstellen, die den Namen der Funktionen haben, so der Linker in der Konfigurationsphase könnte sich darüber beschweren, dass die Symbole nicht kompatibel sind
  • Funktionen erstellen, die eine Abhängigkeit „dont_use_symbol_XXX“, die nie
  • behoben ist
  • oder fälschen .a-Datei mit einem globalen Index, Ihre Funktionen haben würde, aber wo die .o Mitglieder im Archiv das falsche Format
2

FreeBSD 9.x etwas tut, ganz in der Nähe, was wollen Sie mit dem ttyslot() haben Funk tion. Diese Funktion ist mit utmpx bedeutungslos. Der Trick besteht darin, dass es nur Nicht-Standardversionen dieses Symbols gibt. Daher wird ld es nicht finden, aber rtld wird die versionierte Definition finden, wenn eine alte Binärdatei ausgeführt wird. Ich weiß nicht, was passiert, wenn eine alte Binärdatei eine unversionierte Referenz hat, aber wahrscheinlich ist es sinnvoll, wenn es nur eine Definition gibt.

Zum Beispiel

__asm__(".symver hidden_badfunc, [email protected]_1.0"); 

Normalerweise würde es auch eine Standard-Version sein, wie

__asm__(".symver new_badfunc, [email protected]@MYLIB_1.1"); 

oder über eine Solaris-kompatible Version Skript, aber der Trick ist, nicht ein hinzuzufügen.

In der Regel ist die asm-Direktive in ein Makro eingebettet.

Der Trick hängt von den GNU-Erweiterungen ab, um Symbolversionen mit der Assembler-Direktive .symver zu definieren, also wird es wahrscheinlich nur unter Linux und FreeBSD funktionieren. Die Solaris-kompatiblen Versionsskripte können nur eine Definition pro Symbol ausdrücken.

Weitere Informationen: .symver Richtlinie in info gas, Ulrich Drepper des "Wie Shared Libraries zu schreiben", die verpflichten, dass veraltete ttyslot() bei http://gitorious.org/freebsd/freebsd/commit/3f59ed0d571ac62355fc2bde3edbfe9a4e722845

+0

Können Sie besser erklären, wie das funktioniert, oder einen Link bereitstellen? Es klingt, als könnte es meine Bedürfnisse erfüllen. –

+0

@R .. Ich fügte weitere Informationen in einer Bearbeitung hinzu. – jilles