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.

528 lines
14 KiB

  1. /*++
  2. Copyright 1996 - 1997 Microsoft Corporation
  3. Module Name:
  4. symtocv.c
  5. Abstract:
  6. This module handles the conversion activities requires for converting
  7. C7/C8 SYM files to CODEVIEW debug data.
  8. Author:
  9. Wesley A. Witt (wesw) 13-April-1993
  10. Modified: Sivarudrappa Mahesh (smahesh) 08-September-2000
  11. Environment:
  12. Win32, User Mode
  13. --*/
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "cv.h"
  19. #define _SYMCVT_SOURCE_
  20. #include "symcvt.h"
  21. #include "cvcommon.h"
  22. typedef struct tagSYMNAME {
  23. BYTE length;
  24. char name[1];
  25. } SYMNAME, *PSYMNAME;
  26. typedef struct tagSYMSYMBOL {
  27. DWORD offset;
  28. SYMNAME symName;
  29. } SYMSYMBOL, *PSYMSYMBOL;
  30. typedef struct tagSYMFILEHEADER {
  31. DWORD fileSize;
  32. WORD reserved1;
  33. WORD numSyms;
  34. DWORD reserved2;
  35. WORD nextOffset;
  36. BYTE reserved3;
  37. SYMNAME symName;
  38. } SYMFILEHEADER, *PSYMFILEHEADER;
  39. typedef struct tagSYMHEADER {
  40. WORD nextOffset;
  41. WORD numSyms;
  42. WORD symOffsetsOffset;
  43. WORD segment;
  44. BYTE reserved2[6];
  45. BYTE type;
  46. BYTE reserved3[5];
  47. SYMNAME symName;
  48. } SYMHEADER, *PSYMHEADER;
  49. #define SIZEOFSYMFILEHEADER 16
  50. #define SIZEOFSYMHEADER 21
  51. #define SIZEOFSYMBOL 3
  52. #define SYM_SEGMENT_NAME 0
  53. #define SYM_SYMBOL_NAME 1
  54. #define SYM_SEGMENT_ABS 2
  55. #define SYM_SYMBOL_ABS 3
  56. typedef struct tagENUMINFO {
  57. DATASYM32 *dataSym;
  58. DATASYM32 *dataSym2;
  59. DWORD numsyms;
  60. SGI *sgi;
  61. } ENUMINFO, *PENUMINFO;
  62. typedef BOOL (CALLBACK* SYMBOLENUMPROC)(PSYMNAME pSymName, int symType,
  63. SEGMENT segment, UOFF32 offset,
  64. PENUMINFO pEnumInfo);
  65. static VOID GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable,
  66. char * s );
  67. DWORD CreateModulesFromSyms( PPOINTERS p );
  68. DWORD CreatePublicsFromSyms( PPOINTERS p );
  69. DWORD CreateSegMapFromSyms( PPOINTERS p );
  70. static BOOL EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc,
  71. PENUMINFO pEnumInfo );
  72. int CSymSegs;
  73. BOOL CALLBACK
  74. SymbolCount(PSYMNAME pSymName, int symType, SEGMENT segment,
  75. UOFF32 offset, PENUMINFO pEnumInfo )
  76. {
  77. if ((symType == SYM_SEGMENT_NAME) && (segment > 0)) {
  78. CSymSegs += 1;
  79. }
  80. pEnumInfo->numsyms++;
  81. return TRUE;
  82. }
  83. BOOL
  84. ConvertSymToCv( PPOINTERS p )
  85. /*++
  86. Routine Description:
  87. This is the control function for the conversion of COFF to CODEVIEW
  88. debug data. It calls individual functions for the conversion of
  89. specific types of debug data.
  90. Arguments:
  91. p - pointer to a POINTERS structure (see symcvt.h)
  92. Return Value:
  93. TRUE - conversion succeded
  94. FALSE - conversion failed
  95. --*/
  96. {
  97. ENUMINFO enumInfo;
  98. DWORD dwSize;
  99. CSymSegs = 0;
  100. enumInfo.numsyms = 0;
  101. EnumSymbols( p, SymbolCount, &enumInfo );
  102. dwSize = (enumInfo.numsyms * (sizeof(DATASYM32) + 10)) + 512000;
  103. p->pCvCurr = p->pCvStart.ptr = malloc(dwSize);
  104. if (p->pCvStart.ptr == NULL) {
  105. return FALSE;
  106. }
  107. memset( p->pCvStart.ptr, 0, dwSize );
  108. try {
  109. CreateSignature( p );
  110. CreatePublicsFromSyms( p );
  111. CreateSymbolHashTable( p );
  112. CreateAddressSortTable( p );
  113. CreateSegMapFromSyms( p );
  114. CreateModulesFromSyms( p );
  115. CreateDirectories( p );
  116. p->pCvStart.ptr = realloc( p->pCvStart.ptr, p->pCvStart.size );
  117. return TRUE;
  118. } except (EXCEPTION_EXECUTE_HANDLER) {
  119. free( p->pCvStart.ptr );
  120. p->pCvStart.ptr = NULL;
  121. return FALSE;
  122. }
  123. }
  124. DWORD
  125. CreateModulesFromSyms( PPOINTERS p )
  126. /*++
  127. Routine Description:
  128. Creates the individual CV module records. There is one CV module
  129. record for each .FILE record in the COFF debug data. This is true
  130. even if the COFF size is zero.
  131. Arguments:
  132. p - pointer to a POINTERS structure (see symcvt.h)
  133. Return Value:
  134. The number of modules that were created.
  135. --*/
  136. {
  137. char szDrive [_MAX_DRIVE];
  138. char szDir [_MAX_DIR];
  139. char szFname [_MAX_FNAME];
  140. char szExt [_MAX_EXT];
  141. OMFModule *m;
  142. int i;
  143. char * pb;
  144. _splitpath( p->iptrs.szName, szDrive, szDir, szFname, szExt );
  145. m = (OMFModule *) p->pCvCurr;
  146. m->ovlNumber = 0;
  147. m->iLib = 0;
  148. m->cSeg = (unsigned short) CSymSegs;
  149. m->Style[0] = 'C';
  150. m->Style[1] = 'V';
  151. for (i=0; i<CSymSegs; i++) {
  152. m->SegInfo[i].Seg = i+1;
  153. m->SegInfo[i].pad = 0;
  154. m->SegInfo[i].Off = 0;
  155. m->SegInfo[i].cbSeg = 0xffff;
  156. }
  157. pb = (char *) &m->SegInfo[CSymSegs];
  158. sprintf( &pb[1], "%s.c", szFname );
  159. pb[0] = (char)strlen( &pb[1] );
  160. pb = (char *) NextMod(m);
  161. UpdatePtrs( p, &p->pCvModules, (LPVOID)pb, 1 );
  162. return 1;
  163. }
  164. BOOL CALLBACK
  165. ConvertASymtoPublic(PSYMNAME pSymName, int symType, SEGMENT segment,
  166. UOFF32 offset, PENUMINFO pEnumInfo )
  167. {
  168. if (symType != SYM_SYMBOL_NAME) {
  169. return TRUE;
  170. }
  171. pEnumInfo->dataSym->rectyp = S_PUB32;
  172. pEnumInfo->dataSym->seg = segment;
  173. pEnumInfo->dataSym->off = offset;
  174. pEnumInfo->dataSym->typind = 0;
  175. pEnumInfo->dataSym->name[0] = pSymName->length;
  176. strncpy( &pEnumInfo->dataSym->name[1], pSymName->name, pSymName->length );
  177. pEnumInfo->dataSym2 = NextSym32( pEnumInfo->dataSym );
  178. pEnumInfo->dataSym->reclen = (USHORT) ((DWORD)pEnumInfo->dataSym2 -
  179. (DWORD)pEnumInfo->dataSym) - 2;
  180. pEnumInfo->dataSym = pEnumInfo->dataSym2;
  181. pEnumInfo->numsyms++;
  182. return TRUE;
  183. }
  184. DWORD
  185. CreatePublicsFromSyms( PPOINTERS p )
  186. /*++
  187. Routine Description:
  188. Creates the individual CV public symbol records. There is one CV
  189. public record created for each COFF symbol that is marked as EXTERNAL
  190. and has a section number greater than zero. The resulting CV publics
  191. are sorted by section and offset.
  192. Arguments:
  193. p - pointer to a POINTERS structure (see symcvt.h)
  194. Return Value:
  195. The number of publics created.
  196. --*/
  197. {
  198. OMFSymHash *omfSymHash;
  199. ENUMINFO enumInfo;
  200. enumInfo.dataSym = (DATASYM32 *)
  201. (PUCHAR)((DWORD)p->pCvCurr + sizeof(OMFSymHash));
  202. enumInfo.numsyms = 0;
  203. EnumSymbols( p, ConvertASymtoPublic, &enumInfo );
  204. omfSymHash = (OMFSymHash *) p->pCvCurr;
  205. UpdatePtrs(p, &p->pCvPublics, (LPVOID)enumInfo.dataSym,
  206. enumInfo.numsyms );
  207. omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
  208. omfSymHash->symhash = 0;
  209. omfSymHash->addrhash = 0;
  210. omfSymHash->cbHSym = 0;
  211. omfSymHash->cbHAddr = 0;
  212. return enumInfo.numsyms;
  213. }
  214. BOOL CALLBACK
  215. ConvertASegment( PSYMNAME pSymName, int symType, SEGMENT segment,
  216. UOFF32 offset, PENUMINFO pEnumInfo )
  217. {
  218. if (symType != SYM_SEGMENT_NAME) {
  219. return TRUE;
  220. }
  221. if (segment == 0) {
  222. return TRUE;
  223. }
  224. pEnumInfo->numsyms++;
  225. pEnumInfo->sgi->sgf.fRead = TRUE;
  226. pEnumInfo->sgi->sgf.fWrite = TRUE;
  227. pEnumInfo->sgi->sgf.fExecute = TRUE;
  228. pEnumInfo->sgi->sgf.f32Bit = 0;
  229. pEnumInfo->sgi->sgf.fSel = 0;
  230. pEnumInfo->sgi->sgf.fAbs = 0;
  231. pEnumInfo->sgi->sgf.fGroup = 1;
  232. pEnumInfo->sgi->iovl = 0;
  233. pEnumInfo->sgi->igr = 0;
  234. pEnumInfo->sgi->isgPhy = (USHORT) pEnumInfo->numsyms;
  235. pEnumInfo->sgi->isegName = 0;
  236. pEnumInfo->sgi->iclassName = 0;
  237. pEnumInfo->sgi->doffseg = offset;
  238. pEnumInfo->sgi->cbSeg = 0xFFFF;
  239. pEnumInfo->sgi++;
  240. return TRUE;
  241. }
  242. DWORD
  243. CreateSegMapFromSyms( PPOINTERS p )
  244. /*++
  245. Routine Description:
  246. Creates the CV segment map. The segment map is used by debuggers
  247. to aid in address lookups. One segment is created for each COFF
  248. section in the image.
  249. Arguments:
  250. p - pointer to a POINTERS structure (see symcvt.h)
  251. Return Value:
  252. The number of segments in the map.
  253. --*/
  254. {
  255. SGM *sgm;
  256. ENUMINFO enumInfo;
  257. sgm = (SGM *) p->pCvCurr;
  258. enumInfo.sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
  259. enumInfo.numsyms = 0;
  260. EnumSymbols( p, ConvertASegment, &enumInfo );
  261. sgm->cSeg = (USHORT)enumInfo.numsyms;
  262. sgm->cSegLog = (USHORT)enumInfo.numsyms;
  263. UpdatePtrs( p, &p->pCvSegMap, (LPVOID)enumInfo.sgi, enumInfo.numsyms );
  264. return enumInfo.numsyms;
  265. }
  266. BOOL
  267. EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc, PENUMINFO pEnumInfo )
  268. /*++
  269. Routine Description:
  270. This function enumerates all symbols ine the mapped SYM file
  271. Arguments:
  272. p - pointer to a POINTERS structure
  273. lpEnumProc - function to be called once for each function
  274. pEnumInfo - data to be passed between the caller and the enum func
  275. Return Value:
  276. TRUE - success
  277. FALSE - failure
  278. --*/
  279. {
  280. PSYMFILEHEADER pSymFileHead;
  281. PSYMHEADER pSymHead;
  282. PSYMHEADER pSymHead2;
  283. PSYMSYMBOL pSymSymbol;
  284. DWORD i;
  285. DWORD startPosition;
  286. DWORD position;
  287. BOOL fV86Mode;
  288. WORD Segment;
  289. UOFF32 Offset;
  290. BYTE* pSymOffsets;
  291. DWORD dwSymOffset;
  292. pSymFileHead = (PSYMFILEHEADER) p->iptrs.fptr;
  293. pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymFileHead + SIZEOFSYMFILEHEADER +
  294. pSymFileHead->symName.length + 1);
  295. if (!lpEnumProc(&pSymFileHead->symName, SYM_SEGMENT_ABS,
  296. 0, 0, pEnumInfo )) {
  297. return FALSE;
  298. }
  299. for (i=0; i<pSymFileHead->numSyms; i++) {
  300. if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_ABS,
  301. 0, pSymSymbol->offset, pEnumInfo )) {
  302. return FALSE;
  303. }
  304. pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymSymbol + SIZEOFSYMBOL +
  305. pSymSymbol->symName.length);
  306. }
  307. position = startPosition = ((LONG)pSymFileHead->nextOffset) << 4;
  308. //
  309. // Determine if this is a V86Mode sym file.
  310. //
  311. // We'll read the first two headers. If their segment numbers are
  312. // not 1 and 2, then we assume V86Mode.
  313. //
  314. pSymHead = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  315. position = ((LONG)pSymHead->nextOffset) << 4;
  316. if ( position != startPosition && position != 0 ) {
  317. pSymHead2 = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  318. } else {
  319. pSymHead2 = NULL;
  320. }
  321. if ( pSymHead->segment == 1 &&
  322. (!pSymHead2 || pSymHead2->segment == 2)) {
  323. fV86Mode = FALSE;
  324. } else {
  325. fV86Mode = TRUE;
  326. Segment = 0;
  327. }
  328. position = startPosition;
  329. do {
  330. pSymHead = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
  331. // BIG SYMDEF
  332. if (pSymHead->type & 0x04) {
  333. pSymOffsets = (BYTE*) ((DWORD)pSymHead + (pSymHead->symOffsetsOffset << 4));
  334. }
  335. else {
  336. pSymOffsets = (BYTE*) ((DWORD)pSymHead + pSymHead->symOffsetsOffset);
  337. }
  338. if ( fV86Mode ) {
  339. Segment++;
  340. Offset = pSymHead->segment;
  341. } else {
  342. Segment = pSymHead->segment;
  343. Offset = 0;
  344. }
  345. position = ((LONG)pSymHead->nextOffset) << 4;
  346. if (!lpEnumProc( &pSymHead->symName, SYM_SEGMENT_NAME,
  347. Segment, Offset, pEnumInfo )) {
  348. return FALSE;
  349. }
  350. for (i=0; i<pSymHead->numSyms; i++) {
  351. // BIG SYMDEF
  352. if (pSymHead->type & 0x04) {
  353. pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymHead +
  354. pSymOffsets[i*3+0] +
  355. pSymOffsets[i*3+1] * 256 +
  356. pSymOffsets[i*3+2] * 65536);
  357. dwSymOffset = pSymSymbol->offset;
  358. }
  359. else {
  360. // HACKHACK: The Symbol Name and Offset are contiguous in the case of
  361. // MSF_32BITSYMS and are separated by 2 bytes in all other cases.
  362. pSymSymbol = (PSYMSYMBOL)((DWORD)pSymHead +
  363. pSymOffsets[i*2+0] +
  364. pSymOffsets[i*2+1] * 256);
  365. dwSymOffset = pSymSymbol->offset;
  366. pSymSymbol = (PSYMSYMBOL)((DWORD)pSymHead +
  367. pSymOffsets[i*2+0] +
  368. pSymOffsets[i*2+1] * 256 -
  369. sizeof(SHORT) * (1 - (pSymHead->type & 0x01)));
  370. }
  371. // MSF_32BITSYMS
  372. if (pSymHead->type & 0x01) {
  373. if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_NAME,
  374. Segment, dwSymOffset,
  375. pEnumInfo )) {
  376. return FALSE;
  377. }
  378. }
  379. // 16 BIT SYMS
  380. else {
  381. if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_NAME,
  382. Segment, dwSymOffset & 0x0000FFFF,
  383. pEnumInfo )) {
  384. return FALSE;
  385. }
  386. }
  387. }
  388. } while ( position != startPosition && position != 0 );
  389. return 0;
  390. }