• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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