Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ elf_begin(3E) — Reliant UNIX 5.44c4

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

creat(2)

lseek(2)

mmap(2)

open(2)

truncate(3C)

elf(3E)

ar(4)

elf_begin(3E)                                                 elf_begin(3E)

NAME
     elfbegin - Dateideskriptor erzeugen

SYNTAX
     cc [option ...] datei ... -lelf [bibliothek ...]

     #include <libelf.h>

     Elf *elfbegin(int fildes, ElfCmd cmd, Elf *ref);

BESCHREIBUNG
     elfbegin(), elfnext(), elfrand() und elfend() arbeiten zusammen.
     Sie bearbeiten ELF-Objektdateien entweder einzeln oder als Archivkom-
     ponenten. Nachdem ein ELF-Deskriptor von elfbegin() erzeugt wurde,
     kann das Programm eine existierende Datei lesen, aktualisieren oder
     eine neue Datei erzeugen. fildes ist ein geöffneter Dateideskriptor,
     den elfbegin() zum Lesen oder Schreiben benutzt. Der anfängliche
     Datei-Offset [siehe lseek(2)] spielt keine Rolle, und der resultie-
     rende Datei-Offset ist undefiniert.

     Für cmd sind die folgenden Werte möglich:

     ELFCNULL
          elfbegin() liefert einen Nullzeiger, ohne daß ein neuer Deskrip-
          tor angelegt wird. ref wird bei diesem Kommando ignoriert. Siehe
          elfnext(3E) und die dazugehörigen Beispiele für weitere Informa-
          tionen.

     ELFCREAD
          Wenn ein Programm den Inhalt einer existierenden Datei prüfen
          will, sollte es cmd auf diesen Wert setzen. Abhängig vom ref-Wert
          prüft dieses Kommando Archivkomponenten oder ganze Dateien. Dabei
          können folgende drei Fälle auftreten:

          -  Wenn ref ein Nullzeiger ist, belegt elfbegin() einen neuen
             ELF-Deskriptor und bereitet die Bearbeitung der ganzen Datei
             vor. Wenn die zu lesende Datei ein Archiv ist, bereitet
             elfbegin() den resultierenden Deskriptor darauf vor, beim
             nächsten Aufruf von elfbegin() auf die erste Archivkomponente
             der kompletten Datei zuzugreifen, als ob das Programm
             elfnext() oder elfrand() zur Positionierung auf die erste
             Komponente verwenden würde.

          -  Wenn ref ein mit einer Archivdatei verknüpfter Deskriptor
             ungleich null ist, erlaubt elfbegin() einem Programm das
             Anlegen eines separaten ELF-Deskriptors, der mit einer eigenen
             Komponente verknüpft ist. Das Programm sollte elfnext() oder
             elfrand() verwenden, um ref entsprechend zu positionieren
             (außer für die erste Komponente, welche elfbegin() automa-
             tisch einstellt; siehe folgendes Beispiel). In diesem Fall
             sollte fildes derselbe Dateideskriptor sein, der auch für das
             Vaterarchiv verwendet wird.



Seite 1                      Reliant UNIX 5.44               Gedruckt 11/98

