• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SpecificationBuilder(const string dir_path,int epoch_count,const string & callback_socket_name)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*
FindComponentSpecification(const int target_class,const int target_type,const float target_version,const string submodule_name,const string package,const string component_name)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 
GetFuzzerBase(const vts::ComponentSpecificationMessage & iface_spec_msg,const char * dll_file_name,const char *)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 
GetFuzzerBaseSubModule(const vts::ComponentSpecificationMessage & iface_spec_msg,void * object_pointer)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 
GetFuzzerBaseAndAddAllFunctionsToQueue(const vts::ComponentSpecificationMessage & iface_spec_msg,const char * dll_file_name)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 
LoadTargetComponent(const char * dll_file_name,const char * spec_lib_file_path,int target_class,int target_type,float target_version,const char * target_package,const char * target_component_name,const char * hw_binder_service_name,const char * module_name)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 
CallFunction(FunctionSpecificationMessage * func_msg)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 
GetAttribute(FunctionSpecificationMessage * func_msg)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 
Process(const char * dll_file_name,const char * spec_lib_file_path,int target_class,int target_type,float target_version,const char * target_package,const char * target_component_name)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*
GetComponentSpecification() const718 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