PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/client_v4_2_comm/CLR/Tools/Parser/Support.cpp

#
C++ | 367 lines | 255 code | 84 blank | 28 comment | 48 complexity | 3cadd3264640c16515dd128df3af0098 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, MIT, MPL-2.0-no-copyleft-exception
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. _COM_SMRT_PTR(ISymUnmanagedMethod);
  6. ////////////////////////////////////////////////////////////////////////////////////////////////////
  7. // Following two functions lifted from NT sources, imagedir.c
  8. static PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection( IN PIMAGE_NT_HEADERS NtHeaders ,
  9. IN PVOID Base ,
  10. IN ULONG Rva )
  11. {
  12. PIMAGE_SECTION_HEADER NtSection;
  13. ULONG i;
  14. NtSection = IMAGE_FIRST_SECTION( NtHeaders );
  15. for(i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, NtSection++)
  16. {
  17. if(Rva >= NtSection->VirtualAddress && Rva < NtSection->VirtualAddress + NtSection->SizeOfRawData)
  18. {
  19. return NtSection;
  20. }
  21. }
  22. return NULL;
  23. }
  24. static PVOID Cor_RtlImageRvaToVa( IN PIMAGE_NT_HEADERS NtHeaders ,
  25. IN PVOID Base ,
  26. IN ULONG Rva ,
  27. IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL )
  28. {
  29. PIMAGE_SECTION_HEADER NtSection;
  30. if(!LastRvaSection ||
  31. (NtSection = *LastRvaSection) == NULL ||
  32. Rva < NtSection->VirtualAddress ||
  33. Rva >= NtSection->VirtualAddress + NtSection->SizeOfRawData )
  34. {
  35. NtSection = Cor_RtlImageRvaToSection( NtHeaders, Base, Rva );
  36. }
  37. if(NtSection != NULL)
  38. {
  39. if(LastRvaSection != NULL)
  40. {
  41. *LastRvaSection = NtSection;
  42. }
  43. return (PVOID)((PCHAR)Base + (Rva - NtSection->VirtualAddress) + NtSection->PointerToRawData);
  44. }
  45. else
  46. {
  47. return NULL;
  48. }
  49. }
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////
  51. PELoader::PELoader()
  52. {
  53. InitToZero();
  54. }
  55. PELoader::~PELoader()
  56. {
  57. Close();
  58. m_hMod = NULL;
  59. m_pNT = NULL;
  60. }
  61. PELoader::PELoader( const PELoader& pe )
  62. {
  63. InitToZero();
  64. }
  65. PELoader& PELoader::operator= ( const PELoader& pe )
  66. {
  67. InitToZero();
  68. return *this;
  69. }
  70. void PELoader::InitToZero()
  71. {
  72. m_hFile = INVALID_HANDLE_VALUE;
  73. m_hMod = NULL;
  74. m_hMapFile = NULL;
  75. m_pNT = NULL;
  76. }
  77. void PELoader::Close()
  78. {
  79. if(m_hFile != INVALID_HANDLE_VALUE)
  80. {
  81. if(m_hMod)
  82. {
  83. UnmapViewOfFile( (void*)m_hMod );
  84. m_hMod = NULL;
  85. }
  86. if(m_hMapFile)
  87. {
  88. CloseHandle( m_hMapFile );
  89. m_hMapFile = NULL;
  90. }
  91. CloseHandle( m_hFile );
  92. m_hFile = INVALID_HANDLE_VALUE;
  93. }
  94. }
  95. HRESULT PELoader::OpenAndMapToMemory( LPCWSTR moduleName )
  96. {
  97. TINYCLR_HEADER();
  98. if(!moduleName)
  99. {
  100. TINYCLR_SET_AND_LEAVE(E_INVALIDARG);
  101. }
  102. m_hFile = ::CreateFileW( moduleName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  103. if(m_hFile == INVALID_HANDLE_VALUE)
  104. {
  105. wprintf( L"Cannot open '%s'!\n", moduleName );
  106. TINYCLR_SET_AND_LEAVE(HRESULT_FROM_WIN32(::GetLastError()));
  107. }
  108. m_hMapFile = CreateFileMapping( m_hFile, NULL, PAGE_READONLY, 0, 0, NULL );
  109. if(m_hMapFile == NULL)
  110. {
  111. TINYCLR_SET_AND_LEAVE(HRESULT_FROM_WIN32(::GetLastError()));
  112. }
  113. m_hMod = (HMODULE)MapViewOfFile( m_hMapFile, FILE_MAP_READ, 0, 0, 0 );
  114. if(m_hMod == NULL)
  115. {
  116. TINYCLR_SET_AND_LEAVE(HRESULT_FROM_WIN32(::GetLastError()));
  117. }
  118. TINYCLR_NOCLEANUP();
  119. }
  120. HRESULT PELoader::OpenAndDecode( LPCWSTR moduleName )
  121. {
  122. TINYCLR_HEADER();
  123. TINYCLR_CHECK_HRESULT(OpenAndMapToMemory( moduleName ));
  124. TINYCLR_CHECK_HRESULT(Initialize());
  125. TINYCLR_NOCLEANUP();
  126. }
  127. HRESULT PELoader::Initialize()
  128. {
  129. TINYCLR_HEADER();
  130. IMAGE_DOS_HEADER* pdosHeader = (IMAGE_DOS_HEADER*)m_hMod; // get the dos header...
  131. if(pdosHeader->e_magic == IMAGE_DOS_SIGNATURE && 0 < pdosHeader->e_lfanew && pdosHeader->e_lfanew < 0xFF0) // has to start on first page
  132. {
  133. m_pNT = (IMAGE_NT_HEADERS*)(pdosHeader->e_lfanew + (DWORD_PTR)m_hMod);
  134. if((m_pNT->Signature != IMAGE_NT_SIGNATURE ) ||
  135. (m_pNT->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) )
  136. {
  137. // @TODO - add some SetLastError info? Not sure that in this case this could happen...But!
  138. // Make this appear uninitalized because for some reason this file is toast...
  139. // Not sure that this could ever happen because this file has already been loaded
  140. // bye the system loader unless someone gave us garbage as the hmod
  141. m_pNT = NULL;
  142. m_hMod = NULL;
  143. TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);
  144. }
  145. }
  146. else
  147. {
  148. m_hMod = NULL;
  149. TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);
  150. }
  151. TINYCLR_NOCLEANUP();
  152. }
  153. bool PELoader::GetCOMHeader( IMAGE_COR20_HEADER*& pCorHeader )
  154. {
  155. // Get the image header from the image, then get the directory location
  156. // of the COM+ header which may or may not be filled out.
  157. DWORD pCOMHeader = m_pNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress;
  158. PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)Cor_RtlImageRvaToVa( m_pNT, m_hMod, pCOMHeader, NULL );
  159. // If the section header exists, then return ok and the address.
  160. if(pSectionHeader)
  161. {
  162. pCorHeader = (IMAGE_COR20_HEADER*)pSectionHeader;
  163. return true;
  164. }
  165. // If there is no COM+ Data in this image, return false.
  166. else
  167. {
  168. pCorHeader = NULL;
  169. return false;
  170. }
  171. }
  172. bool PELoader::GetResource( DWORD dwOffset, BYTE*& pResource, DWORD& dwSize )
  173. {
  174. IMAGE_COR20_HEADER *pCorHeader;
  175. if(GetCOMHeader( pCorHeader ))
  176. {
  177. pResource = (BYTE *)Cor_RtlImageRvaToVa( m_pNT, m_hMod, pCorHeader->Resources.VirtualAddress, NULL );
  178. if(pResource && dwOffset < pCorHeader->Resources.Size)
  179. {
  180. pResource += dwOffset;
  181. memcpy( &dwSize, pResource, sizeof(dwSize) );
  182. pResource += sizeof(dwSize);
  183. return true;
  184. }
  185. }
  186. return false;
  187. }
  188. bool PELoader::GetVAforRVA( DWORD rva, void*& va )
  189. {
  190. PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)Cor_RtlImageRvaToVa( m_pNT, m_hMod, rva, NULL );
  191. // If the section header exists, then return ok and the address.
  192. if(pSectionHeader)
  193. {
  194. va = pSectionHeader;
  195. return true;
  196. }
  197. // If there is no COM+ Data in this image, return false.
  198. else
  199. {
  200. va = NULL;
  201. return false;
  202. }
  203. }
  204. // Main.cs(17,20):Command line warning CS0168: The variable 'foo' is declared but never used
  205. // -------------- ------------ ------- ------ ----------------------------------------------
  206. // Origin SubCategory Cat. Code Text
  207. /** (line)
  208. * (line-line)
  209. * (line,col)
  210. * (line,col-col)
  211. * (line,col,len)
  212. * (line,col,line,col)
  213. */
  214. void ErrorReporting::Print( LPCWSTR szOrigin, LPCWSTR szSubCategory, BOOL fError, int code, LPCWSTR szTextFormat, ... )
  215. {
  216. va_list arg;
  217. va_start( arg, szTextFormat );
  218. wprintf( L"%s: ", szOrigin ? szOrigin : L"MMP" );
  219. if(szSubCategory) wprintf( L"%s " , szSubCategory );
  220. /***************/ wprintf( L"%s MMP%04d: ", fError ? L"error" : L"warning", code );
  221. if(szTextFormat ) vwprintf( szTextFormat, arg );
  222. /***************/ wprintf( L"\n" );
  223. va_end( arg );
  224. }
  225. //VS#299537 will define this constant in corsym header files
  226. #define NO_SOURCE_AVAILABLE 0x00FeeFee
  227. HRESULT ErrorReporting::ConstructErrorOrigin( std::wstring &str, ISymUnmanagedReader* pSymReader, mdMethodDef md, ULONG32 ipOffset )
  228. {
  229. TINYCLR_HEADER();
  230. ISymUnmanagedMethodPtr pMethod = NULL;
  231. ULONG32 cSeqPoints = 0;
  232. ULONG32* pOffsets = NULL;
  233. ULONG32* pLines = NULL;
  234. ULONG32* pCols = NULL;
  235. ULONG32* pEndCols = NULL;
  236. ULONG32* pEndLines = NULL;
  237. ISymUnmanagedDocument** pDocs = NULL;
  238. WCHAR szName[512];
  239. WCHAR buf[512];
  240. if(!pSymReader) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);
  241. TINYCLR_CHECK_HRESULT(pSymReader->GetMethod( md, &pMethod ));
  242. TINYCLR_CHECK_HRESULT(pMethod->GetSequencePointCount( &cSeqPoints ));
  243. pOffsets = new ULONG32[cSeqPoints];
  244. pDocs = new ISymUnmanagedDocument*[cSeqPoints];
  245. pLines = new ULONG32[cSeqPoints];
  246. pCols = new ULONG32[cSeqPoints];
  247. pEndLines = new ULONG32[cSeqPoints];
  248. pEndCols = new ULONG32[cSeqPoints];
  249. TINYCLR_CHECK_HRESULT(pMethod->GetSequencePoints( cSeqPoints, &cSeqPoints, pOffsets, pDocs, pLines, pCols, pEndLines, pEndCols ));
  250. for(ULONG32 i = 0; i < cSeqPoints; i++)
  251. {
  252. if(i == cSeqPoints || ipOffset < pOffsets[i+1])
  253. {
  254. //We found the correct offset. Now find the closest line of code
  255. while(i > 0 && pLines[i] == NO_SOURCE_AVAILABLE) i--;
  256. while(i < cSeqPoints - 1 && pLines[i] == NO_SOURCE_AVAILABLE) i++;
  257. if(pLines[i] == NO_SOURCE_AVAILABLE) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);
  258. ISymUnmanagedDocument *pDoc = pDocs[i];
  259. TINYCLR_CHECK_HRESULT(pDoc->GetURL( ARRAYSIZE(szName), NULL, szName ));
  260. _snwprintf_s( buf, ARRAYSIZE(buf), L"%s(%d,%d,%d,%d)", szName, pLines[i], pCols[i], pEndLines[i], pEndCols[i] );
  261. str = buf;
  262. break;
  263. }
  264. }
  265. TINYCLR_CLEANUP();
  266. if(pDocs)
  267. {
  268. for(ULONG32 i = 0; i < cSeqPoints; i++)
  269. {
  270. if(pDocs[i])
  271. {
  272. pDocs[i]->Release();
  273. }
  274. }
  275. }
  276. delete[] pOffsets;
  277. delete[] pDocs;
  278. delete[] pLines;
  279. delete[] pCols;
  280. delete[] pEndLines;
  281. delete[] pEndCols;
  282. TINYCLR_CLEANUP_END();
  283. }