elf_begin(3E)                                                 elf_begin(3E)

          -  Wenn ref schließlich ein Deskriptor ungleich null ist und kein
             Archiv darstellt, so erhöht elfbegin() die Anzahl der Akti-
             vierungen für den Deskriptor und liefert ref zurück, ohne daß
             ein neuer Deskriptor angelegt wird und ohne daß die Lese- und
             Schreibrechte des Deskriptors verändert werden. Um den
             Deskriptor für ref freizugeben, muß das Programm für jede der
             Aktivierungen elfend() einmal aufrufen. Siehe elfnext(3E)
             und die Beispiele für weitere Informationen.

     ELFCRDWR
          Dieses Kommando führt zu denselben Aktionen wie ELFCREAD,
          erlaubt jedoch dem Programm außerdem das Aktualisieren der Datei-
          inhalte [siehe elfupdate(3E)]. Dies bedeutet, daß ELFCREAD nur
          das Lesen der Datei ermöglicht, während ELFCRDWR dem Programm
          das Lesen und Schreiben der Datei erlaubt. ELFCRDWR ist für
          Archivkomponenten nicht zulässig. Wenn ref ungleich null ist, so
          muß die Datei zuvor mit dem Kommando ELFCRDWR erzeugt worden
          sein.

     ELFCWRITE
          Wenn das Programm einen bereits vorhandenen Dateiinhalt ignorie-
          ren möchte, um eine neue Datei zu erzeugen, sollte cmd auf diesen
          Wert gesetzt werden. ref wird für dieses Kommando ignoriert.

     elfbegin() "arbeitet" mit allen Dateien (einschließlich Dateien mit
     Null-Bytes), vorausgesetzt, es kann genügend Speicher für interne
     Strukturen belegt werden, und die notwendigen Dateiinformationen kön-
     nen gelesen werden. Programme, die Objektdateien auslesen, können
     daher elfkind() oder elfgetehdr() aufrufen, um den Dateityp festzu-
     stellen (nur Objektdateien haben einen ELF-Kopf). Wenn die Datei ein
     Archiv ist, welches keine weiteren Komponenten zum Bearbeiten enthält,
     oder wenn ein Fehler auftritt, so liefert elfbegin() einen Nullzeiger
     zurück. Ansonsten wird ein ELF-Deskriptor ungleich null zurückgegeben.

     Vor dem ersten Aufruf von elfbegin() muß das Programm zur Koordinie-
     rung der Versionen elfversion() aufrufen.

   Systemdienste

     Bei der Bearbeitung einer Datei entscheidet die Bibliothek in Abhän-
     gigkeit von den Programmanforderungen, wann die Datei gelesen oder
     geschrieben wird. Normalerweise geht die Bibliothek davon aus, daß der
     Dateideskriptor bei Verfügbarkeit des ELF-Deskriptors ebenfalls ver-
     fügbar ist. Muß ein Programm viele Dateien gleichzeitig bearbeiten und
     beschränkt das zugrundeliegende Betriebssystem die Anzahl der geöffne-
     ten Dateien, so kann das Programm elfcntl() verwenden, um die Datei-
     deskriptoren wiederzuverwenden. Nachdem elfcntl() mit entsprechenden
     Argumenten aufgerufen wurde, kann das Programm den Dateideskriptor
     schließen, ohne mit der Bibliothek in Konflikt zu kommen.

     Alle Daten, die mit einem ELF-Deskriptor verknüpft sind, bleiben allo-
     kiert, bis elfend() die letzte Aktivierung des Deskriptors beendet


Seite 2                      Reliant UNIX 5.44               Gedruckt 11/98

elf_begin(3E)                                                 elf_begin(3E)

     hat. Nach Freigabe der Deskriptoren wird auch der Speicher freigege-
     ben; der Versuch, auf freigegebene Daten zuzugreifen, führt zu einem
     undefinierten Verhalten. Daher muß ein Programm, welches mit mehreren
     Ein- oder Ausgabedateien operiert, die ELF-Deskriptoren aktiv halten,
     bis die Bearbeitung vollständig abgeschlossen ist.

BEISPIELE
     Ein Prototyp zum Lesen einer Datei ist unten angeführt. Wenn die Datei
     eine einfache Objektdatei ist, führt das Programm die Schleife einmal
     aus und erhält beim zweiten Schleifendurchlauf einen Nulldeskriptor.
     In diesem Fall haben elf und arf denselben Wert; der Aktivierungszäh-
     ler ist 2, und das Programm ruft elfend() zweimal auf, um den
     Deskriptor freizugeben. Wenn die Datei ein Archiv ist, wird die
     Schleife für jede Archivkomponente durchgeführt, wobei die Dateien,
     die keine Objektdateien sind, ignoriert werden.

        if (elfversion(EVCURRENT) == EVNONE)
        {
              /* Bibliothek veraltet */
              /* Fehlerbehandlung */
        }
        cmd = ELFCREAD;
        arf = elfbegin(fildes, cmd, (Elf *)0);
        while ((elf = elfbegin(fildes, cmd, arf)] != 0)
        {
              if ((ehdr = elf32getehdr(elf)] != 0)
              {
                      /* Datei bearbeiten ... */
              }
              cmd = elfnext(elf);
              elfend(elf);
        }
        elfend(arf);

     Alternativ dazu ist auch die wahlfreie Bearbeitung von Archiven mög-
     lich, wie das nächste Beispiel zeigt. Nachdem die Datei als Archiv
     identifiziert ist, bearbeitet das Programm die gewünschten Archivkom-
     ponenten. Der Einfachheit halber sind in diesem Beispiel Fehlerabfra-
     gen ausgelassen; einfache Objektdateien werden ignoriert. Außerdem
     bleiben in diesen Programmzeilen die ELF-Deskriptoren für alle Archiv-
     komponenten bestehen, da elfend() nicht zur Freigabe aufgerufen wird.













Seite 3                      Reliant UNIX 5.44               Gedruckt 11/98

