1 /*
2 * Copyright 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 "code_gen/driver/HalCodeGen.h"
18
19 #include <fstream>
20 #include <iostream>
21 #include <sstream>
22 #include <string>
23
24 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
25
26 #include "VtsCompilerUtils.h"
27 #include "utils/InterfaceSpecUtil.h"
28 #include "utils/StringUtil.h"
29
30 using namespace std;
31 using namespace android;
32
33 namespace android {
34 namespace vts {
35
36 const char* const HalCodeGen::kInstanceVariableName = "device_";
37
38
GenerateCppBodyCallbackFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)39 void HalCodeGen::GenerateCppBodyCallbackFunction(
40 Formatter& out, const ComponentSpecificationMessage& message,
41 const string& fuzzer_extended_class_name) {
42 bool first_callback = true;
43
44 for (int i = 0; i < message.interface().attribute_size(); i++) {
45 const VariableSpecificationMessage& attribute = message.interface().attribute(i);
46 if (attribute.type() != TYPE_FUNCTION_POINTER || !attribute.is_callback()) {
47 continue;
48 }
49 string name =
50 "vts_callback_" + fuzzer_extended_class_name + "_" + attribute.name();
51 if (first_callback) {
52 out << "static string callback_socket_name_;" << "\n";
53 first_callback = false;
54 }
55 out << "\n";
56 out << "class " << name << " : public FuzzerCallbackBase {" << "\n";
57 out << " public:" << "\n";
58 out.indent();
59 out << name << "(const string& callback_socket_name) {" << "\n";
60 out.indent();
61 out << "callback_socket_name_ = callback_socket_name;" << "\n";
62 out.unindent();
63 out << "}" << "\n";
64
65 int primitive_format_index = 0;
66 for (const FunctionPointerSpecificationMessage& func_pt_spec :
67 attribute.function_pointer()) {
68 const string& callback_name = func_pt_spec.function_name();
69 // TODO: callback's return value is assumed to be 'void'.
70 out << "\n";
71 out << "static ";
72 bool has_return_value = false;
73 if (!func_pt_spec.has_return_type() ||
74 !func_pt_spec.return_type().has_type() ||
75 func_pt_spec.return_type().type() == TYPE_VOID) {
76 out << "void" << "\n";
77 } else if (func_pt_spec.return_type().type() == TYPE_PREDEFINED) {
78 out << func_pt_spec.return_type().predefined_type();
79 has_return_value = true;
80 } else {
81 cerr << __func__ << ":" << __LINE__ << " ERROR unknown type "
82 << func_pt_spec.return_type().type() << "\n";
83 exit(-1);
84 }
85 out << " " << callback_name << "(";
86 int primitive_type_index;
87 primitive_type_index = 0;
88 for (const auto& arg : func_pt_spec.arg()) {
89 if (primitive_type_index != 0) {
90 out << ", ";
91 }
92 if (arg.is_const()) {
93 out << "const ";
94 }
95 if (arg.type() == TYPE_SCALAR) {
96 /*
97 if (arg.scalar_type() == "pointer") {
98 out << definition.aggregate_value(
99 primitive_format_index).primitive_name(primitive_type_index)
100 << " ";
101 } */
102 if (arg.scalar_type() == "char_pointer") {
103 out << "char* ";
104 } else if (arg.scalar_type() == "uchar_pointer") {
105 out << "unsigned char* ";
106 } else if (arg.scalar_type() == "bool_t") {
107 out << "bool ";
108 } else if (arg.scalar_type() == "int8_t" ||
109 arg.scalar_type() == "uint8_t" ||
110 arg.scalar_type() == "int16_t" ||
111 arg.scalar_type() == "uint16_t" ||
112 arg.scalar_type() == "int32_t" ||
113 arg.scalar_type() == "uint32_t" ||
114 arg.scalar_type() == "size_t" ||
115 arg.scalar_type() == "int64_t" ||
116 arg.scalar_type() == "uint64_t") {
117 out << arg.scalar_type() << " ";
118 } else if (arg.scalar_type() == "void_pointer") {
119 out << "void*";
120 } else {
121 cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
122 << "\n";
123 exit(-1);
124 }
125 } else if (arg.type() == TYPE_PREDEFINED) {
126 out << arg.predefined_type() << " ";
127 } else {
128 cerr << __func__ << " unsupported type" << "\n";
129 exit(-1);
130 }
131 out << "arg" << primitive_type_index;
132 primitive_type_index++;
133 }
134 out << ") {" << "\n";
135 out.indent();
136 #if USE_VAARGS
137 out << " const char fmt[] = \""
138 << definition.primitive_format(primitive_format_index) << "\";"
139 << "\n";
140 out << " va_list argp;" << "\n";
141 out << " const char* p;" << "\n";
142 out << " int i;" << "\n";
143 out << " char* s;" << "\n";
144 out << " char fmtbuf[256];" << "\n";
145 out << "\n";
146 out << " va_start(argp, fmt);" << "\n";
147 out << "\n";
148 out << " for (p = fmt; *p != '\\0'; p++) {" << "\n";
149 out << " if (*p != '%') {" << "\n";
150 out << " putchar(*p);" << "\n";
151 out << " continue;" << "\n";
152 out << " }" << "\n";
153 out << " switch (*++p) {" << "\n";
154 out << " case 'c':" << "\n";
155 out << " i = va_arg(argp, int);" << "\n";
156 out << " putchar(i);" << "\n";
157 out << " break;" << "\n";
158 out << " case 'd':" << "\n";
159 out << " i = va_arg(argp, int);" << "\n";
160 out << " s = itoa(i, fmtbuf, 10);" << "\n";
161 out << " fputs(s, stdout);" << "\n";
162 out << " break;" << "\n";
163 out << " case 's':" << "\n";
164 out << " s = va_arg(argp, char *);" << "\n";
165 out << " fputs(s, stdout);" << "\n";
166 out << " break;" << "\n";
167 // out << " case 'p':
168 out << " case '%':" << "\n";
169 out << " putchar('%');" << "\n";
170 out << " break;" << "\n";
171 out << " }" << "\n";
172 out << " }" << "\n";
173 out << " va_end(argp);" << "\n";
174 #endif
175 // TODO: check whether bytes is set and handle properly if not.
176 out << "AndroidSystemCallbackRequestMessage callback_message;"
177 << "\n";
178 out << "callback_message.set_id(GetCallbackID(\"" << callback_name
179 << "\"));" << "\n";
180
181 primitive_type_index = 0;
182 for (const auto& arg : func_pt_spec.arg()) {
183 out << "VariableSpecificationMessage* var_msg" << primitive_type_index
184 << " = callback_message.add_arg();" << "\n";
185 if (arg.type() == TYPE_SCALAR) {
186 out << "var_msg" << primitive_type_index << "->set_type("
187 << "TYPE_SCALAR);" << "\n";
188 out << "var_msg" << primitive_type_index << "->set_scalar_type(\""
189 << arg.scalar_type() << "\");" << "\n";
190 out << "var_msg" << primitive_type_index << "->mutable_scalar_value()";
191 if (arg.scalar_type() == "bool_t") {
192 out << "->set_" << arg.scalar_type() << "("
193 << arg.scalar_value().bool_t() << ");" << "\n";
194 } else if (arg.scalar_type() == "int8_t") {
195 out << "->set_" << arg.scalar_type() << "("
196 << arg.scalar_value().int8_t() << ");" << "\n";
197 } else if (arg.scalar_type() == "uint8_t") {
198 out << "->set_" << arg.scalar_type() << "("
199 << arg.scalar_value().uint8_t() << ");" << "\n";
200 } else if (arg.scalar_type() == "int16_t") {
201 out << "->set_" << arg.scalar_type() << "("
202 << arg.scalar_value().int16_t() << ");" << "\n";
203 } else if (arg.scalar_type() == "uint16_t") {
204 out << "->set_" << arg.scalar_type() << "("
205 << arg.scalar_value().uint16_t() << ");" << "\n";
206 } else if (arg.scalar_type() == "int32_t") {
207 out << "->set_" << arg.scalar_type() << "("
208 << arg.scalar_value().int32_t() << ");" << "\n";
209 } else if (arg.scalar_type() == "uint32_t") {
210 out << "->set_" << arg.scalar_type() << "("
211 << arg.scalar_value().uint32_t() << ");" << "\n";
212 } else if (arg.scalar_type() == "size_t") {
213 out << "->set_uint32_t("
214 << arg.scalar_value().uint32_t() << ");" << "\n";
215 } else if (arg.scalar_type() == "int64_t") {
216 out << "->set_" << arg.scalar_type() << "("
217 << arg.scalar_value().int64_t() << ");" << "\n";
218 } else if (arg.scalar_type() == "uint64_t") {
219 out << "->set_" << arg.scalar_type() << "("
220 << arg.scalar_value().uint64_t() << ");" << "\n";
221 } else if (arg.scalar_type() == "char_pointer") {
222 // pointer value is not meaning when it is passed to another machine.
223 out << "->set_" << arg.scalar_type() << "("
224 << arg.scalar_value().char_pointer() << ");" << "\n";
225 } else if (arg.scalar_type() == "uchar_pointer") {
226 // pointer value is not meaning when it is passed to another machine.
227 out << "->set_" << arg.scalar_type() << "("
228 << arg.scalar_value().uchar_pointer() << ");" << "\n";
229 } else if (arg.scalar_type() == "void_pointer") {
230 // pointer value is not meaning when it is passed to another machine.
231 out << "->set_" << arg.scalar_type() << "("
232 << arg.scalar_value().void_pointer() << ");" << "\n";
233 } else {
234 cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
235 << "\n";
236 exit(-1);
237 }
238 } else if (arg.type() == TYPE_PREDEFINED) {
239 out << "var_msg" << primitive_type_index << "->set_type("
240 << "TYPE_PREDEFINED);" << "\n";
241 // TODO: actually handle such case.
242 } else {
243 cerr << __func__ << " unsupported type" << "\n";
244 exit(-1);
245 }
246 primitive_type_index++;
247 }
248 out << "RpcCallToAgent(callback_message, callback_socket_name_);"
249 << "\n";
250 if (has_return_value) {
251 // TODO: consider actual return type.
252 out << "return NULL;";
253 }
254 out.unindent();
255 out << "}" << "\n";
256 out << "\n";
257
258 primitive_format_index++;
259 }
260 out << "\n";
261 out.unindent();
262 out << " private:" << "\n";
263 out << "};" << "\n";
264 out << "\n";
265 }
266 }
267
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)268 void HalCodeGen::GenerateCppBodyFuzzFunction(
269 Formatter& out, const ComponentSpecificationMessage& message,
270 const string& fuzzer_extended_class_name) {
271 for (auto const& sub_struct : message.interface().sub_struct()) {
272 GenerateCppBodyFuzzFunction(out, sub_struct, fuzzer_extended_class_name,
273 message.original_data_structure_name(),
274 sub_struct.is_pointer() ? "->" : ".");
275 }
276
277 out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
278 out << " FunctionSpecificationMessage* func_msg," << "\n";
279 out << " void** result, const string& callback_socket_name) {" << "\n";
280 out.indent();
281 out << "const char* func_name = func_msg->name().c_str();" << "\n";
282 out << "cout << \"Function: \" << __func__ << \" '\" << func_name << \"'\" << endl;"
283 << "\n";
284
285 // to call another function if it's for a sub_struct
286 if (message.interface().sub_struct().size() > 0) {
287 out << "if (func_msg->parent_path().length() > 0) {" << "\n";
288 out.indent();
289 for (auto const& sub_struct : message.interface().sub_struct()) {
290 GenerateSubStructFuzzFunctionCall(out, sub_struct, "");
291 }
292 out.unindent();
293 out << "}" << "\n";
294 }
295
296 out << message.original_data_structure_name()
297 << "* local_device = ";
298 out << "reinterpret_cast<" << message.original_data_structure_name()
299 << "*>(" << kInstanceVariableName << ");" << "\n";
300
301 out << "if (local_device == NULL) {" << "\n";
302 out.indent();
303 out << "cout << \"use hmi \" << (uint64_t)hmi_ << endl;" << "\n";
304 out << "local_device = reinterpret_cast<"
305 << message.original_data_structure_name() << "*>(hmi_);" << "\n";
306 out.unindent();
307 out << "}" << "\n";
308 out << "if (local_device == NULL) {" << "\n";
309 out.indent();
310 out << "cerr << \"both device_ and hmi_ are NULL.\" << endl;"
311 << "\n";
312 out << "return false;" << "\n";
313 out.unindent();
314 out << "}" << "\n";
315
316 for (auto const& api : message.interface().api()) {
317 out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
318 out.indent();
319 out << "cout << \"match\" << endl;" << "\n";
320 // args - definition;
321 int arg_count = 0;
322 for (auto const& arg : api.arg()) {
323 if (arg.is_callback()) { // arg.type() isn't always TYPE_FUNCTION_POINTER
324 string name = "vts_callback_" + fuzzer_extended_class_name + "_" +
325 arg.predefined_type(); // TODO - check to make sure name
326 // is always correct
327 if (name.back() == '*') name.pop_back();
328 out << name << "* arg" << arg_count << "callback = new ";
329 out << name << "(callback_socket_name);" << "\n";
330 out << "arg" << arg_count << "callback->Register(func_msg->arg("
331 << arg_count << "));" << "\n";
332
333 out << GetCppVariableType(arg) << " ";
334 out << "arg" << arg_count << " = (" << GetCppVariableType(arg)
335 << ") malloc(sizeof(" << GetCppVariableType(arg) << "));"
336 << "\n";
337 // TODO: think about how to free the malloced callback data structure.
338 // find the spec.
339 bool found = false;
340 cout << name << "\n";
341 for (auto const& attribute : message.interface().attribute()) {
342 if (attribute.type() == TYPE_FUNCTION_POINTER &&
343 attribute.is_callback()) {
344 string target_name = "vts_callback_" + fuzzer_extended_class_name +
345 "_" + attribute.name();
346 cout << "compare" << "\n";
347 cout << target_name << "\n";
348 if (name == target_name) {
349 if (attribute.function_pointer_size() > 1) {
350 for (auto const& func_pt : attribute.function_pointer()) {
351 out << "arg" << arg_count << "->"
352 << func_pt.function_name() << " = arg" << arg_count
353 << "callback->" << func_pt.function_name() << ";"
354 << "\n";
355 }
356 } else {
357 out << "arg" << arg_count << " = arg" << arg_count
358 << "callback->" << attribute.name() << ";" << "\n";
359 }
360 found = true;
361 break;
362 }
363 }
364 }
365 if (!found) {
366 cerr << __func__ << " ERROR callback definition missing for " << name
367 << " of " << api.name() << "\n";
368 exit(-1);
369 }
370 } else {
371 out << GetCppVariableType(arg) << " ";
372 out << "arg" << arg_count << " = ";
373 if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
374 !strncmp(arg.predefined_type().c_str(),
375 message.original_data_structure_name().c_str(),
376 message.original_data_structure_name().length())) {
377 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
378 << kInstanceVariableName << ")";
379 } else {
380 std::stringstream msg_ss;
381 msg_ss << "func_msg->arg(" << arg_count << ")";
382 string msg = msg_ss.str();
383
384 if (arg.type() == TYPE_SCALAR) {
385 out << "(" << msg << ".type() == TYPE_SCALAR)? ";
386 if (arg.scalar_type() == "pointer" ||
387 arg.scalar_type() == "pointer_pointer" ||
388 arg.scalar_type() == "char_pointer" ||
389 arg.scalar_type() == "uchar_pointer" ||
390 arg.scalar_type() == "void_pointer" ||
391 arg.scalar_type() == "function_pointer") {
392 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
393 }
394 out << "(" << msg << ".scalar_value()";
395
396 if (arg.scalar_type() == "bool_t" ||
397 arg.scalar_type() == "int32_t" ||
398 arg.scalar_type() == "uint32_t" ||
399 arg.scalar_type() == "int64_t" ||
400 arg.scalar_type() == "uint64_t" ||
401 arg.scalar_type() == "int16_t" ||
402 arg.scalar_type() == "uint16_t" ||
403 arg.scalar_type() == "int8_t" ||
404 arg.scalar_type() == "uint8_t" ||
405 arg.scalar_type() == "float_t" ||
406 arg.scalar_type() == "double_t") {
407 out << "." << arg.scalar_type() << "() ";
408 } else if (arg.scalar_type() == "pointer" ||
409 arg.scalar_type() == "char_pointer" ||
410 arg.scalar_type() == "uchar_pointer" ||
411 arg.scalar_type() == "void_pointer") {
412 out << ".pointer() ";
413 } else {
414 cerr << __func__ << " ERROR unsupported scalar type "
415 << arg.scalar_type() << "\n";
416 exit(-1);
417 }
418 out << ") : ";
419 } else {
420 cerr << __func__ << " unknown type " << msg << "\n";
421 }
422
423 out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
424 << ".type() == TYPE_STRUCT || " << msg
425 << ".type() == TYPE_SCALAR)? ";
426 out << GetCppInstanceType(arg, msg);
427 out << " : " << GetCppInstanceType(arg) << " )";
428 // TODO: use the given message and call a lib function which converts
429 // a message to a C/C++ struct.
430 }
431 out << ";" << "\n";
432 }
433 out << "cout << \"arg" << arg_count << " = \" << arg" << arg_count
434 << " << endl;" << "\n";
435 arg_count++;
436 }
437
438 // actual function call
439 GenerateCodeToStartMeasurement(out);
440 out << "cout << \"hit2.\" << device_ << endl;" << "\n";
441
442 // checks whether the function is actually defined.
443 out << "if (reinterpret_cast<"
444 << message.original_data_structure_name() << "*>(local_device)->"
445 << api.name() << " == NULL" << ") {" << "\n";
446 out.indent();
447 out << "cerr << \"api not set.\" << endl;" << "\n";
448 // todo: consider throwing an exception at least a way to tell more
449 // specifically to the caller.
450 out << "return false;" << "\n";
451 out.unindent();
452 out << "}" << "\n";
453
454 out << "cout << \"Call an API.\" << endl;" << "\n";
455 out << "cout << \"local_device = \" << local_device;" << "\n";
456
457 if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
458 out << "*result = NULL;" << "\n";
459 } else {
460 out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
461 }
462 out << "local_device->" << api.name() << "(";
463 if (arg_count > 0) out << "\n";
464
465 for (int index = 0; index < arg_count; index++) {
466 out << "arg" << index;
467 if (index != (arg_count - 1)) {
468 out << "," << "\n";
469 }
470 }
471
472 if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
473 out << "))";
474 }
475 out << ");" << "\n";
476 GenerateCodeToStopMeasurement(out);
477 out << "cout << \"called\" << endl;" << "\n";
478
479 // Copy the output (call by pointer or reference cases).
480 arg_count = 0;
481 for (auto const& arg : api.arg()) {
482 if (arg.is_output()) {
483 // TODO check the return value
484 out << GetConversionToProtobufFunctionName(arg) << "(arg"
485 << arg_count << ", "
486 << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
487 }
488 arg_count++;
489 }
490
491 out << "return true;" << "\n";
492 out.unindent();
493 out << "}" << "\n";
494 }
495 // TODO: if there were pointers, free them.
496 out << "cerr << \"func not found\" << endl;" << "\n";
497 out << "return false;" << "\n";
498 out.unindent();
499 out << "}" << "\n";
500 }
501
GenerateCppBodyFuzzFunction(Formatter & out,const StructSpecificationMessage & message,const string & fuzzer_extended_class_name,const string & original_data_structure_name,const string & parent_path)502 void HalCodeGen::GenerateCppBodyFuzzFunction(
503 Formatter& out, const StructSpecificationMessage& message,
504 const string& fuzzer_extended_class_name,
505 const string& original_data_structure_name, const string& parent_path) {
506 for (auto const& sub_struct : message.sub_struct()) {
507 GenerateCppBodyFuzzFunction(
508 out, sub_struct, fuzzer_extended_class_name,
509 original_data_structure_name,
510 parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
511 }
512
513 string parent_path_printable(parent_path);
514 ReplaceSubString(parent_path_printable, "->", "_");
515 replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
516
517 out << "bool " << fuzzer_extended_class_name << "::Fuzz_"
518 << parent_path_printable + message.name() << "(" << "\n";
519 out << "FunctionSpecificationMessage* func_msg," << "\n";
520 out << "void** result, const string& callback_socket_name) {" << "\n";
521 out.indent();
522 out << "const char* func_name = func_msg->name().c_str();" << "\n";
523 out << "cout << \"Function: \" << __func__ << \" \" << func_name << endl;"
524 << "\n";
525
526 bool is_open;
527 for (auto const& api : message.api()) {
528 is_open = false;
529 if ((parent_path_printable + message.name()) == "_common_methods" &&
530 api.name() == "open") {
531 is_open = true;
532 }
533
534 out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
535 out.indent();
536
537 out << original_data_structure_name << "* local_device = ";
538 out << "reinterpret_cast<" << original_data_structure_name << "*>("
539 << kInstanceVariableName << ");" << "\n";
540
541 out << "if (local_device == NULL) {" << "\n";
542 out.indent();
543 out << "cout << \"use hmi\" << endl;" << "\n";
544 out << "local_device = reinterpret_cast<"
545 << original_data_structure_name << "*>(hmi_);" << "\n";
546 out.unindent();
547 out << "}" << "\n";
548 out << "if (local_device == NULL) {" << "\n";
549 out.indent();
550 out << "cerr << \"both device_ and hmi_ are NULL.\" << endl;"
551 << "\n";
552 out << "return false;" << "\n";
553 out.unindent();
554 out << "}" << "\n";
555
556 // args - definition;
557 int arg_count = 0;
558 for (auto const& arg : api.arg()) {
559 out << GetCppVariableType(arg) << " ";
560 out << "arg" << arg_count << " = ";
561 if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
562 !strncmp(arg.predefined_type().c_str(),
563 original_data_structure_name.c_str(),
564 original_data_structure_name.length())) {
565 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
566 << kInstanceVariableName << ")";
567 } else {
568 std::stringstream msg_ss;
569 msg_ss << "func_msg->arg(" << arg_count << ")";
570 string msg = msg_ss.str();
571
572 if (arg.type() == TYPE_SCALAR) {
573 out << "(" << msg << ".type() == TYPE_SCALAR && " << msg
574 << ".scalar_value()";
575 if (arg.scalar_type() == "pointer" ||
576 arg.scalar_type() == "char_pointer" ||
577 arg.scalar_type() == "uchar_pointer" ||
578 arg.scalar_type() == "void_pointer" ||
579 arg.scalar_type() == "function_pointer") {
580 out << ".has_pointer())? ";
581 out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
582 } else {
583 out << ".has_" << arg.scalar_type() << "())? ";
584 }
585 out << "(" << msg << ".scalar_value()";
586
587 if (arg.scalar_type() == "int32_t" ||
588 arg.scalar_type() == "uint32_t" ||
589 arg.scalar_type() == "int64_t" ||
590 arg.scalar_type() == "uint64_t" ||
591 arg.scalar_type() == "int16_t" ||
592 arg.scalar_type() == "uint16_t" ||
593 arg.scalar_type() == "int8_t" || arg.scalar_type() == "uint8_t" ||
594 arg.scalar_type() == "float_t" ||
595 arg.scalar_type() == "double_t") {
596 out << "." << arg.scalar_type() << "() ";
597 } else if (arg.scalar_type() == "pointer" ||
598 arg.scalar_type() == "char_pointer" ||
599 arg.scalar_type() == "uchar_pointer" ||
600 arg.scalar_type() == "function_pointer" ||
601 arg.scalar_type() == "void_pointer") {
602 out << ".pointer() ";
603 } else {
604 cerr << __func__ << " ERROR unsupported type " << arg.scalar_type()
605 << "\n";
606 exit(-1);
607 }
608 out << ") : ";
609 }
610
611 if (is_open) {
612 if (arg_count == 0) {
613 out << "hmi_;" << "\n";
614 } else if (arg_count == 1) {
615 out << "((hmi_) ? const_cast<char*>(hmi_->name) : NULL)" << "\n";
616 } else if (arg_count == 2) {
617 out << "(struct hw_device_t**) &device_" << "\n";
618 } else {
619 cerr << __func__ << " ERROR additional args for open " << arg_count
620 << "\n";
621 exit(-1);
622 }
623 } else {
624 out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
625 << ".type() == TYPE_STRUCT || " << msg
626 << ".type() == TYPE_SCALAR)? ";
627 out << GetCppInstanceType(arg, msg);
628 out << " : " << GetCppInstanceType(arg) << " )";
629 // TODO: use the given message and call a lib function which converts
630 // a message to a C/C++ struct.
631 }
632 }
633 out << ";" << "\n";
634 out << "cout << \"arg" << arg_count << " = \" << arg" << arg_count
635 << " << endl;" << "\n"
636 << "\n";
637 arg_count++;
638 }
639
640 // actual function call
641 GenerateCodeToStartMeasurement(out);
642 out << "cout << \"hit2.\" << device_ << endl;" << "\n";
643
644 out << "if (reinterpret_cast<" << original_data_structure_name
645 << "*>(local_device)" << parent_path << message.name() << "->"
646 << api.name() << " == NULL";
647 out << ") {" << "\n";
648 out.indent();
649 out << "cerr << \"api not set.\" << endl;" << "\n";
650 // todo: consider throwing an exception at least a way to tell more
651 // specifically to the caller.
652 out << "return false;" << "\n";
653 out.unindent();
654 out << "}" << "\n";
655
656 out << "cout << \"Call an API.\" << endl;" << "\n";
657 if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
658 out << "*result = NULL;" << "\n";
659 } else {
660 out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
661 }
662 out << "local_device" << parent_path << message.name() << "->"
663 << api.name() << "(";
664 if (arg_count > 0) out << "\n";
665
666 for (int index = 0; index < arg_count; index++) {
667 out << "arg" << index;
668 if (index != (arg_count - 1)) {
669 out << "," << "\n";
670 }
671 }
672 if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
673 out << "))";
674 }
675 out << ");" << "\n";
676 GenerateCodeToStopMeasurement(out);
677 out << "cout << \"called\" << endl;" << "\n";
678
679 // Copy the output (call by pointer or reference cases).
680 arg_count = 0;
681 for (auto const& arg : api.arg()) {
682 if (arg.is_output()) {
683 // TODO check the return value
684 out << GetConversionToProtobufFunctionName(arg) << "(arg"
685 << arg_count << ", "
686 << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
687 }
688 arg_count++;
689 }
690
691 out << "return true;" << "\n";
692 out.unindent();
693 out << "}" << "\n";
694 }
695 // TODO: if there were pointers, free them.
696 out << "return false;" << "\n";
697 out.unindent();
698 out << "}" << "\n";
699 }
700
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)701 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
702 Formatter& out, const ComponentSpecificationMessage& message,
703 const string& fuzzer_extended_class_name) {
704 for (auto const& sub_struct : message.interface().sub_struct()) {
705 GenerateCppBodyGetAttributeFunction(
706 out, sub_struct, fuzzer_extended_class_name,
707 message.original_data_structure_name(),
708 sub_struct.is_pointer() ? "->" : ".");
709 }
710
711 out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
712 out << " FunctionSpecificationMessage* func_msg," << "\n";
713 out << " void** result) {" << "\n";
714 out.indent();
715 out << "const char* func_name = func_msg->name().c_str();" << "\n";
716 out << "cout << \"Function: \" << __func__ << \" '\" << func_name << \"'\" << endl;"
717 << "\n";
718
719 // to call another function if it's for a sub_struct
720 if (message.interface().sub_struct().size() > 0) {
721 out << " if (func_msg->parent_path().length() > 0) {" << "\n";
722 out.indent();
723 for (auto const& sub_struct : message.interface().sub_struct()) {
724 GenerateSubStructGetAttributeFunctionCall(out, sub_struct, "");
725 }
726 out.unindent();
727 out << "}" << "\n";
728 }
729
730 out << message.original_data_structure_name()
731 << "* local_device = ";
732 out << "reinterpret_cast<" << message.original_data_structure_name()
733 << "*>(" << kInstanceVariableName << ");" << "\n";
734
735 out << "if (local_device == NULL) {" << "\n";
736 out.indent();
737 out << "cout << \"use hmi \" << (uint64_t)hmi_ << endl;" << "\n";
738 out << "local_device = reinterpret_cast<"
739 << message.original_data_structure_name() << "*>(hmi_);" << "\n";
740 out.unindent();
741 out << "}" << "\n";
742 out << "if (local_device == NULL) {" << "\n";
743 out.indent();
744 out << "cerr << \"both device_ and hmi_ are NULL.\" << endl;"
745 << "\n";
746 out << "return false;" << "\n";
747 out.unindent();
748 out << "}" << "\n";
749
750 for (auto const& attribute : message.interface().attribute()) {
751 if (attribute.type() == TYPE_SUBMODULE ||
752 attribute.type() == TYPE_SCALAR) {
753 out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
754 out.indent();
755 out << "cout << \"match\" << endl;" << "\n";
756
757 // actual function call
758 out << "cout << \"hit2.\" << device_ << endl;" << "\n";
759
760 out << "cout << \"ok. let's read attribute.\" << endl;" << "\n";
761 out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
762 out << "local_device->" << attribute.name();
763 out << "));" << "\n";
764
765 out << "cout << \"got\" << endl;" << "\n";
766
767 out << "return true;" << "\n";
768 out.unindent();
769 out << "}" << "\n";
770 }
771 }
772 // TODO: if there were pointers, free them.
773 out << "cerr << \"attribute not found\" << endl;" << "\n";
774 out << "return false;" << "\n";
775 out.unindent();
776 out << "}" << "\n";
777 }
778
GenerateCppBodyGetAttributeFunction(Formatter & out,const StructSpecificationMessage & message,const string & fuzzer_extended_class_name,const string & original_data_structure_name,const string & parent_path)779 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
780 Formatter& out, const StructSpecificationMessage& message,
781 const string& fuzzer_extended_class_name,
782 const string& original_data_structure_name, const string& parent_path) {
783 for (auto const& sub_struct : message.sub_struct()) {
784 GenerateCppBodyGetAttributeFunction(
785 out, sub_struct, fuzzer_extended_class_name,
786 original_data_structure_name,
787 parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
788 }
789
790 string parent_path_printable(parent_path);
791 ReplaceSubString(parent_path_printable, "->", "_");
792 replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
793
794 out << "bool " << fuzzer_extended_class_name << "::GetAttribute_"
795 << parent_path_printable + message.name() << "(" << "\n";
796 out << " FunctionSpecificationMessage* func_msg," << "\n";
797 out << " void** result) {" << "\n";
798 out.indent();
799 out << "const char* func_name = func_msg->name().c_str();" << "\n";
800 out << "cout << \"Function: \" << __func__ << \" \" << func_name << endl;"
801 << "\n";
802
803 out << original_data_structure_name
804 << "* local_device = ";
805 out << "reinterpret_cast<" << original_data_structure_name
806 << "*>(" << kInstanceVariableName << ");" << "\n";
807
808 out << "if (local_device == NULL) {" << "\n";
809 out.indent();
810 out << " cout << \"use hmi \" << (uint64_t)hmi_ << endl;" << "\n";
811 out << " local_device = reinterpret_cast<"
812 << original_data_structure_name << "*>(hmi_);" << "\n";
813 out.unindent();
814 out << "}" << "\n";
815 out << "if (local_device == NULL) {" << "\n";
816 out.indent();
817 out << "cerr << \"both device_ and hmi_ are NULL.\" << endl;"
818 << "\n";
819 out << "return false;" << "\n";
820 out.unindent();
821 out << "}" << "\n";
822
823 for (auto const& attribute : message.attribute()) {
824 if (attribute.type() == TYPE_SUBMODULE ||
825 attribute.type() == TYPE_SCALAR) {
826 out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
827 out.indent();
828 out << "cout << \"match\" << endl;" << "\n";
829
830 // actual function call
831 out << "cout << \"hit2.\" << device_ << endl;" << "\n";
832
833 out << "cout << \"ok. let's read attribute.\" << endl;" << "\n";
834 out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
835 out << "local_device" << parent_path << message.name() << ".";
836 // TODO: use parent's is_pointer()
837 out << attribute.name();
838 out << "));" << "\n";
839
840 out << "cout << \"got\" << endl;" << "\n";
841
842 out << "return true;" << "\n";
843 out.unindent();
844 out << "}" << "\n";
845 }
846 }
847 // TODO: if there were pointers, free them.
848 out << "cerr << \"attribute not found\" << endl;" << "\n";
849 out << "return false;" << "\n";
850 out.unindent();
851 out << "}" << "\n";
852 }
853
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)854 void HalCodeGen::GenerateClassConstructionFunction(Formatter& out,
855 const ComponentSpecificationMessage& /*message*/,
856 const string& fuzzer_extended_class_name) {
857 out << fuzzer_extended_class_name << "() : FuzzerBase(HAL_CONVENTIONAL) {}\n";
858 }
859
GenerateSubStructFuzzFunctionCall(Formatter & out,const StructSpecificationMessage & message,const string & parent_path)860 void HalCodeGen::GenerateSubStructFuzzFunctionCall(
861 Formatter& out, const StructSpecificationMessage& message,
862 const string& parent_path) {
863 string current_path(parent_path);
864 if (current_path.length() > 0) {
865 current_path += ".";
866 }
867 current_path += message.name();
868
869 string current_path_printable(current_path);
870 replace(current_path_printable.begin(), current_path_printable.end(), '.',
871 '_');
872
873 out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
874 << "\n";
875 out.indent();
876 out << "return Fuzz__" << current_path_printable
877 << "(func_msg, result, callback_socket_name);" << "\n";
878 out.unindent();
879 out << "}" << "\n";
880
881 for (auto const& sub_struct : message.sub_struct()) {
882 GenerateSubStructFuzzFunctionCall(out, sub_struct, current_path);
883 }
884 }
885
GenerateSubStructGetAttributeFunctionCall(Formatter & out,const StructSpecificationMessage & message,const string & parent_path)886 void HalCodeGen::GenerateSubStructGetAttributeFunctionCall(
887 Formatter& out, const StructSpecificationMessage& message,
888 const string& parent_path) {
889 string current_path(parent_path);
890 if (current_path.length() > 0) {
891 current_path += ".";
892 }
893 current_path += message.name();
894
895 string current_path_printable(current_path);
896 replace(current_path_printable.begin(), current_path_printable.end(), '.',
897 '_');
898
899 out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
900 << "\n";
901 out.indent();
902 out << " return GetAttribute__" << current_path_printable
903 << "(func_msg, result);" << "\n";
904 out.unindent();
905 out << "}" << "\n";
906
907 for (auto const& sub_struct : message.sub_struct()) {
908 GenerateSubStructGetAttributeFunctionCall(out, sub_struct, current_path);
909 }
910 }
911
912 } // namespace vts
913 } // namespace android
914