3 * Portable Executable Loader
\r
9 #define DEBUG (ACESS_DEBUG|PE_DEBUG)
\r
11 //#define DLL_BASE_PATH "/Acess/Windows/"
\r
12 #define DLL_BASE_PATH NULL
\r
15 # define DEBUGS(v...) SysDebug(v)
\r
17 # define DEBUGS(v...)
\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
26 int PE_Relocate(void *Base, char *envp[], char *Filename)
\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
35 Uint iBase = (Uint)Base;
\r
38 DEBUGS("PE_Relocate: (Base=0x%x)\n", Base);
\r
40 peHeaders = Base + dosHdr->PeHdrOffs;
\r
42 directory = peHeaders->OptHeader.Directory;
\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
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
54 SysDebug("Unable to load required library '%s'\n", impDir[i].DLLName);
\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
62 if( importTab[j] & 0x80000000 )
\r
63 DEBUGS(" PE_Relocate: Import Ordinal %i\n", importTab[j] & 0x7FFFFFFF);
\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
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
83 DEBUGS("PE_Relocate: RETURN 0x%x\n", iBase + peHeaders->OptHeader.EntryPoint);
\r
85 return iBase + peHeaders->OptHeader.EntryPoint;
\r
89 * \fn int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)
\r
91 int PE_GetSymbol(Uint Base, char *Name, Uint *Ret)
\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
105 peHeaders = (void*)( Base + dosHdr->PeHdrOffs );
\r
106 directory = peHeaders->OptHeader.Directory;
\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
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
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
136 * \fn char *PE_int_GetTrueFile(char *file)
\r
137 * \brief Get the true file name
\r
139 char *PE_int_GetTrueFile(char *file)
\r
142 if(file[0] != ':') return file;
\r
145 for(i=1;file[i];i++)
\r
152 int PE_int_GetForwardSymbol(char *Fwd, Uint *Value)
\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
169 libname = PE_int_GetTrueFile(Fwd);
\r
171 DEBUGS(" PE_int_GetForwardSymbol: Get '%s' from '%s'\n", sym, libname);
\r
173 libbase = LoadLibrary(libname, DLL_BASE_PATH, NULL);
\r
174 ret = GetSymbolFromBase(libbase, sym, Value);
\r
176 SysDebug(" PE_int_GetForwardSymbol: Unable to find '%s' in '%s'\n", sym, libname);
\r