diff options
| author | Tobin Ehlis <tobin@lunarg.com> | 2014-12-17 17:44:50 -0700 |
|---|---|---|
| committer | Courtney Goeltzenleuchter <courtney@LunarG.com> | 2015-02-04 17:58:05 -0700 |
| commit | ad0170c34eef4e8ee453cc0e0b3facace2e73bf5 (patch) | |
| tree | 00c9fd454a352b0d26c7020f01cac2ed507da817 | |
| parent | 269cd0d3ebdc54730181d1e09cdb0a9e6784ad25 (diff) | |
| download | usermoji-ad0170c34eef4e8ee453cc0e0b3facace2e73bf5.tar.xz | |
layers: Initial ParamChecker layer
ParamChecker layer is generated and currently only checks that ENUM input to functions or ENUMS as part of input structs have valid values.
Conflicts:
layers/CMakeLists.txt
| -rw-r--r-- | layers/CMakeLists.txt | 10 | ||||
| -rwxr-xr-x | xgl-layer-generate.py | 132 | ||||
| -rwxr-xr-x | xgl_helper.py (renamed from xgl-helper.py) | 46 |
3 files changed, 169 insertions, 19 deletions
diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt index 86fc0311..618e4917 100644 --- a/layers/CMakeLists.txt +++ b/layers/CMakeLists.txt @@ -2,15 +2,15 @@ cmake_minimum_required (VERSION 2.8.11) macro(run_xgl_helper subcmd) add_custom_command(OUTPUT ${ARGN} - COMMAND ${PROJECT_SOURCE_DIR}/xgl-helper.py --${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h --abs_out_dir ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${PROJECT_SOURCE_DIR}/xgl-helper.py ${PROJECT_SOURCE_DIR}/include/xgl.h + COMMAND ${PROJECT_SOURCE_DIR}/xgl_helper.py --${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h --abs_out_dir ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/xgl_helper.py ${PROJECT_SOURCE_DIR}/include/xgl.h ) endmacro() macro(run_xgl_layer_generate subcmd output) add_custom_command(OUTPUT ${output} - COMMAND ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${subcmd} > ${output} - DEPENDS ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${PROJECT_SOURCE_DIR}/xgl.py + COMMAND ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h > ${output} + DEPENDS ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${PROJECT_SOURCE_DIR}/include/xgl.h ${PROJECT_SOURCE_DIR}/xgl.py ) endmacro() @@ -67,6 +67,7 @@ run_xgl_layer_generate(ApiDumpNoAddr api_dump_no_addr.c) run_xgl_layer_generate(ApiDumpCpp api_dump.cpp) run_xgl_layer_generate(ApiDumpNoAddrCpp api_dump_no_addr.cpp) run_xgl_layer_generate(ObjectTracker object_track.c) +run_xgl_layer_generate(ParamChecker param_checker.c) add_xgl_layer(Basic basic.cpp) add_xgl_layer(Multi multi.cpp) @@ -80,3 +81,4 @@ add_xgl_layer(APIDumpNoAddr api_dump_no_addr.c) add_xgl_layer(APIDumpCpp api_dump.cpp) add_xgl_layer(APIDumpNoAddrCpp api_dump_no_addr.cpp) add_xgl_layer(ObjectTracker object_track.c) +add_xgl_layer(ParamChecker param_checker.c) diff --git a/xgl-layer-generate.py b/xgl-layer-generate.py index d19a63f8..7e2cb742 100755 --- a/xgl-layer-generate.py +++ b/xgl-layer-generate.py @@ -26,8 +26,10 @@ # Chia-I Wu <olv@lunarg.com> import sys +import os import xgl +import xgl_helper class Subcommand(object): def __init__(self, argv): @@ -434,10 +436,9 @@ class Subcommand(object): (pft, pfi) = ("%s", '"addr"') log_func += '%s = %s, ' % (p.name, pft) print_vals += ', %s' % (pfi) - # TODO : Just want this to be simple check for params of STRUCT type - if "pCreateInfo" in p.name or ('const' in p.ty and '*' in p.ty and False not in [tmp_ty not in p.ty for tmp_ty in ['XGL_CHAR', 'XGL_VOID', 'XGL_CMD_BUFFER', 'XGL_QUEUE_SEMAPHORE', 'XGL_FENCE', 'XGL_SAMPLER', 'XGL_UINT32']]): - if 'Wsi' not in proto.name: - cis_param_index.append(pindex) + # 'format' gets special treatment as a small struct that we print inline + if 'Wsi' not in proto.name and 'format' != p.name and xgl_helper.is_type(p.ty.strip('*').strip('const '), 'struct'): + cis_param_index.append(pindex) pindex += 1 log_func = log_func.strip(', ') if proto.ret != "XGL_VOID": @@ -624,13 +625,96 @@ class Subcommand(object): '%s%s' '%s' '}' % (qual, decl, proto.params[0].name, using_line, ret_val, c_call, create_line, destroy_line, stmt)) - - # TODO : Put this code somewhere so it gets called at the end if objects not deleted : - # // Report any remaining objects in LL - # objNode *pTrav = pObjLLHead; - # while (pTrav) { - # printf("WARN : %s object %p has not been destroyed.\n", pTrav->objType, pTrav->pObj); - # } + elif "ParamChecker" == layer: + # TODO : Need to fix up the non-else cases below to do param checking as well + decl = proto.c_func(prefix="xgl", attr="XGLAPI") + param0_name = proto.params[0].name + ret_val = '' + stmt = '' + param_checks = [] + # Add code to check enums and structs + # TODO : Currently only validating enum values, need to validate everything + str_decl = False + for p in proto.params: + if xgl_helper.is_type(p.ty.strip('*').strip('const '), 'enum'): + if not str_decl: + param_checks.append(' char str[1024];') + str_decl = True + param_checks.append(' if (!validate_%s(%s)) {' % (p.ty, p.name)) + param_checks.append(' char str[1024];') + param_checks.append(' sprintf(str, "Parameter %s to function %s has invalid value of %%i.", (int)%s);' % (p.name, proto.name, p.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + elif xgl_helper.is_type(p.ty.strip('*').strip('const '), 'struct') and 'const' in p.ty: + if not str_decl: + param_checks.append(' char str[1024];') + str_decl = True + if '*' in p.ty: # First check for null ptr + param_checks.append(' if (!%s) {' % p.name) + param_checks.append(' sprintf(str, "Struct ptr parameter %s to function %s is NULL.");' % (p.name, proto.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + param_checks.append(' else if (!xgl_validate_%s(%s)) {' % (p.ty.strip('*').strip('const ').lower(), p.name)) + else: + param_checks.append(' if (!xgl_validate_%s(%s)) {' % (p.ty.strip('const ').lower(), p.name)) + param_checks.append(' sprintf(str, "Parameter %s to function %s contains an invalid value.");' % (p.name, proto.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + if proto.ret != "XGL_VOID": + ret_val = "XGL_RESULT result = " + stmt = " return result;\n" + if proto.name == "EnumerateLayers": + c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1) + funcs.append('%s%s\n' + '{\n' + ' char str[1024];\n' + ' if (gpu != NULL) {\n' + ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n' + ' sprintf(str, "At start of layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpu, 0, 0, "PARAMCHECK", str);\n' + ' pCurObj = gpuw;\n' + ' pthread_once(&tabOnce, initLayerTable);\n' + ' %snextTable.%s;\n' + ' sprintf(str, "Completed layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpu, 0, 0, "PARAMCHECK", str);\n' + ' fflush(stdout);\n' + ' %s' + ' } else {\n' + ' if (pOutLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n' + ' return XGL_ERROR_INVALID_POINTER;\n' + ' // This layer compatible with all GPUs\n' + ' *pOutLayerCount = 1;\n' + ' strncpy(pOutLayers[0], "%s", maxStringSize);\n' + ' return XGL_SUCCESS;\n' + ' }\n' + '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt, layer_name)) + elif 'DbgRegisterMsgCallback' == proto.name: + funcs.append(self._gen_layer_dbg_callback_register()) + elif 'DbgUnregisterMsgCallback' == proto.name: + funcs.append(self._gen_layer_dbg_callback_unregister()) + elif proto.params[0].ty != "XGL_PHYSICAL_GPU": + funcs.append('%s%s\n' + '{\n' + '%s\n' + ' %snextTable.%s;\n' + '%s' + '}' % (qual, decl, "\n".join(param_checks), ret_val, proto.c_call(), stmt)) + else: + c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1) + funcs.append('%s%s\n' + '{\n' + ' char str[1024];' + ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n' + ' sprintf(str, "At start of layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpuw, 0, 0, "PARAMCHECK", str);\n' + ' pCurObj = gpuw;\n' + ' pthread_once(&tabOnce, initLayerTable);\n' + ' %snextTable.%s;\n' + ' sprintf(str, "Completed layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpuw, 0, 0, "PARAMCHECK", str);\n' + ' fflush(stdout);\n' + '%s' + '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt)) return "\n\n".join(funcs) @@ -1086,6 +1170,18 @@ class ObjectTrackerSubcommand(Subcommand): return "\n\n".join(body) +class ParamCheckerSubcommand(Subcommand): + def generate_header(self): + return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>\n#include "xglLayer.h"\n#include "xgl_enum_validate_helper.h"\n#include "xgl_struct_validate_helper.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n' + + def generate_body(self): + body = [self._gen_layer_dbg_callback_header(), + self._generate_layer_dispatch_table(), + self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "ParamChecker"), + self._generate_layer_gpa_function()] + + return "\n\n".join(body) + def main(): subcommands = { "layer-funcs" : LayerFuncsSubcommand, @@ -1097,14 +1193,24 @@ def main(): "ApiDumpCpp" : ApiDumpCppSubcommand, "ApiDumpNoAddrCpp" : ApiDumpNoAddrCppSubcommand, "ObjectTracker" : ObjectTrackerSubcommand, + "ParamChecker" : ParamCheckerSubcommand, } - if len(sys.argv) < 2 or sys.argv[1] not in subcommands: - print("Usage: %s <subcommand> [options]" % sys.argv[0]) + if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]): + print("Usage: %s <subcommand> <input_header> [options]" % sys.argv[0]) print print("Available sucommands are: %s" % " ".join(subcommands)) exit(1) + hfp = xgl_helper.HeaderFileParser(sys.argv[2]) + hfp.parse() + xgl_helper.enum_val_dict = hfp.get_enum_val_dict() + xgl_helper.enum_type_dict = hfp.get_enum_type_dict() + xgl_helper.struct_dict = hfp.get_struct_dict() + xgl_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict() + xgl_helper.typedef_rev_dict = hfp.get_typedef_rev_dict() + xgl_helper.types_dict = hfp.get_types_dict() + subcmd = subcommands[sys.argv[1]](sys.argv[2:]) subcmd.run() diff --git a/xgl-helper.py b/xgl_helper.py index 67cada7e..36e05ac0 100755 --- a/xgl-helper.py +++ b/xgl_helper.py @@ -321,11 +321,13 @@ class StructWrapperGen: self.string_helper_no_addr_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr.h") self.string_helper_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_cpp.h") self.string_helper_no_addr_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr_cpp.h") + self.validate_helper_filename = os.path.join(out_dir, self.api+"_struct_validate_helper.h") self.no_addr = False self.hfg = CommonFileGen(self.header_filename) self.cfg = CommonFileGen(self.class_filename) self.shg = CommonFileGen(self.string_helper_filename) self.shcppg = CommonFileGen(self.string_helper_cpp_filename) + self.vhg = CommonFileGen(self.validate_helper_filename) #print(self.header_filename) self.header_txt = "" self.definition_txt = "" @@ -382,6 +384,14 @@ class StructWrapperGen: self.shcppg.setBody(self._generateStringHelperFunctionsCpp()) self.shcppg.generate() + # Generate c-style .h file that contains functions for printing structs + def generateValidateHelper(self): + print("Generating struct validate helper") + self.vhg.setCopyright(self._generateCopyright()) + self.vhg.setHeader(self._generateValidateHelperHeader()) + self.vhg.setBody(self._generateValidateHelperFunctions()) + self.vhg.generate() + def _generateCopyright(self): return "//This is the copyright\n" @@ -445,8 +455,14 @@ class StructWrapperGen: dp_funcs.append("}\n") return "\n".join(dp_funcs) + def _get_func_name(self, struct, mid_str): + return "%s_%s_%s" % (self.api, mid_str, struct.lower().strip("_")) + def _get_sh_func_name(self, struct): - return "%s_print_%s" % (self.api, struct.lower().strip("_")) + return self._get_func_name(struct, 'print') + + def _get_vh_func_name(self, struct): + return self._get_func_name(struct, 'validate') # Return elements to create formatted string for given struct member def _get_struct_print_formatted(self, struct_member, pre_var_name="prefix", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False): @@ -863,6 +879,31 @@ class StructWrapperGen: header.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix);\n") return "".join(header) + def _generateValidateHelperFunctions(self): + sh_funcs = [] + # We do two passes, first pass just generates prototypes for all the functsions + for s in self.struct_dict: + sh_funcs.append('uint32_t %s(const %s* pStruct);' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) + sh_funcs.append('\n') + for s in self.struct_dict: + sh_funcs.append('uint32_t %s(const %s* pStruct)\n{' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) + for m in sorted(self.struct_dict[s]): + if is_type(self.struct_dict[s][m]['type'], 'enum'): + sh_funcs.append(' if (!validate_%s(pStruct->%s))\n return 0;' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) + sh_funcs.append(" return 1;\n}") + + return "\n".join(sh_funcs) + + def _generateValidateHelperHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + if 'xgl_enum_validate_helper' not in f: + header.append("#include <%s>\n" % f) + header.append('#include "xgl_enum_validate_helper.h"\n\n// Function Prototypes\n') + #header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n") + return "".join(header) + def _generateHeader(self): header = [] header.append("//#includes, #defines, globals and such...\n") @@ -940,7 +981,7 @@ class EnumCodeGen: def generateEnumValidate(self): self.evhfg.setHeader(self._generateSHHeader()) - self.evhfg.setHeader(self._generateVHBody()) + self.evhfg.setBody(self._generateVHBody()) self.evhfg.generate() def _generateVHBody(self): @@ -1301,6 +1342,7 @@ def main(argv=None): print("Generating struct wrapper class to %s" % sw.class_filename) sw.generateBody() sw.generateStringHelper() + sw.generateValidateHelper() # Generate a 2nd helper file that excludes addrs sw.set_no_addr(True) sw.generateStringHelper() |
