ec3b6b840016a697fed89613bbebb7d538d94337
[tpg/acess2.git] / pe.c
1 /*\r
2  * Acess v1\r
3  * Portable Executable Loader\r
4  */\r
5 #include "common.h"\r
6 #include "pe.h"\r
7 \r
8 #define PE_DEBUG        0\r
9 #define DEBUG   (ACESS_DEBUG|PE_DEBUG)\r
10 \r
11 //#define DLL_BASE_PATH "/Acess/Windows/"\r
12 #define DLL_BASE_PATH   NULL\r
13 \r
14 #if DEBUG\r
15 # define DEBUGS(v...)   SysDebug(v)\r
16 #else\r
17 # define DEBUGS(v...)\r
18 #endif\r
19 \r
20 // === PROTOTYPES ===\r
21  int    PE_Relocate(void *Base, char **envp, char *Filename);\r
22 char    *PE_int_GetTrueFile(char *file);\r
23  int    PE_int_GetForwardSymbol(char *Fwd, Uint *Value);\r
24 \r
25 // === CODE ===\r
26 int PE_Relocate(void *Base, char *envp[], char *Filename)\r
27 {\r
28         tPE_DOS_HEADER          *dosHdr = Base;\r
29         tPE_IMAGE_HEADERS       *peHeaders;\r
30         tPE_DATA_DIR    *directory;\r
31         tPE_IMPORT_DIR  *impDir;\r
32         tPE_HINT_NAME   *name;\r
33         Uint32  *importTab, *aIAT;\r
34          int    i, j;\r
35         Uint    iBase = (Uint)Base;\r
36         Uint    iLibBase;\r
37         \r
38         DEBUGS("PE_Relocate: (Base=0x%x)\n", Base);\r
39         \r
40         peHeaders = Base + dosHdr->PeHdrOffs;\r
41         \r
42         directory = peHeaders->OptHeader.Directory;\r
43         \r
44         // === Load Import Tables\r
45         impDir = Base + directory[PE_DIR_IMPORT].RVA;\r
46         for( i = 0; impDir[i].DLLName != NULL; i++ )\r
47         {\r
48                 impDir[i].DLLName += iBase;\r
49                 impDir[i].ImportLookupTable += iBase/4;\r
50                 impDir[i].ImportAddressTable += iBase/4;\r
51                 DEBUGS(" PE_Relocate: DLL Required '%s'(0x%x)\n", impDir[i].DLLName, impDir[i].DLLName);\r
52                 iLibBase = LoadLibrary(PE_int_GetTrueFile(impDir[i].DLLName), DLL_BASE_PATH, envp);\r
53                 if(iLibBase == 0) {\r
54                         SysDebug("Unable to load required library '%s'\n", impDir[i].DLLName);\r
55                         return 0;\r
56                 }\r
57                 DEBUGS(" PE_Relocate: Loaded as 0x%x\n", iLibBase);\r
58                 importTab = impDir[i].ImportLookupTable;\r
59                 aIAT = impDir[i].ImportAddressTable;\r
60                 for( j = 0; importTab[j] != 0; j++ )\r
61                 {\r
62                         if( importTab[j] & 0x80000000 )\r
63                                 DEBUGS(" PE_Relocate: Import Ordinal %i\n", importTab[j] & 0x7FFFFFFF);\r
64                         else\r
65                         {\r
66                                 name = (void*)( iBase + importTab[j] );\r
67                                 DEBUGS(" PE_Relocate: Import Name '%s', Hint 0x%x\n", name->Name, name->Hint);\r
68                                 if( GetSymbolFromBase(iLibBase, name->Name, (Uint*)&aIAT[j]) == 0 ) {\r
69                                         SysDebug("Unable to find symbol '%s' in library '%s'\n", name->Name, impDir[i].DLLName);\r
70                                         return 0;\r
71                                 }\r
72                         }\r
73                 }\r
74         }\r
75         \r
76         #if DEBUG\r
77         for(i=0;i<PE_DIR_LAST;i++) {\r
78                 if(directory[i].RVA == 0)       continue;\r
79                 SysDebug("directory[%i] = {RVA=0x%x,Size=0x%x}\n", i, directory[i].RVA, directory[i].Size);\r
80         }\r
81         #endif\r
82         \r
83         DEBUGS("PE_Relocate: RETURN 0x%x\n", iBase + peHeaders->OptHeader.EntryPoint);\r
84         \r
85         return iBase + peHeaders->OptHeader.EntryPoint;\r
86 }\r
87 \r
88 /**\r
89  * \fn int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)\r
90  */\r
91 int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)\r
92 {\r
93         tPE_DOS_HEADER          *dosHdr = (void*)Base;\r
94         tPE_IMAGE_HEADERS       *peHeaders;\r
95         tPE_DATA_DIR    *directory;\r
96         tPE_EXPORT_DIR  *expDir;\r
97         Uint32  *nameTable, *addrTable;\r
98         Uint16  *ordTable;\r
99          int    i;\r
100          int    symbolCount;\r
101         char    *name;\r
102         Uint    retVal;\r
103         Uint    expLen;\r
104         \r
105         peHeaders = (void*)( Base + dosHdr->PeHdrOffs );\r
106         directory = peHeaders->OptHeader.Directory;\r
107         \r
108         expDir = (void*)( Base + directory[PE_DIR_EXPORT].RVA );\r
109         expLen = directory[PE_DIR_EXPORT].Size;\r
110         symbolCount = expDir->NumNamePointers;\r
111         nameTable = (void*)( Base + expDir->NamePointerRVA );\r
112         ordTable = (void*)( Base + expDir->OrdinalTableRVA );\r
113         addrTable = (void*)( Base + expDir->AddressRVA );\r
114         //DEBUGS(" PE_GetSymbol: %i Symbols\n", symbolCount);\r
115         for(i=0;i<symbolCount;i++)\r
116         {\r
117                 name = (char*)( Base + nameTable[i] );\r
118                 //DEBUGS(" PE_GetSymbol: '%s' = 0x%x\n", name, Base + addrTable[ ordTable[i] ]);\r
119                 if(strcmp(name, Name) == 0)\r
120                 {\r
121                         retVal = Base + addrTable[ ordTable[i] ];\r
122                         // Check for forwarding\r
123                         if((Uint)expDir < retVal && retVal < (Uint)expDir + expLen) {\r
124                                 char *fwd = (char*)retVal;\r
125                                 DEBUGS(" PE_GetSymbol: '%s' forwards to '%s'\n", name, fwd);\r
126                                 return PE_int_GetForwardSymbol(fwd, Ret);\r
127                         }\r
128                         *Ret = retVal;\r
129                         return 1;\r
130                 }\r
131         }\r
132         return 0;\r
133 }\r
134 \r
135 /**\r
136  * \fn char *PE_int_GetTrueFile(char *file)\r
137  * \brief Get the true file name\r
138  */\r
139 char *PE_int_GetTrueFile(char *file)\r
140 {\r
141          int    i;\r
142         if(file[0] != ':')      return file;\r
143 \r
144         // Translate name\r
145         for(i=1;file[i];i++)\r
146                 if(file[i] == '_')\r
147                         file[i] = '.';\r
148         \r
149         return &file[1];\r
150 }\r
151 \r
152 int PE_int_GetForwardSymbol(char *Fwd, Uint *Value)\r
153 {\r
154         char    *libname;\r
155         char    *sym;\r
156          int    i;\r
157         Uint    libbase;\r
158          int    ret;\r
159         \r
160         // -- Find seperator\r
161         // PE spec says that there sould only be one, but the string may\r
162         // be mutilated in the loader\r
163         for(i=0;Fwd[i]!='\0';i++);\r
164         for(;i&&Fwd[i]!='.';i--);\r
165         \r
166         Fwd[i] = '\0';\r
167         sym = &Fwd[i+1];\r
168         \r
169         libname = PE_int_GetTrueFile(Fwd);\r
170         \r
171         DEBUGS(" PE_int_GetForwardSymbol: Get '%s' from '%s'\n", sym, libname);\r
172         \r
173         libbase = LoadLibrary(libname, DLL_BASE_PATH, NULL);\r
174         ret = GetSymbolFromBase(libbase, sym, Value);\r
175         if(!ret) {\r
176                 SysDebug(" PE_int_GetForwardSymbol: Unable to find '%s' in '%s'\n", sym, libname);\r
177         }\r
178         Fwd[i] = '.';\r
179         return ret;\r
180 }\r

UCC git Repository :: git.ucc.asn.au