/* begincopyright Copyright (c) 1988 Xerox Corporation. All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. Any distribution of this software or derivative works must comply with all applicable United States export control laws. This software is made available AS IS, and Xerox Corporation makes no warranty about the software, its performance or its conformity to any specification. Any person obtaining a copy of this software is requested to send their name and post office or electronic mail address to: PCR Coordinator Xerox PARC 3333 Coyote Hill Rd. Palo Alto, CA 94304 endcopyright */ /* * IncrementalLoadPrivate.h * * Private data structures and procedures used by Incremental Loader * and by object file readers. * * Demers, January 23, 1990 2:48:16 pm PST */ #ifndef _XR_INCREMENTAL_LOAD_PRIVATE_ #define _XR_INCREMENTAL_LOAD_PRIVATE_ 1 #ifndef _XR_INCREMENTAL_LOAD_ #include #endif #ifndef _XR_THREADS_ #include "xr/Threads.h" #endif #ifndef _XR_UIO_ #include "xr/UIO.h" #endif /* * debugging stuff ... */ #define XR_IL_ASSERT 1 #if defined(XR_IL_ASSERT) extern void XR_Panic(/* char *msg */); # define XR_ILAssert(p,m) { if(!(p)) XR_Panic((m)); } #else # define XR_ILAssert(p,m) {} #endif /* * Setup proc -- called prior to forking VPs and IOPs */ extern void XR_SetupIncrementalLoader(); /* ??? should be part of GC interface ??? */ typedef void (*XR_GCRootCallback)(/* XR_Seg seg, XR_Pointer data */); typedef void (*XR_GCRootEnumerator)(/* XR_GCRootCallback rootCallback, XR_Pointer rootCallbackData, XR_Pointer rootEnumeratorData */); /* ??? end of GC stuff ??? */ /* * Private initialization state ... */ typedef enum { ilis_initial = 0, ilis_allocated = 1, ilis_internalizing = 2, ilis_internalized = 3, ilis_last = 0x7fffffff } XR_ILInitializationState; /* * Registration data */ typedef enum XR_ILOpRep { ilOpNone = 0, ilOpInternalize = 1, /* internalize boot file symbols */ ilOpLoad = 2, /* load a file */ ilOpCommit = 3, /* commit load */ ilOpAbort = 4, /* abort load */ ilOpError = 0x7fffffff /* (32 bits) */ } XR_ILOp; typedef void (*XR_ILReaderProc)(/*struct XR_ILSymTabRep *ilst*/); /* expects ilst->ilst_opArg, ilst->ilst_ilfteArg sets ilst->ilst_result */ typedef struct XR_ILRegistrationRep { /* link in registration list */ struct XR_ILRegistrationRep * ilr_next; /* object file reader proc (see below) */ XR_ILReaderProc ilr_proc; XR_Pointer ilr_data; /* magic numbers this proc can interpret */ int ilr_nMagics; unsigned ilr_magics[/* ilr_nMagics */ 1]; } * XR_ILRegistration; #define XR_ILRegistrationBytes(nm) \ ( sizeof(struct XR_ILRegistrationRep) + ((nm)-1) * sizeof(unsigned) ) /* * IL file table entry * * Allocated in ILSymTab ilst_zone. */ typedef struct XR_ILFileTabEntryRep { /* public part ... */ struct XR_ILFileEntryRep ilfte_ilfe; /* reader responsible for this file */ XR_ILRegistration ilfte_ilr; XR_Pointer ilfte_readerPrivateState; /* PZone revert data for commit points ... */ char * ilfte_revertCookie; char * ilfte_revertCookiePtrFree; /* GC root enumeration data */ XR_GCRootEnumerator ilfte_gcRootEnumerator; XR_Pointer ilfte_gcRootEnumeratorData; /* -> next-most-recently-allocated ilfte ... */ struct XR_ILFileTabEntryRep * ilfte_prev; } * XR_ILFileTabEntry; /* * Relocation item * * Allocated in ILSymTab ilst_zonePerCommit; could be pointer-free if desired. * * A list of these hangs from each undefined symbol; they are processed * and removed after the symbol's value has been determined. * * This is good enough for SPARC, VAX, 68K machines. * We may need to extend it for other architectures. */ typedef struct XR_ILRelocItemRep { /* forward pointer */ struct XR_ILRelocItemRep * ilri_next; /* proc to be called with symbol's val when determined ... */ /* (parameters 'addr', 'type', 'addend' are not interpreted */ /* by this package, just passed along.) */ void (*ilri_proc)(/* char *addr, unsigned type, long addend, unsigned val */); char *ilri_addr; unsigned ilri_type; long ilri_addend; } * XR_ILRelocItem; /* * Symbol table entry * * Allocated in ILSymTab ilst_zonePtrFree. */ typedef struct XR_ILSymTabEntryRep { /* public data */ struct XR_ILSymEntryRep ilste_ilse; XR_ILRelocItem ilste_ilri; /* hash table structure (case-insensitive index by name) */ unsigned ilste_hash; struct XR_ILSymTabEntryRep *ilste_symNext; /* skip list structure (index by value) */ unsigned ilste_height; struct XR_ILSymTabEntryRep *ilste_valNext[/* height */ 1]; } * XR_ILSymTabEntry; #define XR_ILSymTabEntryBytes(height) \ ( sizeof(struct XR_ILSymTabEntryRep) \ + ((height)-1) * sizeof(struct XR_ILSymTabEntryRep *) ) /* * Symbol table */ #define XR_MAX_IL_FILE_DATA 16 typedef char * XR_PZone; typedef struct XR_ILSymTabRep { /* lock */ struct XR_MLRep ilst_ml; struct XR_CVRep ilst_avail; bool ilst_locked; /* state of initialization */ XR_ILInitializationState ilst_initializationState; /* zones */ XR_PZone ilst_zonePerFile; /* freed after each file is loaded */ XR_PZone ilst_zonePerCommit; /* freed after each commit */ XR_PZone ilst_zone; /* not freed, but reverted on abort */ XR_PZone ilst_zonePtrFree; /* not freed, but reverted on abort */ /* registration data */ XR_ILRegistration ilst_registrations; /* file table */ unsigned ilst_seqNum; XR_ILFileTabEntry ilst_ilfte; /* state of current incremental load */ /* result code for most recent operation */ XR_ILError ilst_result; /* new symbols (loaded but but not yet committed) */ XR_ILSymTabEntry ilst_newSymsHd; XR_ILSymTabEntry ilst_newSymsTl; unsigned ilst_numUndefined; XR_ILSymTabEntry ilst_undefinedSymsHdCache; /* readSymbolsOnly is TRUE forinternalizing PCR itself */ bool ilst_readSymbolsOnly; /* cached callbacks used during incremental load */ XR_ILContinueAction (*ilst_activeRefProc)(/* char *sym, XR_ILSymEntry ilseOld, void *clientData */); char *ilst_activeRefClientData; XR_ILContinueAction (*ilst_activeDefProc)(/* XR_ILSymEntry ilseNew, XR_ILSymEntry ilseOld, void *clientData */); char *ilst_activeDefClientData; XR_ILContinueAction (*ilst_activeCommonProc)(/* char *sym, unsigned size, XR_ILSymEntry ilse, void *clientData */); char *ilst_activeCommonClientData; void (*ilst_activePatchSizeProc)(/* XR_ILFileEntry ilfe, void *clientData */); char *ilst_activePatchSizeClientData; /* fildes and reader-proc-specific data */ XR_Fildes ilst_fd; XR_Pointer ilst_readerProcData; XR_ILOp ilst_opArg; XR_ILFileTabEntry ilst_ilfteArg; unsigned ilst_fileData[XR_MAX_IL_FILE_DATA]; /* symbol hash table */ unsigned ilst_numEntries; unsigned ilst_numHdrs; /* must be power of 2 */ XR_ILSymTabEntry * ilst_hdrs; /* value skip list */ XR_ILSymTabEntry ilst_left; unsigned ilst_maxHeight; /* file for file-and-commons information for transform_symtab */ /* ??? THIS OUGHT TO BE PROVIDED MORE GENERALLY ELSEWHERE ??? */ char *ilst_infoFileName; XR_Fildes ilst_infoFile; } * XR_ILSymTab; extern XR_ILSymTab XR_ilSymTab; /* * Registration proc */ extern int XR_RegisterIncrementalLoadProc(/* XR_ILReaderProc proc, XR_Pointer data, int nMagics, unsigned *magics */); /* Register an incremental loading proc. Return 0 (success), -errno (failure). The magic numbers `*magics' are copied, so the args may be volatile. The `data' value is stored in ilst->ilst_readerProcData before `proc' is called. The `proc' is complicated, and embodies all the file-format-specific behavior. It is called once with `op' = load, and once more with `op' = commit or `op' = abort. The commit operations are invoked in the order in which the files were loaded; the abort operations are invoked in reverse order. All this ought to be documented here, but isn't yet ... For an example, see IncrementalLoadADotOut.c. */ /* * An IncrementalLoading package that might be included as part of the * boot file should export the following procedure: */ extern void XR_run_IncrementalLoadDEFAULT(); /* Called by this package to initialize default incremental loader. It should call XR_RegisterIncrementalLoadProc. */ /* * * Utilities for use by registered object file reader procs ... * * In most (but not all) cases, error results are stored in ilst->ilst_result, * and are as described in IncrementalLoad.h. */ extern XR_ILError XR_ILMakeError(/* bool fatal, int code, char * msg */); extern XR_ILError XR_ILMakeNoMemError(/* */); #define XR_ILSetError(ilst,fatal,code,msg) \ (ilst)->ilst_result = XR_ILMakeError((fatal),(code),(msg)) /* Set error indication in *ilst. The characters of *msg are copied. */ #define XR_ILCheckAlloc(p) \ if( ((XR_Pointer)(p)) == NIL ) return( XR_ILMakeNoMemError() ) #define XR_ILCheckAlloc2(ilst,p) \ if( ((XR_Pointer)(p)) == NIL ) { \ (ilst)->ilst_result = XR_ILMakeNoMemError(); \ return; } /* Check if result of an allocation is NIL, return error if so. */ extern void XR_ILGetOpenFile(/* XR_ILSymTab ilst */); /* Check that the descriptor in ilst->ilst_fd is open (>= 0). If necessary, open the file named in ilst->ilst_ilfteActive. If this fails, set ilst->ilst_result appropriately. */ extern void XR_ILRead(/* XR_ILSymTab ilst, unsigned offset, char *buf, unsigned bytes, bool abort */); /* Read the current file as specified. The fOffset field in the pcfe will be added to offset before reading. If this fails, set ilst->ilst_result from XR_GetErrno(), with the sign negative iff abort is TRUE. */ extern void XR_ILAllocSegments(/* XR_ILSymTab ilst, unsigned tBytes, unsigned dBytes, unsigned bBytes */); /* Allocate storage for text, data, bss, and patch segments. Fill in the address and size fields of ilst_ilfteActive. Note: the common segment is allocated at commit time. */ extern unsigned XR_ILHashFromSym(/* char *sym */); /* Hash function used by procs below ... case-insensitive! */ extern XR_ILSymTabEntry XR_ILSetSymDefined(/* XR_ILSymTable ilst, char *sym, unsigned hash, unsigned type, unsigned value, unsigned size */); /* Record a definition of given symbol in file currently being loaded. Return the symbol table entry. The characters of `*sym' are not copied, and symbol table entries are pointer-free, so *sym should be allocated in a permanent place; this is generally ilst_zonePtrFree. The size argument may be zero, meaning "unknown." This may call the redefinedProc associated with the active incremental load, which may return ilca_abort(msg). In this case, XR_ILSetSymDefined returns NIL immediately. */ extern XR_ILSymTabEntry XR_ILSetSymCommon(/* XR_ILSymTable ilst, char *sym, unsigned hash, unsigned size */); /* Record a common symbol in file currently being loaded. Return the symbol table entry. The characters of `*sym' are not copied, and symbol table entries are pointer-free, so *sym should be allocated in a permanent place; this is generally ilst_zonePtrFree. This may call the oldCommonProc associated with the active incremental load, which may return ilca_useOldCommon or ilca_abort(msg). In the abort case, XR_ILSetSymCommon returns NIL immediately. */ extern XR_ILSymTabEntry XR_ILSetSymReferenced(/* XR_ILSymTable ilst, char *sym, unsigned hash, */); /* Record an (external) reference to a given symbol from the file currently being loaded. The characters of `*sym' are not copied, and symbol table entries are pointer-free, so *sym should be allocated in a permanent place; this is generally ilst_zonePtrFree. Return the symbol table entry. This may call the undefinedProc associated with the active incremental load. A result of FALSE from that proc will set ilst->ilst_result and return NIL immediately. */ extern void XR_ILRelocate(/* XR_ILSymTab ilst, XR_ILSymTabEntry ilste, void (*proc)( char *addr, unsigned relocType, long addend, unsigned val ), char *addr, unsigned relocType, long addend */); /* Process a relocation reference to an undefined external symbol described by ilste. The proc, addr, relocType and addend parameters are as in an XR_ILRelocItem structure; the proc will be called once when (if) the external symbol becomes defined. (This may be immediately!) May fail and set ilst->ilst_result. */ extern void XR_ILSetGCRootEnumerator(/* XR_ILSymTab ilst, XR_ILFileTabEntry ilfte, XR_GCRootEnumerator gcRootEnumerator, XR_Pointer gcRootEnumeratorData */); /* Store the ilfte_gcRootEnumerator and ilfte_gcRootEnumeratorData fields carefully (so a concurrent GC doesn't get confused). If the reader proc doesn't call this, default root set is used. For most architectures this will be entire data, bss, common segs. */ #endif