1 /* 2 * Copyright (C) 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 "specification_parser/SpecificationBuilder.h" 18 19 #include <dirent.h> 20 21 #include <iomanip> 22 #include <iostream> 23 #include <queue> 24 #include <string> 25 #include <sstream> 26 27 #include <cutils/properties.h> 28 29 #include "fuzz_tester/FuzzerBase.h" 30 #include "fuzz_tester/FuzzerWrapper.h" 31 #include "specification_parser/InterfaceSpecificationParser.h" 32 #include "utils/InterfaceSpecUtil.h" 33 #include "utils/StringUtil.h" 34 35 #include <google/protobuf/text_format.h> 36 #include "test/vts/proto/ComponentSpecificationMessage.pb.h" 37 38 namespace android { 39 namespace vts { 40 41 SpecificationBuilder::SpecificationBuilder(const string dir_path, 42 int epoch_count, 43 const string& callback_socket_name) 44 : dir_path_(dir_path), 45 epoch_count_(epoch_count), 46 if_spec_msg_(NULL), 47 module_name_(NULL), 48 hw_binder_service_name_(NULL), 49 callback_socket_name_(callback_socket_name) {} 50 51 vts::ComponentSpecificationMessage* 52 SpecificationBuilder::FindComponentSpecification(const int target_class, 53 const int target_type, 54 const float target_version, 55 const string submodule_name, 56 const string package, 57 const string component_name) { 58 DIR* dir; 59 struct dirent* ent; 60 cerr << __func__ << ": component " << component_name << endl; 61 62 // Derive the package-specific dir which contains .vts files 63 string target_dir_path = dir_path_; 64 if (!endsWith(target_dir_path, "/")) { 65 target_dir_path += "/"; 66 } 67 string target_subdir_path = package; 68 ReplaceSubString(target_subdir_path, ".", "/"); 69 target_dir_path += target_subdir_path + "/"; 70 71 stringstream stream; 72 stream << fixed << setprecision(1) << target_version; 73 target_dir_path += stream.str(); 74 75 if (!(dir = opendir(target_dir_path.c_str()))) { 76 cerr << __func__ << ": Can't opendir " << target_dir_path << endl; 77 target_dir_path = ""; 78 return NULL; 79 } 80 81 while ((ent = readdir(dir))) { 82 if (ent->d_type == DT_REG) { 83 if (string(ent->d_name).find(SPEC_FILE_EXT) != std::string::npos) { 84 cout << __func__ << ": Checking a file " << ent->d_name << endl; 85 const string file_path = target_dir_path + "/" + string(ent->d_name); 86 vts::ComponentSpecificationMessage* message = 87 new vts::ComponentSpecificationMessage(); 88 if (InterfaceSpecificationParser::parse(file_path.c_str(), message)) { 89 if (message->component_class() != target_class) continue; 90 91 if (message->component_class() != HAL_HIDL) { 92 if (message->component_type() == target_type && 93 message->component_type_version() == target_version) { 94 if (submodule_name.length() > 0) { 95 if (message->component_class() != HAL_CONVENTIONAL_SUBMODULE || 96 message->original_data_structure_name() != submodule_name) { 97 continue; 98 } 99 } 100 closedir(dir); 101 return message; 102 } 103 } else { 104 if (message->package() == package && 105 message->component_type_version() == target_version) { 106 if (component_name.length() > 0) { 107 if (message->component_name() != component_name) { 108 continue; 109 } 110 } 111 closedir(dir); 112 return message; 113 } 114 } 115 } 116 delete message; 117 } 118 } 119 } 120 closedir(dir); 121 return NULL; 122 } 123 124 FuzzerBase* SpecificationBuilder::GetFuzzerBase( 125 const vts::ComponentSpecificationMessage& iface_spec_msg, 126 const char* dll_file_name, const char* /*target_func_name*/) { 127 cout << __func__ << ":" << __LINE__ << " " << "entry" << endl; 128 FuzzerBase* fuzzer = wrapper_.GetFuzzer(iface_spec_msg); 129 if (!fuzzer) { 130 cerr << __func__ << ": couldn't get a fuzzer base class" << endl; 131 return NULL; 132 } 133 134 // TODO: don't load multiple times. reuse FuzzerBase*. 135 cout << __func__ << ":" << __LINE__ << " " << "got fuzzer" << endl; 136 if (iface_spec_msg.component_class() == HAL_HIDL) { 137 char get_sub_property[PROPERTY_VALUE_MAX]; 138 bool get_stub = false; /* default is binderized */ 139 if (property_get("vts.hidl.get_stub", get_sub_property, "") > 0) { 140 if (!strcmp(get_sub_property, "true") || 141 !strcmp(get_sub_property, "True") || 142 !strcmp(get_sub_property, "1")) { 143 get_stub = true; 144 } 145 } 146 const char* service_name; 147 if (hw_binder_service_name_ && strlen(hw_binder_service_name_) > 0) { 148 service_name = hw_binder_service_name_; 149 } else { 150 service_name = iface_spec_msg.package().substr( 151 iface_spec_msg.package().find_last_of(".") + 1).c_str(); 152 } 153 if (!fuzzer->GetService(get_stub, service_name)) { 154 cerr << __FUNCTION__ << ": couldn't get service" << endl; 155 return NULL; 156 } 157 } else { 158 if (!fuzzer->LoadTargetComponent(dll_file_name)) { 159 cerr << __FUNCTION__ << ": couldn't load target component file, " 160 << dll_file_name << endl; 161 return NULL; 162 } 163 } 164 cout << __func__ << ":" << __LINE__ << " " 165 << "loaded target comp" << endl; 166 167 return fuzzer; 168 /* 169 * TODO: now always return the fuzzer. this change is due to the difficulty 170 * in checking nested apis although that's possible. need to check whether 171 * Fuzz() found the function, while still distinguishing the difference 172 * between that and defined but non-set api. 173 if (!strcmp(target_func_name, "#Open")) return fuzzer; 174 175 for (const vts::FunctionSpecificationMessage& func_msg : iface_spec_msg.api()) 176 { 177 cout << "checking " << func_msg.name() << endl; 178 if (!strcmp(target_func_name, func_msg.name().c_str())) { 179 return fuzzer; 180 } 181 } 182 return NULL; 183 */ 184 } 185 186 FuzzerBase* SpecificationBuilder::GetFuzzerBaseSubModule( 187 const vts::ComponentSpecificationMessage& iface_spec_msg, 188 void* object_pointer) { 189 cout << __func__ << ":" << __LINE__ << " " 190 << "entry object_pointer " << ((uint64_t)object_pointer) << endl; 191 FuzzerWrapper wrapper; 192 if (!wrapper.LoadInterfaceSpecificationLibrary(spec_lib_file_path_)) { 193 cerr << __func__ << " can't load specification lib, " 194 << spec_lib_file_path_ << endl; 195 return NULL; 196 } 197 FuzzerBase* fuzzer = wrapper.GetFuzzer(iface_spec_msg); 198 if (!fuzzer) { 199 cerr << __FUNCTION__ << ": couldn't get a fuzzer base class" << endl; 200 return NULL; 201 } 202 203 // TODO: don't load multiple times. reuse FuzzerBase*. 204 cout << __func__ << ":" << __LINE__ << " " 205 << "got fuzzer" << endl; 206 if (iface_spec_msg.component_class() == HAL_HIDL) { 207 cerr << __func__ << " HIDL not supported" << endl; 208 return NULL; 209 } else { 210 if (!fuzzer->SetTargetObject(object_pointer)) { 211 cerr << __FUNCTION__ << ": couldn't set target object" << endl; 212 return NULL; 213 } 214 } 215 cout << __func__ << ":" << __LINE__ << " " 216 << "loaded target comp" << endl; 217 return fuzzer; 218 } 219 220 FuzzerBase* SpecificationBuilder::GetFuzzerBaseAndAddAllFunctionsToQueue( 221 const vts::ComponentSpecificationMessage& iface_spec_msg, 222 const char* dll_file_name) { 223 FuzzerBase* fuzzer = wrapper_.GetFuzzer(iface_spec_msg); 224 if (!fuzzer) { 225 cerr << __FUNCTION__ << ": couldn't get a fuzzer base class" << endl; 226 return NULL; 227 } 228 229 if (iface_spec_msg.component_class() == HAL_HIDL) { 230 char get_sub_property[PROPERTY_VALUE_MAX]; 231 bool get_stub = false; /* default is binderized */ 232 if (property_get("vts.hidl.get_stub", get_sub_property, "") > 0) { 233 if (!strcmp(get_sub_property, "true") || !strcmp(get_sub_property, "True") 234 || !strcmp(get_sub_property, "1")) { 235 get_stub = true; 236 } 237 } 238 const char* service_name; 239 if (hw_binder_service_name_ && strlen(hw_binder_service_name_) > 0) { 240 service_name = hw_binder_service_name_; 241 } else { 242 service_name = iface_spec_msg.package().substr( 243 iface_spec_msg.package().find_last_of(".") + 1).c_str(); 244 } 245 if (!fuzzer->GetService(get_stub, service_name)) { 246 cerr << __FUNCTION__ << ": couldn't get service" << endl; 247 return NULL; 248 } 249 } else { 250 if (!fuzzer->LoadTargetComponent(dll_file_name)) { 251 cerr << __FUNCTION__ << ": couldn't load target component file, " 252 << dll_file_name << endl; 253 return NULL; 254 } 255 } 256 257 for (const vts::FunctionSpecificationMessage& func_msg : 258 iface_spec_msg.interface().api()) { 259 cout << "Add a job " << func_msg.name() << endl; 260 FunctionSpecificationMessage* func_msg_copy = func_msg.New(); 261 func_msg_copy->CopyFrom(func_msg); 262 job_queue_.push(make_pair(func_msg_copy, fuzzer)); 263 } 264 return fuzzer; 265 } 266 267 bool SpecificationBuilder::LoadTargetComponent( 268 const char* dll_file_name, const char* spec_lib_file_path, int target_class, 269 int target_type, float target_version, const char* target_package, 270 const char* target_component_name, 271 const char* hw_binder_service_name, const char* module_name) { 272 cout << __func__ << " entry dll_file_name = " << dll_file_name << endl; 273 if_spec_msg_ = 274 FindComponentSpecification(target_class, target_type, target_version, 275 module_name, target_package, 276 target_component_name); 277 if (!if_spec_msg_) { 278 cerr << __func__ << ": no interface specification file found for " 279 << "class " << target_class << " type " << target_type << " version " 280 << target_version << endl; 281 return false; 282 } 283 284 if (target_class == HAL_HIDL) { 285 asprintf(&spec_lib_file_path_, "%s@%s-vts.driver.so", target_package, 286 GetVersionString(target_version).c_str()); 287 cout << __func__ << " spec lib path " << spec_lib_file_path_ << endl; 288 } else { 289 spec_lib_file_path_ = (char*)malloc(strlen(spec_lib_file_path) + 1); 290 strcpy(spec_lib_file_path_, spec_lib_file_path); 291 } 292 293 dll_file_name_ = (char*)malloc(strlen(dll_file_name) + 1); 294 strcpy(dll_file_name_, dll_file_name); 295 296 string output; 297 if_spec_msg_->SerializeToString(&output); 298 cout << "loaded ifspec length " << output.length() << endl; 299 300 module_name_ = (char*)malloc(strlen(module_name) + 1); 301 strcpy(module_name_, module_name); 302 cout << __func__ << ":" << __LINE__ << " module_name " << module_name_ 303 << endl; 304 305 if (hw_binder_service_name) { 306 hw_binder_service_name_ = (char*)malloc(strlen(hw_binder_service_name) + 1); 307 strcpy(hw_binder_service_name_, hw_binder_service_name); 308 cout << __func__ << ":" << __LINE__ << " hw_binder_service_name " 309 << hw_binder_service_name_ << endl; 310 } 311 return true; 312 } 313 314 const string empty_string = string(); 315 316 const string& SpecificationBuilder::CallFunction( 317 FunctionSpecificationMessage* func_msg) { 318 cout << __func__ << ":" << __LINE__ << " entry" << endl; 319 if (!wrapper_.LoadInterfaceSpecificationLibrary(spec_lib_file_path_)) { 320 cerr << __func__ << ":" << __LINE__ << " lib loading failed" << endl; 321 return empty_string; 322 } 323 cout << __func__ << ":" << __LINE__ << " " 324 << "loaded if_spec lib " << func_msg << endl; 325 cout << __func__ << " " << dll_file_name_ << " " << func_msg->name() << endl; 326 327 FuzzerBase* func_fuzzer; 328 if (func_msg->submodule_name().size() > 0) { 329 string submodule_name = func_msg->submodule_name(); 330 cout << __func__ << " submodule name " << submodule_name << endl; 331 if (submodule_fuzzerbase_map_.find(submodule_name) 332 != submodule_fuzzerbase_map_.end()) { 333 cout << __func__ << " call is for a submodule" << endl; 334 func_fuzzer = submodule_fuzzerbase_map_[submodule_name]; 335 } else { 336 cerr << __func__ << " called an API of a non-loaded submodule." << endl; 337 return empty_string; 338 } 339 } else { 340 func_fuzzer = GetFuzzerBase(*if_spec_msg_, dll_file_name_, 341 func_msg->name().c_str()); 342 } 343 cout << __func__ << ":" << __LINE__ << endl; 344 if (!func_fuzzer) { 345 cerr << "can't find FuzzerBase for '" << func_msg->name() << "' using '" 346 << dll_file_name_ << "'" << endl; 347 return empty_string; 348 } 349 350 if (func_msg->name() == "#Open") { 351 cout << __func__ << ":" << __LINE__ << " #Open" << endl; 352 if (func_msg->arg().size() > 0) { 353 cout << __func__ << " " << func_msg->arg(0).string_value().message() 354 << endl; 355 func_fuzzer->OpenConventionalHal( 356 func_msg->arg(0).string_value().message().c_str()); 357 } else { 358 cout << __func__ << " no arg" << endl; 359 func_fuzzer->OpenConventionalHal(); 360 } 361 cout << __func__ << " opened" << endl; 362 // return the return value from open; 363 if (func_msg->return_type().has_type()) { 364 cout << __func__ << " return_type exists" << endl; 365 // TODO handle when the size > 1. 366 if (!strcmp(func_msg->return_type().scalar_type().c_str(), "int32_t")) { 367 cout << __func__ << " return_type is int32_t" << endl; 368 func_msg->mutable_return_type()->mutable_scalar_value()->set_int32_t(0); 369 cout << "result " << endl; 370 // todo handle more types; 371 string* output = new string(); 372 google::protobuf::TextFormat::PrintToString(*func_msg, output); 373 return *output; 374 } 375 } 376 cerr << __func__ << " return_type unknown" << endl; 377 string* output = new string(); 378 google::protobuf::TextFormat::PrintToString(*func_msg, output); 379 return *output; 380 } 381 cout << __func__ << ":" << __LINE__ << endl; 382 383 void* result; 384 FunctionSpecificationMessage result_msg; 385 func_fuzzer->FunctionCallBegin(); 386 cout << __func__ << " Call Function " << func_msg->name() << " parent_path(" 387 << func_msg->parent_path() << ")" << endl; 388 // For Hidl HAL, use CallFunction method. 389 if (if_spec_msg_ && if_spec_msg_->component_class() == HAL_HIDL) { 390 if (!func_fuzzer->CallFunction(*func_msg, callback_socket_name_, 391 &result_msg)) { 392 cerr << __func__ << " function not found - todo handle more explicitly" 393 << endl; 394 return *(new string("error")); 395 } 396 } else { 397 if (!func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_)) { 398 cerr << __func__ << " function not found - todo handle more explicitly" 399 << endl; 400 return *(new string("error")); 401 } 402 } 403 cout << __func__ << ": called" << endl; 404 405 // set coverage data. 406 func_fuzzer->FunctionCallEnd(func_msg); 407 408 if (if_spec_msg_ && if_spec_msg_->component_class() == HAL_HIDL) { 409 string* output = new string(); 410 google::protobuf::TextFormat::PrintToString(result_msg, output); 411 return *output; 412 } else { 413 if (func_msg->return_type().type() == TYPE_PREDEFINED) { 414 // TODO: actually handle this case. 415 if (result != NULL) { 416 // loads that interface spec and enqueues all functions. 417 cout << __func__ << " return type: " << func_msg->return_type().type() 418 << endl; 419 } else { 420 cout << __func__ << " return value = NULL" << endl; 421 } 422 cerr << __func__ << " todo: support aggregate" << endl; 423 string* output = new string(); 424 google::protobuf::TextFormat::PrintToString(*func_msg, output); 425 return *output; 426 } else if (func_msg->return_type().type() == TYPE_SCALAR) { 427 // TODO handle when the size > 1. 428 if (!strcmp(func_msg->return_type().scalar_type().c_str(), "int32_t")) { 429 func_msg->mutable_return_type()->mutable_scalar_value()->set_int32_t( 430 *((int*)(&result))); 431 cout << "result " << endl; 432 // todo handle more types; 433 string* output = new string(); 434 google::protobuf::TextFormat::PrintToString(*func_msg, output); 435 return *output; 436 } 437 } else if (func_msg->return_type().type() == TYPE_SUBMODULE) { 438 cerr << __func__ << "[driver:hal] return type TYPE_SUBMODULE" << endl; 439 if (result != NULL) { 440 // loads that interface spec and enqueues all functions. 441 cout << __func__ << " return type: " << func_msg->return_type().type() 442 << endl; 443 } else { 444 cout << __func__ << " return value = NULL" << endl; 445 } 446 // find a VTS spec for that module 447 string submodule_name = func_msg->return_type().predefined_type().substr( 448 0, func_msg->return_type().predefined_type().size() - 1); 449 vts::ComponentSpecificationMessage* submodule_iface_spec_msg; 450 if (submodule_if_spec_map_.find(submodule_name) 451 != submodule_if_spec_map_.end()) { 452 cout << __func__ << " submodule InterfaceSpecification already loaded" 453 << endl; 454 submodule_iface_spec_msg = submodule_if_spec_map_[submodule_name]; 455 func_msg->set_allocated_return_type_submodule_spec( 456 submodule_iface_spec_msg); 457 } else { 458 submodule_iface_spec_msg = 459 FindComponentSpecification( 460 if_spec_msg_->component_class(), if_spec_msg_->component_type(), 461 if_spec_msg_->component_type_version(), submodule_name, 462 if_spec_msg_->package(), if_spec_msg_->component_name()); 463 if (!submodule_iface_spec_msg) { 464 cerr << __func__ << " submodule InterfaceSpecification not found" << endl; 465 } else { 466 cout << __func__ << " submodule InterfaceSpecification found" << endl; 467 func_msg->set_allocated_return_type_submodule_spec( 468 submodule_iface_spec_msg); 469 FuzzerBase* func_fuzzer = GetFuzzerBaseSubModule( 470 *submodule_iface_spec_msg, result); 471 submodule_if_spec_map_[submodule_name] = submodule_iface_spec_msg; 472 submodule_fuzzerbase_map_[submodule_name] = func_fuzzer; 473 } 474 } 475 string* output = new string(); 476 google::protobuf::TextFormat::PrintToString(*func_msg, output); 477 return *output; 478 } 479 } 480 return *(new string("void")); 481 } 482 483 const string& SpecificationBuilder::GetAttribute( 484 FunctionSpecificationMessage* func_msg) { 485 if (!wrapper_.LoadInterfaceSpecificationLibrary(spec_lib_file_path_)) { 486 return empty_string; 487 } 488 cout << __func__ << " " 489 << "loaded if_spec lib" << endl; 490 cout << __func__ << " " << dll_file_name_ << " " << func_msg->name() << endl; 491 492 FuzzerBase* func_fuzzer; 493 if (func_msg->submodule_name().size() > 0) { 494 string submodule_name = func_msg->submodule_name(); 495 cout << __func__ << " submodule name " << submodule_name << endl; 496 if (submodule_fuzzerbase_map_.find(submodule_name) 497 != submodule_fuzzerbase_map_.end()) { 498 cout << __func__ << " call is for a submodule" << endl; 499 func_fuzzer = submodule_fuzzerbase_map_[submodule_name]; 500 } else { 501 cerr << __func__ << " called an API of a non-loaded submodule." << endl; 502 return empty_string; 503 } 504 } else { 505 func_fuzzer = GetFuzzerBase(*if_spec_msg_, dll_file_name_, 506 func_msg->name().c_str()); 507 } 508 cout << __func__ << ":" << __LINE__ << endl; 509 if (!func_fuzzer) { 510 cerr << "can't find FuzzerBase for " << func_msg->name() << " using " 511 << dll_file_name_ << endl; 512 return empty_string; 513 } 514 515 void* result; 516 cout << __func__ << " Get Atrribute " << func_msg->name() << " parent_path(" 517 << func_msg->parent_path() << ")" << endl; 518 if (!func_fuzzer->GetAttribute(func_msg, &result)) { 519 cerr << __func__ << " attribute not found - todo handle more explicitly" 520 << endl; 521 return *(new string("error")); 522 } 523 cout << __func__ << ": called" << endl; 524 525 if (if_spec_msg_ && if_spec_msg_->component_class() == HAL_HIDL) { 526 cout << __func__ << ": for a HIDL HAL" << endl; 527 func_msg->mutable_return_type()->set_type(TYPE_STRING); 528 func_msg->mutable_return_type()->mutable_string_value()->set_message( 529 *(string*)result); 530 func_msg->mutable_return_type()->mutable_string_value()->set_length( 531 ((string*)result)->size()); 532 free(result); 533 string* output = new string(); 534 google::protobuf::TextFormat::PrintToString(*func_msg, output); 535 return *output; 536 } else { 537 cout << __func__ << ": for a non-HIDL HAL" << endl; 538 if (func_msg->return_type().type() == TYPE_PREDEFINED) { 539 // TODO: actually handle this case. 540 if (result != NULL) { 541 // loads that interface spec and enqueues all functions. 542 cout << __func__ << " return type: " << func_msg->return_type().type() 543 << endl; 544 } else { 545 cout << __func__ << " return value = NULL" << endl; 546 } 547 cerr << __func__ << " todo: support aggregate" << endl; 548 string* output = new string(); 549 google::protobuf::TextFormat::PrintToString(*func_msg, output); 550 return *output; 551 } else if (func_msg->return_type().type() == TYPE_SCALAR) { 552 // TODO handle when the size > 1. 553 if (!strcmp(func_msg->return_type().scalar_type().c_str(), "int32_t")) { 554 func_msg->mutable_return_type()->mutable_scalar_value()->set_int32_t( 555 *((int*)(&result))); 556 cout << "result " << endl; 557 // todo handle more types; 558 string* output = new string(); 559 google::protobuf::TextFormat::PrintToString(*func_msg, output); 560 return *output; 561 } else if (!strcmp(func_msg->return_type().scalar_type().c_str(), "uint32_t")) { 562 func_msg->mutable_return_type()->mutable_scalar_value()->set_uint32_t( 563 *((int*)(&result))); 564 cout << "result " << endl; 565 // todo handle more types; 566 string* output = new string(); 567 google::protobuf::TextFormat::PrintToString(*func_msg, output); 568 return *output; 569 } else if (!strcmp(func_msg->return_type().scalar_type().c_str(), "int16_t")) { 570 func_msg->mutable_return_type()->mutable_scalar_value()->set_int16_t( 571 *((int*)(&result))); 572 cout << "result " << endl; 573 // todo handle more types; 574 string* output = new string(); 575 google::protobuf::TextFormat::PrintToString(*func_msg, output); 576 return *output; 577 } else if (!strcmp(func_msg->return_type().scalar_type().c_str(), "uint16_t")) { 578 func_msg->mutable_return_type()->mutable_scalar_value()->set_uint16_t( 579 *((int*)(&result))); 580 cout << "result " << endl; 581 // todo handle more types; 582 string* output = new string(); 583 google::protobuf::TextFormat::PrintToString(*func_msg, output); 584 return *output; 585 } 586 } else if (func_msg->return_type().type() == TYPE_SUBMODULE) { 587 cerr << __func__ << "[driver:hal] return type TYPE_SUBMODULE" << endl; 588 if (result != NULL) { 589 // loads that interface spec and enqueues all functions. 590 cout << __func__ << " return type: " << func_msg->return_type().type() 591 << endl; 592 } else { 593 cout << __func__ << " return value = NULL" << endl; 594 } 595 // find a VTS spec for that module 596 string submodule_name = func_msg->return_type().predefined_type().substr( 597 0, func_msg->return_type().predefined_type().size() - 1); 598 vts::ComponentSpecificationMessage* submodule_iface_spec_msg; 599 if (submodule_if_spec_map_.find(submodule_name) 600 != submodule_if_spec_map_.end()) { 601 cout << __func__ << " submodule InterfaceSpecification already loaded" 602 << endl; 603 submodule_iface_spec_msg = submodule_if_spec_map_[submodule_name]; 604 func_msg->set_allocated_return_type_submodule_spec( 605 submodule_iface_spec_msg); 606 } else { 607 submodule_iface_spec_msg = 608 FindComponentSpecification( 609 if_spec_msg_->component_class(), if_spec_msg_->component_type(), 610 if_spec_msg_->component_type_version(), submodule_name, 611 if_spec_msg_->package(), if_spec_msg_->component_name()); 612 if (!submodule_iface_spec_msg) { 613 cerr << __func__ << " submodule InterfaceSpecification not found" << endl; 614 } else { 615 cout << __func__ << " submodule InterfaceSpecification found" << endl; 616 func_msg->set_allocated_return_type_submodule_spec( 617 submodule_iface_spec_msg); 618 FuzzerBase* func_fuzzer = GetFuzzerBaseSubModule( 619 *submodule_iface_spec_msg, result); 620 submodule_if_spec_map_[submodule_name] = submodule_iface_spec_msg; 621 submodule_fuzzerbase_map_[submodule_name] = func_fuzzer; 622 } 623 } 624 string* output = new string(); 625 google::protobuf::TextFormat::PrintToString(*func_msg, output); 626 return *output; 627 } 628 } 629 return *(new string("void")); 630 } 631 632 bool SpecificationBuilder::Process(const char* dll_file_name, 633 const char* spec_lib_file_path, 634 int target_class, int target_type, 635 float target_version, 636 const char* target_package, 637 const char* target_component_name) { 638 vts::ComponentSpecificationMessage* interface_specification_message = 639 FindComponentSpecification(target_class, target_type, target_version, 640 "", target_package, target_component_name); 641 cout << "ifspec addr " << interface_specification_message << endl; 642 643 if (!interface_specification_message) { 644 cerr << __func__ << ": no interface specification file found for class " 645 << target_class << " type " << target_type << " version " 646 << target_version << endl; 647 return false; 648 } 649 650 if (!wrapper_.LoadInterfaceSpecificationLibrary(spec_lib_file_path)) { 651 return false; 652 } 653 654 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(*interface_specification_message, 655 dll_file_name)) 656 return false; 657 658 for (int i = 0; i < epoch_count_; i++) { 659 // by default, breath-first-searching is used. 660 if (job_queue_.empty()) { 661 cout << "no more job to process; stopping after epoch " << i << endl; 662 break; 663 } 664 665 pair<vts::FunctionSpecificationMessage*, FuzzerBase*> curr_job = 666 job_queue_.front(); 667 job_queue_.pop(); 668 669 vts::FunctionSpecificationMessage* func_msg = curr_job.first; 670 FuzzerBase* func_fuzzer = curr_job.second; 671 672 void* result; 673 FunctionSpecificationMessage result_msg; 674 cout << "Iteration " << (i + 1) << " Function " << func_msg->name() << endl; 675 // For Hidl HAL, use CallFunction method. 676 if (interface_specification_message->component_class() == HAL_HIDL) { 677 func_fuzzer->CallFunction(*func_msg, callback_socket_name_, &result_msg); 678 } else { 679 func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_); 680 } 681 if (func_msg->return_type().type() == TYPE_PREDEFINED) { 682 if (result != NULL) { 683 // loads that interface spec and enqueues all functions. 684 cout << __FUNCTION__ 685 << " return type: " << func_msg->return_type().predefined_type() 686 << endl; 687 // TODO: handle the case when size > 1 688 string submodule_name = func_msg->return_type().predefined_type(); 689 while (!submodule_name.empty() && 690 (std::isspace(submodule_name.back()) || 691 submodule_name.back() == '*')) { 692 submodule_name.pop_back(); 693 } 694 vts::ComponentSpecificationMessage* iface_spec_msg = 695 FindComponentSpecification(target_class, target_type, 696 target_version, submodule_name); 697 if (iface_spec_msg) { 698 cout << __FUNCTION__ << " submodule found - " << submodule_name 699 << endl; 700 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(*iface_spec_msg, 701 dll_file_name)) { 702 return false; 703 } 704 } else { 705 cout << __FUNCTION__ << " submodule not found - " << submodule_name 706 << endl; 707 } 708 } else { 709 cout << __FUNCTION__ << " return value = NULL" << endl; 710 } 711 } 712 } 713 714 return true; 715 } 716 717 vts::ComponentSpecificationMessage* 718 SpecificationBuilder::GetComponentSpecification() const { 719 cout << "ifspec addr get " << if_spec_msg_ << endl; 720 return if_spec_msg_; 721 } 722 723 } // namespace vts 724 } // namespace android 725