dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnet/ilalink link_init.c,NONE,1.1 Makefile.a


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnet/ilalink link_init.c,NONE,1.1 Makefile.am,1.16,1.17 link_create.c,1.20,1.21 link_image.c,1.10,1.11 link_library.c,1.19,1.20 linker.h,1.26,1.27
Date: Wed, 25 Jun 2003 01:30:59 -0400

Update of /cvsroot/dotgnu-pnet/pnet/ilalink
In directory subversions:/tmp/cvs-serv4332/ilalink

Modified Files:
        Makefile.am link_create.c link_image.c link_library.c linker.h 
Added Files:
        link_init.c 
Log Message:


Link initializers and finalizers in C applications.


--- NEW FILE ---
/*
 * link_init.c - Handle initializers and finalizers for C applications.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "linker.h"
#if HAVE_SYS_TYPES_H
        #include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
        #include <sys/stat.h>
#endif
#if HAVE_UNISTD_H
        #include <unistd.h>
#endif

#ifdef  __cplusplus
extern  "C" {
#endif

/* From ilasm/ilasm_main.c */
int ILAsmMain(int argc, char *argv[], FILE *newStdin);

/*
 * Data structures for keeping track of initializers and finalizers.
 */
typedef struct _tagILInitFini ILInitFini;
struct _tagILInitFini
{
        ILMethod   *method;
        ILInitFini *next;
};
typedef struct _tagILOrder ILOrder;
struct _tagILOrder
{
        int                     order;
        ILInitFini *first;
        ILInitFini *last;
        ILOrder    *next;
};
typedef struct
{
        ILOrder    *inits;
        ILOrder    *finis;

} ILInitFiniList;

/*
 * Get an order value from a method attribute.
 */
static int GetInitFiniOrder(ILMethod *method, const char *name)
{
        ILAttribute *attr;
        ILSerializeReader *reader;
        int order;

        /* Get the attribute block */
        attr = ILLinkerFindAttribute(ILToProgramItem(method),
                                                                 name, 
"OpenSystem.C",
                                                                 ILType_Int32, 
ILType_Invalid);
        if(!attr)
        {
                /* The default order value is zero */
                return 0;
        }

        /* Read the attribute's value */
        reader = ILLinkerReadAttribute(attr);
        if(!reader)
        {
                return 0;
        }
        order = 0;
        if(ILSerializeReaderGetParamType(reader) == IL_META_ELEMTYPE_I4)
        {
                order = (int)ILSerializeReaderGetInt32(reader, 
IL_META_ELEMTYPE_I4);
        }
        ILSerializeReaderDestroy(reader);
        return order;
}

/*
 * Insert an initializer into an init/fini list.
 */
static void InsertInitializer(ILLinker *linker, ILInitFiniList *list,
                                                          ILMethod *method, int 
order)
{
        ILOrder *current, *prev;
        ILInitFini *info;

        /* Find the list head for this order value */
        current = list->inits;
        prev = 0;
        while(current != 0 && current->order < order)
        {
                prev = current;
                current = current->next;
        }
        if(!current || current->order != order)
        {
                current = (ILOrder *)ILMalloc(sizeof(ILOrder));
                if(!current)
                {
                        _ILLinkerOutOfMemory(linker);
                        return;
                }
                current->order = order;
                current->first = 0;
                current->last = 0;
                if(prev)
                {
                        current->next = prev->next;
                        prev->next = current;
                }
                else
                {
                        current->next = list->inits;
                        list->inits = current;
                }
        }

        /* Add the initializer to the end of the list for this order */
        info = (ILInitFini *)ILMalloc(sizeof(ILInitFini));
        if(!info)
        {
                _ILLinkerOutOfMemory(linker);
                return;
        }
        info->method = method;
        info->next = 0;
        if(current->last)
        {
                current->last->next = info;
        }
        else
        {
                current->first = info;
                current->last = info;
        }
}

/*
 * Insert a finalizer into an init/fini list.
 */