elf_begin(3E)                                                 elf_begin(3E)

        elfversion(EVCURRENT);
        arf = elfbegin(fildes, ELFCREAD, (Elf *)0);
        if (elfkind(arf) != ELFKAR)
        {
              /* kein Archiv  */
        }
        /* erste Komponente bearbeiten */
        /* offset = ... für gewünschten Kopf der Komponente  */
        while (elfrand(arf, offset) == offset)
        {
              if ((elf = elfbegin(fildes, ELFCREAD, arf)] == 0)
              if ((ehdr = elf32getehdr(elf)] != 0)
              {
                      /* Archivkomponente bearbeiten ... */
              }
              /* offset = ... für gewünschten Kopf der Komponente */
        }

     Der folgende Auszug zeigt, wie eine neue ELF-Datei erzeugt werden
     kann. Um den allgemeinen Ablauf zu beschreiben, ist dieses Beispiel
     vereinfacht:

        elfversion(EVCURRENT);
        fildes = open("pfad/name", ORDWROTRUNCOCREAT, 0666);
        if ((elf = elfbegin(fildes, ELFCWRITE, (Elf *)0)] == 0)
              return;
        ehdr = elf32newehdr(elf);
        phdr = elf32newphdr(elf, count);
        scn = elfnewscn(elf);
        shdr = elf32getshdr(scn);
        data = elfnewdata(scn);
        elfupdate(elf, ELFCWRITE);
        elfend(elf);

     Folgender Auszug beschreibt das Aktualisieren einer bereits vorhande-
     nen ELF-Datei. Dieses Beispiel ist ebenfalls vereinfacht, um den all-
     gemeinen Ablauf darzustellen.

        elfversion(EVCURRENT);
        fildes = open("pfad/name", ORDWR);
        elf = elfbegin(fildes, ELFCRDWR, (Elf *)0);

        /* neue Informationen hinzufügen oder alte Informationen löschen... */

        close(creat("pfad/name", 0666)];
        elfupdate(elf, ELFCWRITE);
        elfend(elf);







Seite 4                      Reliant UNIX 5.44               Gedruckt 11/98

elf_begin(3E)                                                 elf_begin(3E)

     Im obigen Beispiel kürzt der Aufruf creat() die Datei; dadurch wird
     sichergestellt, daß die resultierende Datei die "richtige" Größe hat.
     Ohne Kürzen könnte die aktualisierte genauso groß sein wie die Origi-
     naldatei, selbst wenn Informationen gelöscht wurden. Die Bibliothek
     kürzt, wenn möglich, die Datei durch ftruncate [siehe truncate(3C)].
     Einige Systeme unterstützen jedoch ftruncate() nicht; der Aufruf von
     creat() schützt die Datei davor.

     Bitte beachten Sie, daß beide Beispiele zum Erzeugen von Dateien
     jeweils mit Schreib- und Leserechten öffnen. Die Bibliothek verwendet
     mmap() (sofern das System dies unterstützt), um den Durchsatz zu stei-
     gern, und mmap() erfordert einen lesbaren Dateideskriptor. Die Bibli-
     othek kann auch einen Dateideskriptor verwenden, der nur beschreibbar
     ist; das Anwendungsprogramm erhält dann jedoch nicht die Durchsatzvor-
     teile von mmap().

HINWEIS
     COFF ist ein Objektdateiformat, das vor ELF verwendet wurde. Wenn ein
     Programm elfbegin() mit einer COFF-Datei aufruft, übersetzt die
     Bibliothek die COFF-Strukturen in die entsprechenden ELF-Äquivalente;
     das Programm kann auch eine COFF-Datei lesen (aber nicht schreiben),
     als ob es sich um eine ELF-Datei handeln würde. Diese Konversion fin-
     det nur auf der Speicherabbildung und nicht auf der Datei selbst
     statt. Nach dem Aufruf von elfbegin() behalten die Datei-Offsets, die
     Adressen des ELF-Kopfes, die Programmköpfe und die Abschnittsköpfe die
     originalen COFF-Werte [siehe elfgetehdr(), elfgetphdr() und
     elfgetshdr()). Ein Programm kann elfupdate() aufrufen, um diese
     Werte anzupassen (ohne die Datei zu schreiben). Die Bibliothek liefert
     dann eine konsistente ELF-Abbildung der Datei. Daten, die über
     elfgetdata() gelesen werden, werden übersetzt (die COFF-Symboltabelle
     wird im ELF-Format dargestellt etc.). Daten, die über elfrawdata()
     gelesen werden, unterliegen keiner Umwandlung; das Programm kann somit
     den tatsächlichen Dateiinhalt lesen.

     Einige Debugging-Informationen von COFF werden nicht übersetzt; dies
     beeinflußt die Semantik eines laufenden Programms nicht. Obwohl die
     ELF-Bibliothek COFF unterstützt, wird den Programmierern dringend
     geraten, ihre Programme neu zu übersetzen, um dadurch ELF-
     Objektdateien zu erhalten.

SIEHE AUCH
     creat(2), lseek(2), mmap(2), open(2), truncate(3C), elf(3E),
     elfcntl(3E), elfend(3E), elfgetarhdr(3E), elfgetbase(3E),
     elfgetdata(3E), elfgetehdr(3E), elfgetphdr(3E), elfgetscn(3E),
     elfkind(3E), elfnext(3E), elfrand(3E), elfrawfile(3E),
     elfupdate(3E), elfversion(3E), ar(4).








Seite 5                      Reliant UNIX 5.44               Gedruckt 11/98

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026