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.

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