1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
9 #ifndef STRING_BUFFER_LEN
10 #define STRING_BUFFER_LEN 4096
13 #define OBJ_EXT ".obj"
14 #define OBJ_EXT_W W(".obj")
16 #define LIB_EXT ".lib"
17 #define LIB_EXT_W W(".lib")
20 extern IMetaDataDispenserEx *g_pDisp;
21 extern DWORD g_ValModuleType;
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)
28 IMAGE_FILE_HEADER *pImageHdr; // Header for the .obj file.
29 IMAGE_SECTION_HEADER *pSectionHdr; // Section header.
30 WORD i; // Loop control.
32 // Get a pointer to the header and the first section.
33 pImageHdr = (IMAGE_FILE_HEADER *) pImage;
34 pSectionHdr = (IMAGE_SECTION_HEADER *)(pImageHdr + 1);
40 // Walk each section looking for .cormeta.
41 for (i=0; i<VAL16(pImageHdr->NumberOfSections); i++, pSectionHdr++)
43 // Simple comparison to section name.
44 if (strcmp((const char *) pSectionHdr->Name, g_szCORMETA) == 0)
46 *pcbMetaData = VAL32(pSectionHdr->SizeOfRawData);
47 *ppMetaData = (void *) ((UINT_PTR)pImage + VAL32(pSectionHdr->PointerToRawData));
53 if (*ppMetaData == NULL || *pcbMetaData == 0)
59 // This function returns the address to the MapView of file and file size.
60 void GetMapViewOfFile(__in WCHAR *szFile, PBYTE *ppbMap, DWORD *pdwFileSize)
65 HANDLE hFile = WszCreateFile(szFile,
70 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
72 if (hFile == INVALID_HANDLE_VALUE)
73 MDInfo::Error("CreateFileA failed!");
75 *pdwFileSize = GetFileSize(hFile, &dwHighSize);
77 if ((*pdwFileSize == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
80 MDInfo::Error("GetFileSize failed!");
82 _ASSERTE(dwHighSize == 0);
84 hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
87 MDInfo::Error("CreateFileMappingW failed!");
89 *ppbMap = (PBYTE) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
90 CloseHandle(hMapFile);
93 MDInfo::Error("MapViewOfFile failed!");
94 } // void GetMapViewOfFile()
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)
100 PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
104 pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress;
106 // Get size of the member.
108 for (j = 0; j < 10; j++)
110 if (pMemHdr->Size[j] < '0' || pMemHdr->Size[j] > '9')
113 ulMemSize = ulMemSize * 10 + pMemHdr->Size[j] - '0';
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)
123 } // void SkipMember()
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])
130 if (pMemHdr->Name[0] == '/')
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.");
139 // Calculate the offset into the long names section.
140 for (int j = 1; j < 16; j++)
142 if (pMemHdr->Name[j] < '0' || pMemHdr->Name[j] > '9')
145 ulOffset = ulOffset * 10 + pMemHdr->Name[j] - '0';
147 return (char *)(pbLongNames + ulOffset);
152 for (j = 0; j < 16; j++)
153 if ((szBuf[j] = pMemHdr->Name[j]) == '/')
158 } // char *GetNameOfObj()
160 // DisplayArchive() function
162 // Opens the .LIB file, and displays the metadata in the specified object files.
164 void DisplayArchive(__in_z __in WCHAR* szFile, ULONG DumpFilter, __in_z __in_opt WCHAR* szObjName, strPassBackFn pDisplayString)
167 PBYTE pbStartAddress;
168 PBYTE pbLongNameAddress;
169 PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr;
180 GetMapViewOfFile(szFile, &pbMapAddress, &dwFileSize);
181 pbStartAddress = pbMapAddress;
183 // Verify and skip archive signature.
184 if (dwFileSize < IMAGE_ARCHIVE_START_SIZE ||
185 strncmp((char *)pbMapAddress, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE))
187 MDInfo::Error("Bad file format - archive signature mis-match!");
189 pbMapAddress += IMAGE_ARCHIVE_START_SIZE;
191 // Skip linker member 1, linker member 2.
192 for (i = 0; i < 2; i++)
193 pbMapAddress = SkipMember(pbMapAddress);
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] == '/')
199 pbLongNameAddress = pbMapAddress + IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR;
200 pbMapAddress = SkipMember(pbMapAddress);
203 pbLongNameAddress = 0;
205 pDisplayString ("\n");
206 // Get the MetaData for each object file and display it.
207 while (DWORD(pbMapAddress - pbStartAddress) < dwFileSize)
209 if((szName = GetNameOfObj(pbLongNameAddress, (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress, szBuf))!=NULL)
211 if (Wsz_mbstowcs(wzName, szName, 1024) == -1)
212 MDInfo::Error("Conversion from Multi-Byte to Wide-Char failed.");
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)))
219 // Try to find the MetaData section in the current object file.
220 hr = FindObjMetaData(pbMapAddress+IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR, &pvMetaData, &cbMetaData);
223 sprintf_s (szString,1024,"MetaData for object file %s:\n", szName);
224 pDisplayString(szString);
225 MDInfo archiveInfo(g_pDisp,
230 archiveInfo.DisplayMD();
234 sprintf_s(szString,1024,"MetaData not found for object file %s!\n\n", szName);
235 pDisplayString(szString);
240 // Skip past the object file.
241 pbMapAddress = SkipMember(pbMapAddress);
244 UnmapViewOfFile(pbStartAddress);
245 } // void DisplayArchive()
247 // DisplayFile() function
249 // Opens the meta data content of a .EXE, .CLB, .CLASS, .TLB, .DLL or .LIB file, and
250 // calls RawDisplay()
252 void DisplayFile(__in_z __in WCHAR* szFile, BOOL isFile, ULONG DumpFilter, __in_z __in_opt WCHAR* szObjName, strPassBackFn pDisplayString)
254 // Open the emit scope
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)
267 wcscpy_s(szScope, 1024, W("file:"));
268 wcscat_s(szScope, 1024, szFile);
271 wcscpy_s(szScope, 1024, szFile);
273 // print bar that separates different files
274 pDisplayString("////////////////////////////////////////////////////////////////\n");
275 WCHAR rcFname[_MAX_FNAME], rcExt[_MAX_EXT];
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);
281 if (DumpFilter & MDInfo::dumpValidate)
283 if (!_wcsicmp(rcExt, OBJ_EXT_W) || !_wcsicmp(rcExt, LIB_EXT_W))
284 g_ValModuleType = ValidatorModuleTypeObj;
286 g_ValModuleType = ValidatorModuleTypePE;
289 if (!_wcsicmp(rcExt, LIB_EXT_W))
290 DisplayArchive(szFile, DumpFilter, szObjName, pDisplayString);
293 MDInfo metaDataInfo(g_pDisp, szScope, pDisplayString, DumpFilter);
294 metaDataInfo.DisplayMD();
296 } // void DisplayFile()