Home | History | Annotate | Download | only in specification_parser
      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