1 //////////////////////////////////////////////////////////////////////////////
2 //Copyright 2008
3 //  Andrew Gacek, Steven Holte, Gopalan Nadathur, Xiaochu Qi, Zach Snow
4 //////////////////////////////////////////////////////////////////////////////
5 // This file is part of Teyjus.                                             //
6 //                                                                          //
7 // Teyjus is free software: you can redistribute it and/or modify           //
8 // it under the terms of the GNU General Public License as published by     //
9 // the Free Software Foundation, either version 3 of the License, or        //
10 // (at your option) any later version.                                      //
11 //                                                                          //
12 // Teyjus is distributed in the hope that it will be useful,                //
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of           //
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
15 // GNU General Public License for more details.                             //
16 //                                                                          //
17 // You should have received a copy of the GNU General Public License        //
18 // along with Teyjus.  If not, see <http://www.gnu.org/licenses/>.          //
19 //////////////////////////////////////////////////////////////////////////////
20 #include <stdio.h>
21 #include <string.h>
22 #include "ld_message.h"
23 #include "file.h"
24 #include "../system/memory.h"
25 #include "../simulator/mctypes.h"
26 #include "loader.h"
27 #include "kind.h"
28 #include "tyskel.h"
29 #include "const.h"
30 #include "code.h"
31 #include "strings.h"
32 #include "hashtab.h"
33 #include "bvrtab.h"
34 #include "implgoal.h"
35 #include "importtab.h"
36 
37 static char* LD_LOADER_path = "./";
LD_LOADER_setPath(char * path)38 void  LD_LOADER_setPath(char* path)
39 {
40   if (path) LD_LOADER_path = path;
41 }
42 
LD_LOADER_makePath(char * modname)43 char* LD_LOADER_makePath(char* modname)
44 {
45   char* buf=(char *)EM_malloc(strlen(LD_LOADER_path)+strlen(modname)+1);
46   sprintf(buf,"%s%s",LD_LOADER_path,modname);
47   return buf;
48 }
49 
50 
51 #define LINKCODE_EXT ".lp"
52 #define BYTECODE_EXT ".lpo"
53 
54 void LD_LOADER_LoadLinkcodeVer();
55 
56 void LD_LOADER_LoadModuleName(char* modname);
57 MEM_GmtEnt* LD_LOADER_GetNewGMTEnt(int index);
58 WordPtr LD_LOADER_ExtendModSpace(MEM_GmtEnt* ent, int size);
59 int LD_LOADER_SetName(MEM_GmtEnt* ent,char* modname);
60 void LD_LOADER_AddGMTEnt(MEM_GmtEnt* ent);
61 void LD_LOADER_DropGMTEnt(MEM_GmtEnt* ent);
62 
63 
64 int LD_verbosity = 0;
65 
66 //Defines the primary procedure of the loader: the load function
67 
68 //Loads the module into returns it's index in the global module table
69 //Returns -1 on failure.
LD_LOADER_Load(char * modname,int index)70 int LD_LOADER_Load(char* modname, int index)
71 {
72   MEM_GmtEnt* gmtEnt;
73 
74   EM_TRY{
75     LD_FILE_Open(LD_LOADER_makePath(modname),LINKCODE_EXT);
76     LD_LOADER_LoadLinkcodeVer();
77     LD_LOADER_LoadModuleName(modname);
78   }EM_CATCH{
79     EM_THROW(LD_LoadError);
80   }
81   gmtEnt=LD_LOADER_GetNewGMTEnt(index);
82   EM_TRY{
83     LD_LOADER_SetName(gmtEnt,modname);
84     LD_CODE_LoadCodeSize(gmtEnt);
85     LD_KIND_LoadKst(gmtEnt);
86     LD_TYSKEL_LoadTst(gmtEnt);
87     LD_CONST_LoadCst(gmtEnt);
88     LD_STRING_LoadStrings(gmtEnt);
89     LD_IMPLGOAL_LoadImplGoals(gmtEnt);
90     LD_HASHTAB_LoadHashTabs(gmtEnt);
91     LD_BVRTAB_LoadBvrTabs(gmtEnt);
92     LD_IMPORTTAB_LoadImportTabs(gmtEnt);
93     LD_CODE_LoadCode(gmtEnt);
94     LD_LOADER_AddGMTEnt(gmtEnt);
95   }EM_CATCH{
96     ///\todo Clean up after failed load.
97     LD_LOADER_DropGMTEnt(gmtEnt);
98     EM_THROW(LD_LoadError);
99   }
100 
101   return 0;
102 }
103 
104 #define LINKCODE_VER 3
LD_LOADER_LoadLinkcodeVer()105 void LD_LOADER_LoadLinkcodeVer()
106 {
107   Word tmp=LD_FILE_GETWORD();
108   if(tmp!=LINKCODE_VER){
109     LD_error("Incompatible linkcode version %ld.\n",tmp);
110     EM_THROW(LD_LoadError);
111   }
112 }
113 
114 ///\note Check Purpose of module name in file
LD_LOADER_LoadModuleName(char * modname)115 void LD_LOADER_LoadModuleName(char* modname)
116 {
117   char *buf;
118   int len=LD_FILE_GET4();
119   buf = EM_malloc(len+1);
120   LD_FILE_GetString(buf,len);
121   if(0!=strcmp(buf,modname)){
122     LD_error("Unexpected module name %s in %s%s\n",buf,modname,LINKCODE_EXT);
123     free(buf);
124     EM_THROW(LD_LoadError);
125   }
126   free(buf);
127 }
128 
129 /* get a module table entry of given index from the global module tables   */
130 /* the index is assumed to be calculated by the system front and passed in */
131 /* as an argument upon invoking the loader -- XQ                           */
LD_LOADER_GetNewGMTEnt(int index)132 MEM_GmtEnt* LD_LOADER_GetNewGMTEnt(int index)
133 {
134   MEM_GmtEnt* ent;
135   ent = &(MEM_modTable[index]);
136   ent->modSpaceEnd=ent->modSpaceBeg=MEM_memTop;
137   ent->codeSpaceEnd=ent->codeSpaceBeg=MEM_memBot;
138   return ent;
139 }
140 
LD_LOADER_DropGMTEnt(MEM_GmtEnt * ent)141 void LD_LOADER_DropGMTEnt(MEM_GmtEnt* ent)
142 {
143   ent->modname=NULL;
144 }
145 
146 /* finalize system memory after loading modules -- XQ */
LD_LOADER_AddGMTEnt(MEM_GmtEnt * ent)147 void LD_LOADER_AddGMTEnt(MEM_GmtEnt* ent)
148 {
149   MEM_memTop=ent->modSpaceEnd;
150   MEM_memBot=(MemPtr)ent->codeSpaceBeg;
151 }
152 
153 /* Asking space of given number of WORDS from the system memory -- XQ */
LD_LOADER_ExtendModSpace(MEM_GmtEnt * ent,int size)154 WordPtr LD_LOADER_ExtendModSpace(MEM_GmtEnt* ent, int size)
155 {
156     WordPtr tmp = ent -> modSpaceEnd;
157     ent -> modSpaceEnd += size;
158     if(ent->modSpaceEnd > ent->codeSpaceBeg){
159         LD_error("Out of module space.\n");
160         EM_THROW(LD_LoadError);
161     }
162     return tmp;
163 }
164 
165 /* Asking space of given number of BYTES from the system memory -- XQ */
LD_LOADER_ExtendModSpaceInByte(MEM_GmtEnt * ent,int size)166 BytePtr LD_LOADER_ExtendModSpaceInByte(MEM_GmtEnt* ent, int size)
167 {
168     BytePtr tmp = (BytePtr) (ent -> modSpaceEnd);
169     ent -> modSpaceEnd = (WordPtr)(((BytePtr)ent->modSpaceEnd) + size);
170     if (ent -> modSpaceEnd >  ent->codeSpaceBeg){
171         LD_error("Out of module space.\n");
172         EM_THROW(LD_LoadError);
173     }
174     return tmp;
175 }
176 
177 
LD_LOADER_SetName(MEM_GmtEnt * ent,char * modname)178 int LD_LOADER_SetName(MEM_GmtEnt* ent,char* modname)
179 {
180   //char* namebuf=(char*)LD_LOADER_ExtendModSpace(ent,strlen(modname)+1);--XQ
181   char* namebuf=(char*)LD_LOADER_ExtendModSpaceInByte(ent,strlen(modname)+1);
182   strcpy(namebuf,modname);
183   ent->modname=namebuf;
184   return 0;
185 }
186