Delete unused multibyte methods from PAL (#42157)
[platform/upstream/dotnet/runtime.git] / src / coreclr / src / tools / metainfo / mdobj.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 #include <stdio.h>
5 #include <ctype.h>
6 #include <crtdbg.h>
7 #include "mdinfo.h"
8
9 #ifndef STRING_BUFFER_LEN
10 #define STRING_BUFFER_LEN 4096
11 #endif
12
13 #define OBJ_EXT         ".obj"
14 #define OBJ_EXT_W       W(".obj")
15 #define OBJ_EXT_LEN     4
16 #define LIB_EXT         ".lib"
17 #define LIB_EXT_W       W(".lib")
18 #define LIB_EXT_LEN     4
19
20 extern IMetaDataDispenserEx *g_pDisp;
21 extern DWORD g_ValModuleType;
22
23 // This function is copied from peparse.c file.  Making this static, so we won't end up with
24 // duplicate definitions causing confusion.
25 static const char g_szCORMETA[] = ".cormeta";
26 static HRESULT FindObjMetaData(PVOID pImage, PVOID *ppMetaData, long *pcbMetaData)
27 {
28     IMAGE_FILE_HEADER *pImageHdr;       // Header for the .obj file.
29     IMAGE_SECTION_HEADER *pSectionHdr;  // Section header.
30     WORD        i;                      // Loop control.
31
32     // Get a pointer to the header and the first section.
33     pImageHdr = (IMAGE_FILE_HEADER *) pImage;
34     pSectionHdr = (IMAGE_SECTION_HEADER *)(pImageHdr + 1);
35
36     // Avoid confusion.
37     *ppMetaData = NULL;
38     *pcbMetaData = 0;
39
40     // Walk each section looking for .cormeta.
41     for (i=0;  i<VAL16(pImageHdr->NumberOfSections);  i++, pSectionHdr++)
42     {
43         // Simple comparison to section name.
44         if (strcmp((const char *) pSectionHdr->Name, g_szCORMETA) == 0)
45         {
46             *pcbMetaData = VAL32(pSectionHdr->SizeOfRawData);
47             *ppMetaData = (void *) ((UINT_PTR)pImage + VAL32(pSectionHdr->PointerToRawData));
48             break;
49         }
50     }
51
52     // Check for errors.
53     if (*ppMetaData == NULL || *pcbMetaData == 0)
54         return (E_FAIL);
55     return (S_OK);
56 }
57
58
59 // This function returns the address to the MapView of file and file size.
60 void GetMapViewOfFile(__in WCHAR *szFile, PBYTE *ppbMap, DWORD *pdwFileSize)
61 {
62     HANDLE      hMapFile;
63     DWORD       dwHighSize;
64
65     HANDLE hFile = WszCreateFile(szFile,
66                                GENERIC_READ,
67                                FILE_SHARE_READ,
68                                NULL,
69                                OPEN_EXISTING,
70                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
71                                NULL);
72     if (hFile == INVALID_HANDLE_VALUE)
73         MDInfo::Error("CreateFileA failed!");
74
75     *pdwFileSize = GetFileSize(hFile, &dwHighSize);
76
77     if ((*pdwFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
78     {
79         CloseHandle(hFile);
80         MDInfo::Error("GetFileSize failed!");
81     }
82     _ASSERTE(dwHighSize == 0);
83
84     hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
85     CloseHandle(hFile);
86     if (!hMapFile)
87         MDInfo::Error("CreateFileMappingW failed!");
88
89     *ppbMap = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
90     CloseHandle(hMapFile);
91
92     if (!*ppbMap)
93         MDInfo::Error("MapViewOfFile failed!");
94 } // void GetMapViewOfFile()
95
96 // This function skips a member given the pointer to the member header
97 // and returns a pointer to the next header.
98 PBYTE SkipMember(PBYTE pbMapAddress)
99 {
100     PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
101     ULONG       ulMemSize;
102     int         j;
103
104     pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress;
105
106     // Get size of the member.
107     ulMemSize = 0;
108     for (j = 0; j < 10; j++)
109     {
110         if (pMemHdr->Size[j] < '0' || pMemHdr->Size[j] > '9')
111             break;
112         else
113             ulMemSize = ulMemSize * 10 + pMemHdr->Size[j] - '0';
114     }
115
116     // Skip past the header.
117     pbMapAddress += IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR + ulMemSize;
118     // Find the next even address if the current one is not even.
119     if ((ULONG_PTR)pbMapAddress % 2)
120         pbMapAddress++;
121
122     return pbMapAddress;
123 } // void SkipMember()
124
125 // This function returns the name of the given Obj.  If the name fits in the header,
126 // szBuf will be filled in and returned from the function.  Else an offset into the long
127 // names section will be returned.
128 char *GetNameOfObj(PBYTE pbLongNames, PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr, char szBuf[17])
129 {
130     if (pMemHdr->Name[0] == '/')
131     {
132         ULONG   ulOffset = 0;
133
134         // Long Names section must exist if the .obj file name starts with '/'.
135         _ASSERTE(pbLongNames &&
136             "Corrupt archive file - .obj file name in the header starts with "
137             "'/' but no long names section present in the archive file.");
138
139         // Calculate the offset into the long names section.
140         for (int j = 1; j < 16; j++)
141         {
142             if (pMemHdr->Name[j] < '0' || pMemHdr->Name[j] > '9')
143                 break;
144             else
145                 ulOffset = ulOffset * 10 + pMemHdr->Name[j] - '0';
146         }
147         return (char *)(pbLongNames + ulOffset);
148     }
149     else
150     {
151         int j;
152         for (j = 0; j < 16; j++)
153             if ((szBuf[j] = pMemHdr->Name[j]) == '/')
154                 break;
155         szBuf[j] = '\0';
156         return szBuf;
157     }
158 } // char *GetNameOfObj()
159
160 // DisplayArchive() function
161 //
162 // Opens the .LIB file, and displays the metadata in the specified object files.
163
164 void DisplayArchive(__in_z __in WCHAR* szFile, ULONG DumpFilter, __in_z __in_opt WCHAR* szObjName, strPassBackFn pDisplayString)
165 {
166     PBYTE       pbMapAddress;
167     PBYTE       pbStartAddress;
168     PBYTE       pbLongNameAddress;
169     PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
170     DWORD       dwFileSize;
171     PVOID       pvMetaData;
172     char        *szName;
173     WCHAR     wzName[1024];
174     char        szBuf[17];
175     long        cbMetaData;
176     int         i;
177     HRESULT     hr;
178         char            szString[1024];
179
180     GetMapViewOfFile(szFile, &pbMapAddress, &dwFileSize);
181     pbStartAddress = pbMapAddress;
182
183     // Verify and skip archive signature.
184     if (dwFileSize < IMAGE_ARCHIVE_START_SIZE ||
185         strncmp((char *)pbMapAddress, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE))
186     {
187         MDInfo::Error("Bad file format - archive signature mis-match!");
188     }
189     pbMapAddress += IMAGE_ARCHIVE_START_SIZE;
190
191     // Skip linker member 1, linker member 2.
192     for (i = 0; i < 2; i++)
193         pbMapAddress = SkipMember(pbMapAddress);
194
195     // Save address of the long name member and skip it if there exists one.
196     pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress;
197     if (pMemHdr->Name[0] == '/' && pMemHdr->Name[1] == '/')
198     {
199         pbLongNameAddress = pbMapAddress + IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR;
200         pbMapAddress = SkipMember(pbMapAddress);
201     }
202     else
203         pbLongNameAddress = 0;
204
205     pDisplayString ("\n");
206     // Get the MetaData for each object file and display it.
207     while (DWORD(pbMapAddress - pbStartAddress) < dwFileSize)
208     {
209         if((szName = GetNameOfObj(pbLongNameAddress, (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress, szBuf))!=NULL)
210         {
211             if (Wsz_mbstowcs(wzName, szName, 1024) == -1)
212                 MDInfo::Error("Conversion from Multi-Byte to Wide-Char failed.");
213
214             // Display metadata only for object files.
215             // If szObjName is specified, display metadata only for that one object file.
216             if (!_stricmp(&szName[strlen(szName) - OBJ_EXT_LEN], OBJ_EXT) &&
217                 (!szObjName || !_wcsicmp(szObjName, wzName)))
218             {
219                 // Try to find the MetaData section in the current object file.
220                 hr = FindObjMetaData(pbMapAddress+IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR, &pvMetaData, &cbMetaData);
221                 if (SUCCEEDED(hr))
222                 {
223                     sprintf_s (szString,1024,"MetaData for object file %s:\n", szName);
224                     pDisplayString(szString);
225                     MDInfo archiveInfo(g_pDisp,
226                                     (PBYTE)pvMetaData,
227                                     cbMetaData,
228                                     pDisplayString,
229                                     DumpFilter);
230                     archiveInfo.DisplayMD();
231                 }
232                 else
233                 {
234                     sprintf_s(szString,1024,"MetaData not found for object file %s!\n\n", szName);
235                     pDisplayString(szString);
236                 }
237             }
238         }
239
240         // Skip past the object file.
241         pbMapAddress = SkipMember(pbMapAddress);
242     }
243
244     UnmapViewOfFile(pbStartAddress);
245 } // void DisplayArchive()
246
247 // DisplayFile() function
248 //
249 // Opens the meta data content of a .EXE, .CLB, .CLASS, .TLB, .DLL or .LIB file, and
250 // calls RawDisplay()
251
252 void DisplayFile(__in_z __in WCHAR* szFile, BOOL isFile, ULONG DumpFilter, __in_z __in_opt WCHAR* szObjName, strPassBackFn pDisplayString)
253 {
254     // Open the emit scope
255
256     // We need to make sure this file isn't too long. Checking _MAX_PATH is probably safe, but since we have a much
257     // larger buffer, we might as well use it all.
258     if (wcslen(szFile) > 1000)
259         return;
260
261
262     WCHAR szScope[1024];
263         char szString[1024];
264
265     if (isFile)
266     {
267         wcscpy_s(szScope, 1024, W("file:"));
268         wcscat_s(szScope, 1024, szFile);
269     }
270     else
271         wcscpy_s(szScope, 1024, szFile);
272
273     // print bar that separates different files
274     pDisplayString("////////////////////////////////////////////////////////////////\n");
275     WCHAR rcFname[_MAX_FNAME], rcExt[_MAX_EXT];
276
277     _wsplitpath_s(szFile, NULL, 0, NULL, 0, rcFname, _MAX_FNAME, rcExt, _MAX_EXT);
278     sprintf_s(szString,1024,"\nFile %S%S: \n",rcFname, rcExt);
279     pDisplayString(szString);
280
281     if (DumpFilter & MDInfo::dumpValidate)
282     {
283         if (!_wcsicmp(rcExt, OBJ_EXT_W) || !_wcsicmp(rcExt, LIB_EXT_W))
284             g_ValModuleType = ValidatorModuleTypeObj;
285         else
286             g_ValModuleType = ValidatorModuleTypePE;
287     }
288
289     if (!_wcsicmp(rcExt, LIB_EXT_W))
290         DisplayArchive(szFile, DumpFilter, szObjName, pDisplayString);
291     else
292     {
293         MDInfo metaDataInfo(g_pDisp, szScope, pDisplayString, DumpFilter);
294         metaDataInfo.DisplayMD();
295     }
296 } // void DisplayFile()
297