blob: 9f6e7a39ca6baeb42b988043ac6a178df4dcc066 [file] [log] [blame]
Keun Soo Yim08400372016-03-03 13:28:51 -08001/*
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 <iostream>
Keun Soo Yim2ee90792016-04-27 14:53:54 -070022#include <queue>
Keun Soo Yim08400372016-03-03 13:28:51 -080023#include <string>
24
25#include "fuzz_tester/FuzzerBase.h"
26#include "fuzz_tester/FuzzerWrapper.h"
27#include "specification_parser/InterfaceSpecificationParser.h"
28
29#include "test/vts/sysfuzzer/common/proto/InterfaceSpecificationMessage.pb.h"
30
31namespace android {
32namespace vts {
33
Keun Soo Yim8103c912016-04-22 20:07:13 -070034SpecificationBuilder::SpecificationBuilder(
35 const string dir_path, int epoch_count)
36 : dir_path_(dir_path),
Keun Soo Yimfeceb4d2016-05-11 20:01:00 -070037 epoch_count_(epoch_count),
38 if_spec_msg_(NULL) {}
Keun Soo Yim08400372016-03-03 13:28:51 -080039
40
41vts::InterfaceSpecificationMessage*
42SpecificationBuilder::FindInterfaceSpecification(
43 const int target_class,
44 const int target_type,
Keun Soo Yim2ee90792016-04-27 14:53:54 -070045 const float target_version,
46 const string submodule_name) {
Keun Soo Yim08400372016-03-03 13:28:51 -080047 DIR* dir;
48 struct dirent* ent;
49
50 if (!(dir = opendir(dir_path_.c_str()))) {
51 cerr << __FUNCTION__ << ": Can't opendir " << dir_path_ << endl;
52 return NULL;
53 }
54
55 while ((ent = readdir(dir))) {
56 if (string(ent->d_name).find(SPEC_FILE_EXT) != std::string::npos) {
57 cout << __FUNCTION__ << ": Checking a file " << ent->d_name << endl;
58 const string file_path = string(dir_path_) + "/" + string(ent->d_name);
59 vts::InterfaceSpecificationMessage* message =
60 new vts::InterfaceSpecificationMessage();
61 if (InterfaceSpecificationParser::parse(file_path.c_str(), message)) {
Keun Soo Yim2ee90792016-04-27 14:53:54 -070062 if (message->component_type() == target_type
Keun Soo Yim08400372016-03-03 13:28:51 -080063 && message->component_type_version() == target_version) {
Keun Soo Yim2ee90792016-04-27 14:53:54 -070064 if (submodule_name.length() > 0) {
65 if (message->component_class() != HAL_SUBMODULE
66 || message->original_data_structure_name() != submodule_name) {
67 continue;
68 }
69 } else if (message->component_class() != target_class) continue;
Keun Soo Yim08400372016-03-03 13:28:51 -080070 closedir(dir);
71 return message;
72 }
73 }
74 delete message;
75 }
76 }
77 closedir(dir);
78 return NULL;
79}
80
81
Keun Soo Yim52f51662016-05-12 17:23:24 -070082FuzzerBase* SpecificationBuilder::GetFuzzerBase(
83 const vts::InterfaceSpecificationMessage& iface_spec_msg,
84 const char* dll_file_name,
85 const char* target_func_name) {
86 FuzzerBase* fuzzer = wrapper_.GetFuzzer(iface_spec_msg);
87 if (!fuzzer) {
88 cerr << __FUNCTION__ << ": couldn't get a fuzzer base class" << endl;
89 return NULL;
90 }
Keun Soo Yim072337b2016-05-13 15:58:26 -070091 if (!fuzzer->LoadTargetComponent(dll_file_name)) {
92 cerr << "couln't load target component file, " << dll_file_name << endl;
93 return NULL;
94 }
Keun Soo Yim52f51662016-05-12 17:23:24 -070095
96 for (const vts::FunctionSpecificationMessage& func_msg : iface_spec_msg.api()) {
Keun Soo Yim072337b2016-05-13 15:58:26 -070097 cout << "checking " << func_msg.name() << endl;
Keun Soo Yim52f51662016-05-12 17:23:24 -070098 if (!strcmp(target_func_name, func_msg.name().c_str())) {
99 return fuzzer;
100 }
101 }
102 return NULL;
103}
104
105
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700106FuzzerBase* SpecificationBuilder::GetFuzzerBaseAndAddAllFunctionsToQueue(
107 const vts::InterfaceSpecificationMessage& iface_spec_msg,
108 const char* dll_file_name) {
109 FuzzerBase* fuzzer = wrapper_.GetFuzzer(iface_spec_msg);
110 if (!fuzzer) {
111 cerr << __FUNCTION__ << ": couldn't get a fuzzer base class" << endl;
112 return NULL;
113 }
114 if (!fuzzer->LoadTargetComponent(dll_file_name)) return NULL;
115
116 for (const vts::FunctionSpecificationMessage& func_msg : iface_spec_msg.api()) {
117 cout << "Add a job " << func_msg.name() << endl;
118 FunctionSpecificationMessage* func_msg_copy = func_msg.New();
119 func_msg_copy->CopyFrom(func_msg);
120 job_queue_.push(make_pair(func_msg_copy, fuzzer));
121 }
122 return fuzzer;
123}
124
125
Keun Soo Yimfeceb4d2016-05-11 20:01:00 -0700126bool SpecificationBuilder::LoadTargetComponent(
127 const char* dll_file_name,
128 const char* spec_lib_file_path,
129 int target_class,
130 int target_type,
131 float target_version) {
132 if_spec_msg_ = FindInterfaceSpecification(
133 target_class, target_type, target_version);
134 if (!if_spec_msg_) {
135 cerr << __FUNCTION__ <<
136 ": no interface specification file found for "
137 << "class " << target_class
138 << " type " << target_type
139 << " version " << target_version << endl;
140 return false;
141 }
Keun Soo Yim52f51662016-05-12 17:23:24 -0700142 spec_lib_file_path_ = (char*) malloc(strlen(spec_lib_file_path) + 1);
143 strcpy(spec_lib_file_path_, spec_lib_file_path);
144
145 dll_file_name_ = (char*) malloc(strlen(dll_file_name) + 1);
146 strcpy(dll_file_name_, dll_file_name);
147
Keun Soo Yimfeceb4d2016-05-11 20:01:00 -0700148 cout << "ifspec addr load " << if_spec_msg_ << endl;
149 string output;
150 if_spec_msg_->SerializeToString(&output);
151 cout << "loaded text " << output.length() << endl;
152 cout << "loaded text " << strlen(output.c_str()) << endl;
153 cout << "loaded text " << output << endl;
154 return true;
155}
156
157
Keun Soo Yim52f51662016-05-12 17:23:24 -0700158bool SpecificationBuilder::CallFunction(FunctionSpecificationMessage* func_msg) {
159 if (!wrapper_.LoadInterfaceSpecificationLibrary(spec_lib_file_path_)) {
160 return false;
161 }
162
163 FuzzerBase* func_fuzzer = GetFuzzerBase(
164 *if_spec_msg_, dll_file_name_, func_msg->name().c_str());
165 if (!func_fuzzer) {
Keun Soo Yim072337b2016-05-13 15:58:26 -0700166 cerr << "can't find FuzzerBase for " << func_msg->name() << " using "
167 << dll_file_name_ << endl;
Keun Soo Yim52f51662016-05-12 17:23:24 -0700168 return false;
169 }
170
171 void* result;
172 cout << "Call Function " << func_msg->name() << endl;
173 func_fuzzer->Fuzz(*func_msg, &result);
174 if (func_msg->return_type().has_aggregate_type()) {
175 if (result != NULL) {
176 // loads that interface spec and enqueues all functions.
177 cout << __FUNCTION__ << " return type: "
178 << func_msg->return_type().aggregate_type() << endl;
179 } else {
180 cout << __FUNCTION__ << " return value = NULL" << endl;
181 }
182 }
183
184 return true;
185}
186
187
Keun Soo Yim08400372016-03-03 13:28:51 -0800188bool SpecificationBuilder::Process(
189 const char* dll_file_name,
190 const char* spec_lib_file_path,
191 int target_class,
192 int target_type,
193 float target_version) {
194 vts::InterfaceSpecificationMessage* interface_specification_message =
195 FindInterfaceSpecification(target_class, target_type, target_version);
Keun Soo Yimfeceb4d2016-05-11 20:01:00 -0700196 cout << "ifspec addr " << interface_specification_message << endl;
197
Keun Soo Yim08400372016-03-03 13:28:51 -0800198 if (!interface_specification_message) {
199 cerr << __FUNCTION__ <<
200 ": no interface specification file found for "
201 << "class " << target_class
202 << " type " << target_type
203 << " version " << target_version << endl;
204 return false;
205 }
Keun Soo Yim08400372016-03-03 13:28:51 -0800206
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700207 if (!wrapper_.LoadInterfaceSpecificationLibrary(spec_lib_file_path)) {
Keun Soo Yim08400372016-03-03 13:28:51 -0800208 return false;
209 }
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700210
211 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(
212 *interface_specification_message, dll_file_name)) return false;
213
Keun Soo Yim8103c912016-04-22 20:07:13 -0700214 for (int i = 0; i < epoch_count_; i++) {
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700215 // by default, breath-first-searching is used.
216 if (job_queue_.empty()) {
217 cout << "no more job to process; stopping after epoch " << i << endl;
218 break;
219 }
220
221 pair<vts::FunctionSpecificationMessage*, FuzzerBase*> curr_job =
222 job_queue_.front();
223 job_queue_.pop();
224
225 vts::FunctionSpecificationMessage* func_msg = curr_job.first;
226 FuzzerBase* func_fuzzer = curr_job.second;
227
Keun Soo Yimc5d092a2016-04-28 16:51:56 +0000228 void* result;
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700229 cout << "Iteration " << (i + 1) << " Function " << func_msg->name() << endl;
230 func_fuzzer->Fuzz(*func_msg, &result);
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700231 if (func_msg->return_type().has_aggregate_type()) {
232 if (result != NULL) {
233 // loads that interface spec and enqueues all functions.
234 cout << __FUNCTION__ << " return type: "
235 << func_msg->return_type().aggregate_type() << endl;
236 string submodule_name = func_msg->return_type().aggregate_type();
237 while (!submodule_name.empty()
238 && (std::isspace(submodule_name.back())
239 || submodule_name.back() == '*' )) {
240 submodule_name.pop_back();
241 }
242 vts::InterfaceSpecificationMessage* iface_spec_msg =
243 FindInterfaceSpecification(
244 target_class, target_type, target_version, submodule_name);
245 if (iface_spec_msg) {
246 cout << __FUNCTION__ << " submodule found - " << submodule_name << endl;
247 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(
248 *iface_spec_msg, dll_file_name)) {
249 return false;
250 }
251 } else {
252 cout << __FUNCTION__ << " submodule not found - " << submodule_name << endl;
253 }
254 } else {
255 cout << __FUNCTION__ << " return value = NULL" << endl;
256 }
257 }
Keun Soo Yim08400372016-03-03 13:28:51 -0800258 }
Keun Soo Yim2ee90792016-04-27 14:53:54 -0700259
Keun Soo Yim08400372016-03-03 13:28:51 -0800260 return true;
261}
262
Keun Soo Yimfeceb4d2016-05-11 20:01:00 -0700263
264vts::InterfaceSpecificationMessage*
265SpecificationBuilder::GetInterfaceSpecification() const {
266 cout << "ifspec addr get " << if_spec_msg_ << endl;
267 return if_spec_msg_;
268}
269
Keun Soo Yim08400372016-03-03 13:28:51 -0800270} // namespace vts
271} // namespace android