static void InsertFinalizer(ILLinker *linker, ILInitFiniList *list,
                                                        ILMethod *method, int 
order)
{
        ILOrder *current, *prev;
        ILInitFini *info;

        /* Find the list head for this order value */
        current = list->inits;
        prev = 0;
        while(current != 0 && current->order > order)
        {
                prev = current;
                current = current->next;
        }
        if(!current || current->order != order)
        {
                current = (ILOrder *)ILMalloc(sizeof(ILOrder));
                if(!current)
                {
                        _ILLinkerOutOfMemory(linker);
                        return;
                }
                current->order = order;
                current->first = 0;
                current->last = 0;
                if(prev)
                {
                        current->next = prev->next;
                        prev->next = current;
                }
                else
                {
                        current->next = list->inits;
                        list->inits = current;
                }
        }

        /* Add the finalizer to the start of the list for this order */
        info = (ILInitFini *)ILMalloc(sizeof(ILInitFini));
        if(!info)
        {
                _ILLinkerOutOfMemory(linker);
                return;
        }
        info->method = method;
        info->next = current->first;
        if(!(current->first))
        {
                current->last = info;
        }
        current->first = info;
}

/*
 * Call a list of initializer or finalizer methods.
 */
static void CallInitFini(FILE *stream, ILOrder *list)
{
        ILInitFini *current;
        ILMethod *method;
        while(list != 0)
        {
                current = list->first;
                while(current != 0)
                {
                        fputs("\tcall ", stream);
                        method = current->method;
                        ILDumpMethodType(stream, ILProgramItem_Image(method),
                                                         
ILMethod_Signature(method),
                                                         IL_DUMP_QUOTE_NAMES, 0,
                                                         ILMethod_Name(method), 
0);
                        putc('\n', stream);
                        current = current->next;
                }
                list = list->next;
        }
}

/*
 * Free a list of initializer or finalizer methods.
 */
static void FreeInitFini(ILOrder *list)
{
        ILOrder *next;
        ILInitFini *init, *nextInit;
        while(list != 0)
        {
                next = list->next;
                init = list->first;
                while(init != 0)
                {
                        nextInit = init->next;
                        ILFree(init);
                        init = nextInit;
                }
                ILFree(list);
                list = next;
        }
}

/*
 * Call library initializers.
 */
static void CallLibraryInit(FILE *stream, ILLibrary *library)
{
        while(library != 0)
        {
                if(library->memoryModel)
                {
                        fprintf(stream, "\tcall void [%s]'%s'::'.init'()\n",
                                        library->name, 
IL_LINKER_DLL_MODULE_NAME);
                }
                library = library->next;
        }
}

/*
 * Call library finalizers, in reverse order.
 */
static void CallLibraryFini(FILE *stream, ILLibrary *library)
{
        if(!library)
        {
                return;
        }
        CallLibraryFini(stream, library->next);
        if(library->memoryModel)
        {
                fprintf(stream, "\tcall void [%s]'$Module$'::'.fini'()\n",
                                library->name);
        }
}

