                       ********************************
                       * Resident Symbol Driver V1.20 *
                       ********************************
                       *    Public-Domain-Software    *
                       *       (Stand 05.08.92)       *
                       ********************************


Unter der Voraussetzung, da die Dateien

     README             (diese Datei)
     CHANGES            (bisherige nderungen am Symbol-Treiber)
     C_SOURCE\
        SHOWSYMB.C      (ein Beispielprogramm in C)
        SHOWSYMB.H      (die Definitionen der Symbol-Strukturen)
        SHOWSYMB.PRJ    (die TurboC/PureC-Projektdatei)
        SUBROUT.S       (die Assembler-C-Schnittstelle)
     SYMBOL.120\
        SYMBOL.PRG      (Resident Symbol Driver - der eigentliche Treiber)
        SYSTEM.SMB      (die System-Symboltabelle (s.u.))
        SYM2SMB.PRG     (Konvertierer TurboAss *.SYM => *.SMB)
     TEMPLMON.MOD\
        CHANGES         (nderungen am Templemon-Modul)
        DEUTSCH\
           TMONMODS.EXE (Templemon-Modul zur Symboltabellen-Verwaltung)
        ENGLISH\
           TMONMODS.EXE (Templemon-Modul (Texte in Englisch))
     WATCHDOG.110\
        README          (README zum Shareware-Programm WATCHDOG)
        CHANGES         (nderungen von WATCHDOG)
        WATCHDOG.ACC    (Steueraccessory von WATCHDOG)
        WATCHDOG.RSC    (Resourcedatei fr das Accessory)
        WDOG_TSR.PRG    (speicherresidenter Teil von WATCHDOG)
        BEISPIEL.TOS    (Beispielprogramm; nheres siehe WATCHDOG\README)
        BEISPIEL.C      (Source-Code zum Beispielprogramm)

unverndert  kopiert  werden,  darf  dieses  Programm fr private Anwender frei
kopiert  und  benutzt werden. Kommerzielle Nutzung in jeder Form (dies schliet
auch den Vertrieb ber Public-Domain-Sammeldisketten oder hnliches ein) ist

                          ****************************
                          **   NICHT GESTATTET !!   **
                          ****************************


Hinweis / Copyright:
====================

Fr  eventuelle  auftretende  Probleme  oder  Datenverluste,  die bei Benutzung
dieses Programmes entstehen, wird keine Haftung bernommen.

Aufgrund  der  Funktionsweise  kann es  zu Strungen  beim Betrieb  mit anderen
Programmen kommen. Da ich nicht in der Lage bin, Tests ber die Vertrglichkeit
mit allen vorhandenen Programmen zu machen, wre ich jedem dankbar, der mir ein
Problem beschreiben knnte. Dazu brauche ich allerdings die Sicherheit, da der
Fehler nur im Zusammenhang mit dem betreffenden Programm auftritt und nicht der
Seiteneffekt  eines  anderen  Programmes ist. Deshalb  sollte  man  vorher alle
anderen Programme  entfernen und  versuchen, die  Bedingungen, unter  denen der
Fehler auftrat,  wiederherzustellen.  Wenn der Fehler dann immer noch auftritt,
so bitte ich die betreffende Person,  sich mit mir schriftlich in Verbindung zu
setzen.

Fr Fragen, Wnsche, Verbesserungen oder Probleme wenden Sie sich bitte an:

               Robert Federle, Rungestr. 3, W-8900 Augsburg 22


Funktion:
=========

Dieses  Programm  installiert  fr  jedes  geladene  Programm  zustzlich  eine
Symboltabelle  im  Speicher,  falls  das  Programm eine solche Tabelle besitzt.
Damit  ist  es  nun  mglich,  in  Verbindung mit einem entsprechend angepaten
Debugger  (z.B. Templemon)  Accessories  und speicherresidente Programm wie ein
normales Programm zu debuggen.

