- Timestamp:
- Jul 18, 2015 5:43:19 PM (9 years ago)
- Location:
- trunk/src/bldprogs
- Files:
-
- 2 added
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/Makefile.kmk
r56920 r56977 72 72 73 73 # temp hack. 74 gccplugin.o gccplugin: gccplugin$(SUFF_DLL) 75 gccplugin$(SUFF_DLL): gccplugin.cpp 76 g++ -shared -fPIC -g -I$(shell gcc -print-file-name=plugin/include) -I$(PATH_ROOT)/include -DIN_RING3 -o $@ $< 74 VBoxCompilerPlugInsGcc.o VBoxCompilerPlugInsCommon.o VBoxCompilerPlugIns.o gccplugin: gccplugin$(SUFF_DLL) 75 gccplugin$(SUFF_DLL): VBoxCompilerPlugInsGcc.cpp VBoxCompilerPlugInsCommon.cpp VBoxCompilerPlugIns.h 76 g++ -shared -fPIC -g \ 77 -DIN_RING3 \ 78 $(if-expr "$(KBUILD_TYPE)" != "release",-DDEBUG,) \ 79 -I$(shell gcc -print-file-name=plugin/include) \ 80 -I$(PATH_ROOT)/include \ 81 -o $@ \ 82 VBoxCompilerPlugInsGcc.cpp \ 83 VBoxCompilerPlugInsCommon.cpp 77 84 78 85 -
trunk/src/bldprogs/VBoxCompilerPlugInsGcc.cpp
r56976 r56977 22 22 #include <iprt/cdefs.h> 23 23 #include <iprt/stdarg.h> 24 #include <iprt/string.h>25 24 26 25 #include "plugin.h" … … 31 30 #include "cp/cp-tree.h" 32 31 32 #include "VBoxCompilerPlugIns.h" 33 33 34 34 35 /********************************************************************************************************************************* … … 42 43 * Defined Constants And Macros * 43 44 *********************************************************************************************************************************/ 44 #define GCCPLUGIN_DEBUG45 /** Debug printf. */46 #ifdef GCCPLUGIN_DEBUG47 # define dprintf(...) do { fprintf(stderr, __VA_ARGS__); } while (0)48 #else49 # define dprintf(...) do { } while (0)50 #endif51 52 45 /** Convencience macro not present in earlier gcc versions. */ 53 46 #ifndef VAR_P … … 61 54 #define MY_LOC(a_hPreferred, a_pState) EXPR_LOC_OR_LOC(a_hPreferred, (a_pState)->hFmtLoc) 62 55 63 #define MY_ISDIGIT(c) ((c) >= '0' && (c) <= '9')64 65 66 /*******************************************************************************67 * Structures and Typedefs *68 *******************************************************************************/69 /** Checker state. */70 typedef struct MYCHECKSTATE71 {72 gimple hStmt;73 long iFmt;74 long iArgs;75 location_t hFmtLoc;76 const char *pszFmt;77 } MYCHECKSTATE;78 /** Pointer to my checker state. */79 typedef MYCHECKSTATE *PMYCHECKSTATE;80 56 81 57 … … 147 123 148 124 149 #ifdef GCCPLUGIN_DEBUG125 #ifdef DEBUG 150 126 151 127 /** … … 195 171 } 196 172 197 #endif /* GCCPLUGIN_DEBUG */ 198 199 200 /** 201 * Gate callback for my pass that indicates whether it should execute or not. 202 * @returns true to execute. 203 */ 204 static bool MyPassGateCallback(void) 205 { 206 dprintf("MyPassGateCallback:\n"); 207 return true; 208 } 209 210 211 #define MYSTATE_FMT_FILE(a_pState) LOCATION_FILE((a_pState)->hFmtLoc) 212 #define MYSTATE_FMT_LINE(a_pState) LOCATION_LINE((a_pState)->hFmtLoc) 213 #define MYSTATE_FMT_COLUMN(a_pState) LOCATION_COLUMN((a_pState)->hFmtLoc) 214 215 void MyCheckWarnFmt(PMYCHECKSTATE pState, const char *pszLoc, const char *pszFormat, ...) 216 { 217 char szTmp[1024]; 218 va_list va; 219 va_start(va, pszFormat); 220 vsnprintf(szTmp, sizeof(szTmp), pszFormat, va); 221 va_end(va); 222 223 224 /* Create a location for pszLoc. */ 225 location_t hLoc = pState->hFmtLoc; 173 #endif /* DEBUG */ 174 175 176 static location_t MyGetLocationPlusColumnOffset(location_t hLoc, unsigned int offColumn) 177 { 178 /* 179 * Skip NOOPs, reserved locations and macro expansion. 180 */ 181 if ( offColumn != 0 182 && hLoc >= RESERVED_LOCATION_COUNT 183 && !linemap_location_from_macro_expansion_p(line_table, hLoc)) 184 { 226 185 #if __GNUC__ >= 5 /** @todo figure this... */ 186 /* 187 * There is an API for doing this, nice. 188 */ 189 location_t hNewLoc = linemap_position_for_loc_and_offset(line_table, hLoc, offColumn); 190 if (hNewLoc && hNewLoc != hLoc) 191 { 192 dprintf("MyGetLocationPlusColumnOffset: hNewLoc=%#x hLoc=%#x offColumn=%u\n", hNewLoc, hLoc, offColumn); 193 return hNewLoc; 194 } 195 196 #else 197 /* 198 * Have to do the job ourselves, it seems. This is a bit hairy... 199 */ 200 line_map const *pMap = NULL; 201 location_t hLoc2 = linemap_resolve_location(line_table, hLoc, LRK_SPELLING_LOCATION, &pMap); 202 if (hLoc2) 203 hLoc = hLoc2; 204 205 /* Guard against wrap arounds and overlaps. */ 206 if ( hLoc + offColumn > MAP_START_LOCATION(pMap) /** @todo Use MAX_SOURCE_LOCATION? */ 207 && ( pMap == LINEMAPS_LAST_ORDINARY_MAP(line_table) 208 || hLoc + offColumn < MAP_START_LOCATION((pMap + 1)))) 209 { 210 /* Calc new column and check that it's within the valid range. */ 211 unsigned int uColumn = SOURCE_COLUMN(pMap, hLoc) + offColumn; 212 if (uColumn < RT_BIT_32(ORDINARY_MAP_NUMBER_OF_COLUMN_BITS(pMap))) 213 { 214 /* Try add the position. If we get a valid result, replace the location. */ 215 source_location hNewLoc = linemap_position_for_line_and_column((line_map *)pMap, SOURCE_LINE(pMap, hLoc), uColumn); 216 if ( hNewLoc <= line_table->highest_location 217 && linemap_lookup(line_table, hNewLoc) != NULL) 218 { 219 dprintf("MyGetLocationPlusColumnOffset: hNewLoc=%#x hLoc=%#x offColumn=%u uColumn=%u\n", 220 hNewLoc, hLoc, offColumn, uColumn); 221 return hNewLoc; 222 } 223 } 224 } 225 #endif 226 } 227 dprintf("MyGetLocationPlusColumnOffset: taking fallback\n"); 228 return hLoc; 229 } 230 231 232 static location_t MyGetFormatStringLocation(PVFMTCHKSTATE pState, const char *pszLoc) 233 { 234 location_t hLoc = pState->hFmtLoc; 227 235 intptr_t offString = pszLoc - pState->pszFmt; 228 if ( offString > 0236 if ( offString >= 0 229 237 && !linemap_location_from_macro_expansion_p(line_table, hLoc)) 230 238 { 231 239 unsigned uCol = 1 + offString; 232 240 expanded_location XLoc = expand_location_to_spelling_point(hLoc); 233 int cchLine ;234 # 241 int cchLine = 0; 242 #if __GNUC__ >= 5 /** @todo figure this... */ 235 243 const char *pszLine = location_get_source_line(XLoc, &cchLine); 236 # 244 #else 237 245 const char *pszLine = location_get_source_line(XLoc); 238 int cchLine = 0;239 246 if (pszLine) 240 247 { … … 244 251 cchLine = (int)(pszEol - pszLine); 245 252 } 246 # 253 #endif 247 254 if (pszLine) 248 255 { … … 251 258 cchLine -= XLoc.column - 1; 252 259 } 253 location_t hNewLoc = linemap_position_for_loc_and_offset(line_table, hLoc, 0); 254 if (hNewLoc) 255 hLoc = hNewLoc; 256 } 257 #endif 258 259 /* display the warning. */ 260 warning_at(hLoc, 0, "%s", szTmp); 261 } 262 263 264 265 /** 266 * Checks that @a iFmtArg isn't present or a valid final dummy argument. 267 * 268 * Will issue warning/error if there are more arguments at @a iFmtArg. 269 * 270 * @param pState The format string checking state. 271 * @param iArg The index of the end of arguments, this is 272 * relative to MYCHECKSTATE::iArgs. 273 */ 274 void MyCheckFinalArg(PMYCHECKSTATE pState, unsigned iArg) 275 { 276 dprintf("MyCheckFinalArg: iArg=%u iArgs=%ld cArgs=%u\n", iArg, pState->iArgs, gimple_call_num_args(pState->hStmt)); 277 if (pState->iArgs > 0) 278 { 279 iArg += pState->iArgs - 1; 280 unsigned cArgs = gimple_call_num_args(pState->hStmt); 281 if (iArg == cArgs) 282 { /* fine */ } 283 else if (iArg < cArgs) 284 { 285 tree hArg = gimple_call_arg(pState->hStmt, iArg); 286 if (cArgs - iArg > 1) 287 warning_at(MY_LOC(hArg, pState), 0, "%u extra arguments not consumed by format string", cArgs - iArg); 288 else if ( TREE_CODE(hArg) != INTEGER_CST 289 || !TREE_INT_CST(hArg).fits_shwi() 290 || TREE_INT_CST(hArg).to_shwi() != -99) /* ignore final dummy argument: ..., -99); */ 291 warning_at(MY_LOC(hArg, pState), 0, "one extra argument not consumed by format string"); 292 } 293 /* This should be handled elsewhere, but just in case. */ 294 else if (iArg - 1 == cArgs) 295 warning_at(pState->hFmtLoc, 0, "one argument too few"); 296 else 297 warning_at(pState->hFmtLoc, 0, "%u arguments too few", iArg - cArgs); 298 } 299 } 300 301 void MyCheckIntArg(PMYCHECKSTATE pState, const char *pszFmt, unsigned iArg, const char *pszMessage) 302 { 303 304 } 305 306 307 308 /** 309 * Does the actual format string checking. 310 * 311 * @todo Move this to different file common to both GCC and CLANG later. 312 * 313 * @param pState The format string checking state. 314 * @param pszFmt The format string. 315 */ 316 void MyCheckFormatCString(PMYCHECKSTATE pState, const char *pszFmt) 317 { 318 dprintf("checker2: \"%s\" at %s:%d col %d\n", pszFmt, 319 MYSTATE_FMT_FILE(pState), MYSTATE_FMT_LINE(pState), MYSTATE_FMT_COLUMN(pState)); 320 pState->pszFmt = pszFmt; 321 322 unsigned iArg = 0; 323 for (;;) 324 { 325 /* 326 * Skip to the next argument. 327 * Quits the loop with the first char following the '%' in 'ch'. 328 */ 329 char ch; 330 for (;;) 331 { 332 ch = *pszFmt++; 333 if (ch == '%') 334 { 335 ch = *pszFmt++; 336 if (ch != '%') 337 break; 338 } 339 else if (ch == '\0') 340 { 341 MyCheckFinalArg(pState, iArg); 342 return; 343 } 344 } 345 346 /* 347 * Flags 348 */ 349 uint32_t fFlags = 0; 350 for (;;) 351 { 352 uint32_t fFlag; 353 switch (ch) 354 { 355 case '#': fFlag = RTSTR_F_SPECIAL; break; 356 case '-': fFlag = RTSTR_F_LEFT; break; 357 case '+': fFlag = RTSTR_F_PLUS; break; 358 case ' ': fFlag = RTSTR_F_BLANK; break; 359 case '0': fFlag = RTSTR_F_ZEROPAD; break; 360 case '\'': fFlag = RTSTR_F_THOUSAND_SEP; break; 361 default: fFlag = 0; break; 362 } 363 if (!fFlag) 364 break; 365 if (fFlags & fFlag) 366 MyCheckWarnFmt(pState, pszFmt - 1, "duplicate flag '%c'", ch); 367 fFlags |= fFlag; 368 ch = *pszFmt++; 369 } 370 371 /* 372 * Width. 373 */ 374 int cchWidth = -1; 375 if (MY_ISDIGIT(ch)) 376 { 377 cchWidth = ch - '0'; 378 while ( (ch = *pszFmt++) != '\0' 379 && MY_ISDIGIT(ch)) 380 { 381 cchWidth *= 10; 382 cchWidth += ch - '0'; 383 } 384 fFlags |= RTSTR_F_WIDTH; 385 } 386 else if (ch == '*') 387 { 388 MyCheckIntArg(pState, pszFmt - 1, iArg, "width should be an 'int' sized argument"); 389 iArg++; 390 cchWidth = 0; 391 fFlags |= RTSTR_F_WIDTH; 392 } 393 394 /* 395 * Precision 396 */ 397 int cchPrecision = -1; 398 if (ch == '.') 399 { 400 ch = *pszFmt++; 401 if (MY_ISDIGIT(ch)) 402 { 403 cchPrecision = ch - '0'; 404 while ( (ch = *pszFmt++) != '\0' 405 && MY_ISDIGIT(ch)) 406 { 407 cchPrecision *= 10; 408 cchPrecision += ch - '0'; 409 } 410 } 411 else if (ch == '*') 412 { 413 MyCheckIntArg(pState, pszFmt - 1, iArg, "precision should be an 'int' sized argument"); 414 iArg++; 415 cchWidth = 0; 416 } 417 else 418 MyCheckWarnFmt(pState, pszFmt - 1, "Missing precision value, only got the '.'"); 419 if (cchPrecision < 0) 420 { 421 MyCheckWarnFmt(pState, pszFmt - 1, "Negative precision value: %d", cchPrecision); 422 cchPrecision = 0; 423 } 424 fFlags |= RTSTR_F_PRECISION; 425 } 426 427 /* 428 * Argument size. 429 */ 430 char chArgSize = ch; 431 switch (ch) 432 { 433 default: 434 chArgSize = '\0'; 435 break; 436 437 case 'z': 438 case 'L': 439 case 'j': 440 case 't': 441 ch = *pszFmt++; 442 break; 443 444 case 'l': 445 ch = *pszFmt++; 446 if (ch == 'l') 447 { 448 chArgSize = 'L'; 449 ch = *pszFmt++; 450 } 451 break; 452 453 case 'h': 454 ch = *pszFmt++; 455 if (ch == 'h') 456 { 457 chArgSize = 'H'; 458 ch = *pszFmt++; 459 } 460 break; 461 462 case 'I': /* Used by Win32/64 compilers. */ 463 if ( pszFmt[0] == '6' 464 && pszFmt[1] == '4') 465 { 466 pszFmt += 2; 467 chArgSize = 'L'; 468 } 469 else if ( pszFmt[0] == '3' 470 && pszFmt[1] == '2') 471 { 472 pszFmt += 2; 473 chArgSize = 0; 474 } 475 else 476 chArgSize = 'j'; 477 ch = *pszFmt++; 478 break; 479 480 case 'q': /* Used on BSD platforms. */ 481 chArgSize = 'L'; 482 ch = *pszFmt++; 483 break; 484 } 485 486 /* 487 * The type. 488 */ 489 490 } 260 261 hLoc = MyGetLocationPlusColumnOffset(hLoc, uCol); 262 } 263 return hLoc; 491 264 } 492 265 … … 501 274 * @param hFmtArg The format string node. 502 275 */ 503 DECL_NO_INLINE(static, void) MyCheckFormatNonRecursive(P MYCHECKSTATE pState, tree hFmtArg)276 DECL_NO_INLINE(static, void) MyCheckFormatNonRecursive(PVFMTCHKSTATE pState, tree hFmtArg) 504 277 { 505 278 dprintf("checker: hFmtArg=%p %s\n", hFmtArg, tree_code_name[TREE_CODE(hFmtArg)]); … … 636 409 * @param hFmtArg The format string node. 637 410 */ 638 static void MyCheckFormatRecursive(P MYCHECKSTATE pState, tree hFmtArg)411 static void MyCheckFormatRecursive(PVFMTCHKSTATE pState, tree hFmtArg) 639 412 { 640 413 /* … … 689 462 gimple const hStmt = gsi_stmt(hStmtItr); 690 463 enum gimple_code const enmCode = gimple_code(hStmt); 691 #ifdef GCCPLUGIN_DEBUG464 #ifdef DEBUG 692 465 unsigned const cOps = gimple_num_ops(hStmt); 693 466 dprintf(" hStmt=%p %s (%d) ops=%d\n", hStmt, gimple_code_name[enmCode], enmCode, cOps); … … 709 482 tree const hFnType = gimple_call_fntype(hStmt); 710 483 tree const hAttr = lookup_attribute("iprt_format", TYPE_ATTRIBUTES(hFnType)); 711 #ifdef GCCPLUGIN_DEBUG484 #ifdef DEBUG 712 485 tree const hFnDecl = gimple_call_fndecl(hStmt); 713 486 dprintf(" hFn =%p %s(%d); args=%d\n", … … 725 498 */ 726 499 tree const hAttrArgs = TREE_VALUE(hAttr); 727 MYCHECKSTATE State;500 VFMTCHKSTATE State; 728 501 State.iFmt = TREE_INT_CST(TREE_VALUE(hAttrArgs)).to_shwi(); 729 502 State.iArgs = TREE_INT_CST(TREE_VALUE(TREE_CHAIN(hAttrArgs))).to_shwi(); … … 743 516 744 517 518 /** 519 * Gate callback for my pass that indicates whether it should execute or not. 520 * @returns true to execute. 521 */ 522 static bool MyPassGateCallback(void) 523 { 524 dprintf("MyPassGateCallback:\n"); 525 return true; 526 } 527 745 528 746 529 /** … … 810 593 } 811 594 595 596 597 598 /* 599 * 600 * Functions used by the common code. 601 * Functions used by the common code. 602 * Functions used by the common code. 603 * 604 */ 605 606 void VFmtChkWarnFmt(PVFMTCHKSTATE pState, const char *pszLoc, const char *pszFormat, ...) 607 { 608 char szTmp[1024]; 609 va_list va; 610 va_start(va, pszFormat); 611 vsnprintf(szTmp, sizeof(szTmp), pszFormat, va); 612 va_end(va); 613 614 /* display the warning. */ 615 warning_at(MyGetFormatStringLocation(pState, pszLoc), 0, "%s", szTmp); 616 } 617 618 619 620 void VFmtChkVerifyEndOfArgs(PVFMTCHKSTATE pState, unsigned iArg) 621 { 622 dprintf("VFmtChkVerifyFinalArg: iArg=%u iArgs=%ld cArgs=%u\n", iArg, pState->iArgs, gimple_call_num_args(pState->hStmt)); 623 if (pState->iArgs > 0) 624 { 625 iArg += pState->iArgs - 1; 626 unsigned cArgs = gimple_call_num_args(pState->hStmt); 627 if (iArg == cArgs) 628 { /* fine */ } 629 else if (iArg < cArgs) 630 { 631 tree hArg = gimple_call_arg(pState->hStmt, iArg); 632 if (cArgs - iArg > 1) 633 warning_at(MY_LOC(hArg, pState), 0, "%u extra arguments not consumed by format string", cArgs - iArg); 634 else if ( TREE_CODE(hArg) != INTEGER_CST 635 || !TREE_INT_CST(hArg).fits_shwi() 636 || TREE_INT_CST(hArg).to_shwi() != -99) /* ignore final dummy argument: ..., -99); */ 637 warning_at(MY_LOC(hArg, pState), 0, "one extra argument not consumed by format string"); 638 } 639 /* This should be handled elsewhere, but just in case. */ 640 else if (iArg - 1 == cArgs) 641 warning_at(pState->hFmtLoc, 0, "one argument too few"); 642 else 643 warning_at(pState->hFmtLoc, 0, "%u arguments too few", iArg - cArgs); 644 } 645 } 646 647 648 bool VFmtChkRequirePresentArg(PVFMTCHKSTATE pState, const char *pszLoc, unsigned iArg, const char *pszMessage) 649 { 650 if (pState->iArgs > 0) 651 { 652 iArg += pState->iArgs - 1; 653 unsigned cArgs = gimple_call_num_args(pState->hStmt); 654 if (iArg >= cArgs) 655 { 656 VFmtChkWarnFmt(pState, pszLoc, "Missing argument! %s", pszMessage); 657 return false; 658 } 659 } 660 return true; 661 } 662 663 664 bool VFmtChkRequireIntArg(PVFMTCHKSTATE pState, const char *pszLoc, unsigned iArg, const char *pszMessage) 665 { 666 if (VFmtChkRequirePresentArg(pState, pszLoc, iArg, pszMessage)) 667 { 668 /** @todo type check. */ 669 return true; 670 } 671 return false; 672 } 673 674 675 bool VFmtChkRequireStringArg(PVFMTCHKSTATE pState, const char *pszLoc, unsigned iArg, const char *pszMessage) 676 { 677 if (VFmtChkRequirePresentArg(pState, pszLoc, iArg, pszMessage)) 678 { 679 /** @todo type check. */ 680 return true; 681 } 682 return false; 683 } 684 685 686 bool VFmtChkRequireVaListPtrArg(PVFMTCHKSTATE pState, const char *pszLoc, unsigned iArg, const char *pszMessage) 687 { 688 if (VFmtChkRequirePresentArg(pState, pszLoc, iArg, pszMessage)) 689 { 690 /** @todo type check. */ 691 return true; 692 } 693 return false; 694 } 695 696 697 698 void VFmtChkHandleReplacementFormatString(PVFMTCHKSTATE pState, const char *pszPctM, unsigned iArg) 699 { 700 if (pState->iArgs > 0) 701 { 702 pState->iArgs += iArg; 703 704 } 705 } 706 707 708 const char *VFmtChkGetFmtLocFile(PVFMTCHKSTATE pState) 709 { 710 return LOCATION_FILE(pState->hFmtLoc); 711 } 712 713 714 unsigned int VFmtChkGetFmtLocLine(PVFMTCHKSTATE pState) 715 { 716 return LOCATION_LINE(pState->hFmtLoc); 717 } 718 719 720 unsigned int VFmtChkGetFmtLocColumn(PVFMTCHKSTATE pState) 721 { 722 return LOCATION_COLUMN(pState->hFmtLoc); 723 } 724
Note:
See TracChangeset
for help on using the changeset viewer.