ILImage *_ILLinkerCreateInitFini(ILLinker *linker)
{
        ILMethod *method;
        ILAttribute *attr;
        int order;
        ILInitFiniList list;
        FILE *stream;
        char iltemp[64];
        char otemp[64];
        char *argv[10];
        ILImage *image;

        /* Only generate initializers and finalizers for C applications.
           C# applications will need to explicitly call the initializers
           using helper methods within the "OpenSystem.C" assembly */
        if(!(linker->memoryModel))
        {
                return 0;
        }

        /* Collect up all initializers and finalizers in the image */
        method = 0;
        list.inits = 0;
        list.finis = 0;
        while((method = (ILMethod *)ILImageNextToken
                                (linker->image, IL_META_TOKEN_METHOD_DEF, 
method)) != 0)
        {
                attr = ILLinkerFindAttribute(ILToProgramItem(method),
                                                                         
"InitializerAttribute",
                                                                         
"OpenSystem.C",
                                                                         
ILType_Invalid, ILType_Invalid);
                if(attr)
                {
                        /* This is an initializer */
                        order = GetInitFiniOrder(method, 
"InitializerOrderAttribute");
                        InsertInitializer(linker, &list, method, order);
                }
                attr = ILLinkerFindAttribute(ILToProgramItem(method),
                                                                         
"FinalizerAttribute",
                                                                         
"OpenSystem.C",
                                                                         
ILType_Invalid, ILType_Invalid);
                if(attr)
                {
                        /* This is a finalizer */
                        order = GetInitFiniOrder(method, 
"FinalizerOrderAttribute");
                        InsertFinalizer(linker, &list, method, order);
                }
        }

        /* Open a temporary stream to write the init/fini code to */
#if !defined(IL_WIN32_NATIVE) && defined(HAVE_GETPID)
        sprintf(iltemp, "init-link-%d.iftmp", (int)(getpid()));
        sprintf(otemp, "init-link-%d.oftmp", (int)(getpid()));
#else
        strcpy(iltemp, "init-link.iftmp");
        strcpy(otemp, "init-link.oftmp");
#endif
        stream = fopen(iltemp, "w");
        if(!stream)
        {
                perror(iltemp);
                linker->error = 1;
                return 0;
        }

        /* Generate assembly, module, and memory model information */
        fputs(".assembly '<Assembly>' {}\n", stream);
        fputs(".module '<Module>'\n", stream);
        if(linker->modelFlags != 0)
        {
                fprintf(stream, ".custom instance void "
                                
"[OpenSystem.C]OpenSystem.C.MemoryModelAttribute"
                                "::.ctor(int32, int32) = "
                                "(01 00 %02X 00 00 00 %02X %02X %02X %02X 00 
00)\n",
                                linker->memoryModel,
                                (int)(linker->modelFlags & 0xFF),
                                (int)((linker->modelFlags >> 8) & 0xFF),
                                (int)((linker->modelFlags >> 16) & 0xFF),
                                (int)((linker->modelFlags >> 24) & 0xFF));
        }
        else
        {
                fprintf(stream, ".custom instance void "
                                
"[OpenSystem.C]OpenSystem.C.MemoryModelAttribute"
                                "::.ctor(int32) = "
                                "(01 00 %02X 00 00 00 00 00)\n",
                                linker->memoryModel);
        }
        fputs("\n", stream);

        /* Dump the "init-count" helper class, which keeps track
           of how many times the library has been initialized */
        fputs(".class private sealed 'init-count' extends "
                        "[.library]System.Object\n", stream);
        fputs("{\n", stream);
        fputs("\t.field public static int32 'count'\n", stream);
        fputs("}\n\n", stream);

        /* Generate the code for the global initializer */
        fputs(".method public specialname static void '.init'() cil managed\n",
                  stream);
        fputs("{\n", stream);
        fputs("\t.maxstack 3\n", stream);
        fputs("\t.locals (class [.library]System.Type)\n", stream);
        fputs("\tldtoken 'init-count'\n", stream);
        fputs("\tcall class [.library]System.Type [.library]System.Type::"
                  "GetTypeFromHandle(valuetype 
[.library]System.RuntimeTypeHandle)\n",
                  stream);
        fputs("\tdup\n", stream);
        fputs("\tstloc.0\n", stream);
        fputs("\tcall void [.library]System.Threading.Monitor::Enter"
                  "(class [.library]System.Object)\n", stream);
        fputs("\t.try {\n", stream);
        fputs("\t\tldsfld int32 'init-count'::'count'\n", stream);
        fputs("\t\tdup\n", stream);
        fputs("\t\tldc.i4.1\n", stream);
        fputs("\t\tadd\n", stream);
        fputs("\t\tstsfld int32 'init-count'::'count'\n", stream);
        fputs("\t\tbrtrue L1\n", stream);
        fputs("\t\tleave L2\n", stream);
        fputs("\tL1:\n", stream);
        fputs("\t\tleave L3\n", stream);
        fputs("\t} finally {\n", stream);
        fputs("\t\tldloc.0\n", stream);
        fputs("\t\tcall void [.library]System.Threading.Monitor::Exit"
                  "(class [.library]System.Object)\n", stream);
        fputs("\t\tendfinally\n", stream);
        fputs("\t}\n", stream);
        fputs("L2:\n", stream);
        CallLibraryInit(stream, linker->libraries);
        CallInitFini(stream, list.inits);
        fputs("L3:\n", stream);
        fputs("\tret\n", stream);
        fputs("}\n\n", stream);

        /* Generate the code for the global finalizer */
        fputs(".method public specialname static void '.fini'() cil managed\n",
                  stream);
        fputs("{\n", stream);
        fputs("\t.maxstack 3\n", stream);
        fputs("\t.locals (class [.library]System.Type)\n", stream);
        fputs("\tldtoken 'init-count'\n", stream);
        fputs("\tcall class [.library]System.Type [.library]System.Type::"
                  "GetTypeFromHandle(valuetype 
[.library]System.RuntimeTypeHandle)\n",
                  stream);
        fputs("\tdup\n", stream);
        fputs("\tstloc.0\n", stream);
        fputs("\tcall void [.library]System.Threading.Monitor::Enter"
                  "(class [.library]System.Object)\n", stream);
        fputs("\t.try {\n", stream);
        fputs("\t\tldsfld int32 'init-count'::'count'\n", stream);
        fputs("\t\tldc.i4.1\n", stream);
        fputs("\t\tsub\n", stream);
        fputs("\t\tdup\n", stream);
        fputs("\t\tstsfld int32 'init-count'::'count'\n", stream);
        fputs("\t\tbrtrue L4\n", stream);
        fputs("\t\tleave L5\n", stream);
        fputs("\tL4:\n", stream);
        fputs("\t\tleave L6\n", stream);
        fputs("\t} finally {\n", stream);
        fputs("\t\tldloc.0\n", stream);
        fputs("\t\tcall void [.library]System.Threading.Monitor::Exit"
                  "(class [.library]System.Object)\n", stream);
        fputs("\t\tendfinally\n", stream);
        fputs("\t}\n", stream);
        fputs("L5:\n", stream);
        CallInitFini(stream, list.finis);
        CallLibraryFini(stream, linker->libraries);
        fputs("L6:\n", stream);
        fputs("\tret\n", stream);
        fputs("}\n", stream);

        /* Close the temporary stream and assemble it */
        fclose(stream);
        argv[0] = "ilasm";
        argv[1] = "-j";
        argv[2] = "-o";
        argv[3] = otemp;
        argv[4] = "--";
        argv[5] = iltemp;
        argv[6] = 0;
        if(ILAsmMain(6, argv, 0) != 0)
        {
                ILDeleteFile(iltemp);
                ILDeleteFile(otemp);
                linker->error = 1;
                return 0;
        }
        ILDeleteFile(iltemp);

        /* Load the extra object file that we just created */
        image = 0;
        if(ILImageLoadFromFile(otemp, linker->context, &image,
                                                   IL_LOADFLAG_FORCE_32BIT |
                                                   IL_LOADFLAG_NO_RESOLVE, 1) 
!= 0)
        {
                ILDeleteFile(otemp);
                return 0;
        }
        if((linker->initTempFile = ILDupString(otemp)) == 0)
        {
                _ILLinkerOutOfMemory(linker);
        }

        /* Clean up and exit */
        FreeInitFini(list.inits);
        FreeInitFini(list.finis);
        return image;
}

