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

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