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.

1006 lines
29 KiB

  1. /*++
  2. Copyright 1996 - 1997 Microsoft Corporation
  3. Module Name:
  4. cv.c
  5. Abstract:
  6. This module handles the conversion activities requires for converting
  7. COFF debug data to CODEVIEW debug data.
  8. Author:
  9. Wesley A. Witt (wesw) 19-April-1993
  10. Environment:
  11. Win32, User Mode
  12. --*/
  13. #include <windows.h>
  14. #include <imagehlp.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <strsafe.h>
  19. #include "cv.h"
  20. #define _SYMCVT_SOURCE_
  21. #include "symcvt.h"
  22. #include "cvcommon.h"
  23. #ifndef DIMA
  24. #define DIMAT(Array, EltType) (sizeof(Array) / sizeof(EltType))
  25. #define DIMA(Array) DIMAT(Array, (Array)[0])
  26. #endif
  27. typedef struct tagOFFSETSORT {
  28. DWORD dwOffset; // offset for the symbol
  29. DWORD dwSection; // section number of the symbol
  30. DATASYM32 *dataSym; // pointer to the symbol info
  31. } OFFSETSORT;
  32. #define n_name N.ShortName
  33. #define n_zeroes N.Name.Short
  34. #define n_nptr N.LongName[1]
  35. #define n_offset N.Name.Long
  36. static LPSTR GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s, DWORD size );
  37. DWORD CreateModulesFromCoff( PPOINTERS p );
  38. DWORD CreatePublicsFromCoff( PPOINTERS p );
  39. DWORD CreateSegMapFromCoff( PPOINTERS p );
  40. DWORD CreateSrcLinenumbers( PPOINTERS p );
  41. LONG
  42. GuardPageFilterFunction(
  43. DWORD ec,
  44. LPEXCEPTION_POINTERS lpep
  45. )
  46. /*++
  47. Routine Description:
  48. This function catches all exceptions from the convertcofftocv function
  49. and all that it calls. The purpose of this function is allocate memory
  50. when it is necessary. This happens because the cofftocv conversion cannot
  51. estimate the memory requirements before the conversion takes place. To
  52. handle this properly space in the virtual address space is reserved, the
  53. reservation amount is 10 times the image size. The first page is commited
  54. and then the conversion is started. When an access violation occurs and the
  55. page that is trying to be access has a protection of noaccess then the
  56. page is committed. Any other exception is not handled.
  57. Arguments:
  58. ec - the ecxeption code (should be EXCEPTION_ACCESS_VIOLATION)
  59. lpep - pointer to the exception record and context record
  60. Return Value:
  61. EXCEPTION_CONTINUE_EXECUTION - access violation handled
  62. EXCEPTION_EXECUTE_HANDLER - unknown exception and is not handled
  63. --*/
  64. {
  65. LPVOID vaddr;
  66. SYSTEM_INFO si;
  67. MEMORY_BASIC_INFORMATION mbi;
  68. if (ec == EXCEPTION_ACCESS_VIOLATION) {
  69. vaddr = (LPVOID)lpep->ExceptionRecord->ExceptionInformation[1];
  70. VirtualQuery( vaddr, &mbi, sizeof(mbi) );
  71. if (mbi.AllocationProtect == PAGE_NOACCESS) {
  72. GetSystemInfo( &si );
  73. VirtualAlloc( vaddr, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
  74. return EXCEPTION_CONTINUE_EXECUTION;
  75. }
  76. }
  77. // return EXCEPTION_CONTINUE_SEARCH;
  78. return EXCEPTION_EXECUTE_HANDLER;
  79. }
  80. BOOL
  81. ConvertCoffToCv( PPOINTERS p )
  82. /*++
  83. Routine Description:
  84. This is the control function for the conversion of COFF to CODEVIEW
  85. debug data. It calls individual functions for the conversion of
  86. specific types of debug data.
  87. Arguments:
  88. p - pointer to a POINTERS structure
  89. Return Value:
  90. TRUE - conversion succeded
  91. FALSE - conversion failed
  92. --*/
  93. {
  94. SYSTEM_INFO si;
  95. DWORD cbsize;
  96. BOOL rval = TRUE;
  97. GetSystemInfo( &si );
  98. cbsize = max( p->iptrs.fsize * 10, si.dwPageSize * 10 );
  99. p->cbCvData = cbsize;
  100. //
  101. // reserve all necessary pages
  102. //
  103. p->pCvCurr = p->pCvStart.ptr = VirtualAlloc( NULL, cbsize, MEM_RESERVE, PAGE_NOACCESS );
  104. //
  105. // commit the first pages
  106. //
  107. VirtualAlloc( p->pCvCurr, min( cbsize, 5 * si.dwPageSize), MEM_COMMIT, PAGE_READWRITE );
  108. try {
  109. CreateSignature( p );
  110. CreateModulesFromCoff( p );
  111. CreatePublicsFromCoff( p );
  112. CreateSymbolHashTable( p );
  113. CreateAddressSortTable( p );
  114. CreateSegMapFromCoff( p );
  115. // CreateSrcLinenumbers( p );
  116. CreateDirectories( p );
  117. } except ( GuardPageFilterFunction( GetExceptionCode(), GetExceptionInformation() )) {
  118. VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
  119. p->pCvStart.ptr = NULL;
  120. rval = FALSE;
  121. }
  122. if (rval) {
  123. p->pCvCurr = malloc( p->pCvStart.size );
  124. CopyMemory( p->pCvCurr, p->pCvStart.ptr, p->pCvStart.size );
  125. VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
  126. p->pCvStart.ptr = p->pCvCurr;
  127. }
  128. return rval;
  129. }
  130. DWORD
  131. CreateModulesFromCoff( PPOINTERS p )
  132. /*++
  133. Routine Description:
  134. Creates the individual CV module records. There is one CV module
  135. record for each .FILE record in the COFF debug data. This is true
  136. even if the COFF size is zero.
  137. Arguments:
  138. p - pointer to a POINTERS structure
  139. Return Value:
  140. The number of modules that were created.
  141. --*/
  142. {
  143. int i,j;
  144. DWORD dwOff;
  145. DWORD numaux;
  146. DWORD nummods = 0;
  147. char szSymName[256];
  148. PIMAGE_SYMBOL Symbol;
  149. PIMAGE_AUX_SYMBOL AuxSymbol;
  150. OMFModule *m = NULL;
  151. int cSeg = 0;
  152. char * pb;
  153. BOOLEAN rgfCode[500];
  154. memset(rgfCode, 2, sizeof(rgfCode));
  155. for (i=0,j=0, Symbol=p->iptrs.AllSymbols;
  156. i<(int)p->iptrs.numberOfSymbols;
  157. i+=numaux+1,Symbol+=numaux+1) {
  158. numaux = Symbol->NumberOfAuxSymbols;
  159. if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  160. j++;
  161. }
  162. }
  163. p->pMi = (LPMODULEINFO) malloc( sizeof(MODULEINFO) * (j + 1) );
  164. ZeroMemory( p->pMi, sizeof(MODULEINFO) * (j + 1) );
  165. if (!j) {
  166. //
  167. // Handle the situation where there are not any .file records in the
  168. // COFF symbol table. This can happen for ROM images. If this happens
  169. // then we will fabricate a bogus module.
  170. //
  171. m = (OMFModule *) p->pCvCurr;
  172. m->ovlNumber = 0;
  173. m->iLib = 0;
  174. m->Style[0] = 'C';
  175. m->Style[1] = 'V';
  176. for (i=0,j=0, dwOff=0; i<p->iptrs.numberOfSections; i++) {
  177. if (p->iptrs.sectionHdrs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
  178. m->SegInfo[j].Seg = i + 1;
  179. m->SegInfo[j].cbSeg = p->iptrs.sectionHdrs[i].SizeOfRawData;
  180. m->SegInfo[j++].Off = dwOff;
  181. }
  182. dwOff += p->iptrs.sectionHdrs[i].SizeOfRawData;
  183. }
  184. m->cSeg = (unsigned short) j;
  185. StringCchCopyA(szSymName, DIMA(szSymName), "foo.c");
  186. pb = (char *) &m->SegInfo[j];
  187. *pb = (char)strlen(szSymName);
  188. memcpy(pb+1, szSymName, *pb);
  189. p->pMi[0].name = _strdup(szSymName);
  190. p->pMi[0].iMod = 1;
  191. p->pMi[0].cb = 0;
  192. p->pMi[0].SrcModule = 0;
  193. m = NextMod(m);
  194. p->modcnt = 1;
  195. UpdatePtrs( p, &p->pCvModules, (LPVOID)m, 1 );
  196. return 1;
  197. }
  198. for (i=0, Symbol = p->iptrs.AllSymbols;
  199. i < (int) p->iptrs.numberOfSymbols;
  200. i += numaux + 1, Symbol += numaux + 1) {
  201. //
  202. // Get the number of aux symbol records for this symbol
  203. //
  204. numaux = Symbol->NumberOfAuxSymbols;
  205. AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
  206. if ((i == 0) && ((Symbol+numaux+1)->StorageClass != IMAGE_SYM_CLASS_FILE)) {
  207. //
  208. // we have a situation where the first '.file' record
  209. // is missing. currently this only happens with the
  210. // claxp compiler on alpha.
  211. //
  212. m = (OMFModule *) p->pCvCurr;
  213. cSeg = 0;
  214. m->ovlNumber = 0;
  215. m->iLib = 0;
  216. m->Style[0] = 'C';
  217. m->Style[1] = 'V';
  218. StringCchCopyA( szSymName, DIMA(szSymName), "fake.c" );
  219. } else
  220. //
  221. // If this is a FILE record -- then we need to create a
  222. // module item to correspond to this file record.
  223. //
  224. if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  225. if (m == NULL) {
  226. m = (OMFModule *) p->pCvCurr;
  227. } else {
  228. //
  229. // Clean up the last item, if we saw any
  230. // section records then drop them in here
  231. //
  232. if (cSeg > 0) {
  233. m->cSeg = (unsigned short) cSeg;
  234. pb = (char *) &m->SegInfo[cSeg];
  235. *pb = (char)strlen(szSymName);
  236. memcpy(pb+1, szSymName, *pb);
  237. p->pMi[nummods].name = _strdup(szSymName);
  238. p->pMi[nummods].iMod = nummods + 1;
  239. p->pMi[nummods].cb = 0;
  240. p->pMi[nummods].SrcModule = 0;
  241. m = NextMod(m);
  242. nummods++;
  243. }
  244. }
  245. cSeg = 0;
  246. m->ovlNumber = 0;
  247. m->iLib = 0;
  248. m->Style[0] = 'C';
  249. m->Style[1] = 'V';
  250. /*
  251. * Save off the file name to use when we have finished
  252. * processing this module
  253. */
  254. memcpy(szSymName, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
  255. szSymName[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
  256. }
  257. /*
  258. * We have found a "SECTION" record. Add the info to the
  259. * module record
  260. */
  261. else
  262. if ((Symbol->SectionNumber & 0xffff) > 0xfff0) {
  263. continue;
  264. } else
  265. if (Symbol->SectionNumber > sizeof(rgfCode)/sizeof(rgfCode[0])) {
  266. return 0;
  267. } else
  268. if ((m != NULL) &&
  269. (rgfCode[Symbol->SectionNumber] != 0) &&
  270. (Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC) &&
  271. ((*Symbol->n_name == '.') ||
  272. (Symbol->Type == IMAGE_SYM_TYPE_NULL)) &&
  273. (Symbol->NumberOfAuxSymbols == 1) &&
  274. (AuxSymbol->Section.Length != 0)) {
  275. if (rgfCode[Symbol->SectionNumber] == 2) {
  276. if ((p->iptrs.sectionHdrs[Symbol->SectionNumber - 1].
  277. Characteristics & IMAGE_SCN_CNT_CODE) == 0) {
  278. rgfCode[Symbol->SectionNumber] = 0;
  279. continue;
  280. }
  281. rgfCode[Symbol->SectionNumber] = 1;
  282. }
  283. m->SegInfo[cSeg].Seg = Symbol->SectionNumber;
  284. m->SegInfo[cSeg].cbSeg = AuxSymbol->Section.Length;
  285. m->SegInfo[cSeg].Off = Symbol->Value -
  286. p->iptrs.sectionHdrs[Symbol->SectionNumber-1].
  287. VirtualAddress;
  288. cSeg += 1;
  289. }
  290. }
  291. /*
  292. * Wrap up the last possible open module record
  293. */
  294. if (m != NULL) {
  295. if (cSeg > 0) {
  296. m->cSeg = (unsigned short) cSeg;
  297. pb = (char *) &m->SegInfo[cSeg];
  298. *pb = (char)strlen(szSymName);
  299. memcpy(pb+1, szSymName, *pb);
  300. p->pMi[nummods].name = _strdup(szSymName);
  301. p->pMi[nummods].iMod = nummods + 1;
  302. p->pMi[nummods].cb = 0;
  303. p->pMi[nummods].SrcModule = 0;
  304. m = NextMod(m);
  305. nummods++;
  306. }
  307. }
  308. p->modcnt = nummods;
  309. UpdatePtrs( p, &p->pCvModules, (LPVOID)m, nummods );
  310. return nummods;
  311. }
  312. DWORD
  313. CreatePublicsFromCoff( PPOINTERS p )
  314. /*++
  315. Routine Description:
  316. Creates the individual CV public symbol records. There is one CV
  317. public record created for each COFF symbol that is marked as EXTERNAL
  318. and has a section number greater than zero. The resulting CV publics
  319. are sorted by section and offset.
  320. Arguments:
  321. p - pointer to a POINTERS structure
  322. Return Value:
  323. The number of publics created.
  324. --*/
  325. {
  326. int i;
  327. DWORD numaux;
  328. DWORD numsyms = 0;
  329. char szSymName[256];
  330. PIMAGE_SYMBOL Symbol;
  331. OMFSymHash *omfSymHash;
  332. DATASYM32 *dataSym;
  333. DATASYM32 *dataSym2;
  334. size_t size;
  335. omfSymHash = (OMFSymHash *) p->pCvCurr;
  336. size = (DWORD)omfSymHash + sizeof(OMFSymHash);
  337. dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
  338. for (i= 0, Symbol = p->iptrs.AllSymbols;
  339. i < p->iptrs.numberOfSymbols;
  340. i += numaux + 1, Symbol += numaux + 1) {
  341. if ((Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) &&
  342. (Symbol->SectionNumber > 0)) {
  343. if (GetSymName( Symbol, p->iptrs.stringTable, szSymName, DIMA(szSymName) )) {
  344. dataSym->rectyp = S_PUB32;
  345. dataSym->seg = Symbol->SectionNumber;
  346. dataSym->off = Symbol->Value -
  347. p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
  348. dataSym->typind = 0;
  349. dataSym->name[0] = (char)strlen( szSymName );
  350. #if 0
  351. strcpy( &dataSym->name[1], szSymName );
  352. #endif
  353. StringCchCopyA(&dataSym->name[1],
  354. p->cbCvData - (&dataSym->name[1] - p->pCvStart.ptr),
  355. szSymName);
  356. dataSym2 = NextSym32( dataSym );
  357. dataSym->reclen = (USHORT) ((DWORD)dataSym2 - (DWORD)dataSym) - 2;
  358. dataSym = dataSym2;
  359. numsyms += 1;
  360. }
  361. }
  362. numaux = Symbol->NumberOfAuxSymbols;
  363. }
  364. UpdatePtrs( p, &p->pCvPublics, (LPVOID)dataSym, numsyms );
  365. omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
  366. omfSymHash->symhash = 0;
  367. omfSymHash->addrhash = 0;
  368. omfSymHash->cbHSym = 0;
  369. omfSymHash->cbHAddr = 0;
  370. return numsyms;
  371. } /* CreatePublisFromCoff() */
  372. DWORD
  373. CreateSrcLinenumbers(
  374. PPOINTERS p
  375. )
  376. /*++
  377. Routine Description:
  378. Creates the individual CV soure line number records.
  379. Arguments:
  380. p - pointer to a POINTERS structure
  381. Return Value:
  382. The number of publics created.
  383. --*/
  384. {
  385. typedef struct _SEGINFO {
  386. DWORD start;
  387. DWORD end;
  388. DWORD cbLines;
  389. DWORD ptrLines;
  390. DWORD va;
  391. DWORD num;
  392. BOOL used;
  393. } SEGINFO, *LPSEGINFO;
  394. typedef struct _SRCINFO {
  395. LPSEGINFO seg;
  396. DWORD numSeg;
  397. DWORD cbSeg;
  398. CHAR name[MAX_PATH+1];
  399. } SRCINFO, *LPSRCINFO;
  400. typedef struct _SECTINFO {
  401. DWORD va;
  402. DWORD size;
  403. DWORD ptrLines;
  404. DWORD numLines;
  405. } SECTINFO, *LPSECTINFO;
  406. DWORD i;
  407. DWORD j;
  408. DWORD k;
  409. DWORD l;
  410. DWORD actual;
  411. DWORD sidx;
  412. DWORD NumSrcFiles;
  413. DWORD SrcFileCnt;
  414. DWORD numaux;
  415. PIMAGE_SYMBOL Symbol;
  416. PIMAGE_AUX_SYMBOL AuxSymbol;
  417. BOOL first = TRUE;
  418. OMFSourceModule *SrcModule;
  419. OMFSourceFile *SrcFile;
  420. OMFSourceLine *SrcLine;
  421. LPBYTE lpb;
  422. LPDWORD lpdw;
  423. PUSHORT lps;
  424. PUCHAR lpc;
  425. PIMAGE_LINENUMBER pil, pilSave;
  426. LPSRCINFO si;
  427. LPSECTINFO sections;
  428. //
  429. // setup the section info structure
  430. //
  431. sections = (LPSECTINFO) malloc( sizeof(SECTINFO) * p->iptrs.numberOfSections );
  432. for (i=0; i<(DWORD)p->iptrs.numberOfSections; i++) {
  433. sections[i].va = p->iptrs.sectionHdrs[i].VirtualAddress;
  434. sections[i].size = p->iptrs.sectionHdrs[i].SizeOfRawData;
  435. sections[i].ptrLines = p->iptrs.sectionHdrs[i].PointerToLinenumbers;
  436. sections[i].numLines = p->iptrs.sectionHdrs[i].NumberOfLinenumbers;
  437. }
  438. //
  439. // count the number of source files that contibute linenumbers
  440. //
  441. SrcFileCnt = 100;
  442. si = (LPSRCINFO) malloc( sizeof(SRCINFO) * SrcFileCnt );
  443. ZeroMemory( si, sizeof(SRCINFO) * SrcFileCnt );
  444. for (i=0, j=0, Symbol=p->iptrs.AllSymbols, NumSrcFiles=0;
  445. i<(DWORD)p->iptrs.numberOfSymbols;
  446. i+=(numaux+1), Symbol+=(numaux + 1)) {
  447. numaux = Symbol->NumberOfAuxSymbols;
  448. AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
  449. if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
  450. if (!first) {
  451. si[NumSrcFiles].cbSeg = j;
  452. NumSrcFiles++;
  453. if (NumSrcFiles == SrcFileCnt) {
  454. SrcFileCnt += 100;
  455. si = (LPSRCINFO) realloc( si, sizeof(SRCINFO) * SrcFileCnt );
  456. }
  457. }
  458. memcpy(si[NumSrcFiles].name, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
  459. si[NumSrcFiles].name[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
  460. si[NumSrcFiles].numSeg = 100;
  461. si[NumSrcFiles].seg = (LPSEGINFO) malloc( sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  462. ZeroMemory( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  463. first = FALSE;
  464. j = 0;
  465. }
  466. //
  467. // we do not want to look for segment information until we
  468. // have found a valid source file
  469. //
  470. if (first) {
  471. continue;
  472. }
  473. //
  474. // check the symbol to see if it is a segment record
  475. //
  476. if (numaux && Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC &&
  477. (*Symbol->n_name == '.' ||
  478. ((Symbol->Type & 0xf) == IMAGE_SYM_TYPE_NULL && AuxSymbol->Section.Length)) &&
  479. AuxSymbol->Section.NumberOfLinenumbers > 0) {
  480. //
  481. // find the section that this symbol belongs to
  482. //
  483. for (k=0; k<(DWORD)p->iptrs.numberOfSections; k++) {
  484. if (Symbol->Value >= sections[k].va &&
  485. Symbol->Value < sections[k].va + sections[k].size) {
  486. sidx = k;
  487. break;
  488. }
  489. }
  490. if (k != (DWORD)p->iptrs.numberOfSections &&
  491. p->iptrs.sectionHdrs[k].NumberOfLinenumbers) {
  492. pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + sections[sidx].ptrLines);
  493. k = 0;
  494. while( k < AuxSymbol->Section.NumberOfLinenumbers ) {
  495. //
  496. // count the linenumbers in this section or sub-section
  497. //
  498. for ( pilSave=pil,l=0;
  499. k<AuxSymbol->Section.NumberOfLinenumbers;
  500. k++,pilSave++,l++ ) {
  501. if ((k != (DWORD)AuxSymbol->Section.NumberOfLinenumbers-1) &&
  502. (pilSave->Linenumber > (pilSave+1)->Linenumber)) {
  503. pilSave++;
  504. l++;
  505. break;
  506. }
  507. }
  508. //
  509. // pil == beginning of the range
  510. // pilSave == end of the range
  511. //
  512. si[NumSrcFiles].seg[j].start =
  513. (pil->Type.VirtualAddress - sections[sidx].va);
  514. if (sections[sidx].numLines == l) {
  515. pilSave--;
  516. si[NumSrcFiles].seg[j].end =
  517. (pilSave->Type.VirtualAddress - sections[sidx].va) + 1;
  518. // (Symbol->Value - sections[sidx].va) + 1;
  519. } else {
  520. si[NumSrcFiles].seg[j].end =
  521. (pilSave->Type.VirtualAddress - sections[sidx].va) - 1;
  522. // (Symbol->Value - sections[sidx].va) - 1;
  523. }
  524. si[NumSrcFiles].seg[j].ptrLines = sections[sidx].ptrLines;
  525. si[NumSrcFiles].seg[j].cbLines = l;
  526. si[NumSrcFiles].seg[j].va = sections[sidx].va;
  527. si[NumSrcFiles].seg[j].num = sidx + 1;
  528. si[NumSrcFiles].seg[j].used = FALSE;
  529. sections[sidx].ptrLines += (l * sizeof(IMAGE_LINENUMBER));
  530. sections[sidx].numLines -= l;
  531. j++;
  532. if (j == si[NumSrcFiles].numSeg) {
  533. si[NumSrcFiles].numSeg += 100;
  534. si[NumSrcFiles].seg = (LPSEGINFO) realloc( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
  535. }
  536. k++;
  537. pil = pilSave;
  538. }
  539. }
  540. }
  541. }
  542. lpb = (LPBYTE) p->pCvCurr;
  543. //
  544. // if there is nothing to do then bail out
  545. //
  546. if (!NumSrcFiles) {
  547. UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, 0 );
  548. return 0;
  549. }
  550. for (i=0,actual=0,l=0; i<NumSrcFiles; i++) {
  551. if (si[i].cbSeg == 0) {
  552. continue;
  553. }
  554. //
  555. // create the source module header
  556. //
  557. SrcModule = (OMFSourceModule*) lpb;
  558. SrcModule->cFile = 1;
  559. SrcModule->cSeg = (USHORT)si[i].cbSeg;
  560. SrcModule->baseSrcFile[0] = 0;
  561. //
  562. // write the start/end pairs
  563. //
  564. lpdw = (LPDWORD) ((LPBYTE)SrcModule + sizeof(OMFSourceModule));
  565. for (k=0; k<si[i].cbSeg; k++) {
  566. *lpdw++ = si[i].seg[k].start;
  567. *lpdw++ = si[i].seg[k].end;
  568. }
  569. //
  570. // write the segment numbers
  571. //
  572. lps = (PUSHORT) lpdw;
  573. for (k=0; k<si[i].cbSeg; k++) {
  574. *lps++ = (USHORT)si[i].seg[k].num;
  575. }
  576. //
  577. // align to a dword boundry
  578. //
  579. lps = (PUSHORT) ((LPBYTE)lps + align(lps));
  580. //
  581. // update the base pointer
  582. //
  583. SrcModule->baseSrcFile[0] = (DWORD) ((LPBYTE)lps - (LPBYTE)SrcModule);
  584. //
  585. // write the source file record
  586. //
  587. SrcFile = (OMFSourceFile*) lps;
  588. SrcFile->cSeg = (USHORT)si[i].cbSeg;
  589. SrcFile->reserved = 0;
  590. for (k=0; k<si[i].cbSeg; k++) {
  591. SrcFile->baseSrcLn[k] = 0;
  592. }
  593. //
  594. // write the start/end pairs
  595. //
  596. lpdw = (LPDWORD) ((LPBYTE)SrcFile + 4 + (4 * si[i].cbSeg));
  597. for (k=0; k<si[i].cbSeg; k++) {
  598. *lpdw++ = si[i].seg[k].start;
  599. *lpdw++ = si[i].seg[k].end;
  600. }
  601. //
  602. // write the source file name
  603. //
  604. lpc = (PUCHAR) lpdw;
  605. k = strlen(si[i].name);
  606. *lpc++ = (UCHAR) k;
  607. StringCchCopyA(lpc, p->cbCvData - (lpc - p->pCvStart.ptr), si[i].name);
  608. lpb = lpc + k;
  609. //
  610. // find the module info struct
  611. //
  612. for (; l<p->modcnt; l++) {
  613. if (_stricmp(p->pMi[l].name,si[i].name)==0) {
  614. break;
  615. }
  616. }
  617. p->pMi[l].SrcModule = (DWORD) SrcModule;
  618. //
  619. // align to a dword boundry
  620. //
  621. lpb = (LPBYTE) (lpb + align(lpb));
  622. //
  623. // create the line number pairs
  624. //
  625. for (k=0; k<si[i].cbSeg; k++) {
  626. //
  627. // find the first line number that applies to this segment
  628. //
  629. pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + si[i].seg[k].ptrLines);
  630. //
  631. // update the base pointer
  632. //
  633. SrcFile->baseSrcLn[k] = (DWORD) (lpb - (LPBYTE)SrcModule);
  634. //
  635. // write the line numbers
  636. //
  637. SrcLine = (OMFSourceLine*) lpb;
  638. SrcLine->Seg = (USHORT)si[i].seg[k].num;
  639. SrcLine->cLnOff = (USHORT) si[i].seg[k].cbLines;
  640. pilSave = pil;
  641. lpdw = (LPDWORD) (lpb + 4);
  642. for (j=0; j<SrcLine->cLnOff; j++) {
  643. *lpdw++ = pil->Type.VirtualAddress - si[i].seg[k].va;
  644. pil++;
  645. }
  646. lps = (PUSHORT) lpdw;
  647. pil = pilSave;
  648. for (j=0; j<SrcLine->cLnOff; j++) {
  649. *lps++ = pil->Linenumber;
  650. pil++;
  651. }
  652. //
  653. // align to a dword boundry
  654. //
  655. lps = (PUSHORT) ((LPBYTE)lps + align(lps));
  656. lpb = (LPBYTE) lps;
  657. }
  658. p->pMi[l].cb = (DWORD)lpb - (DWORD)SrcModule;
  659. actual++;
  660. }
  661. UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, actual );
  662. //
  663. // cleanup all allocated memory
  664. //
  665. free( sections );
  666. for (i=0; i<SrcFileCnt; i++) {
  667. if (si[i].seg) {
  668. free( si[i].seg );
  669. }
  670. }
  671. free( si );
  672. return NumSrcFiles;
  673. } /* CreateSrcLinenumbers() */
  674. DWORD
  675. CreateSegMapFromCoff( PPOINTERS p )
  676. /*++
  677. Routine Description:
  678. Creates the CV segment map. The segment map is used by debuggers
  679. to aid in address lookups. One segment is created for each COFF
  680. section in the image.
  681. Arguments:
  682. p - pointer to a POINTERS structure
  683. Return Value:
  684. The number of segments in the map.
  685. --*/
  686. {
  687. int i;
  688. SGM *sgm;
  689. SGI *sgi;
  690. PIMAGE_SECTION_HEADER sh;
  691. sgm = (SGM *) p->pCvCurr;
  692. sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
  693. sgm->cSeg = (unsigned short) p->iptrs.numberOfSections;
  694. sgm->cSegLog = (unsigned short) p->iptrs.numberOfSections;
  695. sh = p->iptrs.sectionHdrs;
  696. for (i=0; i<p->iptrs.numberOfSections; i++, sh++) {
  697. sgi->sgf.fRead = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_READ) == IMAGE_SCN_MEM_READ;
  698. sgi->sgf.fWrite = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_WRITE) == IMAGE_SCN_MEM_WRITE;
  699. sgi->sgf.fExecute = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE;
  700. sgi->sgf.f32Bit = 1;
  701. sgi->sgf.fSel = 0;
  702. sgi->sgf.fAbs = 0;
  703. sgi->sgf.fGroup = 1;
  704. sgi->iovl = 0;
  705. sgi->igr = 0;
  706. sgi->isgPhy = (USHORT) i + 1;
  707. sgi->isegName = 0;
  708. sgi->iclassName = 0;
  709. sgi->doffseg = 0;
  710. sgi->cbSeg = sh->SizeOfRawData;
  711. sgi++;
  712. }
  713. UpdatePtrs( p, &p->pCvSegMap, (LPVOID)sgi, i );
  714. return i;
  715. }
  716. LPSTR
  717. GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s, DWORD size )
  718. /*++
  719. Routine Description:
  720. Extracts the COFF symbol from the image symbol pointer and puts
  721. the ascii text in the character pointer passed in.
  722. Arguments:
  723. Symbol - COFF Symbol Record
  724. StringTable - COFF string table
  725. s - buffer for the symbol string
  726. Return Value:
  727. void
  728. --*/
  729. {
  730. DWORD i;
  731. if (Symbol->n_zeroes) {
  732. for (i=0; i<8; i++) {
  733. if ((Symbol->n_name[i]>0x1f) && (Symbol->n_name[i]<0x7f)) {
  734. *s++ = Symbol->n_name[i];
  735. }
  736. }
  737. *s = 0;
  738. }
  739. else {
  740. if (StringTable[Symbol->n_offset] == '?') {
  741. i = UnDecorateSymbolName( &StringTable[Symbol->n_offset],
  742. s,
  743. 255,
  744. UNDNAME_COMPLETE |
  745. UNDNAME_NO_LEADING_UNDERSCORES |
  746. UNDNAME_NO_MS_KEYWORDS |
  747. UNDNAME_NO_FUNCTION_RETURNS |
  748. UNDNAME_NO_ALLOCATION_MODEL |
  749. UNDNAME_NO_ALLOCATION_LANGUAGE |
  750. UNDNAME_NO_MS_THISTYPE |
  751. UNDNAME_NO_CV_THISTYPE |
  752. UNDNAME_NO_THISTYPE |
  753. UNDNAME_NO_ACCESS_SPECIFIERS |
  754. UNDNAME_NO_THROW_SIGNATURES |
  755. UNDNAME_NO_MEMBER_TYPE |
  756. UNDNAME_NO_RETURN_UDT_MODEL |
  757. UNDNAME_NO_ARGUMENTS |
  758. UNDNAME_NO_SPECIAL_SYMS |
  759. UNDNAME_NAME_ONLY
  760. );
  761. if (!i) {
  762. return NULL;
  763. }
  764. } else {
  765. StringCchCopyA( s, size, &StringTable[Symbol->n_offset] );
  766. }
  767. }
  768. return s;
  769. }