#ifdef  __cplusplus
};
#endif

Index: Makefile.am
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ilalink/Makefile.am,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -r1.16 -r1.17
*** Makefile.am 3 May 2003 21:12:45 -0000       1.16
--- Makefile.am 25 Jun 2003 05:30:57 -0000      1.17
***************
*** 5,9 ****
  
  ilalink_SOURCES = ilalink.c
! ilalink_LDADD   = libILLink.a ../dumpasm/libILDumpAsm.a \
                                  ../image/libILImage.a 
../support/libILSupport.a
  
--- 5,9 ----
  
  ilalink_SOURCES = ilalink.c
! ilalink_LDADD   = libILLink.a ../ilasm/libILAsm.a ../dumpasm/libILDumpAsm.a \
                                  ../image/libILImage.a 
../support/libILSupport.a
  
***************
*** 13,16 ****
--- 13,17 ----
                                          link_field.c \
                                          link_image.c \
+                                         link_init.c \
                                          link_library.c \
                                          link_main.c \

Index: link_create.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ilalink/link_create.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -r1.20 -r1.21
*** link_create.c       16 Jun 2003 05:15:40 -0000      1.20
--- link_create.c       25 Jun 2003 05:30:57 -0000      1.21
***************
*** 93,96 ****
--- 93,97 ----
        }
        linker->moduleClass = 0;
+       linker->initTempFile = 0;
  
        /* Ready to go */
***************
*** 267,270 ****
--- 268,277 ----
                ILFree(image);
                image = nextImage;
