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.

284 lines
8.1 KiB

  1. /*
  2. Copyright 1999 Microsoft Corporation
  3. Neptune data collection server
  4. Walter Smith (wsmith)
  5. Matches Symbols with The Corresponding Binary
  6. */
  7. #include <windows.h>
  8. #include <dbghelp.h>
  9. #include <symres.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <shlwapi.h>
  13. #include <sys\stat.h>
  14. #include <string.h>
  15. #undef UNICODE
  16. #include <strsafe.h>
  17. #ifndef DIMA
  18. #define DIMAT(Array, EltType) (sizeof(Array) / sizeof(EltType))
  19. #define DIMA(Array) DIMAT(Array, (Array)[0])
  20. #endif
  21. void
  22. UndecorateSymbol(
  23. LPTSTR szSymbol // [in] [out] function name undecorated in place
  24. )
  25. {
  26. char szTemp[MAX_PATH];
  27. PIMAGEHLP_SYMBOL pihsym;
  28. DWORD dwSize;
  29. dwSize = sizeof(IMAGEHLP_SYMBOL)+MAX_PATH;
  30. pihsym = (IMAGEHLP_SYMBOL *) malloc(dwSize);
  31. pihsym->SizeOfStruct = dwSize;
  32. pihsym->Address = 0;
  33. pihsym->Flags = 0;
  34. pihsym->MaxNameLength = MAX_PATH;
  35. wcstombs(pihsym->Name,szSymbol, lstrlen(szSymbol));
  36. SymUnDName(pihsym,szTemp,MAX_PATH);
  37. mbstowcs(szSymbol,szTemp, strlen(szTemp));
  38. }
  39. // select file from list of open files, or open and add to list
  40. // maintain files in usage order, least recently used at end of list
  41. OPENFILE* // pointer to open file info
  42. SymbolResolver::GetFile(
  43. LPWSTR szwModule // [in] name of file
  44. )
  45. {
  46. OPENFILE* pFile = NULL;
  47. MAPDEF map;
  48. DWORD dwCread;
  49. WCHAR wszBuffer[MAX_PATH];
  50. StringCchCopyW(wszBuffer, DIMA(wszBuffer), szwModule);
  51. PathRemoveExtension(wszBuffer);
  52. PathAddExtension(wszBuffer, L".sym");
  53. pFile = new OPENFILE;
  54. // open SYM file
  55. pFile->hfFile = CreateFileW(wszBuffer,
  56. GENERIC_READ,
  57. FILE_SHARE_READ,
  58. NULL,
  59. OPEN_EXISTING,
  60. FILE_ATTRIBUTE_NORMAL,
  61. NULL);
  62. if (pFile->hfFile == INVALID_HANDLE_VALUE) return NULL;
  63. // copy filename and version into pFile node
  64. StringCchCopyW(pFile->szwName, DIMA(pFile->szwName), szwModule);
  65. // read map definition
  66. ReadFile(pFile->hfFile, &map, sizeof(MAPDEF)-1, &dwCread, NULL);
  67. if (dwCread != sizeof(MAPDEF)-1)
  68. {
  69. if (pFile->hfFile)
  70. CloseHandle(pFile->hfFile);
  71. if (pFile)
  72. delete pFile;
  73. throw E_FAIL;
  74. }
  75. pFile->ulFirstSeg = map.md_spseg*16;
  76. pFile->nSeg = map.md_cseg;
  77. pFile->psCurSymDefPtrs = NULL;
  78. return pFile;
  79. }
  80. // parse sym file to resolve address
  81. // read segment defintion for dwSection
  82. ULONG // return offset of segment definition, 0 if failed
  83. SymbolResolver::GetSegDef(OPENFILE* pFile, // [in] pointer to open file info
  84. DWORD dwSection, // [in] section number
  85. SEGDEF* pSeg) // [out] pointer to segment definition
  86. {
  87. ULONG ulCurSeg = pFile->ulFirstSeg;
  88. int iSectionIndex = 0;
  89. DWORD dwCread;
  90. // step through segments
  91. while (iSectionIndex < pFile->nSeg)
  92. {
  93. // go to segment beginning
  94. if (SetFilePointer(pFile->hfFile, ulCurSeg, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  95. {
  96. ulCurSeg = 0;
  97. break;
  98. }
  99. // read seg defn
  100. if (!ReadFile(pFile->hfFile, pSeg, sizeof(SEGDEF)-1, &dwCread, NULL))
  101. {
  102. ulCurSeg = 0;
  103. break;
  104. }
  105. iSectionIndex++;
  106. if (iSectionIndex == (int)dwSection) // gotcha
  107. {
  108. break;
  109. }
  110. // go to next segment definition
  111. ulCurSeg = pSeg->gd_spsegnext*16;
  112. }
  113. // found our section and it's non-empty?
  114. if (iSectionIndex != (int)dwSection || !pSeg->gd_csym) // no
  115. {
  116. ulCurSeg = 0;
  117. }
  118. return ulCurSeg;
  119. }
  120. // parse sym file to resolve address
  121. bool
  122. SymbolResolver::GetNameFromAddr(
  123. LPWSTR szwModule, // [in] name of symbol file
  124. DWORD dwSection, // [in] section part of address to resolve
  125. DWORD dwOffsetToRva, // [in] Section base
  126. UINT_PTR uRva, // [in] offset part of address to resolve
  127. LPWSTR wszFuncName // [out] resolved function name,
  128. )
  129. {
  130. SEGDEF seg;
  131. DWORD dwSymAddr;
  132. TCHAR sztFuncName[MAX_NAME+1];
  133. int i;
  134. int nNameLen;
  135. DWORD dwCread;
  136. int nToRead;
  137. unsigned char cName;
  138. ULONG ulCurSeg;
  139. ULONG ulSymNameOffset = 0;
  140. HANDLE hfFile;
  141. OPENFILE* pFile = NULL;
  142. DWORD dwArrayOffset;
  143. DWORD dwSymOffset;
  144. bool fResult = false;
  145. // get file from open list, or open file
  146. pFile = GetFile(szwModule);
  147. if (!pFile)
  148. return false;
  149. if ((ulCurSeg = GetSegDef(pFile, dwSection, &seg)) == 0)
  150. {
  151. goto Cleanup;
  152. }
  153. BYTE* pSymDefPtrs;
  154. // big symbols?
  155. if (seg.gd_type & MSF_BIGSYMDEF)
  156. {
  157. dwArrayOffset = seg.gd_psymoff * 16;
  158. pSymDefPtrs = (BYTE*)(new BYTE[seg.gd_csym*3]);
  159. }
  160. else
  161. {
  162. dwArrayOffset = seg.gd_psymoff;
  163. pSymDefPtrs = (BYTE*)(new BYTE[seg.gd_csym*2]);
  164. }
  165. hfFile = pFile->hfFile;
  166. SetFilePointer(hfFile, ulCurSeg + dwArrayOffset, NULL, FILE_BEGIN);
  167. // read symbol definition pointers array
  168. ReadFile(hfFile, pSymDefPtrs, seg.gd_csym * ((seg.gd_type & MSF_BIGSYMDEF)?3:2), &dwCread, NULL);
  169. pFile->psCurSymDefPtrs = pSymDefPtrs;
  170. // save this section
  171. pFile->dwCurSection = dwSection;
  172. // read symbols
  173. for (i = 0; i < seg.gd_csym; i++)
  174. {
  175. // go to offset of sym defintion
  176. if (seg.gd_type & MSF_BIGSYMDEF)
  177. {
  178. dwSymOffset = pFile->psCurSymDefPtrs[i*3+0]
  179. + pFile->psCurSymDefPtrs[i*3+1]*256
  180. + pFile->psCurSymDefPtrs[i*3+2]*65536;
  181. }
  182. else
  183. {
  184. dwSymOffset = pFile->psCurSymDefPtrs[i*2+0]
  185. + pFile->psCurSymDefPtrs[i*2+1]*256;
  186. }
  187. SetFilePointer(hfFile, ulCurSeg + dwSymOffset, NULL, FILE_BEGIN);
  188. // read symbol address DWORD
  189. ReadFile(hfFile,&dwSymAddr,sizeof(DWORD),&dwCread,NULL);
  190. // symbol address is 1 word or two?
  191. nToRead = sizeof(SHORT) + ((seg.gd_type & MSF_32BITSYMS) * sizeof(SHORT));
  192. // calculate offset of symbol name
  193. ulSymNameOffset = ulCurSeg + dwSymOffset + nToRead;
  194. // use just lower word of address if 16-bit symbol
  195. if (!(seg.gd_type & MSF_32BITSYMS))
  196. {
  197. dwSymAddr = dwSymAddr & 0x0000FFFF;
  198. }
  199. dwSymAddr += dwOffsetToRva;
  200. if (dwSymAddr > uRva ) break;
  201. if (dwSymAddr == uRva )
  202. {
  203. // do we have our function?
  204. // if current address is greater than offset, then since we are
  205. // traversing in the increasing order of addresses, the previous
  206. // symbol must be our quarry
  207. SetFilePointer(hfFile, ulSymNameOffset, NULL, FILE_BEGIN);
  208. // read length of name
  209. ReadFile(hfFile,&cName,sizeof(TCHAR),&dwCread,NULL);
  210. nNameLen = (int) cName;
  211. // read symbol name
  212. ReadFile(hfFile,sztFuncName,nNameLen,&dwCread,NULL);
  213. sztFuncName[nNameLen/2 - (nNameLen+1)%2] = TCHAR('\0');
  214. UndecorateSymbol(sztFuncName);
  215. StrCpyNW(wszFuncName, sztFuncName, MAX_NAME);
  216. fResult = true;
  217. }
  218. }
  219. Cleanup:
  220. if (pFile->hfFile)
  221. CloseHandle(pFile->hfFile);
  222. if (pFile->psCurSymDefPtrs)
  223. delete pFile->psCurSymDefPtrs;
  224. if (pFile)
  225. delete pFile;
  226. return fResult;
  227. }