Source code of Windows XP (NT5)
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.

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