Changeset 2278 in kBuild
- Timestamp:
- Feb 24, 2009 2:19:35 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/kDepObj.c
r2267 r2278 34 34 #include <errno.h> 35 35 #include <ctype.h> 36 #include <stdarg.h> 36 37 #ifdef HAVE_ALLOCA_H 37 38 # include <alloca.h> … … 66 67 #define KDEPOMF_THEADR 0x80 67 68 #define KDEPOMF_LHEADR 0x82 68 #define KDEPOMF_COMMENT 0x88 69 #define KDEPOMF_CMTCLS_DEPENDENCY 0xe9 69 #define KDEPOMF_COMENT 0x88 70 #define KDEPOMF_CMTCLS_DEPENDENCY 0xe9 71 #define KDEPOMF_CMTCLS_DBGTYPE 0xa1 72 #define KDEPOMF_LINNUM 0x94 73 #define KDEPOMF_LINNUM32 0x95 70 74 /** @} */ 71 75 … … 170 174 /** the executable name. */ 171 175 static const char *argv0 = ""; 176 static const char *g_pszFile = NULL; 177 178 179 /** 180 * Prints an error message. 181 * 182 * @returns rc. 183 * @param rc The return code, for making one line return statements. 184 * @param pszFormat The message format string. 185 * @param ... Format arguments. 186 * @todo Promote this to kDep.c. 187 */ 188 static int kDepErr(int rc, const char *pszFormat, ...) 189 { 190 va_list va; 191 const char *psz; 192 const char *pszName = argv0; 193 194 fflush(stdout); 195 196 /* The message prefix. */ 197 while ((psz = strpbrk(pszName, "/\\:")) != NULL) 198 pszName = psz + 1; 199 200 if (g_pszFile) 201 fprintf(stderr, "%s: %s: error: ", pszName, g_pszFile); 202 else 203 fprintf(stderr, "%s: error: ", pszName); 204 205 /* The message. */ 206 va_start(va, pszFormat); 207 vfprintf(stderr, pszFormat, va); 208 va_end(va); 209 210 return rc; 211 } 212 213 214 /** 215 * Gets an index from the data. 216 * 217 * @returns The index, KU16_MAX on buffer underflow. 218 * @param puData The current data stream position (in/out). 219 * @param pcbLeft Number of bytes left (in/out). 220 */ 221 static KU16 kDepObjOMFGetIndex(KPCUINT *puData, KU16 *pcbLeft) 222 { 223 KU16 u16; 224 225 if (*pcbLeft >= 1 && *pcbLeft != KU16_MAX) 226 { 227 *pcbLeft -= 1; 228 u16 = *puData->pb++; 229 if (u16 & KU16_C(0x80)) 230 { 231 if (*pcbLeft >= 1) 232 { 233 *pcbLeft -= 1; 234 u16 = ((u16 & KU16_C(0x7f)) << 8) | *puData->pb++; 235 } 236 else 237 u16 = KU16_MAX; 238 } 239 } 240 else 241 u16 = KU16_MAX; 242 return u16; 243 } 172 244 173 245 … … 175 247 * Parses the OMF file. 176 248 * 177 * @returns 0 on success, 1 on failure .249 * @returns 0 on success, 1 on failure, 2 if no dependencies was found. 178 250 * @param pbFile The start of the file. 179 251 * @param cbFile The file size. … … 181 253 int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile) 182 254 { 183 PCKDEPOMFHDR pHdr = (PCKDEPOMFHDR)pbFile; 184 KSIZE cbLeft = cbFile; 185 255 PCKDEPOMFHDR pHdr = (PCKDEPOMFHDR)pbFile; 256 KSIZE cbLeft = cbFile; 257 char uDbgType = 0; /* H or C */ 258 KU8 uDbgVer = KU8_MAX; 259 KU32 iSrc = 0; 260 KU32 iMaybeSrc = 0; 261 KU8 uLinNumType = KU8_MAX; 262 KU16 cLinNums = 0; 263 KU32 cLinFiles = 0; 264 KU32 iLinFile = 0; 186 265 187 266 /* … … 191 270 && cbLeft >= pHdr->cbRec + sizeof(*pHdr)) 192 271 { 272 KPCUINT uData; 273 uData.pv = pHdr + 1; 274 193 275 /* process selected record types. */ 194 276 dprintf(("%#07x: %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec)); … … 205 287 PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr; 206 288 if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec) 289 return kDepErr(1, "%#07x - Bad %cHEADR record, length mismatch.\n", 290 (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L'); 291 if ( ( pTHeadr->Name.cch > 2 292 && pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == '.' 293 && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'o' 294 || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'O')) 295 || ( pTHeadr->Name.cch > 4 296 && pTHeadr->Name.ach[pTHeadr->Name.cch - 4] == '.' 297 && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'o' 298 || pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'O') 299 && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'b' 300 || pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'B') 301 && ( pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'j' 302 || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'J')) 303 ) 304 dprintf(("%cHEADR: %.*s [ignored]\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); 305 else 207 306 { 208 fprintf(stderr, "%s: error: %#07x - Bad %cHEADR record, length mismatch.\n",209 argv0, (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L');210 return 1;307 dprintf(("%cHEADR: %.*s\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach)); 308 depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch); 309 iMaybeSrc++; 211 310 } 212 depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch);311 uLinNumType = KU8_MAX; 213 312 break; 214 313 } 215 314 216 case KDEPOMF_COMMENT: 217 if (pHdr->cbRec < 2) 218 { 219 fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, too small.\n", 220 argv0, (const KU8*)pHdr - pbFile); 221 return 1; 222 } 223 if (((const KU8 *)(pHdr+1))[0] & 0x3f) 224 { 225 fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, reserved flags set.\n", 226 argv0, (const KU8*)pHdr - pbFile); 227 return 1; 228 } 229 switch (((const KU8 *)(pHdr+1))[1]) 315 case KDEPOMF_COMENT: 316 { 317 KU8 uClass; 318 319 if (pHdr->cbRec < 2 + 1) 320 return kDepErr(1, "%#07x - Bad COMMENT record, too small.\n", (const KU8*)pHdr - pbFile); 321 if (uData.pb[0] & 0x3f) 322 return kDepErr(1, "%#07x - Bad COMMENT record, reserved flags set.\n", (const KU8*)pHdr - pbFile); 323 uClass = uData.pb[1]; 324 uData.pb += 2; 325 switch (uClass) 230 326 { 231 327 /* … … 241 337 if (pHdr->cbRec == 2 + 1) 242 338 return 0; 243 244 fprintf(stderr, "%s: error: %#07x - Bad DEPENDENCY FILE record, length mismatch. (%d/%d)\n", 245 argv0, (const KU8*)pHdr - pbFile, 246 K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1, 247 pHdr->cbRec + sizeof(*pHdr)); 248 return 1; 249 339 return kDepErr(1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u)\n", 340 (long)((const KU8 *)pHdr - pbFile), 341 K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1, 342 (unsigned)(pHdr->cbRec + sizeof(*pHdr))); 250 343 } 251 344 depAdd(pDep->Name.ach, pDep->Name.cch); 345 iSrc++; 252 346 break; 253 347 } 254 348 255 /** @todo Check for class A1 and pick up the debug info type (HL/CV(/DX)). */ 349 /* 350 * Pick up the debug type so we can parse the LINNUM records. 351 */ 352 case KDEPOMF_CMTCLS_DBGTYPE: 353 if (pHdr->cbRec < 2 + 3 + 1) 354 break; /* ignore, Borland used this for something else apparently. */ 355 if ( !(uData.pb[1] == 'C' && uData.pb[2] == 'V') 356 && !(uData.pb[1] == 'H' && uData.pb[2] == 'L')) 357 { 358 dprintf(("Unknown debug type: %c%c (%u)\n", uData.pb[1], uData.pb[2], uData.pb[0])); 359 break; 360 } 361 uDbgType = uData.pb[1]; 362 uDbgVer = uData.pb[0]; 363 dprintf(("Debug Type %s ver %u\n", uDbgType == 'H' ? "HLL" : "CodeView", uDbgVer)); 364 break; 365 256 366 } 367 break; /* COMENT */ 368 } 369 370 /* 371 * LINNUM + THEADR == sigar. 372 */ 373 case KDEPOMF_LINNUM: 374 if (uDbgType == 'C') 375 iMaybeSrc |= KU32_C(0x80000000); 376 dprintf(("LINNUM:\n")); 257 377 break; 258 /** @todo add support for HLL line number segments and stuff. */ 378 379 /* 380 * The HLL v4 and v6 file names table will include all files when present, which 381 * is perfect for generating dependencies. 382 */ 383 case KDEPOMF_LINNUM32: 384 if ( uDbgType == 'H' 385 && uDbgVer >= 3 386 && uDbgVer <= 6) 387 { 388 /* skip two indexes (group & segment) */ 389 KU16 cbRecLeft = pHdr->cbRec - 1; 390 KU16 uGrp = kDepObjOMFGetIndex(&uData, &cbRecLeft); 391 KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft); 392 if (uSeg == KU16_MAX) 393 return kDepErr(1, "%#07lx - Bad LINNUM32 record\n", (long)((const KU8 *)pHdr - pbFile)); 394 395 if (uLinNumType == KU8_MAX) 396 { 397 static const char * const s_apsz[5] = 398 { 399 "source file", "listing file", "source & listing file", "file names table", "path table" 400 }; 401 KU16 uLine; 402 KU8 uReserved; 403 KU16 uSeg2; 404 KU32 cbLinNames; 405 406 if (cbRecLeft < 2+1+1+2+2+4) 407 return kDepErr(1, "%#07lx - Bad LINNUM32 record, too short\n", (long)((const KU8 *)pHdr - pbFile)); 408 cbRecLeft -= 2+1+1+2+2+4; 409 uLine = *uData.pu16++; 410 uLinNumType = *uData.pu8++; 411 uReserved = *uData.pu8++; 412 cLinNums = *uData.pu16++; 413 uSeg2 = *uData.pu16++; 414 cbLinNames = *uData.pu32++; 415 416 dprintf(("LINNUM32: uGrp=%#x uSeg=%#x uSeg2=%#x uLine=%#x (MBZ) uReserved=%#x\n", 417 uGrp, uSeg, uSeg2, uLine, uReserved)); 418 dprintf(("LINNUM32: cLinNums=%#x (%u) cbLinNames=%#x (%u) uLinNumType=%#x (%s)\n", 419 cLinNums, cLinNums, cbLinNames, cbLinNames, uLinNumType, 420 uLinNumType < K_ELEMENTS(s_apsz) ? s_apsz[uLinNumType] : "??")); 421 if (uLine != 0) 422 return kDepErr(1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)\n", (long)((const KU8 *)pHdr - pbFile), uLine); 423 cLinFiles = iLinFile = KU32_MAX; 424 if ( uLinNumType == 3 /* file names table */ 425 || uLinNumType == 4 /* path table */) 426 cLinNums = 0; /* no line numbers */ 427 else if (uLinNumType > 4) 428 return kDepErr(1, "%#07lx - Bad LINNUM32 record, type %#x unknown\n", (long)((const KU8 *)pHdr - pbFile), uLinNumType); 429 } 430 else 431 dprintf(("LINNUM32: uGrp=%#x uSeg=%#x\n", uGrp, uSeg)); 432 433 434 /* Skip file numbers (we parse them to follow the stream correctly). */ 435 if (uLinNumType != 3 && uLinNumType != 4) 436 { 437 static const unsigned s_acbTypes[3] = { 2+2+4, 4+4+4, 2+2+4+4+4 }; 438 unsigned cbEntry = s_acbTypes[uLinNumType]; 439 440 while (cLinNums && cbRecLeft) 441 { 442 if (cbRecLeft < cbEntry) 443 return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete line entry\n", (long)((const KU8 *)pHdr - pbFile)); 444 445 switch (uLinNumType) 446 { 447 case 0: /* source file */ 448 dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI " at %#010" KX32_PRI "\n", 449 uData.pu16[0], uData.pu16[1], uData.pu32[1])); 450 break; 451 case 1: /* listing file */ 452 dprintf((" Line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", 453 uData.pu32[0], uData.pu32[1], uData.pu32[2])); 454 break; 455 case 2: /* source & listing file */ 456 dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI ", listning line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n", 457 uData.pu16[0], uData.pu16[1], uData.pu32[1], uData.pu32[2], uData.pu32[3])); 458 break; 459 } 460 uData.pb += cbEntry; 461 cbRecLeft -= cbEntry; 462 cLinNums--; 463 } 464 465 /* If at end of the announced line number entiries, we may find a file names table 466 here (who is actually emitting this?). */ 467 if (!cLinNums) 468 { 469 uLinNumType = cbRecLeft > 0 ? 3 : KU8_MAX; 470 dprintf(("End-of-line-numbers; uLinNumType=%u cbRecLeft=%#x\n", uLinNumType, cbRecLeft)); 471 } 472 } 473 474 if (uLinNumType == 3 || uLinNumType == 4) 475 { 476 /* Read the file/path table header (first time only). */ 477 if (cLinFiles == KU32_MAX && iLinFile == KU32_MAX) 478 { 479 KU32 iFirstCol; 480 KU32 cCols; 481 482 if (cbRecLeft < 4+4+4) 483 return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header\n", (long)((const KU8 *)pHdr - pbFile)); 484 cbRecLeft -= 4+4+4; 485 486 iFirstCol = *uData.pu32++; 487 cCols = *uData.pu32++; 488 cLinFiles = *uData.pu32++; 489 dprintf(("%s table header: cLinFiles=%#" KX32_PRI " (%" KU32_PRI ") iFirstCol=%" KU32_PRI " cCols=%" KU32_PRI"\n", 490 uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols)); 491 if (cLinFiles == KU32_MAX) 492 return kDepErr(1, "%#07lx - Bad LINNUM32 record, too many file/path table entries.\n", (long)((const KU8 *)pHdr - pbFile)); 493 iLinFile = 0; 494 } 495 496 /* Parse the file names / path table. */ 497 while (iLinFile < cLinFiles && cbRecLeft) 498 { 499 int cbName = *uData.pb++; 500 if (cbRecLeft < 1 + cbName) 501 return kDepErr(1, "%#07lx - Bad LINNUM32 record, file/path table entry too long.\n", (long)((const KU8 *)pHdr - pbFile)); 502 iLinFile++; 503 dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch)); 504 if (uLinNumType == 3) 505 { 506 depAdd(uData.pch, cbName); 507 iSrc++; 508 } 509 cbRecLeft -= 1 + cbName; 510 uData.pb += cbName; 511 } 512 513 /* The end? */ 514 if (iLinFile == cLinFiles) 515 { 516 uLinNumType = KU8_MAX; 517 dprintf(("End-of-file/path-table; cbRecLeft=%#x\n", cbRecLeft)); 518 } 519 } 520 } 521 else 522 dprintf(("LINNUM32: Unknown or unsupported format\n")); 523 break; 524 259 525 } 260 526 … … 265 531 266 532 if (cbLeft) 267 { 268 fprintf(stderr, "%s: error: %#07x - Unexpected EOF. cbLeft=%#x\n", 269 argv0, (const KU8*)pHdr - pbFile, cbLeft); 270 return 1; 271 } 533 return kDepErr(1, "%#07x - Unexpected EOF. cbLeft=%#x\n", (const KU8*)pHdr - pbFile, cbLeft); 534 535 if (iSrc == 0 && iMaybeSrc <= 1) 536 { 537 dprintf(("kDepObjOMFParse: No cylindrical smoking thing: iSrc=0 iMaybeSrc=%#" KX32_PRI"\n", iMaybeSrc)); 538 return 2; 539 } 540 dprintf(("kDepObjOMFParse: iSrc=%" KU32_PRI " iMaybeSrc=%#" KX32_PRI "\n", iSrc, iMaybeSrc)); 272 541 return 0; 273 542 } … … 303 572 * Parses a CodeView 8 symbol section. 304 573 * 305 * @returns 0 on success, 1 on failure .574 * @returns 0 on success, 1 on failure, 2 if no dependencies was found. 306 575 * @param pbSyms Pointer to the start of the symbol section. 307 576 * @param cbSyms Size of the symbol section. … … 364 633 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData)); 365 634 if (pchStrTab) 366 fprintf(stderr, "%s: warning: Found yet another string table!\n" );635 fprintf(stderr, "%s: warning: Found yet another string table!\n", argv0); 367 636 pchStrTab = uData.pch; 368 637 cbStrTab = cbData; … … 373 642 dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData)); 374 643 if (uSrcFiles.pb) 375 fprintf(stderr, "%s: warning: Found yet another source files table!\n" );644 fprintf(stderr, "%s: warning: Found yet another source files table!\n", argv0); 376 645 uSrcFiles = uData; 377 646 cbSrcFiles = cbData; … … 401 670 if (!pchStrTab || !uSrcFiles.pv) 402 671 { 403 dprintf((" No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv));672 dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv)); 404 673 return 2; 405 674 } … … 471 740 if (iSrc == 0) 472 741 { 473 dprintf((" No cylindrical smoking thing: iSrc=0\n"));742 dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: iSrc=0\n")); 474 743 return 2; 475 744 } 476 dprintf((" iSrc=%" KU32_PRI "\n", iSrc));745 dprintf(("kDepObjCOFFParseCV8SymbolSection: iSrc=%" KU32_PRI "\n", iSrc)); 477 746 return 0; 478 747 }
Note:
See TracChangeset
for help on using the changeset viewer.