Der   Treiber   installiert   sich   resident  im  Speicher  und  verbiegt  den
GEMDOS-Vektor (TRAP  #1) sowie etv_term nach dem XBRA-Verfahren.

Auerdem  wird  in  der  Cookie-Jar-Tabelle  ein  Cookie  mit  dem Namen "SYMB"
angelegt,  dessen  Parameter  ein  Zeiger  auf  die  Schnittstellen-Struktur
SymbolCookie (siehe unten) ist.

Folgende GEMDOS-Funktionsaufrufe werden abgefangen:

              PEXEC, PTERM0, PTERM, PTERMRES und MFREE.

Wenn nun ein Programm mit PEXEC (0, ...) oder PEXEC (3, ...) gestartet wird, so
wird  aus  dem  Dateikopf  ermittelt,  ob  eine  Symboltabelle  an das Programm
angehngt ist. Dann wird ein Speicherblock angefordert, der gro genug ist, die
Tabelle  sowie  Zusatzinformationen  aufzunehmen.  Diese Tabelle wird ber eine
Struktur  in  die verkettete Liste eingehngt. Danach wird das Programm mit dem
Modus  3  geladen,  die  Daten  aus der Basepage geholt und dann PEXEC (4, ...)
ausgefhrt.

Wenn  ein  Programm beendet wird, so wird die zugehrige Struktur aus der Liste
ausgehngt  und  der  Speicher  fr  das  Programm  sowie fr die Symboltabelle
freigegeben.

Der  MFREE-Aufruf  wird  nur deshalb abgefangen, um auch das Debuggen von ACCs,
die  mit  Hilfe  von  Chamleon  nachgeladen wurden, zu ermglichen. Diese ACCs
werden  mittels PEXEC (3, ...) geladen, jedoch niemals mit PTERM o.. beendet!!
Aus   diesem   Grund   wird  bei einem MFREE-Aufruf geprft, ob es sich bei der
bergebenen   Adresse   um   die   Basepage   eines   im  Speicher befindlichen
Programms handelt.


Die verwendeten Strukturen:
===========================

Die  Liste  der  im Speicher befindlichen Symbol-Strukturen ist ber den Cookie
"SYMB"  erreichbar. Der Cookie-Parameter stellt dabei einen Zeiger auf folgende
Struktur dar:

typedef struct SYMBOLCOOKIE
{
    WORD    Version;                 /* Aktuelle Versionsnummer des Treibers */
    WORD    Revision;                /* Aktuelle Revisionsnr. des Treibers */
    SymbolHeader    *First;          /* Zeiger auf die 1. Struktur oder NULL */
    long    (*GetSymbolName) ();     /* Adresse in Symbolnamen umwandeln */
    long    (*GetSymbolValue) ();    /* Symbolname in Adresse umwandeln */
    long    (*AddSymbolTable) ();    /* Symboltabelle hinzufgen */
    long    (*RemoveSymbolTable) (); /* Symboltabelle entfernen */
} SymbolCookie;

oder in Assembler:

SymbolCookie:
    Version            EQU 0
    Revision           EQU 2
    First              EQU 4
    GetSymbolName      EQU 8
    GetSymbolValue     EQU 12
    AddSymbolTable     EQU 16
    RemoveSymbolTable  EQU 20


Die Struktur fr jede Symbol-Tabelle hat folgendes Format:

typedef struct SYMBOLHEADER
{
    char    ProgramName [13];   /* Programmname (gro, 0-terminiert) */

    char    reserved;           /* reserviert */

    WORD    SymbolCount;        /* Anzahl der Symbole (TEXT, DATA, BSS) */
    WORD    FirstData;          /* Index des ersten DATA-Symbols */
    WORD    FirstBss;           /* Index des ersten BSS-Symbols */

    void    *SymbolValues;      /* Zeiger auf die Werte-Offset-Tabelle */
    void    *SymbolNames;       /* Zeiger auf die Namens-Offset-Tabelle */
    Symbol  *SymbolData;        /* Zeiger auf die Symboldaten */

    LONG    FirstAddress;       /* TEXT-Segment-Start */
    LONG    LastAddress;        /* BSS-Segment-Start + BSS-Segment-Gre */
    BASPAG  *Basepage;          /* Zeiger auf die Basepage des Programms */

    struct SYMBOLHEADER *Next;  /* Zeiger auf die nchste Struktur */

} SymbolHeader;

oder in Assembler:

    ProgramName:   ds.b 13
    reserved:      ds.b 1

    SymbolCount:   ds.w 1
    FirstData:     ds.w 1
    FirstBss:      ds.w 1

    SymbolValues:  ds.l 1
    SymbolNames:   ds.l 1
    SymbolData:    ds.l 1

    FirstAddress:  ds.l 1
    LastAddress:   ds.l 1
    Basepage:      ds.l 1

    Next:          ds.l 1


Bei  den Offsettabellen SymbolValues und SymbolNames handelt es sich jeweils um
16-Bit  groe  Eintrge,  die  relativ  zu  den  Symboldaten  ab  SymbolData zu
verstehen sind.


Die Symboldaten werden in einem eigenen Format im Speicher abgelegt:

typedef struct SYMBOL
{
    LONG    Value;              /* Wert des Symbols */
    BYTE    Type;               /* Typ-Byte / Gren-Byte des Symbols */
    BYTE    Name [];            /* Symbolname (0-terminiert) */
} Symbol;

oder in Assembler:

Symbol:
    Value:   ds.l 1
    Type:    ds.b 1
    Name:    ds.b 1 ; bis zu 22 Zeichen + 1 Null-Byte

Die  Bits  7  bis  5 von Type bestimmen den Typ des Symbols. Wenn Bit 7 gesetzt
ist,  so handelt es sich um ein DATA-Symbol. Bit 6 ist fr TEXT-Symbole und Bit
5  fr BSS-Symbole zustndig. Wenn alle 3 Bits gesetzt sind, so handelt es sich
um ein System-Symbol aus einer Symboldatei.

Die restlichen Bits 6-0 geben an, wie gro die aktuelle Struktur in Bytes ist.


Beispieladressierung:
=====================

Jeder   Eintrag   in   der  Offset-Tabelle  gibt an, ab welcher Position in den
Symboldaten das zugehrige Symbol steht. Z.B.:

    SymbolData = $10000, Offset = $246  =>  Symboldaten stehen bei $10246

Um z.B. das erste DATA-Symbol zu erreichen, sind folgende Schritte ntig:

In C: (Pointer zeigt auf die Symbol-Struktur)

    WORD    Index, Offset;
    Symbol  *SymbolPointer;

    Index = Pointer->FirstData;
    Offset = (Pointer->SymbolValues) [Index];
    SymbolPointer = (Symbol *) ((LONG) Pointer->SymbolData + (LONG) (Offset);

oder in Assembler: (A0 zeigt auf die Symbol-Struktur)

    move.w  FirstData(A0),D0        ; 1. Index der DATA-Symbole holen
    add.w   D0,D0                   ; mal 2 (wegen WORD)
    movea.l SymbolValues(A0),A1     ; Zeiger auf die Werte-Offsets holen
    move.w  0(A1,D0.w),D0           ; Offset holen
    movea.l SymbolData(A0),A1       ; Zeiger auf die Symbol-Daten holen
    adda.w  D0,A1                   ; Offset addieren


Die Funktionen-Schnittstelle:
=============================

Der  Cookie-Wert zeigt auf die Schnittstellen-Struktur vom Typ SymbolCookie. In
diese  Struktur  sind  die  Adressen  von 4 Routinen eingetragen, mit denen die
internen Routinen aufgerufen werden knnen.

Allen  Routinen  ist gemeinsam, da sie nur die Register verndern, die fr die
Parameterbergabe  bentigt  werden.  Die  restlichen  Register  werden von den
Routinen vorher gerettet.

Folgende Routinen stehen derzeit zur Verfgung:

******************
* GetSymbolName: *
****************************************************
* IN:  D0.l: Adresse, zu der der Name gesucht wird *
* OUT: D0.l: = 0: Symbol gefunden                  *
*                 A0.l: Zeiger auf Symboldaten     *
*                 A1.l: Zeiger auf die Struktur    *
*            <>0: Symbol nicht gefunden            *
****************************************************

Diese  Routine  wird  eingesetzt, um zu einer bekannten Adresse einen passenden
Symbolnamen  zu suchen, falls ein Symbol mit einem entsprechenden Wert in einem
der im Speicher befindlichen Programm existiert.

Die  Adresse,  zu  der  der Symbolwert gesucht wird, wird in D0 bergeben. Nach
Aufruf  der Routine gibt D0 an, ob das Symbol gefunden wurde (D0.l = 0) oder ob
ein  passendes  Symbol  nicht  existiert  (D0.l <> 0). Nach einer erfolgreichen
Suche  zeigt  A0  auf  die interne Symbolstruktur (siehe unten), wohingegen das
Register  A1  auf  die  zugehrige Symboltabellenstruktur zeigt. Somit kann man
herausbekommen, in welchem Programm die Adresse liegt.


*******************
* GetSymbolValue: *
**********************************************************************
* IN:  A0.l: Zeiger auf Symbolnamen                                  *
*      A1.l: Zeiger auf Programmnamen oder NULL fr alle Programme   *
*            Der Programmname kann auch den Allquantor '*' enthalten *
* OUT: D0.l: = 0: Symbol gefunden                                    *
*                 A0.l: Zeiger auf Symboldaten                       *
*                 A1.l: Zeiger auf die Struktur                      *
*            <>0: Symbol nicht gefunden                              *
**********************************************************************

Diese  Routine  stellt  das  Gegenstck  zu  GetSymbolName  dar, indem zu einem
gegebenen Symbolnamen der zugehrige Symbolwert gesucht wird.

Hierzu  wird  in A0 ein Zeiger auf den 0-terminierten Symbolnamen und in A1 ein
Zeiger  auf  den  Programmnamen  bergeben.  Wenn in A1 der Wert NULL bergeben
wird,  so  wird  zuerst  die  Symboltabelle des aktuellen Programms durchsucht.
Sollte  dabei  kein  Treffer  erzielt werden, so wird die Tabelle vom Anfang an
durchsucht.

Wenn  in  A1  ein  Zeiger  ungleich  NULL  bergeben  wird  oder wenn der in A0
bergebene  String  das Format 'Programmname:Symbolname' besitzt, so werden nur
die Symboltabellen der Programme untersucht,  auf die der Programmname pat. Da
im  Programmnamen  auch  der  Wildcard '*' zugelassen ist, kann man somit auch
Programme debuggen, die aus mehreren Teilen bestehen (z.B. ein vektorverbiegen-
des, residentes Programm zusammen mit seinem Steueraccessory).

In  D0  wird  nach  dem  Aufruf  wieder  der  Erfolg (D0.l = 0) oder Misserfolg
(D0.l <> 0) gemeldet. Die Register A0 und A1 enthalten nach einer erfolgreichen
Suche die entsprechenden Zeiger (nheres siehe GetSymbolName).


*******************
* AddSymbolTable: *
************************************************
* IN:  A0.l: Zeiger auf den Programmnamen      *
*      A1.l: Zeiger auf die Basepage oder NULL *
* OUT: D0.l: = 0: Tabelle geladen              *
*            <>0: Fehler aufgetreten           *
************************************************

Mit  dieser Funktion kann nachtrglich eine Symboltabelle in die verkette Liste
eingehngt werden. Hierzu wird in A0 ein Zeiger auf den Programmnamen und in A1
ein Zeiger auf die Basepage im Speicher oder der Wert  NULL  bergeben.  A0 mu
dabei auch den Pfad enthalten,  wenn das Programm nicht im  aktuellen Directory
steht.

Der Wert NULL hat fr das Register  A1  eine besondere Bedeutung:  hiermit wird
angezeigt,  da es sich  bei dem  Pfadnamen in  A0 um den Namen  einer fertigen
Symboltabelle handelt, die nur eingelesen werden mu.

Als  Ergebnis  erhlt  man  in D0 entweder den Wert 0 (= Tabelle konnte geladen
werden),  den Wert  1  (= ein Fehler ist aufgetreten) oder den  Wert  2  (= der
Treiber ist gerade durch einen anderen Prozess belegt).


**********************
* RemoveSymbolTable: *
*******************************************
* IN:  A0.l: Zeiger auf Programmnamen     *
* OUT: D0.l: = 0: Tabelle entfernt        *
*            <>0: Programm nicht gefunden *
*******************************************

Mit  dieser  Routine kann eine Symboltabelle aus der verketten Liste ausgehngt
werden.   Hierzu   bergibt   man  in  A0  einen  Zeiger  auf den eigentlichen
Programmname (z.B. "EDITOR.PRG").

Als  Ergebnis  erhlt  man in D0 entweder den Wert 0 (= Tabelle konnte entfernt
werden),  den Wert 1 (= Programm konnte nicht gefunden werden) oder den  Wert 2
(= der Treiber ist gerade durch einen anderen Prozess belegt).


Beispielprogramm:
=================

Im  Ordner C_SOURCE findet sich der Sourcecode fr ein Programm, mit dem die im
Speicher  befindlichen  Strukturen  angezeigt  werden  knnen.  Dieses Programm
demonstriert   auerdem  die  Anwendung  der  internen  Funktionen  und  stellt
zustzlich eine Schnittstelle fr PureC-Programm dar (siehe SUBROUT.S).


Utilities:
==========

Die Datei SYSTEM.SMB enthlt alle Definitionen bis einschlielich TOS 3.01, die
fr  die Betriebssystemvariablen und Hardwareadressen ntig sind (entnommen aus
dem  Atari  Profibuch  ST/STE/TT  von  Jankowski/Rabich/Reschke  aus dem Sybex-
Verlag. Diese Datei sollte in den Auto-Ordner des Bootlaufwerks kopiert werden,
da  der  Symbol-Treiber  beim  Hochfahren  des Rechners diese Datei automatisch
ldt.

Das Format einer solchen Symboldatei mu wie folgt aussehen:

typedef struct
{
    LONG    Size;          /* Gre der Symboldaten in Bytes */
    WORD    Count;         /* Anzahl der folgenden Symbole */
    Symbol  Data [Size];   /* Symboldaten */
} SymbolFile;

Bei  den  Symboldaten mu man darauf achten, da jedes Symbol aus einer geraden
Anzahl an Bytes besteht. Notfalls mu man ein Fllbyte am Schlu hinzufgen und
die Gre der Symbolstruktur (Definition siehe oben) anpassen.

Die  Dateiextension  fr  die  Symboldateien des Resident Symbol Drivers sollte
SMB lauten, damit es nicht zu einer Verwechslung mit den TurboAss-Symboldateien
*.SYM kommt.

Damit  die  Erstellung  einer  Symboldatei einfacher ist, kann man das Programm
SYM2SMB.PRG  benutzen,  das  eine  Symboldatei  des TurboAss  von -Soft in das
bentigte Symbolformat konvertiert.

***************************************************************************
* Achtung! Die Symboldateien tauchen in der Programmbersicht nicht auf!! *
***************************************************************************


Autor:
======

Robert Federle
Rungestr. 3
8900 Augsburg 22