+       }
+ 
+       /* Destroy the temporary init/fini file */
+       if(linker->initTempFile)
+       {
+               ILDeleteFile(linker->initTempFile);
        }
  

Index: link_image.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ilalink/link_image.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** link_image.c        16 Jun 2003 05:15:40 -0000      1.10
--- link_image.c        25 Jun 2003 05:30:57 -0000      1.11
***************
*** 263,267 ****
--- 263,270 ----
  {
        ILLinkImage *image = linker->images;
+       ILImage *initImage;
        int ok = 1;
+ 
+       /* Process the main images */
        linker->imageNum = 1;
        while(image != 0)
***************
*** 274,277 ****
--- 277,292 ----
                image = image->next;
        }
+ 
+       /* Create the initializers and finalizers for C applications */
+       initImage = _ILLinkerCreateInitFini(linker);
+       if(initImage)
+       {
+               if(!ProcessImage(linker, initImage, "init-link"))
+               {
+                       ok = 0;
+               }
+       }
+ 
+       /* Finished the link process */
        return ok;
  }

Index: link_library.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ilalink/link_library.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -r1.19 -r1.20
*** link_library.c      22 Jun 2003 01:20:35 -0000      1.19
--- link_library.c      25 Jun 2003 05:30:57 -0000      1.20
***************
*** 2,6 ****
   * link_library.c - Process libraries within a linker context.
   *
!  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
   *
   * This program is free software; you can redistribute it and/or modify
--- 2,6 ----
   * link_library.c - Process libraries within a linker context.
   *
!  * Copyright (C) 2001, 2003  Southern Storm Software, Pty Ltd.
   *
   * This program is free software; you can redistribute it and/or modify
***************
*** 333,339 ****
--- 333,343 ----
                        nextLibrary->classHash = 0;
                        nextLibrary->symbolHash = 0;
+                       nextLibrary->memoryModel = library->memoryModel;
+                       nextLibrary->modelFlags = library->modelFlags;
                }
                else
                {
+                       nextLibrary->memoryModel =
+                               ILLinkerCMemoryModel(image, 
&(nextLibrary->modelFlags));
                        originator = ILAssemblyGetOriginator(assem, 
&originatorLen);
                        if(originator && originatorLen)

Index: linker.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ilalink/linker.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -r1.26 -r1.27
*** linker.h    16 Jun 2003 05:15:40 -0000      1.26
--- linker.h    25 Jun 2003 05:30:57 -0000      1.27
***************
*** 2,6 ****
   * linker.h - Internal definitions for image linking.
   *
!  * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
   *
   * This program is free software; you can redistribute it and/or modify
--- 2,6 ----
   * linker.h - Internal definitions for image linking.
   *
!  * Copyright (C) 2001, 2003  Southern Storm Software, Pty Ltd.
   *
   * This program is free software; you can redistribute it and/or modify
***************
*** 92,95 ****
--- 92,97 ----
        ILHashTable    *classHash;              /* Hash table for class name 
lookup */
        ILHashTable    *symbolHash;             /* Hash table for global symbol 
lookup */
+       int                             memoryModel;    /* Memory model for the 
library */
+       int                             modelFlags;             /* Memory model 
flags for the library */
        ILMemPool               pool;                   /* Memory pool for 
symbol allocation */
        ILContext      *context;                /* Context containing the 
library image */
***************
*** 140,143 ****
--- 142,146 ----
        const char     *moduleName;             /* Name of the "<Module>" class 
*/
        ILClass        *moduleClass;    /* Reference to the "<Module>" class */
+       char               *initTempFile;       /* Temporary object file for 
init/fini */
  
  };
***************
*** 344,347 ****
--- 347,357 ----
  int _ILLinkerLibraryReplacement(ILLinker *linker, ILLibraryFind *find,
                                                                ILClass 
*classInfo);
+ 
+ /*
+  * Create the global initializer and finalizer methods for C applications.
+  * Returns a new image to be linked into the application, or NULL if
+  * the application does not need initializers or finalizers.
+  */
+ ILImage *_ILLinkerCreateInitFini(ILLinker *linker);
  
  #ifdef        __cplusplus





reply via email to

[Prev in Thread] Current Thread [Next in Thread]