Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
7.3 KiB

  1. // Adapted from Minidbg.c
  2. // Original Authors : Matthew Hendel (math) and Matt Ruhlen (mruhlen)
  3. // Copyright (c) 1999 Microsoft Corporation
  4. //
  5. // Changed by (smahesh)
  6. // The MdpExc Program which resolves sym files has been adapted to match sym files with
  7. // the corresponding binary images. This is done by comparing the RVA's of the exported
  8. // functions in the binary image with the RVA's of their symbols in the sym file.
  9. #include <windows.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <sys\stat.h>
  13. #include <string.h>
  14. #include <shlwapi.h>
  15. #include "symres.h"
  16. #include <dbghelp.h>
  17. #define MAX_PATH 260
  18. #define MAXSYMNAME 512
  19. // parameter is used to typecast the result to the appropriate pointer type.
  20. #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (addValue) )
  21. typedef DWORD ULONG_PTR;
  22. PVOID
  23. OpenMapping(
  24. IN PCWSTR FilePath
  25. )
  26. {
  27. HANDLE hFile;
  28. HANDLE hMappedFile;
  29. PVOID MappedFile;
  30. hFile = CreateFileW(
  31. FilePath,
  32. GENERIC_READ,
  33. FILE_SHARE_READ | FILE_SHARE_WRITE,
  34. NULL,
  35. OPEN_EXISTING,
  36. 0,
  37. NULL
  38. );
  39. if (hFile == INVALID_HANDLE_VALUE) {
  40. return NULL;
  41. }
  42. hMappedFile = CreateFileMapping(
  43. hFile,
  44. NULL,
  45. PAGE_READONLY,
  46. 0,
  47. 0,
  48. NULL
  49. );
  50. if (!hMappedFile) {
  51. CloseHandle (hFile);
  52. return FALSE;
  53. }
  54. MappedFile = MapViewOfFile (
  55. hMappedFile,
  56. FILE_MAP_READ,
  57. 0,
  58. 0,
  59. 0
  60. );
  61. CloseHandle (hMappedFile);
  62. CloseHandle (hFile);
  63. return MappedFile;
  64. }
  65. PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader)
  66. {
  67. PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  68. unsigned i;
  69. for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ ) {
  70. // Is the RVA within this section?
  71. if ( (rva >= section->VirtualAddress) &&
  72. (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
  73. return section;
  74. }
  75. return 0;
  76. }
  77. // Compares the RVA's of the Exported Methods in the Binary with the RVA's of the corresponding
  78. // Symbols in the Sym file.
  79. bool CheckSymFile(LPWSTR wszDllFileName, LPWSTR wszSymFileName)
  80. {
  81. PVOID Mapping;
  82. PIMAGE_DOS_HEADER dosHeader;
  83. PIMAGE_EXPORT_DIRECTORY exportDir;
  84. PIMAGE_SECTION_HEADER header;
  85. PIMAGE_NT_HEADERS pNTHeader;
  86. INT delta;
  87. LPSTR filename;
  88. DWORD base;
  89. DWORD i;
  90. PDWORD functions;
  91. PWORD ordinals;
  92. LPSTR *name;
  93. DWORD exportsStartRVA, exportsEndRVA;
  94. bool fResult = true;
  95. Mapping = OpenMapping(wszDllFileName);
  96. dosHeader = (PIMAGE_DOS_HEADER)Mapping;
  97. if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
  98. return false;
  99. }
  100. base = (DWORD) dosHeader;
  101. pNTHeader = MakePtr(PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew );
  102. exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  103. exportsEndRVA = exportsStartRVA + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
  104. // Get the IMAGE_SECTION_HEADER that contains the exports. This is
  105. // usually the .edata section, but doesn't have to be.
  106. header = GetEnclosingSectionHeader(exportsStartRVA, pNTHeader);
  107. if ( !header ) {
  108. printf("No Exports Table Found:");
  109. return false;
  110. }
  111. delta = (INT)(header->VirtualAddress - header->PointerToRawData);
  112. exportDir = MakePtr(PIMAGE_EXPORT_DIRECTORY, base, exportsStartRVA - delta);
  113. filename = (PSTR)(exportDir->Name - delta + base);
  114. functions = (PDWORD)((DWORD)exportDir->AddressOfFunctions - delta + base);
  115. ordinals = (PWORD)((DWORD)exportDir->AddressOfNameOrdinals - delta + base);
  116. name = (PSTR *)((DWORD)exportDir->AddressOfNames - delta + base);
  117. PIMAGE_SECTION_HEADER pSecHeader;
  118. for (i=0; i < exportDir->NumberOfFunctions; i++) {
  119. DWORD entryPointRVA = functions[i];
  120. DWORD j;
  121. if ( entryPointRVA == 0 ) // Skip over gaps in exported function
  122. continue; // ordinals (the entrypoint is 0 for
  123. // these functions).
  124. pSecHeader = ImageRvaToSection(pNTHeader, Mapping, entryPointRVA);
  125. // See if this function has an associated name exported for it.
  126. for ( j=0; j < exportDir->NumberOfNames; j++ ) {
  127. if ( ordinals[j] == i ) {
  128. SymbolResolver sr;
  129. WCHAR wszFunctionName[MAX_NAME];
  130. wszFunctionName[0] = L'\0';
  131. if (sr.GetNameFromAddr(wszSymFileName, 1, pSecHeader->VirtualAddress, entryPointRVA, wszFunctionName))
  132. ;
  133. else if (sr.GetNameFromAddr(wszSymFileName, 2, pSecHeader->VirtualAddress, entryPointRVA, wszFunctionName))
  134. ;
  135. else {
  136. printf("\nNot Found %s %S", (char *)(name[j] - delta + base), wszFunctionName );
  137. fResult = false;
  138. }
  139. }
  140. }
  141. // Is it a forwarder? If so, the entry point RVA is inside the
  142. // .edata section, and is an RVA to the DllName.EntryPointName
  143. if ((entryPointRVA >= exportsStartRVA) &&
  144. (entryPointRVA <= exportsEndRVA)) {
  145. SymbolResolver sr;
  146. WCHAR wszFunctionName[MAX_NAME];
  147. wszFunctionName[0] = L'\0';
  148. if (sr.GetNameFromAddr(wszSymFileName, 1, pSecHeader->VirtualAddress, entryPointRVA, wszFunctionName))
  149. ;
  150. else if (sr.GetNameFromAddr(wszSymFileName, 2, pSecHeader->VirtualAddress, entryPointRVA, wszFunctionName))
  151. ;
  152. else {
  153. printf("Not Found %s %S", (char *)(entryPointRVA - delta + base), wszFunctionName );
  154. fResult = false;
  155. }
  156. }
  157. }
  158. return fResult;
  159. }
  160. void __cdecl wmain(int argc,WCHAR ** argv)
  161. {
  162. WCHAR wszDllFileName[MAX_PATH] = L"";
  163. WCHAR wszSymFileName[MAX_PATH] = L"";
  164. bool fVerbose = false;
  165. int nCount = 0;
  166. __try {
  167. if (argc < 2 || argc > 4) {
  168. printf("\nUsage: Symchk [-v] [Binary] [Sym File]");
  169. printf("\n[v] Verbose");
  170. return;
  171. }
  172. nCount++;
  173. if (argv[nCount][0] == L'-' && argc > 3) {
  174. fVerbose = true;
  175. nCount++;
  176. }
  177. StrCpyNW(wszDllFileName, argv[nCount], MAX_NAME);
  178. nCount++;
  179. StrCpyNW(wszSymFileName, argv[nCount], MAX_NAME);
  180. if (CheckSymFile(wszDllFileName, wszSymFileName))
  181. printf("\n Result: Sym File Matched");
  182. }
  183. __except(1) {
  184. // do nothing, just don't pass it to the user.
  185. }
  186. return;
  187. }