home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * StartupSharedLib.c - init/startup/termination routines for Metrowerks C++ (PowerPC)
- *
- * Copyright © 1995 metrowerks inc. All Rights Reserved.
- *
- *
- * THEORY OF OPERATION
- *
- * This version of the PPC startup code is intended to be used for shared library
- * components of multi-fragment applications. It is designed to properly support
- * exceptions thrown across fragment boundaries, and proper initialization and
- * termination--including construction and destruction of static objects--for
- * a shared library that is one component of a complex, multi-fragment program.
- *
- * The startup file defines 2 entry-points:
- *
- * __initialize This must be the Initialization Entry-Point for the Application.
- * __initialize() registers the exception-handling info for
- * the application, and calls all static initializers.
- *
- * __terminate This must be the Termination Entry-Point for the Application
- * __terminate() unregisters the exception-handling info for the
- * shared application before the fragment is unloaded.
- *
- * The new zero-runtime-overhead exception-handling mechanism requires that we
- * keep track of all loaded fragments and their code/data section ranges--we
- * cannot use the OS data structures to do this--so we must call routines which
- * register and unregister the exception-handling info as a fragment is loaded/unloaded.
- *
- * When the shared library is loaded, __sinit() will call constructors for static
- * objects, linking them into the (per-application) global destructor chain. These
- * objects will be destroyed when the application component of the program calls
- * __destroy_global_chain() as part of its exit() handling. This will ensure the
- * proper ordering of destruction wrt calling _atexit() handlers, cleaning up the
- * I/O and console packages, etc.
- *
- * This startup file must -not- be used for shared libraries with shared data sections,
- * since these may be linked into multiple applications simultaneously, and cannot
- * have its static objects linked into the application's global destructor chain.
- *
- */
-
- #include <Types.h>
- #include <exception.h>
- #include "ExceptionPPC.h"
- #include <NMWException.h>
-
-
- /* external data */
-
- extern char __code_start__[]; /* (defined by linker) */
- extern char __code_end__[]; /* (defined by linker) */
- extern char __data_start__[]; /* (defined by linker) */
- extern char __data_end__[]; /* (defined by linker) */
- extern char __exception_table_start__[]; /* (defined by linker) */
- extern char __exception_table_end__[]; /* (defined by linker) */
-
-
- /* private data */
-
- static int fragmentID; /* ID given to fragment by exception-handling */
-
- typedef struct FragmentInfo {
- ExceptionTableIndex* exception_start; // start of exception table index for fragment
- ExceptionTableIndex* exception_end; // end of exception table index for fragment
- char* code_start; // start of code section for fragment
- char* code_end; // end of code section for fragment
- char* data_start; // start of data section for fragment
- char* data_end; // end of data section for fragment
- char* TOC; // TOC pointer for fragment
- } FragmentInfo;
-
- #define MAXFRAGMENTS 32 // maximum # of code fragments we can register
- static FragmentInfo fragmentinfo[MAXFRAGMENTS];
-
- /* prototypes */
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- void __sinit(void); /* (generated by linker) */
- OSErr __initialize(void);
- void __terminate(void);
-
- #ifdef __cplusplus
- }
- #endif
-
-
- /*
- * __RTOC - return the TOC pointer for our code fragment
- *
- */
-
- static asm char *__RTOC(void)
- {
- mr r3,RTOC
- blr
- }
-
-
- /*
- * __initialize - Default initialization routine for Metrowerks C++ (PowerPC)
- *
- * This routine should be specified as the PEF initialization routine in the container
- * for any multi-fragment application.
- *
- */
-
- short __initialize(void)
- {
- // register this code fragment with the Exception Handling mechanism
- fragmentID = __register_fragment(__code_start__, __code_end__,
- __data_start__, __data_end__,
- __exception_table_start__, __exception_table_end__,
- __RTOC());
-
- // call all static initializers
- __sinit();
-
- // return success to Code Fragment Manager
- return(noErr);
- }
-
-
- /*
- * __terminate - Default termination routine for Metrowerks C++ (PowerPC)
- *
- * This routine should be specified as the PEF termination routine in the container
- * for any multi-fragment application.
- *
- */
-
- void __terminate(void)
- {
- // unregister this code fragment with the Exception Handling mechanism
- __unregister_fragment(fragmentID);
- }
-
- /************************************************************************/
- /* Purpose..: Register a code fragment and its exception tables */
- /* Input....: pointer to start of fragments code section */
- /* Input....: pointer to end of fragments code section */
- /* Input....: pointer to start of fragments data section */
- /* Input....: pointer to end of fragments data section */
- /* Input....: pointer to start of fragments exception table index */
- /* Input....: pointer to end of fragments exception table index */
- /* Input....: RTOC for fragment */
- /* Return...: unique ID for __ex_unregister_fragment */
- /************************************************************************/
- int __register_fragment(char *code_start, char *code_end,
- char *data_start, char *data_end,
- char *exception_start, char *exception_end,
- char *TOC)
- {
- FragmentInfo *f;
- int i;
-
- // find a free entry in the fragment table
- for(i=0,f=fragmentinfo;i<MAXFRAGMENTS;++i,++f) if(f->code_start==0)
- {
- f->code_start=code_start;
- f->code_end=code_end;
- f->data_start=data_start;
- f->data_end=data_end;
- f->exception_start=(ExceptionTableIndex *)exception_start;
- f->exception_end=(ExceptionTableIndex *)exception_end;
- f->TOC=TOC;
- return(i);
- }
- // couldn't register the fragment
- return(-1);
- }
-
- /************************************************************************/
- /* Purpose..: Un-register a code fragment and its exception tables */
- /* Input....: unique ID assigned in __ex_register_fragment */
- /* Return...: --- */
- /************************************************************************/
- void __unregister_fragment(int fragmentID)
- {
- FragmentInfo *f;
-
- if(fragmentID>=0 && fragmentID<MAXFRAGMENTS)
- {
- f = &fragmentinfo[fragmentID];
- f->code_start=0; f->code_end=0;
- f->data_start=0; f->data_end=0;
- f->exception_start=0; f->exception_end=0;
- f->TOC=0;
- }
- }
-
-