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 "code_gen/driver/HalCodeGen.h" 18 19 #include <iostream> 20 #include <string> 21 22 #include "VtsCompilerUtils.h" 23 #include "test/vts/proto/ComponentSpecificationMessage.pb.h" 24 #include "utils/InterfaceSpecUtil.h" 25 #include "utils/StringUtil.h" 26 27 using namespace std; 28 using namespace android; 29 30 namespace android { 31 namespace vts { 32 33 const char* const HalCodeGen::kInstanceVariableName = "device_"; 34 35 void HalCodeGen::GenerateCppBodyInterfaceImpl( 36 Formatter& out, const ComponentSpecificationMessage& message, 37 const string& fuzzer_extended_class_name) { 38 bool first_callback = true; 39 40 for (int i = 0; i < message.interface().attribute_size(); i++) { 41 const VariableSpecificationMessage& attribute = message.interface().attribute(i); 42 if (attribute.type() != TYPE_FUNCTION_POINTER || !attribute.is_callback()) { 43 continue; 44 } 45 string name = 46 "vts_callback_" + fuzzer_extended_class_name + "_" + attribute.name(); 47 if (first_callback) { 48 out << "static string callback_socket_name_;" << "\n"; 49 first_callback = false; 50 } 51 out << "\n"; 52 out << "class " << name << " : public DriverCallbackBase {" 53 << "\n"; 54 out << " public:" << "\n"; 55 out.indent(); 56 out << name << "(const string& callback_socket_name) {" << "\n"; 57 out.indent(); 58 out << "callback_socket_name_ = callback_socket_name;" << "\n"; 59 out.unindent(); 60 out << "}" << "\n"; 61 62 int primitive_format_index = 0; 63 for (const FunctionPointerSpecificationMessage& func_pt_spec : 64 attribute.function_pointer()) { 65 const string& callback_name = func_pt_spec.function_name(); 66 // TODO: callback's return value is assumed to be 'void'. 67 out << "\n"; 68 out << "static "; 69 bool has_return_value = false; 70 if (!func_pt_spec.has_return_type() || 71 !func_pt_spec.return_type().has_type() || 72 func_pt_spec.return_type().type() == TYPE_VOID) { 73 out << "void" << "\n"; 74 } else if (func_pt_spec.return_type().type() == TYPE_PREDEFINED) { 75 out << func_pt_spec.return_type().predefined_type(); 76 has_return_value = true; 77 } else { 78 cerr << __func__ << ":" << __LINE__ << " ERROR unknown type " 79 << func_pt_spec.return_type().type() << "\n"; 80 exit(-1); 81 } 82 out << " " << callback_name << "("; 83 int primitive_type_index; 84 primitive_type_index = 0; 85 for (const auto& arg : func_pt_spec.arg()) { 86 if (primitive_type_index != 0) { 87 out << ", "; 88 } 89 if (arg.is_const()) { 90 out << "const "; 91 } 92 if (arg.type() == TYPE_SCALAR) { 93 /* 94 if (arg.scalar_type() == "pointer") { 95 out << definition.aggregate_value( 96 primitive_format_index).primitive_name(primitive_type_index) 97 << " "; 98 } */ 99 if (arg.scalar_type() == "char_pointer") { 100 out << "char* "; 101 } else if (arg.scalar_type() == "uchar_pointer") { 102 out << "unsigned char* "; 103 } else if (arg.scalar_type() == "bool_t") { 104 out << "bool "; 105 } else if (arg.scalar_type() == "int8_t" || 106 arg.scalar_type() == "uint8_t" || 107 arg.scalar_type() == "int16_t" || 108 arg.scalar_type() == "uint16_t" || 109 arg.scalar_type() == "int32_t" || 110 arg.scalar_type() == "uint32_t" || 111 arg.scalar_type() == "size_t" || 112 arg.scalar_type() == "int64_t" || 113 arg.scalar_type() == "uint64_t") { 114 out << arg.scalar_type() << " "; 115 } else if (arg.scalar_type() == "void_pointer") { 116 out << "void*"; 117 } else { 118 cerr << __func__ << " unsupported scalar type " << arg.scalar_type() 119 << "\n"; 120 exit(-1); 121 } 122 } else if (arg.type() == TYPE_PREDEFINED) { 123 out << arg.predefined_type() << " "; 124 } else { 125 cerr << __func__ << " unsupported type" << "\n"; 126 exit(-1); 127 } 128 out << "arg" << primitive_type_index; 129 primitive_type_index++; 130 } 131 out << ") {" << "\n"; 132 out.indent(); 133 #if USE_VAARGS 134 out << " const char fmt[] = \"" 135 << definition.primitive_format(primitive_format_index) << "\";" 136 << "\n"; 137 out << " va_list argp;" << "\n"; 138 out << " const char* p;" << "\n"; 139 out << " int i;" << "\n"; 140 out << " char* s;" << "\n"; 141 out << " char fmtbuf[256];" << "\n"; 142 out << "\n"; 143 out << " va_start(argp, fmt);" << "\n"; 144 out << "\n"; 145 out << " for (p = fmt; *p != '\\0'; p++) {" << "\n"; 146 out << " if (*p != '%') {" << "\n"; 147 out << " putchar(*p);" << "\n"; 148 out << " continue;" << "\n"; 149 out << " }" << "\n"; 150 out << " switch (*++p) {" << "\n"; 151 out << " case 'c':" << "\n"; 152 out << " i = va_arg(argp, int);" << "\n"; 153 out << " putchar(i);" << "\n"; 154 out << " break;" << "\n"; 155 out << " case 'd':" << "\n"; 156 out << " i = va_arg(argp, int);" << "\n"; 157 out << " s = itoa(i, fmtbuf, 10);" << "\n"; 158 out << " fputs(s, stdout);" << "\n"; 159 out << " break;" << "\n"; 160 out << " case 's':" << "\n"; 161 out << " s = va_arg(argp, char *);" << "\n"; 162 out << " fputs(s, stdout);" << "\n"; 163 out << " break;" << "\n"; 164 // out << " case 'p': 165 out << " case '%':" << "\n"; 166 out << " putchar('%');" << "\n"; 167 out << " break;" << "\n"; 168 out << " }" << "\n"; 169 out << " }" << "\n"; 170 out << " va_end(argp);" << "\n"; 171 #endif 172 // TODO: check whether bytes is set and handle properly if not. 173 out << "AndroidSystemCallbackRequestMessage callback_message;" 174 << "\n"; 175 out << "callback_message.set_id(GetCallbackID(\"" << callback_name 176 << "\"));" << "\n"; 177 178 primitive_type_index = 0; 179 for (const auto& arg : func_pt_spec.arg()) { 180 out << "VariableSpecificationMessage* var_msg" << primitive_type_index 181 << " = callback_message.add_arg();" << "\n"; 182 if (arg.type() == TYPE_SCALAR) { 183 out << "var_msg" << primitive_type_index << "->set_type(" 184 << "TYPE_SCALAR);" << "\n"; 185 out << "var_msg" << primitive_type_index << "->set_scalar_type(\"" 186 << arg.scalar_type() << "\");" << "\n"; 187 out << "var_msg" << primitive_type_index << "->mutable_scalar_value()"; 188 if (arg.scalar_type() == "bool_t") { 189 out << "->set_" << arg.scalar_type() << "(" 190 << arg.scalar_value().bool_t() << ");" << "\n"; 191 } else if (arg.scalar_type() == "int8_t") { 192 out << "->set_" << arg.scalar_type() << "(" 193 << arg.scalar_value().int8_t() << ");" << "\n"; 194 } else if (arg.scalar_type() == "uint8_t") { 195 out << "->set_" << arg.scalar_type() << "(" 196 << arg.scalar_value().uint8_t() << ");" << "\n"; 197 } else if (arg.scalar_type() == "int16_t") { 198 out << "->set_" << arg.scalar_type() << "(" 199 << arg.scalar_value().int16_t() << ");" << "\n"; 200 } else if (arg.scalar_type() == "uint16_t") { 201 out << "->set_" << arg.scalar_type() << "(" 202 << arg.scalar_value().uint16_t() << ");" << "\n"; 203 } else if (arg.scalar_type() == "int32_t") { 204 out << "->set_" << arg.scalar_type() << "(" 205 << arg.scalar_value().int32_t() << ");" << "\n"; 206 } else if (arg.scalar_type() == "uint32_t") { 207 out << "->set_" << arg.scalar_type() << "(" 208 << arg.scalar_value().uint32_t() << ");" << "\n"; 209 } else if (arg.scalar_type() == "size_t") { 210 out << "->set_uint32_t(" 211 << arg.scalar_value().uint32_t() << ");" << "\n"; 212 } else if (arg.scalar_type() == "int64_t") { 213 out << "->set_" << arg.scalar_type() << "(" 214 << arg.scalar_value().int64_t() << ");" << "\n"; 215 } else if (arg.scalar_type() == "uint64_t") { 216 out << "->set_" << arg.scalar_type() << "(" 217 << arg.scalar_value().uint64_t() << ");" << "\n"; 218 } else if (arg.scalar_type() == "char_pointer") { 219 // pointer value is not meaning when it is passed to another machine. 220 out << "->set_" << arg.scalar_type() << "(" 221 << arg.scalar_value().char_pointer() << ");" << "\n"; 222 } else if (arg.scalar_type() == "uchar_pointer") { 223 // pointer value is not meaning when it is passed to another machine. 224 out << "->set_" << arg.scalar_type() << "(" 225 << arg.scalar_value().uchar_pointer() << ");" << "\n"; 226 } else if (arg.scalar_type() == "void_pointer") { 227 // pointer value is not meaning when it is passed to another machine. 228 out << "->set_" << arg.scalar_type() << "(" 229 << arg.scalar_value().void_pointer() << ");" << "\n"; 230 } else { 231 cerr << __func__ << " unsupported scalar type " << arg.scalar_type() 232 << "\n"; 233 exit(-1); 234 } 235 } else if (arg.type() == TYPE_PREDEFINED) { 236 out << "var_msg" << primitive_type_index << "->set_type(" 237 << "TYPE_PREDEFINED);" << "\n"; 238 // TODO: actually handle such case. 239 } else { 240 cerr << __func__ << " unsupported type" << "\n"; 241 exit(-1); 242 } 243 primitive_type_index++; 244 } 245 out << "RpcCallToAgent(callback_message, callback_socket_name_);" 246 << "\n"; 247 if (has_return_value) { 248 // TODO: consider actual return type. 249 out << "return NULL;"; 250 } 251 out.unindent(); 252 out << "}" << "\n"; 253 out << "\n"; 254 255 primitive_format_index++; 256 } 257 out << "\n"; 258 out.unindent(); 259 out << " private:" << "\n"; 260 out << "};" << "\n"; 261 out << "\n"; 262 } 263 } 264 265 void HalCodeGen::GenerateCppBodyFuzzFunction( 266 Formatter& out, const ComponentSpecificationMessage& message, 267 const string& fuzzer_extended_class_name) { 268 for (auto const& sub_struct : message.interface().sub_struct()) { 269 GenerateCppBodyFuzzFunction(out, sub_struct, fuzzer_extended_class_name, 270 message.original_data_structure_name(), 271 sub_struct.is_pointer() ? "->" : "."); 272 } 273 274 out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n"; 275 out << " FunctionSpecificationMessage* func_msg," << "\n"; 276 out << " void** result, const string& callback_socket_name) {" << "\n"; 277 out.indent(); 278 out << "const char* func_name = func_msg->name().c_str();" << "\n"; 279 out << "LOG(INFO) << \" '\" << func_name << \"'\";" 280 << "\n"; 281 282 // to call another function if it's for a sub_struct 283 if (message.interface().sub_struct().size() > 0) { 284 out << "if (func_msg->parent_path().length() > 0) {" << "\n"; 285 out.indent(); 286 for (auto const& sub_struct : message.interface().sub_struct()) { 287 GenerateSubStructFuzzFunctionCall(out, sub_struct, ""); 288 } 289 out.unindent(); 290 out << "}" << "\n"; 291 } 292 293 out << message.original_data_structure_name() 294 << "* local_device = "; 295 out << "reinterpret_cast<" << message.original_data_structure_name() 296 << "*>(" << kInstanceVariableName << ");" << "\n"; 297 298 out << "if (local_device == NULL) {" << "\n"; 299 out.indent(); 300 out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;" 301 << "\n"; 302 out << "local_device = reinterpret_cast<" 303 << message.original_data_structure_name() << "*>(hmi_);\n"; 304 out.unindent(); 305 out << "}" << "\n"; 306 out << "if (local_device == NULL) {" << "\n"; 307 out.indent(); 308 out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n"; 309 out << "return false;" << "\n"; 310 out.unindent(); 311 out << "}" << "\n"; 312 313 for (auto const& api : message.interface().api()) { 314 out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n"; 315 out.indent(); 316 out << "LOG(INFO) << \"match\" <<;\n"; 317 // args - definition; 318 int arg_count = 0; 319 for (auto const& arg : api.arg()) { 320 if (arg.is_callback()) { // arg.type() isn't always TYPE_FUNCTION_POINTER 321 string name = "vts_callback_" + fuzzer_extended_class_name + "_" + 322 arg.predefined_type(); // TODO - check to make sure name 323 // is always correct 324 if (name.back() == '*') name.pop_back(); 325 out << name << "* arg" << arg_count << "callback = new "; 326 out << name << "(callback_socket_name);" << "\n"; 327 out << "arg" << arg_count << "callback->Register(func_msg->arg(" 328 << arg_count << "));" << "\n"; 329 330 out << GetCppVariableType(arg) << " "; 331 out << "arg" << arg_count << " = (" << GetCppVariableType(arg) 332 << ") malloc(sizeof(" << GetCppVariableType(arg) << "));" 333 << "\n"; 334 // TODO: think about how to free the malloced callback data structure. 335 // find the spec. 336 bool found = false; 337 cout << name << "\n"; 338 for (auto const& attribute : message.interface().attribute()) { 339 if (attribute.type() == TYPE_FUNCTION_POINTER && 340 attribute.is_callback()) { 341 string target_name = "vts_callback_" + fuzzer_extended_class_name + 342 "_" + attribute.name(); 343 cout << "compare" << "\n"; 344 cout << target_name << "\n"; 345 if (name == target_name) { 346 if (attribute.function_pointer_size() > 1) { 347 for (auto const& func_pt : attribute.function_pointer()) { 348 out << "arg" << arg_count << "->" 349 << func_pt.function_name() << " = arg" << arg_count 350 << "callback->" << func_pt.function_name() << ";" 351 << "\n"; 352 } 353 } else { 354 out << "arg" << arg_count << " = arg" << arg_count 355 << "callback->" << attribute.name() << ";" << "\n"; 356 } 357 found = true; 358 break; 359 } 360 } 361 } 362 if (!found) { 363 cerr << __func__ << " ERROR callback definition missing for " << name 364 << " of " << api.name() << "\n"; 365 exit(-1); 366 } 367 } else { 368 out << GetCppVariableType(arg) << " "; 369 out << "arg" << arg_count << " = "; 370 if (arg_count == 0 && arg.type() == TYPE_PREDEFINED && 371 !strncmp(arg.predefined_type().c_str(), 372 message.original_data_structure_name().c_str(), 373 message.original_data_structure_name().length())) { 374 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">(" 375 << kInstanceVariableName << ")"; 376 } else { 377 std::stringstream msg_ss; 378 msg_ss << "func_msg->arg(" << arg_count << ")"; 379 string msg = msg_ss.str(); 380 381 if (arg.type() == TYPE_SCALAR) { 382 out << "(" << msg << ".type() == TYPE_SCALAR)? "; 383 if (arg.scalar_type() == "pointer" || 384 arg.scalar_type() == "pointer_pointer" || 385 arg.scalar_type() == "char_pointer" || 386 arg.scalar_type() == "uchar_pointer" || 387 arg.scalar_type() == "void_pointer" || 388 arg.scalar_type() == "function_pointer") { 389 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">"; 390 } 391 out << "(" << msg << ".scalar_value()"; 392 393 if (arg.scalar_type() == "bool_t" || 394 arg.scalar_type() == "int32_t" || 395 arg.scalar_type() == "uint32_t" || 396 arg.scalar_type() == "int64_t" || 397 arg.scalar_type() == "uint64_t" || 398 arg.scalar_type() == "int16_t" || 399 arg.scalar_type() == "uint16_t" || 400 arg.scalar_type() == "int8_t" || 401 arg.scalar_type() == "uint8_t" || 402 arg.scalar_type() == "float_t" || 403 arg.scalar_type() == "double_t") { 404 out << "." << arg.scalar_type() << "() "; 405 } else if (arg.scalar_type() == "pointer" || 406 arg.scalar_type() == "char_pointer" || 407 arg.scalar_type() == "uchar_pointer" || 408 arg.scalar_type() == "void_pointer") { 409 out << ".pointer() "; 410 } else { 411 cerr << __func__ << " ERROR unsupported scalar type " 412 << arg.scalar_type() << "\n"; 413 exit(-1); 414 } 415 out << ") : "; 416 } else { 417 cerr << __func__ << " unknown type " << msg << "\n"; 418 } 419 420 out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg 421 << ".type() == TYPE_STRUCT || " << msg 422 << ".type() == TYPE_SCALAR)? "; 423 out << GetCppInstanceType(arg, msg); 424 out << " : " << GetCppInstanceType(arg) << " )"; 425 // TODO: use the given message and call a lib function which converts 426 // a message to a C/C++ struct. 427 } 428 out << ";" << "\n"; 429 } 430 out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count 431 << ";\n"; 432 arg_count++; 433 } 434 435 // actual function call 436 GenerateCodeToStartMeasurement(out); 437 out << "LOG(INFO) << \"hit2.\" << device_;\n"; 438 439 // checks whether the function is actually defined. 440 out << "if (reinterpret_cast<" 441 << message.original_data_structure_name() << "*>(local_device)->" 442 << api.name() << " == NULL" << ") {" << "\n"; 443 out.indent(); 444 out << "LOG(ERROR) << \"api not set.\";\n"; 445 // todo: consider throwing an exception at least a way to tell more 446 // specifically to the caller. 447 out << "return false;" << "\n"; 448 out.unindent(); 449 out << "}" << "\n"; 450 451 out << "LOG(INFO) << \"Call an API.\";\n"; 452 out << "LOG(INFO) << \"local_device = \" << local_device;\n"; 453 454 if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) { 455 out << "*result = NULL;" << "\n"; 456 } else { 457 out << "*result = const_cast<void*>(reinterpret_cast<const void*>("; 458 } 459 out << "local_device->" << api.name() << "("; 460 if (arg_count > 0) out << "\n"; 461 462 for (int index = 0; index < arg_count; index++) { 463 out << "arg" << index; 464 if (index != (arg_count - 1)) { 465 out << "," << "\n"; 466 } 467 } 468 469 if (api.has_return_type() && api.return_type().type() != TYPE_VOID) { 470 out << "))"; 471 } 472 out << ");" << "\n"; 473 GenerateCodeToStopMeasurement(out); 474 out << "LOG(INFO) << \"called\";\n"; 475 476 // Copy the output (call by pointer or reference cases). 477 arg_count = 0; 478 for (auto const& arg : api.arg()) { 479 if (arg.is_output()) { 480 // TODO check the return value 481 out << GetConversionToProtobufFunctionName(arg) << "(arg" 482 << arg_count << ", " 483 << "func_msg->mutable_arg(" << arg_count << "));" << "\n"; 484 } 485 arg_count++; 486 } 487 488 out << "return true;" << "\n"; 489 out.unindent(); 490 out << "}" << "\n"; 491 } 492 // TODO: if there were pointers, free them. 493 out << "LOG(ERROR) << \"func not found\";\n"; 494 out << "return false;" << "\n"; 495 out.unindent(); 496 out << "}" << "\n"; 497 } 498 499 void HalCodeGen::GenerateCppBodyFuzzFunction( 500 Formatter& out, const StructSpecificationMessage& message, 501 const string& fuzzer_extended_class_name, 502 const string& original_data_structure_name, const string& parent_path) { 503 for (auto const& sub_struct : message.sub_struct()) { 504 GenerateCppBodyFuzzFunction( 505 out, sub_struct, fuzzer_extended_class_name, 506 original_data_structure_name, 507 parent_path + message.name() + (sub_struct.is_pointer() ? "->" : ".")); 508 } 509 510 string parent_path_printable(parent_path); 511 ReplaceSubString(parent_path_printable, "->", "_"); 512 replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_'); 513 514 out << "bool " << fuzzer_extended_class_name << "::Fuzz_" 515 << parent_path_printable + message.name() << "(" << "\n"; 516 out << "FunctionSpecificationMessage* func_msg," << "\n"; 517 out << "void** result, const string& callback_socket_name) {" << "\n"; 518 out.indent(); 519 out << "const char* func_name = func_msg->name().c_str();" << "\n"; 520 out << "LOG(INFO) << func_name;\n"; 521 522 bool is_open; 523 for (auto const& api : message.api()) { 524 is_open = false; 525 if ((parent_path_printable + message.name()) == "_common_methods" && 526 api.name() == "open") { 527 is_open = true; 528 } 529 530 out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n"; 531 out.indent(); 532 533 out << original_data_structure_name << "* local_device = "; 534 out << "reinterpret_cast<" << original_data_structure_name << "*>(" 535 << kInstanceVariableName << ");" << "\n"; 536 537 out << "if (local_device == NULL) {" << "\n"; 538 out.indent(); 539 out << "LOG(INFO) << \"use hmi\";\n"; 540 out << "local_device = reinterpret_cast<" 541 << original_data_structure_name << "*>(hmi_);" << "\n"; 542 out.unindent(); 543 out << "}" << "\n"; 544 out << "if (local_device == NULL) {" << "\n"; 545 out.indent(); 546 out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n"; 547 out << "return false;" << "\n"; 548 out.unindent(); 549 out << "}" << "\n"; 550 551 // args - definition; 552 int arg_count = 0; 553 for (auto const& arg : api.arg()) { 554 out << GetCppVariableType(arg) << " "; 555 out << "arg" << arg_count << " = "; 556 if (arg_count == 0 && arg.type() == TYPE_PREDEFINED && 557 !strncmp(arg.predefined_type().c_str(), 558 original_data_structure_name.c_str(), 559 original_data_structure_name.length())) { 560 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">(" 561 << kInstanceVariableName << ")"; 562 } else { 563 std::stringstream msg_ss; 564 msg_ss << "func_msg->arg(" << arg_count << ")"; 565 string msg = msg_ss.str(); 566 567 if (arg.type() == TYPE_SCALAR) { 568 out << "(" << msg << ".type() == TYPE_SCALAR && " << msg 569 << ".scalar_value()"; 570 if (arg.scalar_type() == "pointer" || 571 arg.scalar_type() == "char_pointer" || 572 arg.scalar_type() == "uchar_pointer" || 573 arg.scalar_type() == "void_pointer" || 574 arg.scalar_type() == "function_pointer") { 575 out << ".has_pointer())? "; 576 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">"; 577 } else { 578 out << ".has_" << arg.scalar_type() << "())? "; 579 } 580 out << "(" << msg << ".scalar_value()"; 581 582 if (arg.scalar_type() == "int32_t" || 583 arg.scalar_type() == "uint32_t" || 584 arg.scalar_type() == "int64_t" || 585 arg.scalar_type() == "uint64_t" || 586 arg.scalar_type() == "int16_t" || 587 arg.scalar_type() == "uint16_t" || 588 arg.scalar_type() == "int8_t" || arg.scalar_type() == "uint8_t" || 589 arg.scalar_type() == "float_t" || 590 arg.scalar_type() == "double_t") { 591 out << "." << arg.scalar_type() << "() "; 592 } else if (arg.scalar_type() == "pointer" || 593 arg.scalar_type() == "char_pointer" || 594 arg.scalar_type() == "uchar_pointer" || 595 arg.scalar_type() == "function_pointer" || 596 arg.scalar_type() == "void_pointer") { 597 out << ".pointer() "; 598 } else { 599 cerr << __func__ << " ERROR unsupported type " << arg.scalar_type() 600 << "\n"; 601 exit(-1); 602 } 603 out << ") : "; 604 } 605 606 if (is_open) { 607 if (arg_count == 0) { 608 out << "hmi_;" << "\n"; 609 } else if (arg_count == 1) { 610 out << "((hmi_) ? const_cast<char*>(hmi_->name) : NULL)" << "\n"; 611 } else if (arg_count == 2) { 612 out << "(struct hw_device_t**) &device_" << "\n"; 613 } else { 614 cerr << __func__ << " ERROR additional args for open " << arg_count 615 << "\n"; 616 exit(-1); 617 } 618 } else { 619 out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg 620 << ".type() == TYPE_STRUCT || " << msg 621 << ".type() == TYPE_SCALAR)? "; 622 out << GetCppInstanceType(arg, msg); 623 out << " : " << GetCppInstanceType(arg) << " )"; 624 // TODO: use the given message and call a lib function which converts 625 // a message to a C/C++ struct. 626 } 627 } 628 out << ";" << "\n"; 629 out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count 630 << "\n\n"; 631 arg_count++; 632 } 633 634 // actual function call 635 GenerateCodeToStartMeasurement(out); 636 out << "LOG(INFO) << \"hit2.\" << device_;\n"; 637 638 out << "if (reinterpret_cast<" << original_data_structure_name 639 << "*>(local_device)" << parent_path << message.name() << "->" 640 << api.name() << " == NULL"; 641 out << ") {" << "\n"; 642 out.indent(); 643 out << "LOG(ERROR) << \"api not set.\";\n"; 644 // todo: consider throwing an exception at least a way to tell more 645 // specifically to the caller. 646 out << "return false;" << "\n"; 647 out.unindent(); 648 out << "}" << "\n"; 649 650 out << "LOG(INFO) << \"Call an API.\";\n"; 651 if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) { 652 out << "*result = NULL;" << "\n"; 653 } else { 654 out << "*result = const_cast<void*>(reinterpret_cast<const void*>("; 655 } 656 out << "local_device" << parent_path << message.name() << "->" 657 << api.name() << "("; 658 if (arg_count > 0) out << "\n"; 659 660 for (int index = 0; index < arg_count; index++) { 661 out << "arg" << index; 662 if (index != (arg_count - 1)) { 663 out << "," << "\n"; 664 } 665 } 666 if (api.has_return_type() && api.return_type().type() != TYPE_VOID) { 667 out << "))"; 668 } 669 out << ");" << "\n"; 670 GenerateCodeToStopMeasurement(out); 671 out << "LOG(INFO) << \"called\";\n"; 672 673 // Copy the output (call by pointer or reference cases). 674 arg_count = 0; 675 for (auto const& arg : api.arg()) { 676 if (arg.is_output()) { 677 // TODO check the return value 678 out << GetConversionToProtobufFunctionName(arg) << "(arg" 679 << arg_count << ", " 680 << "func_msg->mutable_arg(" << arg_count << "));" << "\n"; 681 } 682 arg_count++; 683 } 684 685 out << "return true;" << "\n"; 686 out.unindent(); 687 out << "}" << "\n"; 688 } 689 // TODO: if there were pointers, free them. 690 out << "return false;" << "\n"; 691 out.unindent(); 692 out << "}" << "\n"; 693 } 694 695 void HalCodeGen::GenerateCppBodyGetAttributeFunction( 696 Formatter& out, const ComponentSpecificationMessage& message, 697 const string& fuzzer_extended_class_name) { 698 for (auto const& sub_struct : message.interface().sub_struct()) { 699 GenerateCppBodyGetAttributeFunction( 700 out, sub_struct, fuzzer_extended_class_name, 701 message.original_data_structure_name(), 702 sub_struct.is_pointer() ? "->" : "."); 703 } 704 705 out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n"; 706 out << " FunctionSpecificationMessage* func_msg," << "\n"; 707 out << " void** result) {" << "\n"; 708 out.indent(); 709 out << "const char* func_name = func_msg->name().c_str();" << "\n"; 710 out << "LOG(INFO) << \" '\" << func_name << \"'\";\n"; 711 712 // to call another function if it's for a sub_struct 713 if (message.interface().sub_struct().size() > 0) { 714 out << " if (func_msg->parent_path().length() > 0) {" << "\n"; 715 out.indent(); 716 for (auto const& sub_struct : message.interface().sub_struct()) { 717 GenerateSubStructGetAttributeFunctionCall(out, sub_struct, ""); 718 } 719 out.unindent(); 720 out << "}" << "\n"; 721 } 722 723 out << message.original_data_structure_name() 724 << "* local_device = "; 725 out << "reinterpret_cast<" << message.original_data_structure_name() 726 << "*>(" << kInstanceVariableName << ");" << "\n"; 727 728 out << "if (local_device == NULL) {" << "\n"; 729 out.indent(); 730 out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n"; 731 out << "local_device = reinterpret_cast<" 732 << message.original_data_structure_name() << "*>(hmi_);" << "\n"; 733 out.unindent(); 734 out << "}" << "\n"; 735 out << "if (local_device == NULL) {" << "\n"; 736 out.indent(); 737 out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n"; 738 out << "return false;" << "\n"; 739 out.unindent(); 740 out << "}" << "\n"; 741 742 for (auto const& attribute : message.interface().attribute()) { 743 if (attribute.type() == TYPE_SUBMODULE || 744 attribute.type() == TYPE_SCALAR) { 745 out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n"; 746 out.indent(); 747 out << "LOG(INFO) << \"match\";\n"; 748 749 // actual function call 750 out << "LOG(INFO) << \"hit2.\" << device_ ;\n"; 751 752 out << "LOG(INFO) << \"ok. let's read attribute.\";\n"; 753 out << "*result = const_cast<void*>(reinterpret_cast<const void*>("; 754 out << "local_device->" << attribute.name(); 755 out << "));" << "\n"; 756 757 out << "LOG(INFO) << \"got\";\n"; 758 759 out << "return true;" << "\n"; 760 out.unindent(); 761 out << "}" << "\n"; 762 } 763 } 764 // TODO: if there were pointers, free them. 765 out << "LOG(ERROR) << \"attribute not found\";\n"; 766 out << "return false;" << "\n"; 767 out.unindent(); 768 out << "}" << "\n"; 769 } 770 771 void HalCodeGen::GenerateCppBodyGetAttributeFunction( 772 Formatter& out, const StructSpecificationMessage& message, 773 const string& fuzzer_extended_class_name, 774 const string& original_data_structure_name, const string& parent_path) { 775 for (auto const& sub_struct : message.sub_struct()) { 776 GenerateCppBodyGetAttributeFunction( 777 out, sub_struct, fuzzer_extended_class_name, 778 original_data_structure_name, 779 parent_path + message.name() + (sub_struct.is_pointer() ? "->" : ".")); 780 } 781 782 string parent_path_printable(parent_path); 783 ReplaceSubString(parent_path_printable, "->", "_"); 784 replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_'); 785 786 out << "bool " << fuzzer_extended_class_name << "::GetAttribute_" 787 << parent_path_printable + message.name() << "(" << "\n"; 788 out << " FunctionSpecificationMessage* func_msg," << "\n"; 789 out << " void** result) {" << "\n"; 790 out.indent(); 791 out << "const char* func_name = func_msg->name().c_str();" << "\n"; 792 out << "LOG(INFO) << func_name;\n"; 793 794 out << original_data_structure_name 795 << "* local_device = "; 796 out << "reinterpret_cast<" << original_data_structure_name 797 << "*>(" << kInstanceVariableName << ");" << "\n"; 798 799 out << "if (local_device == NULL) {" << "\n"; 800 out.indent(); 801 out << " LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n"; 802 out << " local_device = reinterpret_cast<" 803 << original_data_structure_name << "*>(hmi_);" << "\n"; 804 out.unindent(); 805 out << "}" << "\n"; 806 out << "if (local_device == NULL) {" << "\n"; 807 out.indent(); 808 out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n"; 809 out << "return false;" << "\n"; 810 out.unindent(); 811 out << "}" << "\n"; 812 813 for (auto const& attribute : message.attribute()) { 814 if (attribute.type() == TYPE_SUBMODULE || 815 attribute.type() == TYPE_SCALAR) { 816 out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n"; 817 out.indent(); 818 out << "LOG(INFO) << \"match\";\n"; 819 820 // actual function call 821 out << "LOG(INFO) << \"hit2.\" << device_;\n"; 822 823 out << "LOG(INFO) << \"ok. let's read attribute.\";\n"; 824 out << "*result = const_cast<void*>(reinterpret_cast<const void*>("; 825 out << "local_device" << parent_path << message.name() << "."; 826 // TODO: use parent's is_pointer() 827 out << attribute.name(); 828 out << "));" << "\n"; 829 830 out << "LOG(INFO) << \"got\";\n"; 831 832 out << "return true;" << "\n"; 833 out.unindent(); 834 out << "}" << "\n"; 835 } 836 } 837 // TODO: if there were pointers, free them. 838 out << "LOG(ERROR) << \"attribute not found\";\n"; 839 out << "return false;" << "\n"; 840 out.unindent(); 841 out << "}" << "\n"; 842 } 843 844 void HalCodeGen::GenerateClassConstructionFunction(Formatter& out, 845 const ComponentSpecificationMessage& /*message*/, 846 const string& fuzzer_extended_class_name) { 847 out << fuzzer_extended_class_name << "() : DriverBase(HAL_CONVENTIONAL) {}\n"; 848 } 849 850 void HalCodeGen::GenerateSubStructFuzzFunctionCall( 851 Formatter& out, const StructSpecificationMessage& message, 852 const string& parent_path) { 853 string current_path(parent_path); 854 if (current_path.length() > 0) { 855 current_path += "."; 856 } 857 current_path += message.name(); 858 859 string current_path_printable(current_path); 860 replace(current_path_printable.begin(), current_path_printable.end(), '.', 861 '_'); 862 863 out << "if (func_msg->parent_path() == \"" << current_path << "\") {" 864 << "\n"; 865 out.indent(); 866 out << "return Fuzz__" << current_path_printable 867 << "(func_msg, result, callback_socket_name);" << "\n"; 868 out.unindent(); 869 out << "}" << "\n"; 870 871 for (auto const& sub_struct : message.sub_struct()) { 872 GenerateSubStructFuzzFunctionCall(out, sub_struct, current_path); 873 } 874 } 875 876 void HalCodeGen::GenerateSubStructGetAttributeFunctionCall( 877 Formatter& out, const StructSpecificationMessage& message, 878 const string& parent_path) { 879 string current_path(parent_path); 880 if (current_path.length() > 0) { 881 current_path += "."; 882 } 883 current_path += message.name(); 884 885 string current_path_printable(current_path); 886 replace(current_path_printable.begin(), current_path_printable.end(), '.', 887 '_'); 888 889 out << "if (func_msg->parent_path() == \"" << current_path << "\") {" 890 << "\n"; 891 out.indent(); 892 out << " return GetAttribute__" << current_path_printable 893 << "(func_msg, result);" << "\n"; 894 out.unindent(); 895 out << "}" << "\n"; 896 897 for (auto const& sub_struct : message.sub_struct()) { 898 GenerateSubStructGetAttributeFunctionCall(out, sub_struct, current_path); 899 } 900 } 901 902 } // namespace vts 903 } // namespace android 904