Changeset 105378 in vbox for trunk/src/bldprogs
- Timestamp:
- Jul 17, 2024 2:07:15 PM (8 months ago)
- svn:sync-xref-src-repo-rev:
- 164031
- Location:
- trunk/src/bldprogs
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/VBoxCompilerPlugIns.h
r98103 r105378 51 51 typedef struct VFMTCHKSTATE 52 52 { 53 long iFmt; 54 long iArgs; 55 const char *pszFmt; 56 bool fMaybeNull; 53 long iFmt; /**< The format argument number from the attribute. */ 54 long iArgs; /**< The arguments argument number from the attribute. */ 55 bool fMaybeNull; /**< Set if in iprt_format_maybe_null mode. */ 56 const char *pszFmt; /**< The format string being validated, if a constant. */ 57 57 58 #if defined(__GNUC__) && !defined(VBOX_COMPILER_PLUG_IN_AGNOSTIC) 59 /** @name GCC specifics 60 * @{ */ 58 61 # if RT_GNUC_PREREQ(6, 0) 59 62 gimple const *hStmt; … … 61 64 gimple hStmt; 62 65 # endif 63 location_t hFmtLoc; 66 location_t hFmtLoc; /**< The statement or format-string location */ 67 /** @} */ 64 68 #endif 65 69 } VFMTCHKSTATE; -
trunk/src/bldprogs/VBoxCompilerPlugInsGcc.cpp
r105352 r105378 49 49 #include "tree.h" 50 50 #include "tree-pass.h" 51 #include "tree-pretty-print.h" 51 52 #if __GNUC__ == 5 && __GNUC_MINOR__ == 4 52 53 # include "tree-ssa-alias.h" … … 148 149 149 150 /********************************************************************************************************************************* 151 * Structures and Typedefs * 152 *********************************************************************************************************************************/ 153 /** gimple statement handle. */ 154 #if RT_GNUC_PREREQ(6, 0) 155 typedef const gimple *MY_GIMPLE_HSTMT_T; 156 #else 157 typedef gimple MY_GIMPLE_HSTMT_T; 158 #endif 159 160 161 /********************************************************************************************************************************* 150 162 * Internal Functions * 151 163 *********************************************************************************************************************************/ … … 153 165 static unsigned int MyPassExecuteCallback(void); 154 166 static unsigned int MyPassExecuteCallbackWithFunction(struct function *pFun); 155 static tree AttributeHandler(tree *, tree, tree, int, bool *); 167 static tree AttributeHandlerFormat(tree *, tree, tree, int, bool *); 168 static tree AttributeHandlerCallReq(tree *, tree, tree, int, bool *); 156 169 157 170 … … 213 226 { 214 227 type : GIMPLE_PASS, 215 name : "*iprt-format- checks", /* asterisk = no dump */228 name : "*iprt-format-and-callreq-checks", /* asterisk = no dump */ 216 229 # if RT_GNUC_PREREQ(4, 6) 217 230 optinfo_flags : 0, … … 257 270 affects_type_identity : false, 258 271 #endif 259 handler : AttributeHandler ,272 handler : AttributeHandlerFormat, 260 273 #if RT_GNUC_PREREQ(6, 3) && !RT_GNUC_PREREQ(8, 0) 261 274 affects_type_identity : false, … … 275 288 affects_type_identity : false, 276 289 #endif 277 handler : AttributeHandler, 290 handler : AttributeHandlerFormat, 291 #if RT_GNUC_PREREQ(6, 3) && !RT_GNUC_PREREQ(8, 0) 292 affects_type_identity : false, 293 #endif 294 #if RT_GNUC_PREREQ(8, 0) 295 exclude : NULL, 296 #endif 297 }, 298 { 299 name : "iprt_callreq", 300 min_length : 3, 301 max_length : 3, 302 decl_required : false, 303 type_required : true, 304 function_type_required : true, 305 #if RT_GNUC_PREREQ(4, 6) && !(RT_GNUC_PREREQ(6, 3) && !RT_GNUC_PREREQ(8, 0)) 306 affects_type_identity : false, 307 #endif 308 handler : AttributeHandlerCallReq, 278 309 #if RT_GNUC_PREREQ(6, 3) && !RT_GNUC_PREREQ(8, 0) 279 310 affects_type_identity : false, … … 319 350 tree const hType = TREE_TYPE(hDecl); 320 351 enum tree_code const enmTypeCode = hType ? TREE_CODE(hType) : (enum tree_code)-1; 321 # if 0352 # if 0 322 353 if ( enmTypeCode == RECORD_TYPE 323 354 && enmDeclCode == TYPE_DECL 324 355 && DECL_ARTIFICIAL(hDecl)) 325 356 dprint_class(hType); 326 # endif357 # endif 327 358 328 359 dprintf("%s ", get_tree_code_name(enmDeclCode)); … … 636 667 637 668 669 /** 670 * Check VMR3ReqCallU stuff. 671 * 672 * @param pState The checking state. 673 */ 674 static void MyCheckCallReq(MY_GIMPLE_HSTMT_T const hStmt, location_t const hStmtLoc, 675 long const idxFn, long const idxArgc, long const idxArgs, unsigned const cCallArgs) 676 { 677 #ifdef DEBUG 678 expanded_location const XLoc = expand_location_to_spelling_point(hStmtLoc); 679 dprintf("checker-call: cCallArgs=%#lx - %s:%u\n", cCallArgs, XLoc.file ? XLoc.file : "<nofile>", XLoc.line); 680 #endif 681 682 /* 683 * Catch incorrect attribute use. 684 */ 685 if (idxFn > cCallArgs) 686 { 687 error_at(hStmtLoc, "Incorrect function argument number (first param) in IPRT call attribute: %lu (max %u)", 688 idxFn, cCallArgs); 689 return; 690 } 691 if (idxArgc > cCallArgs) 692 { 693 error_at(hStmtLoc, "Incorrect argument count argument number (second param) in IPRT call attribute: %lu (max %u)", 694 idxArgc, cCallArgs); 695 return; 696 } 697 if (idxArgs > cCallArgs + 1) 698 { 699 error_at(hStmtLoc, "Incorrect arguments argument number (last param) in IPRT call attribute: %lu (max %u)", 700 idxArgs, cCallArgs + 1); 701 return; 702 } 703 704 /* 705 * Get the argument count argument and check how it compares to cCallArgs if constant. 706 */ 707 tree hArgCount = gimple_call_arg(hStmt, idxArgc - 1); 708 if (!hArgCount) 709 { 710 error_at(hStmtLoc, "Failed to get the parameter counter argument (%lu)", idxArgc); 711 return; 712 } 713 HOST_WIDE_INT cArgsValue = -1; 714 if (TREE_CODE(hArgCount) == INTEGER_CST) 715 { 716 if (!MY_DOUBLE_INT_FITS_SHWI(hArgCount)) 717 error_at(hStmtLoc, "Unexpected integer overflow in argument count constant"); 718 else 719 { 720 cArgsValue = MY_DOUBLE_INT_TO_SHWI(hArgCount); 721 if ( cArgsValue < 0 722 || cArgsValue != (int)cArgsValue) 723 error_at(hStmtLoc, "Unexpected integer argument count constant value: %ld", cArgsValue); 724 else 725 { 726 /* HARD CODED MAX and constants */ 727 dprintf("checker-call: cArgsValue=%#lx\n", cArgsValue); 728 if ( cArgsValue <= 9 729 || ((cArgsValue & 0x8000) && ((unsigned)cArgsValue & ~(unsigned)0x8000) <= 15) ) 730 { /* likely */ } 731 else 732 error_at(hStmtLoc, "Bad integer argument count constant value: %lx (max is 9, or 15 with flag)", 733 cArgsValue); 734 735 cArgsValue = (unsigned)cArgsValue & ~(unsigned)0x8000; 736 if (idxArgs != 0 && idxArgs + cArgsValue - 1 != (long)cCallArgs) 737 error_at(hStmtLoc, "Argument count %ld starting at %ld (1-based) does not match argument count: %u", 738 cArgsValue, idxArgs, cCallArgs); 739 } 740 } 741 } 742 743 /* 744 * Get the function pointer statement and strip any coercion. 745 */ 746 tree const hFnArg = gimple_call_arg(hStmt, idxFn - 1); 747 if (!hFnArg) 748 { 749 error_at(hStmtLoc, "Failed to get function argument (%lu)", idxFn); 750 return; 751 } 752 tree hFnType = 0; 753 if (TREE_CODE(hFnArg) == SSA_NAME) 754 { 755 dprintf(" * hFnArg=%p %s(%d) %s (SSA)\n", hFnArg, get_tree_code_name(TREE_CODE(hFnArg)), TREE_CODE(hFnArg), 756 SSA_NAME_IDENTIFIER(hFnArg) ? IDENTIFIER_POINTER(SSA_NAME_IDENTIFIER(hFnArg)) : "<unnamed-ssa-name>"); 757 hFnType = TREE_TYPE(hFnArg); 758 if (hFnType && TREE_CODE(hFnType) != POINTER_TYPE) 759 { 760 error_at(hStmtLoc, "Expected pointer_type for hFnType=%p, not %s(%d)", 761 hFnType, get_tree_code_name(TREE_CODE(hFnType)), TREE_CODE(hFnType)); 762 return; 763 } 764 if (hFnType) 765 hFnType = TREE_TYPE(hFnType); 766 } 767 else 768 { 769 dprintf(" * hFnArg=%p %s(%d)\n", hFnArg, get_tree_code_name(TREE_CODE(hFnArg)), TREE_CODE(hFnArg)); 770 tree const hFnDecl = gimple_call_addr_fndecl(hFnArg); 771 if (hFnDecl) 772 { 773 #ifdef DEBUG 774 dprintDecl(hFnDecl); 775 dprintf("\n"); 776 #endif 777 hFnType = TREE_TYPE(hFnDecl); 778 } 779 } 780 if (hFnType) 781 { 782 dprintf(" * hFnType=%p %s(%d)\n", hFnType, get_tree_code_name(TREE_CODE(hFnType)), TREE_CODE(hFnType)); 783 if (TREE_CODE(hFnType) != FUNCTION_TYPE) 784 { 785 error_at(hStmtLoc, "Expected function_type for hFnType=%p, not %s(%d)", 786 hFnType, get_tree_code_name(TREE_CODE(hFnType)), TREE_CODE(hFnType)); 787 return; 788 } 789 790 /* Count the arguments. */ 791 unsigned cFnTypeArgs = 0; 792 tree const hArgList = TYPE_ARG_TYPES(hFnType); 793 dprintf(" * hArgList=%p %s(%d)\n", hFnType, get_tree_code_name(TREE_CODE(hArgList)), TREE_CODE(hArgList)); 794 if (!hArgList) 795 error_at(hStmtLoc, "Using unprototyped function (arg %lu)?", idxFn); 796 else if (hArgList != void_list_node) 797 for (tree hArg = hArgList; hArg && hArg != void_list_node; hArg = TREE_CHAIN(hArg)) 798 cFnTypeArgs++; 799 800 /* Check that it matches the argument value. */ 801 if ((long)cFnTypeArgs != cArgsValue && cArgsValue >= 0) 802 error_at(hStmtLoc, "Function prototype takes %u arguments, but %u specified in the call request", 803 cFnTypeArgs, (unsigned)cArgsValue); 804 805 /* 806 * Check that there are no oversized arguments in the function type. 807 * If there are more than 9 arguments, also check the size of the lasts 808 * ones, up to but not including the last argument. 809 */ 810 HOST_WIDE_INT const cPtrBits = MY_DOUBLE_INT_TO_SHWI(TYPE_SIZE(TREE_TYPE(null_pointer_node))); 811 HOST_WIDE_INT const cIntBits = MY_DOUBLE_INT_TO_SHWI(TYPE_SIZE(integer_type_node)); 812 unsigned iArg = 0; 813 for (tree hArg = hArgList; hArg && hArg != void_list_node; hArg = TREE_CHAIN(hArg), iArg++) 814 { 815 tree const hArgType = TREE_VALUE(hArg); 816 HOST_WIDE_INT const cArgBits = MY_DOUBLE_INT_TO_SHWI(TYPE_SIZE(hArgType)); 817 if (cArgBits > cPtrBits) 818 error_at(hStmtLoc, "Argument #%u (1-based) is too large: %lu bits, max %lu", iArg + 1, cArgBits, cPtrBits); 819 if (cArgBits != cPtrBits && iArg >= 8 && iArg != cFnTypeArgs - 1) 820 error_at(hStmtLoc, "Argument #%u (1-based) must be pointer sized: %lu bits, expect %lu", 821 iArg + 1, cArgBits, cPtrBits); 822 823 if (idxArgs > 0) 824 { 825 tree const hArgPassed = gimple_call_arg(hStmt, idxArgs - 1 + iArg); 826 tree hArgPassedType = TREE_TYPE(hArgPassed); 827 828 HOST_WIDE_INT const cArgPassedBits = MY_DOUBLE_INT_TO_SHWI(TYPE_SIZE(hArgPassedType)); 829 if ( cArgPassedBits != cArgBits 830 && ( cArgPassedBits != cIntBits /* expected promotion target is INT */ 831 || cArgBits > cIntBits /* no promotion required */ )) 832 error_at(hStmtLoc, 833 "Argument #%u (1-based) passed to call request differs in size from target type: %lu bits, expect %lu", 834 iArg + 1, cArgPassedBits, cArgBits); 835 } 836 } 837 838 /** @todo check that the arguments passed in the VMR3ReqXxxx call matches. */ 839 } 840 else if (idxArgs != 0) 841 error_at(hStmtLoc, "Failed to get function declaration (%lu) for non-va_list call", idxFn); 842 } 843 844 638 845 #if !RT_GNUC_PREREQ(4, 9) 639 846 /** … … 665 872 /* 666 873 * Enumerate the statements in the current basic block. 667 * We're interested in calls to functions with the __iprt_format__ attribute. 874 * 875 * We're interested in calls to functions with the __iprt_format__, 876 * iprt_format_maybe_null and __iprt_callreq__ attributes. 668 877 */ 669 878 for (gimple_stmt_iterator hStmtItr = gsi_start_bb(hBasicBlock); !gsi_end_p(hStmtItr); gsi_next(&hStmtItr)) … … 715 924 && gimple_call_internal_p(hStmt) /* va_arg() kludge */) 716 925 continue; 717 error_at(gimple_location(hStmt), "Failed to resolve function type [fn=%s fndecl=%s] \n",926 error_at(gimple_location(hStmt), "Failed to resolve function type [fn=%s fndecl=%s]", 718 927 hFn ? get_tree_code_name(TREE_CODE(hFn)) : "<null>", 719 928 hFnDecl ? get_tree_code_name(TREE_CODE(hFnDecl)) : "<null>"); 720 929 } 721 930 else if (POINTER_TYPE_P(hFnType)) 722 error_at(gimple_location(hStmt), "Got a POINTER_TYPE when expecting a function type [fn=%s] \n",931 error_at(gimple_location(hStmt), "Got a POINTER_TYPE when expecting a function type [fn=%s]", 723 932 get_tree_code_name(TREE_CODE(hFn))); 724 933 if (hFnType) … … 727 936 ? IDENTIFIER_POINTER(DECL_NAME(TYPE_NAME(hFnType))) : "<unamed>"); 728 937 729 tree const hAttr = hFnType ? lookup_attribute("iprt_format", TYPE_ATTRIBUTES(hFnType)) : NULL_TREE; 730 tree const hAttrMaybe0 = hFnType ? lookup_attribute("iprt_format_maybe_null", TYPE_ATTRIBUTES(hFnType)) : NULL_TREE; 731 if (hAttr || hAttrMaybe0) 938 tree const hAttrCall = hFnType ? lookup_attribute("iprt_callreq", TYPE_ATTRIBUTES(hFnType)) : NULL_TREE; 939 tree const hAttrFmt = hFnType ? lookup_attribute("iprt_format", TYPE_ATTRIBUTES(hFnType)) : NULL_TREE; 940 tree const hAttrFmtMaybe0 = hFnType ? lookup_attribute("iprt_format_maybe_null", TYPE_ATTRIBUTES(hFnType)) : NULL_TREE; 941 if (hAttrCall || hAttrFmt || hAttrFmtMaybe0) 732 942 { 733 943 /* 734 * Yeah, it has the attribute!944 * Yeah, it has one of the attributes! 735 945 */ 736 tree const hAttrArgs = hAttr ? TREE_VALUE(hAttr) : TREE_VALUE(hAttrMaybe0); 737 VFMTCHKSTATE State; 738 State.iFmt = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(hAttrArgs)); 739 State.iArgs = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(hAttrArgs))); 740 State.pszFmt = NULL; 741 State.fMaybeNull = hAttr == NULL_TREE; 742 State.hStmt = hStmt; 743 State.hFmtLoc = gimple_location(hStmt); 744 dprintf(" %s() __iprt_format%s__(iFmt=%ld, iArgs=%ld)\n", 745 hFnDecl && DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", 746 State.fMaybeNull ? "_maybe_null" : "", State.iFmt, State.iArgs); 747 748 unsigned cCallArgs = gimple_call_num_args(hStmt); 749 if (cCallArgs >= State.iFmt) 750 MyCheckFormatRecursive(&State, gimple_call_arg(hStmt, State.iFmt - 1)); 946 unsigned const cCallArgs = gimple_call_num_args(hStmt); 947 tree hAttrArgs; 948 if (hAttrCall) 949 { 950 hAttrArgs = TREE_VALUE(hAttrCall); 951 long const idxFn = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(hAttrArgs)); 952 long const idxArgc = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(hAttrArgs))); 953 long const idxArgs = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(TREE_CHAIN(hAttrArgs)))); 954 dprintf(" %s() __iprt_callreq__(idxFn=%ld, idxArgc=%ld, idxArgs=%ld)\n", 955 hFnDecl && DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", 956 idxFn, idxArgc, idxArgs); 957 MyCheckCallReq(hStmt, gimple_location(hStmt), idxFn, idxArgc, idxArgs, cCallArgs); 958 } 751 959 else 752 error_at(gimple_location(hStmt), 753 "Call has only %d arguments; %s() format string is argument #%lu (1-based), thus missing\n", 754 cCallArgs, DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", State.iFmt); 960 { 961 hAttrArgs = hAttrFmt ? TREE_VALUE(hAttrFmt) : TREE_VALUE(hAttrFmtMaybe0); 962 VFMTCHKSTATE State; 963 State.hStmt = hStmt; 964 State.hFmtLoc = gimple_location(hStmt); 965 State.fMaybeNull = hAttrFmt ? false : true; 966 State.iFmt = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(hAttrArgs)); 967 State.iArgs = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(hAttrArgs))); 968 State.pszFmt = NULL; 969 dprintf(" %s() __iprt_format%s__(iFmt=%ld, iArgs=%ld)\n", 970 hFnDecl && DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", 971 State.fMaybeNull ? "_maybe_null" : "", State.iFmt, State.iArgs); 972 if (cCallArgs >= State.iFmt) 973 MyCheckFormatRecursive(&State, gimple_call_arg(hStmt, State.iFmt - 1)); 974 else 975 error_at(gimple_location(hStmt), 976 "Call has only %d arguments; %s() format string is argument #%lu (1-based), thus missing", 977 cCallArgs, DECL_NAME(hFnDecl) ? IDENTIFIER_POINTER(DECL_NAME(hFnDecl)) : "<unamed>", 978 State.iFmt); 979 } 755 980 } 756 981 } … … 773 998 774 999 /** 775 * Validate the use of an attribute.1000 * Validate the use of an format attribute. 776 1001 * 777 1002 * @returns ?? … … 782 1007 * @param pfDontAddAttrib Whether to add the attribute to this node or not. 783 1008 */ 784 static tree AttributeHandler (tree *phOnNode, tree hAttrName, tree hAttrArgs, int fFlags, bool *pfDontAddAttrib)785 { 786 dprintf("AttributeHandler : name=%s fFlags=%#x", IDENTIFIER_POINTER(hAttrName), fFlags);1009 static tree AttributeHandlerFormat(tree *phOnNode, tree hAttrName, tree hAttrArgs, int fFlags, bool *pfDontAddAttrib) 1010 { 1011 dprintf("AttributeHandlerFormat: name=%s fFlags=%#x", IDENTIFIER_POINTER(hAttrName), fFlags); 787 1012 long iFmt = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(hAttrArgs)); 788 1013 long iArgs = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(hAttrArgs))); 789 1014 dprintf(" iFmt=%ld iArgs=%ld", iFmt, iArgs); 1015 1016 tree hType = *phOnNode; 1017 dprintf(" hType=%p %s(%d)\n", hType, get_tree_code_name(TREE_CODE(hType)), TREE_CODE(hType)); 1018 1019 if (pfDontAddAttrib) 1020 *pfDontAddAttrib = false; 1021 return NULL_TREE; 1022 } 1023 1024 1025 /** 1026 * Validate the use of an call request attribute. 1027 * 1028 * @returns ?? 1029 * @param phOnNode The node the attribute is being used on. 1030 * @param hAttrName The attribute name. 1031 * @param hAttrArgs The attribute arguments. 1032 * @param fFlags Some kind of flags... 1033 * @param pfDontAddAttrib Whether to add the attribute to this node or not. 1034 */ 1035 static tree AttributeHandlerCallReq(tree *phOnNode, tree hAttrName, tree hAttrArgs, int fFlags, bool *pfDontAddAttrib) 1036 { 1037 dprintf("AttributeHandlerCallReq: name=%s fFlags=%#x", IDENTIFIER_POINTER(hAttrName), fFlags); 1038 long iFn = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(hAttrArgs)); 1039 long iArgc = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(hAttrArgs))); 1040 long iArgs = MY_DOUBLE_INT_TO_SHWI(TREE_VALUE(TREE_CHAIN(TREE_CHAIN(hAttrArgs)))); 1041 dprintf(" iFn=%ld iArgc=%ld iArgs=%ld", iFn, iArgc, iArgs); 790 1042 791 1043 tree hType = *phOnNode; … … 932 1184 hType, get_tree_code_name(TREE_CODE(hType)), tree_code_class_strings[TREE_CODE_CLASS(TREE_CODE(hType))]); 933 1185 dprintf(" nm=%p\n", TYPE_NAME(hType)); 934 dprintf(" c b=%p %s value=%ld\n", TYPE_SIZE(hType), get_tree_code_name(TREE_CODE(TYPE_SIZE(hType))),1186 dprintf(" cBits=%p %s value=%ld\n", TYPE_SIZE(hType), get_tree_code_name(TREE_CODE(TYPE_SIZE(hType))), 935 1187 MY_DOUBLE_INT_TO_SHWI(TYPE_SIZE(hType)) ); 936 1188 dprintf(" unit=%p %s value=%ld\n", TYPE_SIZE_UNIT(hType), get_tree_code_name(TREE_CODE(TYPE_SIZE_UNIT(hType))),
Note:
See TracChangeset
for help on using the changeset viewer.