1 /* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "HalHidlFuzzerCodeGen.h" 18 #include "VtsCompilerUtils.h" 19 #include "code_gen/common/HalHidlCodeGenUtils.h" 20 #include "utils/InterfaceSpecUtil.h" 21 #include "utils/StringUtil.h" 22 23 using std::cerr; 24 using std::cout; 25 using std::endl; 26 using std::vector; 27 28 namespace android { 29 namespace vts { 30 31 void HalHidlFuzzerCodeGen::GenerateSourceIncludeFiles(Formatter &out) { 32 out << "#include <iostream>\n\n"; 33 out << "#include \"FuncFuzzerUtils.h\"\n"; 34 35 string package_path = comp_spec_.package(); 36 ReplaceSubString(package_path, ".", "/"); 37 string comp_version = GetVersionString(comp_spec_.component_type_version()); 38 string comp_name = comp_spec_.component_name(); 39 40 out << "#include <" << package_path << "/" << comp_version << "/" << comp_name 41 << ".h>\n"; 42 out << "\n"; 43 } 44 45 void HalHidlFuzzerCodeGen::GenerateUsingDeclaration(Formatter &out) { 46 out << "using std::cerr;\n"; 47 out << "using std::endl;\n"; 48 out << "using std::string;\n\n"; 49 50 string package_path = comp_spec_.package(); 51 ReplaceSubString(package_path, ".", "::"); 52 string comp_version = 53 GetVersionString(comp_spec_.component_type_version(), true); 54 55 out << "using namespace ::" << package_path << "::" << comp_version << ";\n"; 56 out << "using namespace ::android::hardware;\n"; 57 out << "\n"; 58 } 59 60 void HalHidlFuzzerCodeGen::GenerateGlobalVars(Formatter &out) { 61 out << "static string target_func;\n\n"; 62 } 63 64 void HalHidlFuzzerCodeGen::GenerateLLVMFuzzerInitialize(Formatter &out) { 65 out << "extern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) " 66 "{\n"; 67 out.indent(); 68 out << "FuncFuzzerParams params{ExtractFuncFuzzerParams(*argc, *argv)};\n"; 69 out << "target_func = params.target_func_;\n"; 70 out << "return 0;\n"; 71 out.unindent(); 72 out << "}\n\n"; 73 } 74 75 void HalHidlFuzzerCodeGen::GenerateLLVMFuzzerTestOneInput(Formatter &out) { 76 out << "extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t " 77 "size) {\n"; 78 out.indent(); 79 out << "static ::android::sp<" << comp_spec_.component_name() << "> " 80 << GetHalPointerName() << " = " << comp_spec_.component_name() 81 << "::getService(true);\n"; 82 out << "if (" << GetHalPointerName() << " == nullptr) {\n"; 83 out.indent(); 84 out << "cerr << \"" << comp_spec_.component_name() 85 << "::getService() failed\" << endl;\n"; 86 out << "exit(1);\n"; 87 out.unindent(); 88 out << "}\n\n"; 89 for (const auto &func_spec : comp_spec_.interface().api()) { 90 GenerateHalFunctionCall(out, func_spec); 91 } 92 out << "{\n"; 93 out.indent(); 94 out << "cerr << \"No such function: \" << target_func << endl;\n"; 95 out << "exit(1);\n"; 96 out.unindent(); 97 out << "}\n"; 98 99 out.unindent(); 100 out << "}\n\n"; 101 } 102 103 string HalHidlFuzzerCodeGen::GetHalPointerName() { 104 string prefix = "android.hardware."; 105 string hal_pointer_name = comp_spec_.package().substr(prefix.size()); 106 ReplaceSubString(hal_pointer_name, ".", "_"); 107 return hal_pointer_name; 108 } 109 110 void HalHidlFuzzerCodeGen::GenerateReturnCallback( 111 Formatter &out, const FunctionSpecificationMessage &func_spec) { 112 if (CanElideCallback(func_spec)) { 113 return; 114 } 115 out << "// No-op. Only need this to make HAL function call.\n"; 116 out << "auto " << return_cb_name << " = []("; 117 size_t num_cb_arg = func_spec.return_type_hidl_size(); 118 for (size_t i = 0; i < num_cb_arg; ++i) { 119 const auto &return_val = func_spec.return_type_hidl(i); 120 out << GetCppVariableType(return_val, nullptr, 121 IsConstType(return_val.type())); 122 out << " arg" << i << ((i != num_cb_arg - 1) ? ", " : ""); 123 } 124 out << "){};\n\n"; 125 } 126 127 void HalHidlFuzzerCodeGen::GenerateHalFunctionCall( 128 Formatter &out, const FunctionSpecificationMessage &func_spec) { 129 string func_name = func_spec.name(); 130 out << "if (target_func == \"" << func_name << "\") {\n"; 131 out.indent(); 132 133 GenerateReturnCallback(out, func_spec); 134 vector<string> types{GetFuncArgTypes(func_spec)}; 135 for (size_t i = 0; i < types.size(); ++i) { 136 out << "size_t type_size" << i << " = sizeof(" << types[i] << ");\n"; 137 out << "if (size < type_size" << i << ") { return 0; }\n"; 138 out << "size -= type_size" << i << ";\n"; 139 out << types[i] << " arg" << i << ";\n"; 140 out << "memcpy(&arg" << i << ", data, type_size" << i << ");\n"; 141 out << "data += type_size" << i << ";\n\n"; 142 } 143 144 out << GetHalPointerName() << "->" << func_spec.name() << "("; 145 for (size_t i = 0; i < types.size(); ++i) { 146 out << "arg" << i << ((i != types.size() - 1) ? ", " : ""); 147 } 148 if (!CanElideCallback(func_spec)) { 149 if (func_spec.arg_size() > 0) { 150 out << ", "; 151 } 152 out << return_cb_name; 153 } 154 out << ");\n"; 155 out << "return 0;\n"; 156 157 out.unindent(); 158 out << "} else "; 159 } 160 161 bool HalHidlFuzzerCodeGen::CanElideCallback( 162 const FunctionSpecificationMessage &func_spec) { 163 if (func_spec.return_type_hidl_size() == 0) { 164 return true; 165 } 166 // Can't elide callback for void or tuple-returning methods 167 if (func_spec.return_type_hidl_size() != 1) { 168 return false; 169 } 170 const VariableType &type = func_spec.return_type_hidl(0).type(); 171 if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) { 172 return false; 173 } 174 return IsElidableType(type); 175 } 176 177 vector<string> HalHidlFuzzerCodeGen::GetFuncArgTypes( 178 const FunctionSpecificationMessage &func_spec) { 179 vector<string> types{}; 180 for (const auto &var_spec : func_spec.arg()) { 181 string type = GetCppVariableType(var_spec); 182 types.emplace_back(GetCppVariableType(var_spec)); 183 } 184 return types; 185 } 186 187 } // namespace vts 188 } // namespace android 189