- Timestamp:
- Jan 24, 2009 2:00:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/kDepObj.c
r2263 r2267 44 44 #include "../../lib/k/kDefs.h" 45 45 #include "../../lib/k/kTypes.h" 46 #include "../../lib/k/kLdrFmts/pe.h" 46 47 #include "../../lib/kDep.h" 47 48 #include "kmkbuiltin.h" … … 73 74 * Structures and Typedefs * 74 75 *******************************************************************************/ 75 /** @name OMF structure76 /** @name OMF Structures 76 77 * @{ */ 77 78 #pragma pack(1) … … 117 118 typedef KDEPOMFDEPFILE *PKDEPOMFDEPFILE; 118 119 typedef const KDEPOMFDEPFILE *PCKDEPOMFDEPFILE; 120 121 #pragma pack() 122 /** @} */ 123 124 125 /** @name COFF Structures 126 * @{ */ 127 #pragma pack(1) 128 129 typedef struct KDEPCVSYMHDR 130 { 131 /** The record size minus the size field. */ 132 KU16 cb; 133 /** The record type. */ 134 KU16 uType; 135 } KDEPCVSYMHDR; 136 typedef KDEPCVSYMHDR *PKDEPCVSYMHDR; 137 typedef const KDEPCVSYMHDR *PCKDEPCVSYMHDR; 138 139 /** @name Selection of KDEPCVSYMHDR::uType values. 140 * @{ */ 141 #define K_CV8_S_MSTOOL KU16_C(0x1116) 142 /** @} */ 143 144 typedef struct KDEPCV8SYMHDR 145 { 146 /** The record type. */ 147 KU32 uType; 148 /** The record size minus the size field. */ 149 KU32 cb; 150 } KDEPCV8SYMHDR; 151 typedef KDEPCV8SYMHDR *PKDEPCV8SYMHDR; 152 typedef const KDEPCV8SYMHDR *PCKDEPCV8SYMHDR; 153 154 /** @name Known KDEPCV8SYMHDR::uType Values. 155 * @{ */ 156 #define K_CV8_SYMBOL_INFO KU32_C(0x000000f1) 157 #define K_CV8_LINE_NUMBERS KU32_C(0x000000f2) 158 #define K_CV8_STRING_TABLE KU32_C(0x000000f3) 159 #define K_CV8_SOURCE_FILES KU32_C(0x000000f4) 160 #define K_CV8_COMDAT_XXXXX KU32_C(0x000000f5) /**< no idea about the format... */ 161 /** @} */ 119 162 120 163 #pragma pack() … … 243 286 PCKDEPOMFTHEADR pHdr = (PCKDEPOMFTHEADR)pbFile; 244 287 245 if (cbFile < sizeof(*pHdr))288 if (cbFile <= sizeof(*pHdr)) 246 289 return K_FALSE; 247 290 if ( pHdr->Hdr.bType != KDEPOMF_THEADR … … 252 295 if (pHdr->Hdr.cbRec != 1 + pHdr->Name.cch + 1) 253 296 return K_FALSE; 297 298 return K_TRUE; 299 } 300 301 302 /** 303 * Parses a CodeView 8 symbol section. 304 * 305 * @returns 0 on success, 1 on failure. 306 * @param pbSyms Pointer to the start of the symbol section. 307 * @param cbSyms Size of the symbol section. 308 */ 309 int kDepObjCOFFParseCV8SymbolSection(const KU8 *pbSyms, KSIZE cbSyms) 310 { 311 char const * pchStrTab = NULL; 312 KU32 cbStrTab = 0; 313 KPCUINT uSrcFiles = {0}; 314 KU32 cbSrcFiles = 0; 315 KU32 off = 4; 316 KU32 iSrc = 0; 317 318 if (cbSyms < 16) 319 return 1; 320 321 /* 322 * The parsing loop. 323 */ 324 while (off < cbSyms) 325 { 326 PCKDEPCV8SYMHDR pHdr = (PCKDEPCV8SYMHDR)(pbSyms + off); 327 KPCUINT uData; 328 KU32 cbData; 329 uData.pv = pHdr + 1; 330 331 if (off + sizeof(*pHdr) >= cbSyms) 332 { 333 fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbSyms=%#" KSIZE_PRI "\n", 334 argv0, off, cbSyms); 335 return 1; /* FIXME */ 336 } 337 338 cbData = pHdr->cb; 339 if (off + cbData + sizeof(*pHdr) > cbSyms) 340 { 341 fprintf(stderr, "%s: CV symbol table entry at %08" KX32_PRI " is too long; cbData=%#" KX32_PRI " cbSyms=%#" KSIZE_PRI "\n", 342 argv0, off, cbData, cbSyms); 343 return 1; /* FIXME */ 344 } 345 346 /* If the size is 0, assume it covers the rest of the section. VC++ 2003 has 347 been observed doing thing. */ 348 if (!cbData) 349 cbData = cbSyms - off; 350 351 switch (pHdr->uType) 352 { 353 case K_CV8_SYMBOL_INFO: 354 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Symbol Info\n", off, cbData)); 355 /*dump(uData.pb, cbData, 0);*/ 356 break; 357 358 case K_CV8_LINE_NUMBERS: 359 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Line numbers\n", off, cbData)); 360 /*dump(uData.pb, cbData, 0);*/ 361 break; 362 363 case K_CV8_STRING_TABLE: 364 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData)); 365 if (pchStrTab) 366 fprintf(stderr, "%s: warning: Found yet another string table!\n"); 367 pchStrTab = uData.pch; 368 cbStrTab = cbData; 369 /*dump(uData.pb, cbData, 0);*/ 370 break; 371 372 case K_CV8_SOURCE_FILES: 373 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData)); 374 if (uSrcFiles.pb) 375 fprintf(stderr, "%s: warning: Found yet another source files table!\n"); 376 uSrcFiles = uData; 377 cbSrcFiles = cbData; 378 /*dump(uData.pb, cbData, 0);*/ 379 break; 380 381 case K_CV8_COMDAT_XXXXX: 382 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": 0xf5 Unknown COMDAT stuff\n", off, cbData)); 383 /*dump(uData.pb, cbData, 0);*/ 384 break; 385 386 default: 387 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Unknown type %#" KX32_PRI "\n", 388 off, cbData, pHdr->uType)); 389 dump(uData.pb, cbData, 0); 390 break; 391 } 392 393 /* next */ 394 cbData = (cbData + 3) & ~KU32_C(3); 395 off += cbData + sizeof(*pHdr); 396 } 397 398 /* 399 * Did we find any source files and strings? 400 */ 401 if (!pchStrTab || !uSrcFiles.pv) 402 { 403 dprintf(("No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv)); 404 return 2; 405 } 406 407 /* 408 * Iterate the source file table. 409 */ 410 off = 0; 411 while (off < cbSrcFiles) 412 { 413 KU32 offFile; 414 const char *pszFile; 415 KSIZE cchFile; 416 KU16 u16Type; 417 KPCUINT uSrc; 418 KU32 cbSrc; 419 420 /* 421 * Validate and parse the entry (variable length record are fun). 422 */ 423 if (off + 8 > cbSrcFiles) 424 { 425 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KSIZE_PRI "\n", 426 argv0, off, cbSrcFiles); 427 return 1; 428 } 429 uSrc.pb = uSrcFiles.pb + off; 430 u16Type = uSrc.pu16[2]; 431 cbSrc = u16Type == 0x0110 ? 6 + 16 + 2 : 6 + 2; 432 if (off + cbSrc > cbSrcFiles) 433 { 434 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KSIZE_PRI "\n", 435 argv0, off, cbSrc, cbSrcFiles); 436 return 1; 437 } 438 439 offFile = *uSrc.pu32; 440 if (offFile > cbStrTab) 441 { 442 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is out side the string table; offFile=%#" KX32_PRI " cbStrTab=%#" KX32_PRI "\n", 443 argv0, off, offFile, cbStrTab); 444 return 1; 445 } 446 pszFile = pchStrTab + offFile; 447 cchFile = strlen(pszFile); 448 if (cchFile == 0) 449 { 450 fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " has an empty file name; offFile=%#x" KX32_PRI "\n", 451 argv0, off, offFile); 452 return 1; 453 } 454 455 /* 456 * Display the result and add it to the dependency database. 457 */ 458 depAdd(pszFile, cchFile); 459 if (u16Type == 0x0110) 460 dprintf(("#%03" KU32_PRI ": {todo-md5-todo} '%s'\n", 461 iSrc, pszFile)); 462 else 463 dprintf(("#%03" KU32_PRI ": type=%#06" KX16_PRI " '%s'\n", iSrc, u16Type, pszFile)); 464 465 466 /* next */ 467 iSrc++; 468 off += cbSrc; 469 } 470 471 if (iSrc == 0) 472 { 473 dprintf(("No cylindrical smoking thing: iSrc=0\n")); 474 return 2; 475 } 476 dprintf(("iSrc=%" KU32_PRI "\n", iSrc)); 477 return 0; 478 } 479 480 481 /** 482 * Parses the OMF file. 483 * 484 * @returns 0 on success, 1 on failure, 2 if no dependencies was found. 485 * @param pbFile The start of the file. 486 * @param cbFile The file size. 487 */ 488 int kDepObjCOFFParse(const KU8 *pbFile, KSIZE cbFile) 489 { 490 IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; 491 IMAGE_SECTION_HEADER const *paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); 492 unsigned cSHdrs = pFileHdr->NumberOfSections; 493 unsigned iSHdr; 494 KPCUINT u; 495 int rcRet = 2; 496 int rc; 497 498 printf("COFF file!\n"); 499 500 for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) 501 { 502 if ( !memcmp(paSHdrs[iSHdr].Name, ".debug$S", sizeof(".debug$S") - 1) 503 && paSHdrs[iSHdr].SizeOfRawData > 4) 504 { 505 u.pb = pbFile + paSHdrs[iSHdr].PointerToRawData; 506 dprintf(("CV symbol table: version=%x\n", *u.pu32)); 507 if (*u.pu32 == 0x000000004) 508 rc = kDepObjCOFFParseCV8SymbolSection(u.pb, paSHdrs[iSHdr].SizeOfRawData); 509 else 510 rc = 2; 511 dprintf(("rc=%d\n", rc)); 512 if (rcRet == 2) 513 rcRet = rc; 514 if (rcRet != 2) 515 return rc; 516 } 517 printf("#%d: %.8s\n", iSHdr, paSHdrs[iSHdr].Name); 518 } 519 return rcRet; 520 } 521 522 523 /** 524 * Checks if this file is a COFF file or not. 525 * 526 * @returns K_TRUE if it's COFF, K_FALSE otherwise. 527 * 528 * @param pb The start of the file. 529 * @param cb The file size. 530 */ 531 KBOOL kDepObjCOFFTest(const KU8 *pbFile, KSIZE cbFile) 532 { 533 IMAGE_FILE_HEADER const *pFileHdr = (IMAGE_FILE_HEADER const *)pbFile; 534 IMAGE_SECTION_HEADER const *paSHdrs = (IMAGE_SECTION_HEADER const *)((KU8 const *)(pFileHdr + 1) + pFileHdr->SizeOfOptionalHeader); 535 unsigned cSHdrs = pFileHdr->NumberOfSections; 536 unsigned iSHdr; 537 KSIZE cbHdrs = (const KU8 *)&paSHdrs[cSHdrs] - (const KU8 *)pbFile; 538 539 if (cbFile <= sizeof(*pFileHdr)) 540 return K_FALSE; 541 if ( pFileHdr->Machine != IMAGE_FILE_MACHINE_I386 542 && pFileHdr->Machine != IMAGE_FILE_MACHINE_AMD64) 543 return K_FALSE; 544 if (pFileHdr->SizeOfOptionalHeader != 0) 545 return K_FALSE; /* COFF files doesn't have an optional header */ 546 547 if ( pFileHdr->NumberOfSections <= 1 548 || pFileHdr->NumberOfSections > cbFile) 549 return K_FALSE; 550 551 if (cbHdrs >= cbFile) 552 return K_FALSE; 553 554 if ( pFileHdr->PointerToSymbolTable != 0 555 && ( pFileHdr->PointerToSymbolTable < cbHdrs 556 || pFileHdr->PointerToSymbolTable > cbFile)) 557 return K_FALSE; 558 if ( pFileHdr->PointerToSymbolTable == 0 559 && pFileHdr->NumberOfSymbols != 0) 560 return K_FALSE; 561 if ( pFileHdr->Characteristics 562 & ( IMAGE_FILE_DLL 563 | IMAGE_FILE_SYSTEM 564 | IMAGE_FILE_UP_SYSTEM_ONLY 565 | IMAGE_FILE_NET_RUN_FROM_SWAP 566 | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 567 | IMAGE_FILE_EXECUTABLE_IMAGE 568 | IMAGE_FILE_RELOCS_STRIPPED)) 569 return K_FALSE; 570 571 for (iSHdr = 0; iSHdr < cSHdrs; iSHdr++) 572 { 573 if ( paSHdrs[iSHdr].PointerToRawData != 0 574 && ( paSHdrs[iSHdr].PointerToRawData < cbHdrs 575 || paSHdrs[iSHdr].PointerToRawData >= cbFile 576 || paSHdrs[iSHdr].PointerToRawData + paSHdrs[iSHdr].SizeOfRawData > cbFile)) 577 return K_FALSE; 578 if ( paSHdrs[iSHdr].PointerToRelocations != 0 579 && ( paSHdrs[iSHdr].PointerToRelocations < cbHdrs 580 || paSHdrs[iSHdr].PointerToRelocations >= cbFile 581 || paSHdrs[iSHdr].PointerToRelocations + paSHdrs[iSHdr].NumberOfRelocations * 10 > cbFile)) /* IMAGE_RELOCATION */ 582 return K_FALSE; 583 if ( paSHdrs[iSHdr].PointerToLinenumbers != 0 584 && ( paSHdrs[iSHdr].PointerToLinenumbers < cbHdrs 585 || paSHdrs[iSHdr].PointerToLinenumbers >= cbFile 586 || paSHdrs[iSHdr].PointerToLinenumbers + paSHdrs[iSHdr].NumberOfLinenumbers * 6 > cbFile)) /* IMAGE_LINENUMBER */ 587 return K_FALSE; 588 } 254 589 255 590 return K_TRUE; … … 279 614 if (kDepObjOMFTest(pbFile, cbFile)) 280 615 rc = kDepObjOMFParse(pbFile, cbFile); 616 else if (kDepObjCOFFTest(pbFile, cbFile)) 617 rc = kDepObjCOFFParse(pbFile, cbFile); 281 618 else 282 619 {
Note:
See TracChangeset
for help on using the changeset viewer.