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/LibSharedCodeGen.h"
18 
19 #include <iostream>
20 #include <string>
21 
22 #include "VtsCompilerUtils.h"
23 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
24 
25 using namespace std;
26 using namespace android;
27 
28 namespace android {
29 namespace vts {
30 
31 const char* const LibSharedCodeGen::kInstanceVariableName = "sharedlib_";
32 
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)33 void LibSharedCodeGen::GenerateCppBodyFuzzFunction(
34     Formatter& out, const ComponentSpecificationMessage& message,
35     const string& fuzzer_extended_class_name) {
36   out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
37   out << "    FunctionSpecificationMessage* func_msg," << "\n";
38   out << "    void** result, const string& callback_socket_name) {" << "\n";
39   out.indent();
40   out << "const char* func_name = func_msg->name().c_str();" << "\n";
41   out << "LOG(INFO) << \"Function: \" << func_name;\n";
42 
43   for (auto const& api : message.interface().api()) {
44     std::stringstream ss;
45 
46     out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
47 
48     // args - definition;
49     int arg_count = 0;
50     for (auto const& arg : api.arg()) {
51       if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
52           !strncmp(arg.predefined_type().c_str(),
53                    message.original_data_structure_name().c_str(),
54                    message.original_data_structure_name().length()) &&
55           message.original_data_structure_name().length() > 0) {
56         out << "    " << GetCppVariableType(arg) << " "
57             << "arg" << arg_count << " = ";
58         out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
59                << kInstanceVariableName << ")";
60       } else if (arg.type() == TYPE_SCALAR) {
61         if (arg.scalar_type() == "char_pointer" ||
62             arg.scalar_type() == "uchar_pointer") {
63           if (arg.scalar_type() == "char_pointer") {
64             out << "    char ";
65           } else {
66             out << "    unsigned char ";
67           }
68           out << "arg" << arg_count
69                  << "[func_msg->arg(" << arg_count
70                  << ").string_value().length() + 1];" << "\n";
71           out << "    if (func_msg->arg(" << arg_count
72                  << ").type() == TYPE_SCALAR && "
73                  << "func_msg->arg(" << arg_count
74                  << ").string_value().has_message()) {" << "\n";
75           out << "      strcpy(arg" << arg_count << ", "
76                  << "func_msg->arg(" << arg_count << ").string_value()"
77                  << ".message().c_str());" << "\n";
78           out << "    } else {" << "\n";
79           out << "   strcpy(arg" << arg_count << ", "
80                  << GetCppInstanceType(arg) << ");" << "\n";
81           out << "    }" << "\n";
82         } else {
83           out << "    " << GetCppVariableType(arg) << " "
84                  << "arg" << arg_count << " = ";
85           out << "(func_msg->arg(" << arg_count
86                  << ").type() == TYPE_SCALAR && "
87                  << "func_msg->arg(" << arg_count
88                  << ").scalar_value().has_" << arg.scalar_type() << "()) ? ";
89           if (arg.scalar_type() == "void_pointer") {
90             out << "reinterpret_cast<" << GetCppVariableType(arg) << ">(";
91           }
92           out << "func_msg->arg(" << arg_count << ").scalar_value()."
93                  << arg.scalar_type() << "()";
94           if (arg.scalar_type() == "void_pointer") {
95             out << ")";
96           }
97           out << " : " << GetCppInstanceType(arg);
98         }
99       } else {
100         out << "    " << GetCppVariableType(arg) << " "
101                << "arg" << arg_count << " = ";
102         out << GetCppInstanceType(arg);
103       }
104       out << ";" << "\n";
105       out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
106           << ";\n";
107       arg_count++;
108     }
109 
110     out << "    ";
111     out << "typedef void* (*";
112     out << "func_type_" << api.name() << ")(...";
113     out << ");" << "\n";
114 
115     // actual function call
116     if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
117       out << "*result = NULL;" << "\n";
118     } else {
119       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
120     }
121     out << "    ";
122     out << "((func_type_" << api.name() << ") "
123            << "target_loader_.GetLoaderFunction(\"" << api.name() << "\"))(";
124     // out << "reinterpret_cast<" << message.original_data_structure_name()
125     //    << "*>(" << kInstanceVariableName << ")->" << api.name() << "(";
126 
127     if (arg_count > 0) out << "\n";
128 
129     for (int index = 0; index < arg_count; index++) {
130       out << "      arg" << index;
131       if (index != (arg_count - 1)) {
132         out << "," << "\n";
133       }
134     }
135     if (api.has_return_type() || api.return_type().type() != TYPE_VOID) {
136       out << "))";
137     }
138     out << ");" << "\n";
139     out << "    return true;" << "\n";
140     out << "  }" << "\n";
141   }
142   // TODO: if there were pointers, free them.
143   out << "return false;" << "\n";
144   out.unindent();
145   out << "}" << "\n";
146 }
147 
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)148 void LibSharedCodeGen::GenerateCppBodyGetAttributeFunction(
149     Formatter& out,
150     const ComponentSpecificationMessage& /*message*/,
151     const string& fuzzer_extended_class_name) {
152   out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
153   out << "    FunctionSpecificationMessage* func_msg," << "\n";
154   out << "    void** result) {" << "\n";
155   out.indent();
156   out << "const char* func_name = func_msg->name().c_str();" << "\n";
157   out << "LOG(INFO) << \" '\" << func_name << \"'\";\n";
158   out << "LOG(ERROR) << \"attribute not supported for shared lib yet.\";"
159       << "\n";
160   out << "return false;" << "\n";
161   out.unindent();
162   out << "}" << "\n";
163 }
164 
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)165 void LibSharedCodeGen::GenerateClassConstructionFunction(Formatter& out,
166     const ComponentSpecificationMessage& /*message*/,
167     const string& fuzzer_extended_class_name) {
168   out << fuzzer_extended_class_name << "() : DriverBase(LIB_SHARED) {}\n";
169 }
170 
171 }  // namespace vts
172 }  // namespace android
173