-
Die
Erfindung betrifft Verfahren, Vorrichtungen und Computerprogrammprodukte
zur Versionsmarkierung und Versionsüberprüfung von binären Dateien
auf einem Computersystem.
-
Bei
der Softwareentwicklung werden häufig verwendete
Funktionen und Routinen oder solche mit speziellen Anwendungsbereichen,
wie z.B. arithmetische, I/O- oder Graphikfunktionen, dem Programmierer
meist in Form von Funktionssammlungen bzw. Programmbibliotheken
zur Verfügung
gestellt. Dadurch werden Funktionen wiederverwendbar, da ein Programmierer
nur die entsprechende Bibliothek in seine Applikation (ausführbare Programmdatei)
einbindet, anstatt die Funktion neu schreiben zu müssen.
-
Es
gibt prinzipiell zwei verschiedenen Arten von Bibliotheken, statisch
bindbare und dynamisch bindbare Bibliotheken („Dynamic Linked Libraries", DLL). Die statisch
bindbaren Bibliotheken haben den Nachteil, daß beim Kompilieren bzw. Binden
an eine Applikation die statische Bibliothek vollständig in
die Applikationsdatei einkopiert wird. Diese Binde-Strategie verbraucht
viel Speicherplatz, weil sie zu großen Programmdateien führt und
eine häufig
benutzte Bibliothek auf einem Rechnersystem oft hundertfach kopiert
vorliegt.
-
Diesen
Nachteil vermeiden dynamisch bindbaren Bibliotheken (DLLs), da beim
Kompilieren bzw. Binden einer Applikation lediglich Verweise auf
die Stelle im Speicher, an der die benötigte Funktion der DLL liegt,
in die Applikation eingefügt
werden. Der gleiche Mechanismus des Verweisens wird verwendet, wenn
eine DLL ihrerseits Funktionen einer anderen DLL verwendet. Dadurch
wird die Binärdateigröße von kompilierten
Applikationen und DLLs minimiert. Es wird kein Speicherplatz mehr
durch Kopieren ver schwendet, da jede Applikation und jede DLL auf
die gleiche (in der Regel einzige) Kopie einer DLL zugreifen kann,
deren Funktionen sie benötigt.
-
Ein
Nachteil gegenüber
statisch bindbaren Bibliotheken ergibt sich bei der Softwareentwicklung allerdings
häufig,
wenn DLLs anderer Applikationen in die eigenen Applikation eingebunden
werden. Bei einem Windows-System ist hierbei das übliche Szenario,
daß solche
DLLs in das Windows-Systemverzeichnis
kopiert werden, wo sie dann prinzipiell allen Applikationen zum
Einbinden zur Verfügung
stehen.
-
Wenn
nun für
eine bestimmte Applikation durch Änderung oder Weiterentwicklung
eine neue Version einer DLL erstellt wird, wird die neue Version der
DLL mit unverändertem
Namen wieder in das Systemverzeichnis kopiert und die alte Version
der DLL überschrieben.
Häufig
betreffen die Änderungen einer
DLL die Vereinbarungen über
die Art, wie die Funktionen der DLL aufgerufen werden – also die Schnittstelle
zwischen Applikationen und DLLs. Andere Applikationen, die die bisherige
Schnittstelle verwenden, werden bei diesem Vorgang meist nicht angepaßt, allein
schon, weil man als Programmierer/Softwarehersteller in der Regel
nicht weiß,
welche anderen Applikationen noch auf die eigene DLL zugreifen.
Die Folge ist, daß derartige
Applikationen die Funktionen der DLL nicht mehr korrekt aufrufen können und
zumeist unkontrolliert mit teilweise gravierenden Nebenwirkungen „abstürzen".
-
Ein
derart undefiniertes Verhalten einer Applikation gefährdet die
Integrität
des Systems und ist insbesondere in sicherheitsrelevanten Bereichen
gefährlich.
Die Ursache für
solche Programmabstürze ist
besonders bei größeren Softwaresystemen
und verteilten Architekturen nur sehr schwer nachzuvollziehen und
zu beheben. Selbst eine Neuinstallation von Applikation und DLL löst entweder
das Problem nicht oder schafft neue Probleme, da das Fehlerverhalten
u.a. von der Installationsreihenfolge abhängig ist.
-
Ein
weiteres typisches Szenario besteht darin, daß die DLLs einer Applikation
zwar in einem lokalen Installationsverzeichnis der Applikation liegen, diese
aber häufig
von verschieden Programmierern oder Benutzern verbessert, erweitert
oder ausgetauscht werden. Dies ist insbesondere bei solchen Applikationen
der Fall, bei denen aus marktstrategischen oder technischen Gründen häufige und schnelle
Anpassungen einzelner Funktionalitäten vorgenommen werden müssen. Im
Ergebnis führt dies
schnell zu einer unübersichtlichen
Sammlung von DLL-Versionen und Derivaten, deren Inkonsistenzen sich
erst sehr spät
bemerkbar machen, oft zu einem Zeitpunkt, zu dem die Fehlerbehebung
außerordentlich
schwierig geworden ist. Die Gefahr der Bibliotheksinkonsistenz verschärft sich
bei offenen Plattformen zusätzlich
noch dadurch, daß auch
die Benutzer selbst weitere Bibliotheken einbringen, ändern und
benutzen können.
-
Demzufolge
liegt der vorliegenden Erfindung die Aufgabe zugrunde, die Konsistenz
zwischen Applikationen und den von ihnen dynamisch eingebundenen
Bibliotheken (DLLs) in einfacher Weise überprüfen zu können und die aus Inkonsistenzen
resultierenden Sicherheitsrisiken zu minimieren.
-
Diese
Aufgabe wird erfindungsgemäß durch Verfahren
zur Versionsmarkierung und Versionsüberprüfung, sowie entsprechenden
Vorrichtungen und Softwareprogrammprodukte mit den Merkmalen der unabhängigen Ansprüche gelöst. In davon
abhängigen
Ansprüchen
sind vorteilhafte Ausgestaltungen und Weiterbildungen der Erfindung
angegeben.
-
Erfindungsgemäß wird für eine dynamisch bindbare,
binäre
Bibliothek (DLL), die als funktionsbereitstellende Binärdatei von
einer binären
Applikationsdatei eingebunden wird, um die bereitgestellten Funktionen
aufrufen zu können,
eine Versionscodierung erzeugt, aus der die Version der funktionsbereitstellenden
Binärdatei
eindeutig hervorgeht. Diese Versionscodierung wird in den Binärcode der
Bibliothek (also in das Kompilat der Bibliothek) so eingebracht,
daß die
Version einer Bibliothek anhand ihres Binärcodes überprüft werden kann, bevor eine
Funktion der Bibliothek von einer Applikation aufgerufen wird.
-
Ebenso
wie in die funktionsbereitstellende Binärdatei wird die Versionscodierung
auch in eine sie einbindende funktionsaufrufende Binärdatei eingebracht,
so daß diese „weiß", welche Version
der funktionsbereitstellenden Binärdatei sie in Zukunft benötigt. Als
funktionsaufrufende Binärdateien
werden im folgenden alle Programmdateien bezeichnet, die funktionsbereitstellende
Binärdateien
einbinden um deren Funktionen zu verwenden. Dies können sowohl
ausführbare
Binärdateien
(Applikationen) als auch funktionsbereitstellenden Binärdateien
sein, die ihrerseits andere funktionsbereitstellende Binärdateien
einbinden, um deren Funktionen zu benutzen.
-
Die
Versionscodierung bietet den Vorteil, daß die Versionskontrolle einer
funktionsbereitstellenden Binärdatei
direkt durch die sie einbindenden funktionsaufrufenden Binärdateien
erfolgen kann, bevor die aufzurufenden Funktionen der funktionsbereitstellenden
Binärdatei
ausgeführt
werden. Dies ermöglicht
bei Versionskonflikten einen kontrollierten Abbruch und eine adäquate Fehlerbehandlung.
-
Es
ist möglich,
die Erzeugung und das Einbringen der Versionscodierung in die entsprechenden
Binärdateien
getrennt durch eine Codierungseinrichtung und eine Markierungseinrichtung
vorzunehmen, oder gemeinsam durch eine entsprechend kombinierte
Einrichtung. In jedem Falle ist es vorteilhaft, zur Einbringung
eine Versionscodierung eine von den funktionsbereitstellenden Bibliotheken
und den funktionsaufrufenden Applikationen physikalisch und/oder
logisch unabhängige
Instanz vorzusehen.
-
Ebenso
ist es auch möglich,
das Einbringen der Versionscodierung in eine funktionsaufrufende Binärdateien
getrennt von der Erzeugung der Versionscodierung und ihrem Einbringen
in die entsprechende Binärdatei
durchzuführen
oder gemeinsam in einem Schritt.
-
Die
eigentliche Versionsüberprüfung einer funktionsbereitstellenden
Binärdatei
durch die sie einbindende funktionsaufrufende Binärdatei wird
zur Laufzeit der Applikation durchgeführt. Dazu wird die funktionsbereitstellende
Binärdatei
zunächst
von der funktionsaufrufende Binärdatei
geladen. Sodann wird die Versionscodierung der funktionsbereitstellenden Binärdatei anhand
der in die funktionsaufrufende Binärdatei eingebrachten Versionscodierung überprüft. Falls
sich eine Übereinstimmung
der beiden Versionscodierungen ergibt, liegt die korrekte Version
der funktionsbereitstellenden Binärdatei vor und die Applikation
kann mit der Programmausführung
fortfahren. Falls die Versionscodierungen nicht übereinstimmen, oder falls die
funktionsbereitstellende Binärdatei
keine Versionscodierung besitzt, schließt sich eine geeignete Fehlerbehandlung
an und die Applikation wir kontrolliert beendet.
-
Der
Vorteil dieses Verfahrens liegt darin, daß die Korrektheit der Version
einer Bibliothek von der Applikation selbst überprüft werden kann, es hierzu also
keiner weiteren Instanz bedarf. Falls eine falsche Version der Bibliothek
vorliegt, richtet diese keinen Schaden durch unkontrollierten Programmabsturz
und unerwünschte
Nebeneffekte an. Darüber hinaus
kann dem Pro grammierer oder Benutzer einer Applikation durch eine
entsprechende Fehlermeldung mitgeteilt werden, welche Bibliothek
für die
Inkonsistenz verantwortlich ist.
-
Es
ist vorteilhaft, die Versionscodierungen sowohl bei funktionsaufrufenden
als auch bei funktionsbereitstellenden Binärdateien immer an die gleiche
Stelle im Binärcode
in einen hierfür
reservierten Bereich einzubringen, so daß eine Applikation bei der Versionsüberprüfung nur
aus dem reservierten Bereich die Versionscodierung der geladenen
Binärbibliothek
auslesen muß.
Falls ein solcher reservierter Bereich nicht vorhanden ist, wird
die Applikation mit einer entsprechenden Fehlermeldung kontrolliert
beendet. Die eigentliche Überprüfung kann
dann durch einen einfachen bitweisen Vergleich der Versionscodierungen
durchgeführt
werden.
-
Es
ist bei der Erzeugung der Versionscodierung darüber hinaus vorteilhaft, die
individuelle Versionscodierung automatisch aus den Schnittstellendateien
der funktionsbereitstellenden Binärdatei zu ermitteln. Dies kann
besonders vorteilhaft durch ein Spezialprogramm zur Versionsmarkierung
realisiert werden, das einen speziellen Algorithmus zur Ermittlung
der Versionscodierung aus den Schnittstellendateien verwendet.
-
Als
Schnittstellendateien werden dabei alle Dateien bezeichnet, die
den Zugriff einer funktionsaufrufenden Binärdatei auf die Funktionen der
funktionsbereitstellenden Binärdatei
ermöglichen,
also alle Dateien, die zwischen beiden Binärdateien gemeinsam sind. Dies
sind insbesondere die Deklarations- bzw. H-Dateien (Header), die
die Konventionen der Funktionsaufrufe (z.B. Funktionsname, Parameter, Rückgabewerte,
Datentypen, etc.) nach außen
bereitstellen. Dadurch ändert
sich die Versionscodierung einer funktionsbereitstellenden Bibliothek
nur dann, wenn sich Ihre Schnittstellendatei än dert, nicht aber wenn sich
ausschließlich
die funktionsbereitstellende Binärdatei
selbst ändert.
-
Dies
hat den Vorteil, daß sich
bei routinemäßigen Wartungen
und Verbesserungen (z.B. zur algorithmischen Effizienzsteigerung)
der Funktionen einer Bibliothek keine Versionskonflikte mit funktionsaufrufenden
Binärdateien
ergeben, da sich bei solchen Programmierarbeiten die Schnittstellendateien in
der Regel nicht ändern
und insofern die Versionscodierung konstant bleibt. Dies ist insofern
sinnvoll, als beispielsweise eine effizientere, aber ansonsten unveränderte neue
Version einer Funktion ohne Konflikte von einer Applikation über die
ihr bekannte Schnittstelle weiterhin aufgerufen werden kann.
-
Daraus
ergibt sich, daß für eine funktionsbereitstellende
Binärdatei
eine neue Versionscodierung nur dann erzeugt werden und in die Binärdatei eingebracht
werden muß,
wenn sich die zugehörige Schnittstelle ändert. Dabei
ist es vorteilhaft, die alte Versionscodierung im reservierten Bereich
durch die neue Versionscodierung zu ersetzen. Eine Applikation,
die über
die alte Schnittstelle eine Funktion der Bibliothek aufzurufen versucht,
wird nun aufgrund der Versionsüberprüfung selbst
die Inkonsistenz feststellen und kann sich kontrolliert beenden.
Falls ein Programmierer daraufhin die Funktionsaufrufe der Applikation
an die geänderte
Schnittstelle anpaßt und
die neue Versionscodierung in den entsprechend reservierten Bereich
der Applikation eingebracht ist, tritt kein weiterer Versionskonflikt
mehr auf.
-
Es
ist vorteilhaft, die Versionscodierung einer Bibliothek so zu erzeugen,
daß sie
einzigartig ist, sie sich also von jeder anderen möglichen
Versionscodierung anderer Bibliotheken unterscheidet. Durch diese
Eigenschaft der Versionscodierung wird ausgeschlossen, daß zwei verschiedene
funktionsbereitstellende Binärdateien
die gleiche Versionscodierung führen.
-
Desweiteren
ist es vorteilhaft, die Erzeugung der Versionscodierung reproduzierbar,
d.h. jederzeit mit dem gleichen Ergebnis wiederholbar, einzurichten.
Auf diese Weise können
sowohl Bibliotheken als auch Applikationen auf anderen Rechnersystemen installiert
oder dorthin portiert werden, ohne daß die dann u.U. nötige Einbringung
von Versionscodierungen zu Versionskonflikten führt.
-
Die
beiden vorgenannten vorteilhaften Eigenschaften der Versionscodierung
werden durch viele verschiedene Algorithmen prinzipiell sichergestellt.
Besonders vorteilhaft ist es jedoch, die Versionscodierung durch
einen Hash-Algorithmus
durchzuführen,
da dieser Algorithmus eine zuverlässige und robuste Einweg-Funktion
ist, die Zeichenketten variabler Länge auf eindeutige Zeichenketten
konstanter Länge
reproduzierbar abbildet.
-
Der
besondere Vorteil der automatischen Erzeugung der Versionscodierung
z.B. durch einen Hash-Algorithmus liegt darin, daß im Gegensatz
zur manuellen Vergabe von Versionsnummern durch einen Programmierer,
eindeutige Versionscodierungen verwendet werden und diese auch automatisch überprüfbar sind.
Die Gefahr der Versionskonflikte wird dadurch minimiert.
-
Zur
reproduzierbaren Erzeugung einer eindeutigen Versionscodierung aus
einer Schnittstellendatei der funktionsbereitstellenden Binärdatei werden
diejenigen Bestandteile der Datei, die nicht zum Programmcode gehören, zunächst entfernt.
Dabei handelt es sich beispielsweise um Leerzeichen oder Steuersequenzen
wie „Wagenrücklauf (CR)", „Tabulator
(tab)" oder „Dateiende
(EOF)" sowie automatisch
oder manuell eingebrachte Kommentare. Dadurch kann gewährleistet
werden, daß wirklich
nur die semantisch relevanten Bestandteile (also die, die von der
Syntaxanalyse eines Compiliers/Parsers als solche erkannt werden)
in die Versionscodierung eingehen. Aus der so bereinigten, temporären Schnittstellendatei
wird dann mit Hilfe eines geeigneten Algorithmus, z.B. mit dem Hash-Algorithmus,
die eindeutige Versionscodierung erzeugt.
-
Häufig binden
Applikationen mehrere Bibliotheken zur Benutzung ihrer Funktionen
ein. In die funktionsaufrufenden Binärdateien wird dann für jede eingebundene,
funktionsbereitstellende Binärdatei eine
eigene Versionscodierung eingebracht. In diesem Fall ist es vorteilhaft
aus diesen mehreren Versionscodierungen eine einzige Meta-Versionscodierung
für diese
spezielle Kombination der funktionsaufrufenden Binärdateien
zu erzeugen, die alle einzelnen Versionscodierungen integriert.
-
Bei
der Versionsüberprüfung einer
funktionsbereitstellenden Binärdatei
durch eine funktionsaufrufende Binärdatei ist zu unterscheiden
zwischen Bibliotheken, die statisch geladen werden und solchen, die
dynamisch geladen werden. Beim statischen Laden wird die Bibliothek
geladen, wenn auch die Applikation geladen wird und die Funktionsreferenzen werden
bereits zur Bindezeit aufgelöst – es erfolgt eine „frühe Bindung". Die Versionsüberprüfung wird dann
in der Instanziierungsroutine der Applikation durchgeführt.
-
Beim
dynamischen Laden werden die Bibliotheken erst bei Bedarf geladen
und können
wieder freigegeben werden, wenn sie nicht mehr benötigt werden.
Die Versionsüberprüfung wird
hierbei zur der Laufzeit der Applikation, unmittelbar nach dem Laden der
Bibliothek durchgeführt – es erfolgt
eine „späte Bindung"..
-
Weitere
Merkmale und Vorteile der Erfindung ergeben sich aus der folgenden
Beschreibung verschiedener erfindungsgemäßer Ausführungsbeispiele und Ausführungsalternativen
im Zusammenhang mit den begleitenden Figuren. Darin zeigen:
-
1 ein
Schema eines Computers mit einem Programm zur Versionsmarkierung
und versionsmarkierten funktionsaufrufenden und funktionsbereitstellenden
Binärdateien;
-
2 ein
Flußdiagram
der Versionsmarkierung einer funktionsbereitstellenden Binärdatei;
-
3 ein
Flußdiagram
der Versionsmarkierung einer funktionsaufrufenden Binärdatei;
-
4 ein Flußdiagram der Versionsüberprüfung;
-
5 ein
Schema der Versionsüberprüfung von
funktionsbereitstellenden Binärdateien;
und
-
6 ein
Schema der Versionsüberprüfung von
sich gegenseitig einbindenden, funktionsbereitstellenden Binärdateien.
-
Eine
bevorzugte Ausführungsform
der vorliegenden Erfindung besteht in dem in 1 schematisch
dargestellten Computersystem C. Im Hauptspeicher MEM des Computers
C befinden sich mehrere Programme: Eine Applikation EXE, zwei von
der Applikation zur Laufzeit dynamisch einzubindende Bibliotheken
DLL1 und DLL2 sowie ein spezialisiertes Programm VAC zur Generierung
von Versionscodierungen VC1, VC2 und zur Einbringung der Versionscodierungen
VC1, VC2 in die Binärdateien
EXE, DLL1, DLL2.
-
Alle
Programme VAC, EXE, DLL1, DLL2 liegen im Speicher MEM im Binärformat
vor und sind prinzipiell geeignet, von dem Prozessor CPU des Rechners
C ausgeführt
zu werden. Desweiteren umfaßt
der Rechner C ein Betriebssystem OS, das u.a. die Ausführung von
Programmen und die Vergabe von Prozessor- und Speicherressourcen überwacht und
steuert. Das Betriebssystem OS residiert, wie im Schema angedeutet,
in einem eigenen Permanentspeicher oder mit den anderen Programmen
in einem gemeinsamen Speicher. Zur Laufzeit befinden sich die einzelnen
Betriebssystemprozesse jedoch im Hauptspeicher MEM des Rechners
C.
-
Zwischen
Prozessor CPU, Speicher MEM und dem Permanentspeicher des Betriebsystems
OS existiert ein Bussystem BUS zum Datentransfer zwischen den Rechnerkomponenten.
Die Auswahl der dargestellten Komponenten und Ihre schematische Anordnung
stellt keine Einschränkung
der Erfindung dar, vielmehr sind viele verschiedene Varianten von Rechnerarchitekturen,
weitere Komponenten und Peripherie geeignet, die Erfindung ebenso
zu realisieren.
-
Im
Sinne der Erfindung ist die Applikation EXE eine funktionsaufrufende
Binärdatei,
da sie bei Ihrer Ausführung
auf Funktionen zugreift, die in den funktionsbereitstellenden Binärdateien
DLL1, DLL2 definiert sind. Zum Zugriff auf solche Funktionen verwendet
die Applikation EXE die entsprechenden, in der jeweiligen Schnittstellendatei
H1, H2 der Bibliothek DLL1, DLL2 abgelegten Zugriffsvorschriften. Diese
Deklarationen bzw. Prototypen legen beispielsweise Funktionsnamen,
Anzahl, Reihenfolge und Datentyp der Eingabeparameter sowie die
Datentypen der Rückgabewerte
fest. Ebenso kann die Aufrufkonvention in Form von abstrakten Klassen oder
Zeigerfeldern (Pointer Arrays) in den Schnittstellendateien H1,
H2 vereinbart werden.
-
Abhängig vom
verwendeten Betriebssystem OS und der Programmiersprache, können unterschiedliche
Binärformate
für funktionsaufrufende
Binärdateien
(Applikationen EXE oder Bibliotheken DLL1, DLL2) und funktionsbereitstellende
Binärdateien
(nur Bibliotheken DLL1, DLL2) existieren. Bei Verwendung eines Windows-Betriebssystems
sind funktionsbereitstellende Binärdateien meist vom Typ DLL („Dynamic
Linked Libray")
oder OCX („OLE
Control Extension"),
während
unter Linux/UNIX sogenannte SO-Dateien („Shared Objects") bzw. ELF-Dateien („Extended
Linking Format")
als Bibliotheksformat verwendet werden. Die funktionsaufrufenden
Binärdateien
sind in der Regel vom jeweiligen Betriebssystem direkt ausführbare Applikationen
(„Executables", EXE). Natürlich können auch
Bibliotheken ihrerseits andere Bibliotheken einbinden, weshalb funktionsbereitstellende
Binärdateien
auch gleichzeitig funktionsaufrufende Binärdateien sein können.
-
Für einen
erfolgreichen Zugriff einer Applikation EXE auf Funktionen von dynamisch
gebundenen Bibliotheken DLL1, DLL2 muß gewährleistet sein, daß die Bibliotheken
DLL1, DLL2 in der richtigen Version vorliegen. Andernfalls kann
der Zugriff einen Programmfehler bzw. „Absturz" verursachen, da sich aufgrund von Änderungen
oder Weiterentwicklungen einer Bibliothek DLL1, DLL2 möglicherweise
der Funktionsaufruf der Applikation EXE nicht mehr mit der in zugehörigen der
Schnittstellendatei H1, H2 definierten Aufrufkonvention deckt. Aus
derartigen Versionskonflikten resultierende Fehler können bei
realistisch dimensionierten Rechnersystemen u.U. sehr schwer erkennbar
und behebbar sein, da Versionskonflikte nicht ohne weiteres nachvollziehbar
und auch durch Neuinstallation oft nicht behebbar sind.
-
Dieses
Szenario wird von der in 1 illustrierten Ausführungsform
der Erfindung durch individuelle Versionsmarkierung und -überprüfung von funktionsbereitstellenden
wie funktionsaufrufenden Binärdateien
verhindert.
-
Dabei
wird die Versionsmarkierung der Bibliotheken DLL1, DLL2 und der
Applikationen EXE von einem eigenen Programm VAC durchgeführt, das
ein Modul einer Software-Entwicklungsumgebung oder auch des Betriebssystems
OS sein kann, während die
Versionsüberprüfung von
der jeweiligen Applikation EXE selbst bzw. von einer Routine VER
der Applikation EXE durchgeführt
wird.
-
Im
Kontext einer Software-Entwicklungsumgebung auf einem Computer C
kann das Programm VAC, das Versionscodierungen VC1, VC2 automatisch
erzeugt und diese in die entsprechenden Binärdateien DLL1, DLL2, EXE einbringt,
ein weiteres Entwicklungswerkzeug neben den üblichen Werkzeugen Compiler,
Debugger, Klassen-Browser, Editor etc. sein.
-
Das
ausführbare
Programm VAC zur Versionsmarkierung von Binärdateien soll im folgenden kurz „Impfprogramm" genannt werden,
da es kompilierten, fertigen Binärprogrammen
nachträglich
und separat eine Markierung „injiziert", um Inkonsistenzen
vorzubeugen. Ein erfindungsgemäßes Impfprogramm
VAC stellt im wesentlichen zwei Funktionalitäten bereit, die Erzeugung einer
individuellen Versionscodierung VC1, VC2, durchgeführt durch
das Erzeugungsmodul GEN, und das Einbringen der Versionscodierung
VC1, VC2 in die entsprechenden Binärdateien durch das Impfmodul
INC.
-
Während die
Aufrufkonventionen der Schnittstellendateien H1, H2 die in Bezug
auf Versionskonflikte kritische und unveränderliche Information darstellen,
können
die eigentlichen Funktionen der Bibliotheken DLL1, DLL2 in gewissen
Grenzen durchaus geändert
werden, ohne einen Versionskonflikt zu verursachen. So ist eine
reine Geschwindigkeits- oder Genauigkeitsoptimierung des Programmcodes
in der Regel unkritisch, da das Ein-/Ausgabe verhalten der Funktionen
davon meist nicht betroffen ist. Jedoch können erfindungsgemäße, individuelle Versionscodierungen
prinzipiell auch völlig
unabhängig
vom Programmcode generiert werden.
-
Erfindungsgemäß wird deshalb
zur Erzeugung einer individuellen Versionsmarkierung einer Bibliothek
DLL1, DLL2 durch das Erzeugungsmodul GEN des Impfprogramms VAC nur
die jeweilige Schnittstellendatei H1, H2 herangezogen. Dabei wird für jede Bibliothek
DLL1, DLL2 eine zugehörige
Versionscodierung VC1, VC2 erzeugt und durch das Impfmodul INC in
reservierte Bereiche R1 der Bibliotheken DLL1, DLL2 eingebracht
bzw. „eingeimpft". Dieser Prozeß wird später in Bezug
auf 2 genauer beschrieben.
-
Nach
der Impfung der Bibliotheken DLL1, DLL2 wird auch die Applikation
EXE geimpft. Dabei werden die Versionscodierungen VC1, VC2 derjenigen
Bibliotheken DLL1, DLL2, auf die die Applikation EXE zugreift, in
einen reservierten Bereich R2 der Applikation EXE eingebracht. In
der Applikation EXE werden also alle Versionscodierungen VC1, VC2
gesammelt. Dieser Prozeß kann
prinzipiell auch unabhängig
von dem zuerst stattfindenden Prozeß der Erzeugung und Einbringung
einer Versionscodierung VC1, VC2 in die entsprechende Bibliothek
DLL1, DLL2 stattfinden und durch eine separate Einrichtung zum Impfen
von Applikationen EXE realisiert sein. Die Applikation EXE nimmt
dann später
die Zuweisung der Versionscodierungen VC1, VC2 beim Laden der Bibliotheken
DLL1, DLL2 vor. Dieser Vorgang wird später in Bezug auf 3 im
Detail erläutert.
-
Beim
Zugriff der Applikation EXE auf die Funktionen der Bibliotheken
DLL1, DLL2 wird die Kompatibilität
der Funktionsaufrufe mit den Aufrufkonventionen der Bibliotheken
DLL1, DLL2 von der Applikation EXE bzw. von einem Überprüfungsmodul VER
der Applikation EXE selbst überprüft. Das Überprüfungsmodul
VER kann dabei direkt als Teil der Applikation EXE realisiert sein
oder, zweckmäßiger und effizienter,
in einer statischen Bibliothek abgelegt sein, von wo es von der
Applikation EXE bei Bedarf aufgerufen werden kann.
-
Für jede einzubindende
Bibliothek DLL1, DLL2 überprüft das Überprüfungsmodul
VER, ob sich die entsprechende Versionscodierung VC1, VC2 in dem
reservierten Bereich R2 der Applikation EXE befindet. Nur falls
dies für
alle einzubindenden Bibliotheken der Fall ist, kann die Applikation
EXE weiter ausgeführt
werden. Andernfalls liegt ein Versionskonflikt vor und die Applikation
EXE wird kontrolliert und ohne schädigende Nebeneffekte beendet.
Hierbei wird dem Benutzer der Applikation EXE eine ausführliche
Fehlermeldung ausgegeben, um den Versionskonflikt auflösen zu können.
-
2 illustriert
den Prozeß des
Erzeugens einer individuellen Versionscodierung VC einer Bibliothek
DLL und des Impfens der Bibliothek DLL mit dieser Versionscodierung
VC durch das Impfprogramm VAC. Die erste Aufgabe wird von dem Erzeugungsmodul
GEN durchgeführt,
die zweite von dem Impfmodul INC.
-
Falls
das Impfprogramm VAC mit einer zu markierenden Bibliothek DLL aufgerufen
wird, wird diese Bibliothek DLL zunächst in den entsprechenden
Verzeichnissen des Systems lokalisiert (Schritt S1). Anschließend wird
die Schnittstellendatei H (Header-Datei) der gefundenen Bibliothek
DLL im System lokalisiert (Schritt S2) und gelesen (Schritt S3).
Um eine möglichst
nur vom funktional relevanten Programmcode der Header-Datei abhängige Versionscodierung
VC zu erhalten, werden im einem Bereinigungs- oder Komprimierschritt
(Schritt S4) sämtliche
Zeichen und Symbole aus der Header-Datei H, die keine semantische Information
darstellen – z.B. Kommentare (Versionsverwaltungen
des Quellcodes , Erklärungen
etc.), Steuerzeichen (z.B. „newline", „carriage
return", „tab") oder Leerzeichen
-, vorzugsweise so vollständig
entfernt, daß nach
der Bereinigung/Kompression ein weiteres Entfernen eines einzigen
Symbols beim Binden der Bibliothek zu einem Fehler führen würde.
-
Im
Bereinigungsschritt S4 wird also eine Syntax-Analyse der Header-Datei
H (Parsing) durchgeführt,
um die semantisch irrelevanten Symbole zu finden und diese unter
Erzeugung eines temporären Datenobjekts
aus der Header-Datei
H herauszufiltern. Dies ermöglicht
die Erzeugung einer eindeutigen Versionscodierung VC aus dem verbleibenden semantisch
relevanten Inhalt des bereinigten temporären Datenobjekts, obwohl Header-Dateien
z.B. selbst mehrfach in verschiedenen Versionen oder in unterschiedlichen
Quellcode-Verwaltungen
vorliegen können.
-
Da
Schnittstellendateien in vielen Programmiersprachen nur Funktions-Deklarationen bzw.
Prototypen enthalten, kann zusätzlich
durch eine geeignete Vorsortieren der Deklarationsblöcke der
Einfluß der
Reihenfolge der Deklarationen auf die Versionscodierung ausgeschlossen
werden.
-
Aus
der Zeichenfolge der bereinigten Header-Datei H wird dann in Schritt
S5 die Versionscodierung VC durch einen geeigneten Algorithmus erzeugt.
Prinzipiell sind unterschiedlichste Algorithmen, z.B. auch Zufallsgeneratoren,
geeignet, sichere und hinreichend individuelle Versionscodierungen
zu erzeugen. Es bietet sich jedoch insbesondere der Hash-Algorithmus
an, da er reproduzierbare und mit einer hinreichenden Wahrscheinlichkeit
einzigartige Hash-Werte als Versionscodierungen erzeugt.
-
Neben
dem konkreten Beispiel der Header-Dateien H existieren in anderen
Programmiersprachen auch andere Schnittstellen zwischen den funktionsbereitstellenden
Bibliotheken DLL und funktionsaufrufenden Applikationen EXE. Deshalb
werden bei der vorliegenden Erfindung mit dem Begriff der Schnittstellendatei
prinzipiell alle Dateien bezeichnet, die notwendig sind, damit eine
Applikation EXE die Schnittstelle einer Bibliothek DLL korrekt ansprechen
kann, also alle Dateien, die zwischen diesen funktionsaufrufenden
und funktionsbereitstellenden Binärdateien gemeinsam sind.
-
Dabei
ist es selbstverständlich
auch möglich, daß die Verbindung
einer Bibliothek DLL mit einer Applikation EXE über mehrere Schnittstellendateien charakterisiert
ist. In die Versionscodierung VC gehen dann entweder alle oder nur
ausgewählte Schnittstellendateien
H ein. Ebenso ist es denkbar, daß eine Bibliothek DLL, die
mehrere Schnittstellendateien H besitzt, für jede Schnittstellendatei
eine eigene Versionscodierung VC besitzt, so daß eine funktionsaufrufende
Applikation EXE genau mit derjenigen Versionscodierung geimpft wird,
die die Aufrufkonvention der aufzurufenden Funktion beinhaltet.
-
Nachdem
mit Schritt S5 die Erzeugung eines Hash-Wertes der Versionscodierung
abgeschlossen ist, wird die Bibliothek DLL mit der Versionscodierung VC
durch das Impfmodul INC geimpft. Dazu wird zunächst ein vorgegebener und dafür reservierter
Bereich R1 der Bibliothek DLL aufgesucht (Schritt S6) und die Versionscodierung
VC dort eingeschrieben (Schritt S7).
-
Die
Funktion „search
R1 in DLL" (Schritte
S6, S11, S16) kann dabei – ebenso
wie auch die Funktion „search
R2 in EXE" (Schritt
S18) – beispielsweise eine
exportierte C- Funktion der Bibliothek DLL sein, deren Existenz
in C z.B. mittels der „GetProcAddress"- Methode abgefragt
werden kann. Dabei wird eine Funktion der Bibliothek DLL gesucht,
die die betreffende Versionscodierung VC zurückgibt. Falls in der Bibliothek
DLL keine entsprechende Funktion existiert, ist der Rückgabewert
der „GetProcAddress"-Funktion NULL. Die
Gültigkeit
der Bibliothek DLL kann also nicht überprüft werden. Falls jedoch eine
solche „GetVersionCode"-Funktion in der Bibliothek
DLL existiert, liefert „GetProcAddress" einen Zeiger auf
diese Funktion, der dann direkt zum Auslesen der Versionscodierung
VC verwendet werden kann. Die Funktion „GetVersionCode" liegt also in der
Bibliothek DLL vor und wird von der funktionsaufrufende Binärdatei EXE über den
oben beschriebenen Mechanismus aufgerufen.
-
Zusätzlich zur
eigentlichen Versionscodierung VC kann zum Zwecke der Benutzerinformation noch
eine Versionsnummer in Klartext, beispielsweise als String, in die
Bibliothek DLL eingebracht werden. Im Falle eines Versionskonfliktes
beim Laden der Bibliothek DLL, kann dem Benutzer die Versionsnummer
der fehlerhaften Bibliothek DLL über
eine entsprechende Ausgabe mitgeteilt werden.
-
Neben
der in 2 dargestellten Impfung einer Bibliothek DLL ist
das Impfmodul INC des Impfprogramms VAC auch vorgesehen, um die
Applikationen EXE zu impfen, die auf dynamisch bindbare Bibliotheken
DLL zugreifen. Diesen Prozeß illustriert 3.
Beide Verfahren, die Impfung von Bibliotheken DLL in 2 und
die Impfung einer Applikationen EXE in 3 können wahlweise
gemeinsam in einem Programm oder in zwei separaten Programmen realisiert
werden. Jedoch muß die
Erzeugung der Versionscodierung VC immer Teil des Programms zur
Impfung der Bibliotheken DLL sein.
-
Im
initialen Schritt S8 wird zunächst
die zu impfende Applikation EXE im System lokalisiert. Danach wird
die Applikatione in Schritt S9 analysiert, um alle Bibliotheken
DLL, die die Applikation EXE einbindet und mit deren Versionscodierungen
sie geimpft werden soll, zu identifizieren. Für jede dieser Bibliotheken
DLL wird die folgende Schleife von Schritt S10 bis Schritt S13 durchlaufen.
Falls die Abfrage Q1 nach weiteren einzubindenden Bibliotheken DLL
verneint wird, wird der Prozeß beendet
und die Applikation EXE gilt als „geimpft".
-
Eine
einzubindende Bibliothek DLL wird im System lokalisiert (Schritt
S10) und ihr für
die Versionscodierung VC reservierter Bereich R1 gesucht (Schritt
S11). Falls die Bibliothek DLL keinen Bereich R1 besitzt, wird die
Abfrage Q2 negativ beantwortet und der Impfprozeß abgebrochen. Andernfalls
wird die Versionscodierung VC in Schritt S12 aus dem Bereich R1
ausgelesen, in den Bereich R2 der Applikation EXE hineingeschrieben
(Schritte S12, S13) und zur Abfrage Q1 weiterverzweigt.
-
Bei
der Impfung einer Applikation EXE mit den Versionscodierungen VC
mehrerer Bibliotheken DLL1, DLL2 gibt es dann prinzipiell zwei Möglichkeiten.
Die Versionscodierungen können
dann einzeln in einer Liste oder einem Feld (Array) der Applikation hinterlegt
werden, oder sie werden zu einer Versionscodierung zusammengefaßt, die
alle einzelnen Versionscodierungen verlustfrei repräsentiert.
So kann beispielsweise ein Hash-Wert über die Summe aller Hash-Werte
gebildet und abgespeichert werden. In diesem Falle wird in 3 zwischen
den Schritten S12 und S13 ein Aktualisierungsschritt eingefügt, der die
im Bereich R2 der Applikation EXE abgespeicherte Versionscodierung
ausliest und mit der Versionscodierung VC der aktuellen Bibliothek
DLL aktualisiert.
-
4 zeigt schließlich den Prozeß des Überprüfens der
Versionscodierung VC einer einzubindenden Bibliothek DLL durch das Überprüfungsmodul VER
der Applikation EXE anhand eines Flußdiagrams. Dazu wird die Applikation
EXE zunächst
gestartet (Schritt S14) und die Abfrage Q3 nach der Existenz einer
zu bindenden Bibliothek DLL ausgeführt. Falls die Applikation
EXE Bibliotheken DLL dynamisch einbindet, wird anschließend die
folgende Schleife von Schritt S15 bis Abfrage Q5 für jede zu bindende
Bibliothek DLL durchlaufen.
-
In
Schritt S15 wird die einzubindende Bibliothek DLL von der Applikation
EXE dynamisch oder statisch geladen. Beim dynamischen Laden wird
eine Bibliothek DLL bei Bedarf durch die Applikation EXE vor den
Aufruf einer Bibliotheksfunktion geladen. Die Versionsüberprüfung der
Bibliothek DLL schließt
sich dann unmittelbar an den Ladevorgang an und wird somit zur Laufzeit
der Applikation EXE durchgeführt.
-
Beim
statischen Laden wird eine Bibliothek DLL direkt nach dem Start
der Applikation EXE und vor dem Aufrufen des Konstruktors der Applikation EXE
geladen. Die anschließende Überprüfung der Versionscodierung
VC der Bibliothek DLL findet dann in der Instanziierungsroutine
der Applikation EXE statt. Diese kann dann entweder im Konstruktor
der Applikation EXE oder in der später auszuführenden InitInstance-Routine
der Windows-Laufzeitumgebung
durchgeführt
werden. Im Gegensatz zum dynamischen Laden können statisch geladene Bibliotheken
DLL während
der Laufzeit der Applikation EXE nicht mehr gewechselt werden.
-
Innerhalb
des Binärcodes
der Bibliothek DLL wird dann der ausgezeichnete Bereich R1 gesucht,
in dem die Versionscodierung VC der Bibliothek zu finden ist (Schritt
S16). Falls dieser Bereich R1 in der funktionsbereitstellenden Binärdatei DLL
nicht existiert, z.B. weil die Bibliothek DLL gar nicht geimpft wurde,
wird sie bei der Abfrage Q4 sofort zurückgewiesen. Diese Zurückwei sung
erfolgt vorteilhaft während
des Ladevorgangs der Bibliothek DLL. Der Benutzer kann also sofort
erkennen, ob die vorhandenen Bibliotheken DLL in den richtigen Versionen
vorliegen. Im negativen Fall wird die Applikation EXE ohne schädigende
Nebeneffekte zu verursachen und mit einer instruktiven Fehlermeldung
kontrolliert beendet.
-
Falls
der Bereich R1 gefunden wurde, wird in Schritt S17 die Versionscodierung
VC ausgelesen und in Schritt S18 der ausgezeichnete Bereich R2 der
Applikation lokalisiert, der die Versionscodierungen VC aller von
der Applikation eingebundenen Bibliotheken DLL vorhält. In Schritt 19 wird
die Versionscodierung VC der Bibliothek DLL überprüft indem sie mit allen im Bereich
R2 der Applikation EXE befindlichen Versionscodierungen verglichen
wird. Falls der Vergleich eine Übereinstimmung
ergibt, liegt die Bibliothek in der passenden Version vor und es
wird über
die Abfrage Q5 wieder zurück
zur Abfrage Q3 und gegebenenfalls zur Überprüfung der nächsten Bibliothek verzweigt.
Andernfalls wird die Überprüfung kontrolliert
beendet.
-
Falls
im Bereich R2 nicht jede Versionscodierung der verschiedenen Bibliotheken
einzeln vorliegt, sondern, wie im Zusammenhang mit 3 beschrieben,
eine integrierte Versionscodierung verwendet wird, werden die einzelnen
Versionscodierungen vor dem Vergleichsschritt S19 zunächst wieder
aus der Gesamt-Versionscodierung extrahiert.
-
Bei
Zurückweisung
auch nur einer Bibliothek DLL, wird die Applikation EXE sofort kontrolliert
beendet. In diesem Falle wird dem Benutzer die inkompatible Bibliothek
DLL mitgeteilt, so daß einerseits
die Systemintegrität
gewahrt bleibt und sich anderseits eine sinnvolle Fehlerbeseitigung
anschließen
kann. Dieses Verfahren schließt
also die mit einem Versionskonflikt verbundenen unerwünschten
Fehlereffekte vollständig
aus.
-
Die 5 und 6 zeigen
zwei Szenarien der Versionsüberprüfung von
Bibliotheken DLL1, DLL2, DLL3 mit im jeweiligen Bereich R1 befindlichen
Versionscodierungen VC1, VC2, VC3 durch die einbindende Applikation
EXE.
-
In 5 bindet
die funktionsaufrufende Binärdatei
EXE drei rein funktionsbereitstellende Binärdateien DLL1, DLL2, DLL3 ein.
Es handelt sich hierbei also um eine 1-zu-N Relation, da jede Bibliothek DLL1,
DLL2, DLL3 nur mit der Applikation EXE in Verbindung steht. Wie
zuvor beschrieben, besitzt eine derartige Applikation EXE nach dem
erfolgreichen Impfen in ihrem Bereich R2 die Versionscodierungen
VC1, VC2, VC3 aller drei einzubindenden Bibliotheken DLL1, DLL2,
DLL3. Bei der Ausführung der
Applikation EXE überprüft das Überprüfungsmodul
VER in der Reihenfolge des Aufrufs der drei Bibliotheken DLL1, DLL2,
DLL3 die jeweilige Versionscodierungen VC1, VC2, VC3 und stellt
eine vollständige Kompatibilität fest.
-
6 zeigt
sehr realistischen Fall, daß die von
der Applikation EXE eingebundenen Bibliotheken DLL1, DLL2, DLL3
ihrerseits andere Bibliotheken einbinden, um auf deren Funktionen
zuzugreifen. Auf diese Weise können
umfangreiche Kaskaden von Bindeverhältnissen entstehen. So bindet
in 6 beispielsweise die Applikation EXE die Bibliotheken DLL1
und DLL2 ein, während
diese sich gegenseitig einbinden und die Bibliothek DLL1 zusätzlich die
Bibliothek DLL3 einbindet. Hier liegt also keine 1-zu-N Relation
wie in 5 vor, sondern eine M-zu-N Relation, weil sich
einige Bibliotheken gegenseitig einbinden. Eine N-zu-N läge demnach
vor, wenn sich alle für
die Ausführung
der Applikation EXE benötigten Bibliotheken
DLL1, DLL2, DLL3 gegenseitig einbinden.
-
Während in 6 die
Applikation EXE also eine rein funktionsaufrufende Binärdatei und
die Bibliothek DLL3 eine rein funktionsbereitstellende Binärdatei darstellt,
sind die Binärdateien
DLL2 und DLL3 sowohl funktionsaufrufend als auch funktionsbereitstellend.
Deshalb benötigen
die zusätzlich funktionsaufrufenden
Bibliotheken DLL1 und DLL2 ebenfalls einen Mechanismus zur Versionskontrolle derjenigen
Bibliotheken, die sie ihrerseits einbinden. Zu diesem Zweck haben
zumindest die Bibliotheken DLL1 und DLL2 zur Überprüfung der Versionen der einzubindenden
Bibliotheken selbst auch Zugriff auf das entsprechende Überprüfungsmodul
VER.
-
Neben
dem Ansatz, die Überprüfung durch die
funktionsaufrufende Binärdatei
selbst durchführen
zu lassen, ist es im Rahmen dieser Erfindung analog zum separaten
Impfprogramm VAC natürlich auch
möglich,
ein separates Verifikationsprogramm bereitzustellen, das eine initiale Überprüfung einer Applikation
und der davon abhängigen
Bibliothekskaskade durchführt.
-
Im
Falle einer M-zu-N Relation ist der Impfprozeß nicht mehr so strikt zu trennen
in je einen separaten Anwendungsfall für funktionsaufrufende Applikationen
und funktionsbereitstellende Bibliotheken. Vielmehr muß bei der
Impfung beispielsweise der Bibliothek DLL1 zunächst eine „funktionsbereitstellende
Impfung' mit der
in den Bereich R1 einzubringenden Versionscodierung VC1 und anschließend eine „funktionsaufrufende
Impfung' mit den
in den Bereich R2 einzubringenden Versionscodierungen VC2 und VC3
der Bibliotheken DLL2 und DLL3 durchgeführt werden. Daraus ergeben
sich bei der Impfung einer ganzen Kaskade von Applikationen und
Bibliotheken bestimmte zeitliche Abhängigkeiten, die beim Impfprozeß zu berücksichtigen
sind.