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