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