1 /**
2  * This file has no copyright assigned and is placed in the Public Domain.
3  * This file is part of the mingw-w64 runtime package.
4  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5  */
6 
7 #include <windows.h>
8 #include <string.h>
9 
10 #if defined (_WIN64) && defined (__ia64__)
11 #error FIXME: Unsupported __ImageBase implementation.
12 #else
13 #ifdef __GNUC__
14 /* Hack, for bug in ld.  Will be removed soon.  */
15 #define __ImageBase __MINGW_LSYMBOL(_image_base__)
16 #endif
17 /* This symbol is defined by the linker.  */
18 extern IMAGE_DOS_HEADER __ImageBase;
19 #endif
20 
21 WINBOOL _ValidateImageBase (PBYTE);
22 
23 WINBOOL
_ValidateImageBase(PBYTE pImageBase)24 _ValidateImageBase (PBYTE pImageBase)
25 {
26   PIMAGE_DOS_HEADER pDOSHeader;
27   PIMAGE_NT_HEADERS pNTHeader;
28   PIMAGE_OPTIONAL_HEADER pOptHeader;
29 
30   pDOSHeader = (PIMAGE_DOS_HEADER) pImageBase;
31   if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
32     return FALSE;
33   pNTHeader = (PIMAGE_NT_HEADERS) ((PBYTE) pDOSHeader + pDOSHeader->e_lfanew);
34   if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
35     return FALSE;
36   pOptHeader = (PIMAGE_OPTIONAL_HEADER) &pNTHeader->OptionalHeader;
37   if (pOptHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
38     return FALSE;
39   return TRUE;
40 }
41 
42 PIMAGE_SECTION_HEADER _FindPESection (PBYTE, DWORD_PTR);
43 
44 PIMAGE_SECTION_HEADER
_FindPESection(PBYTE pImageBase,DWORD_PTR rva)45 _FindPESection (PBYTE pImageBase, DWORD_PTR rva)
46 {
47   PIMAGE_NT_HEADERS pNTHeader;
48   PIMAGE_SECTION_HEADER pSection;
49   unsigned int iSection;
50 
51   pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
52 
53   for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
54     iSection < pNTHeader->FileHeader.NumberOfSections;
55     ++iSection,++pSection)
56     {
57       if (rva >= pSection->VirtualAddress
58 	  && rva < pSection->VirtualAddress + pSection->Misc.VirtualSize)
59 	return pSection;
60     }
61   return NULL;
62 }
63 
64 PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
65 
66 PIMAGE_SECTION_HEADER
_FindPESectionByName(const char * pName)67 _FindPESectionByName (const char *pName)
68 {
69   PBYTE pImageBase;
70   PIMAGE_NT_HEADERS pNTHeader;
71   PIMAGE_SECTION_HEADER pSection;
72   unsigned int iSection;
73 
74   /* Long names aren't supported.  */
75   if (strlen (pName) > IMAGE_SIZEOF_SHORT_NAME)
76     return NULL;
77 
78   pImageBase = (PBYTE) &__ImageBase;
79   if (! _ValidateImageBase (pImageBase))
80     return NULL;
81 
82   pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
83 
84   for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
85     iSection < pNTHeader->FileHeader.NumberOfSections;
86     ++iSection,++pSection)
87     {
88       if (!strncmp ((char *) &pSection->Name[0], pName, IMAGE_SIZEOF_SHORT_NAME))
89 	return pSection;
90     }
91   return NULL;
92 }
93 
94 int __mingw_GetSectionCount (void);
95 PIMAGE_SECTION_HEADER __mingw_GetSectionForAddress (LPVOID p);
96 
97 PIMAGE_SECTION_HEADER
__mingw_GetSectionForAddress(LPVOID p)98 __mingw_GetSectionForAddress (LPVOID p)
99 {
100   PBYTE pImageBase;
101   DWORD_PTR rva;
102 
103   pImageBase = (PBYTE) &__ImageBase;
104   if (! _ValidateImageBase (pImageBase))
105     return NULL;
106 
107   rva = (DWORD_PTR) (((PBYTE) p) - pImageBase);
108   return _FindPESection (pImageBase, rva);
109 }
110 
111 int
__mingw_GetSectionCount(void)112 __mingw_GetSectionCount (void)
113 {
114   PBYTE pImageBase;
115   PIMAGE_NT_HEADERS pNTHeader;
116 
117   pImageBase = (PBYTE) &__ImageBase;
118   if (! _ValidateImageBase (pImageBase))
119     return 0;
120 
121   pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
122 
123   return (int) pNTHeader->FileHeader.NumberOfSections;
124 }
125 
126 
127 PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
128 
129 PIMAGE_SECTION_HEADER
_FindPESectionExec(size_t eNo)130 _FindPESectionExec (size_t eNo)
131 {
132   PBYTE pImageBase;
133   PIMAGE_NT_HEADERS pNTHeader;
134   PIMAGE_SECTION_HEADER pSection;
135   unsigned int iSection;
136 
137   pImageBase = (PBYTE) &__ImageBase;
138   if (! _ValidateImageBase (pImageBase))
139     return NULL;
140 
141   pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
142 
143   for (iSection = 0, pSection = IMAGE_FIRST_SECTION (pNTHeader);
144     iSection < pNTHeader->FileHeader.NumberOfSections;
145     ++iSection,++pSection)
146     {
147       if ((pSection->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0)
148       {
149 	if (!eNo)
150 	  return pSection;
151 	--eNo;
152       }
153     }
154   return NULL;
155 }
156 
157 PBYTE _GetPEImageBase (void);
158 
159 PBYTE
_GetPEImageBase(void)160 _GetPEImageBase (void)
161 {
162   PBYTE pImageBase;
163   pImageBase = (PBYTE) &__ImageBase;
164   if (! _ValidateImageBase (pImageBase))
165     return NULL;
166   return pImageBase;
167 }
168 
169 WINBOOL _IsNonwritableInCurrentImage (PBYTE);
170 
171 WINBOOL
_IsNonwritableInCurrentImage(PBYTE pTarget)172 _IsNonwritableInCurrentImage (PBYTE pTarget)
173 {
174   PBYTE pImageBase;
175   DWORD_PTR rvaTarget;
176   PIMAGE_SECTION_HEADER pSection;
177 
178   pImageBase = (PBYTE) &__ImageBase;
179   if (! _ValidateImageBase (pImageBase))
180     return FALSE;
181   rvaTarget = pTarget - pImageBase;
182   pSection = _FindPESection (pImageBase, rvaTarget);
183   if (pSection == NULL)
184     return FALSE;
185   return (pSection->Characteristics & IMAGE_SCN_MEM_WRITE) == 0;
186 }
187 
188 const char *
189 __mingw_enum_import_library_names (int);
190 
191 const char *
__mingw_enum_import_library_names(int i)192 __mingw_enum_import_library_names (int i)
193 {
194   PBYTE pImageBase;
195   PIMAGE_NT_HEADERS pNTHeader;
196   PIMAGE_IMPORT_DESCRIPTOR importDesc;
197   PIMAGE_SECTION_HEADER pSection;
198   DWORD importsStartRVA;
199 
200   pImageBase = (PBYTE) &__ImageBase;
201   if (! _ValidateImageBase (pImageBase))
202     return NULL;
203 
204   pNTHeader = (PIMAGE_NT_HEADERS) (pImageBase + ((PIMAGE_DOS_HEADER) pImageBase)->e_lfanew);
205 
206   importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
207   if (!importsStartRVA)
208     return NULL;
209 
210   pSection = _FindPESection (pImageBase, importsStartRVA);
211   if (!pSection)
212       return NULL;
213 
214   importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (pImageBase + importsStartRVA);
215   if (!importDesc)
216     return NULL;
217 
218   for (;;)
219     {
220       if (importDesc->TimeDateStamp == 0 && importDesc->Name == 0)
221         break;
222 
223       if (i <= 0)
224        return (char *) (pImageBase + importDesc->Name);
225       --i;
226       importDesc++;
227     }
228 
229   return NULL;
230 }
231