1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "repr/protobuf/ir_reader.h"
16 
17 #include "repr/ir_representation_internal.h"
18 #include "repr/protobuf/api.h"
19 #include "repr/protobuf/converter.h"
20 
21 #include <fstream>
22 #include <memory>
23 
24 #include <google/protobuf/text_format.h>
25 
26 
27 namespace header_checker {
28 namespace repr {
29 
30 
ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl & type_info,TypeIR * typep)31 void ProtobufIRReader::ReadTypeInfo(
32     const abi_dump::BasicNamedAndTypedDecl &type_info, TypeIR *typep) {
33   typep->SetLinkerSetKey(type_info.linker_set_key());
34   typep->SetName(type_info.name());
35   typep->SetSourceFile(type_info.source_file());
36   typep->SetReferencedType(type_info.referenced_type());
37   typep->SetSelfType(type_info.self_type());
38   typep->SetSize(type_info.size());
39   typep->SetAlignment(type_info.alignment());
40 }
41 
ReadDumpImpl(const std::string & dump_file)42 bool ProtobufIRReader::ReadDumpImpl(const std::string &dump_file) {
43   abi_dump::TranslationUnit tu;
44   std::ifstream input(dump_file);
45   google::protobuf::io::IstreamInputStream text_is(&input);
46 
47   if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) {
48     llvm::errs() << "Failed to parse protobuf TextFormat file\n";
49     return false;
50   }
51   ReadFunctions(tu);
52   ReadGlobalVariables(tu);
53 
54   ReadEnumTypes(tu);
55   ReadRecordTypes(tu);
56   ReadFunctionTypes(tu);
57   ReadArrayTypes(tu);
58   ReadPointerTypes(tu);
59   ReadQualifiedTypes(tu);
60   ReadBuiltinTypes(tu);
61   ReadLvalueReferenceTypes(tu);
62   ReadRvalueReferenceTypes(tu);
63 
64   ReadElfFunctions(tu);
65   ReadElfObjects(tu);
66   return true;
67 }
68 
TemplateInfoProtobufToIR(const abi_dump::TemplateInfo & template_info_protobuf)69 TemplateInfoIR ProtobufIRReader::TemplateInfoProtobufToIR(
70     const abi_dump::TemplateInfo &template_info_protobuf) {
71   TemplateInfoIR template_info_ir;
72   for (auto &&template_element : template_info_protobuf.elements()) {
73     TemplateElementIR template_element_ir(template_element.referenced_type());
74     template_info_ir.AddTemplateElement(std::move(template_element_ir));
75   }
76   return template_info_ir;
77 }
78 
79 template <typename T>
SetupCFunctionLikeIR(const T & cfunction_like_protobuf,CFunctionLikeIR * cfunction_like_ir)80 static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf,
81                                  CFunctionLikeIR *cfunction_like_ir) {
82   cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type());
83   for (auto &&parameter: cfunction_like_protobuf.parameters()) {
84     ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
85                      false);
86     cfunction_like_ir->AddParameter(std::move(param_ir));
87   }
88 }
89 
FunctionProtobufToIR(const abi_dump::FunctionDecl & function_protobuf)90 FunctionIR ProtobufIRReader::FunctionProtobufToIR(
91     const abi_dump::FunctionDecl &function_protobuf) {
92   FunctionIR function_ir;
93   function_ir.SetReturnType(function_protobuf.return_type());
94   function_ir.SetLinkerSetKey(function_protobuf.linker_set_key());
95   function_ir.SetName(function_protobuf.function_name());
96   function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access()));
97   function_ir.SetSourceFile(function_protobuf.source_file());
98   // Set parameters
99   for (auto &&parameter: function_protobuf.parameters()) {
100     ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
101                      parameter.is_this_ptr());
102     function_ir.AddParameter(std::move(param_ir));
103   }
104   // Set Template info
105   function_ir.SetTemplateInfo(
106       TemplateInfoProtobufToIR(function_protobuf.template_info()));
107   return function_ir;
108 }
109 
FunctionTypeProtobufToIR(const abi_dump::FunctionType & function_type_protobuf)110 FunctionTypeIR ProtobufIRReader::FunctionTypeProtobufToIR(
111     const abi_dump::FunctionType &function_type_protobuf) {
112   FunctionTypeIR function_type_ir;
113   ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir);
114   SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir);
115   return function_type_ir;
116 }
117 
VTableLayoutProtobufToIR(const abi_dump::VTableLayout & vtable_layout_protobuf)118 VTableLayoutIR ProtobufIRReader::VTableLayoutProtobufToIR(
119     const abi_dump::VTableLayout &vtable_layout_protobuf) {
120   VTableLayoutIR vtable_layout_ir;
121   for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) {
122     VTableComponentIR vtable_component_ir(
123         vtable_component.mangled_component_name(),
124         VTableComponentKindProtobufToIR(vtable_component.kind()),
125         vtable_component.component_value(),
126         vtable_component.is_pure());
127     vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir));
128   }
129   return vtable_layout_ir;
130 }
131 
RecordFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> & rfp)132 std::vector<RecordFieldIR> ProtobufIRReader::RecordFieldsProtobufToIR(
133     const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) {
134   std::vector<RecordFieldIR> record_type_fields_ir;
135   for (auto &&field : rfp) {
136     RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(),
137                                   field.field_offset(),
138                                   AccessProtobufToIR(field.access()));
139     record_type_fields_ir.emplace_back(std::move(record_field_ir));
140   }
141   return record_type_fields_ir;
142 }
143 
144 std::vector<CXXBaseSpecifierIR>
RecordCXXBaseSpecifiersProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> & rbs)145 ProtobufIRReader::RecordCXXBaseSpecifiersProtobufToIR(
146     const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) {
147   std::vector<CXXBaseSpecifierIR> record_type_bases_ir;
148   for (auto &&base : rbs) {
149     CXXBaseSpecifierIR record_base_ir(
150         base.referenced_type(), base.is_virtual(),
151         AccessProtobufToIR(base.access()));
152     record_type_bases_ir.emplace_back(std::move(record_base_ir));
153   }
154   return record_type_bases_ir;
155 }
156 
RecordTypeProtobufToIR(const abi_dump::RecordType & record_type_protobuf)157 RecordTypeIR ProtobufIRReader::RecordTypeProtobufToIR(
158     const abi_dump::RecordType &record_type_protobuf) {
159   RecordTypeIR record_type_ir;
160   ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir);
161   record_type_ir.SetTemplateInfo(
162       TemplateInfoProtobufToIR(record_type_protobuf.template_info()));
163   record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access()));
164   record_type_ir.SetVTableLayout(
165       VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout()));
166   // Get fields
167   record_type_ir.SetRecordFields(RecordFieldsProtobufToIR(
168       record_type_protobuf.fields()));
169   // Base Specifiers
170   record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR(
171       record_type_protobuf.base_specifiers()));
172   record_type_ir.SetRecordKind(
173       RecordKindProtobufToIR(record_type_protobuf.record_kind()));
174   record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous());
175   return record_type_ir;
176 }
177 
EnumFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> & efp)178 std::vector<EnumFieldIR> ProtobufIRReader::EnumFieldsProtobufToIR(
179     const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) {
180   std::vector<EnumFieldIR> enum_type_fields_ir;
181   for (auto &&field : efp) {
182     EnumFieldIR enum_field_ir(field.name(), field.enum_field_value());
183     enum_type_fields_ir.emplace_back(std::move(enum_field_ir));
184   }
185   return enum_type_fields_ir;
186 }
187 
EnumTypeProtobufToIR(const abi_dump::EnumType & enum_type_protobuf)188 EnumTypeIR ProtobufIRReader::EnumTypeProtobufToIR(
189     const abi_dump::EnumType &enum_type_protobuf) {
190   EnumTypeIR enum_type_ir;
191   ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir);
192   enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type());
193   enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access()));
194   enum_type_ir.SetFields(
195       EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields()));
196   return enum_type_ir;
197 }
198 
ReadGlobalVariables(const abi_dump::TranslationUnit & tu)199 void ProtobufIRReader::ReadGlobalVariables(
200     const abi_dump::TranslationUnit &tu) {
201   for (auto &&global_variable_protobuf : tu.global_vars()) {
202     GlobalVarIR global_variable_ir;
203     global_variable_ir.SetName(global_variable_protobuf.name());
204     global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access()));
205     global_variable_ir.SetSourceFile(global_variable_protobuf.source_file());
206     global_variable_ir.SetReferencedType(
207         global_variable_protobuf.referenced_type());
208     global_variable_ir.SetLinkerSetKey(
209         global_variable_protobuf.linker_set_key());
210     module_->AddGlobalVariable(std::move(global_variable_ir));
211   }
212 }
213 
ReadPointerTypes(const abi_dump::TranslationUnit & tu)214 void ProtobufIRReader::ReadPointerTypes(const abi_dump::TranslationUnit &tu) {
215   for (auto &&pointer_type_protobuf : tu.pointer_types()) {
216     PointerTypeIR pointer_type_ir;
217     ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir);
218     module_->AddPointerType(std::move(pointer_type_ir));
219   }
220 }
221 
ReadBuiltinTypes(const abi_dump::TranslationUnit & tu)222 void ProtobufIRReader::ReadBuiltinTypes(const abi_dump::TranslationUnit &tu) {
223   for (auto &&builtin_type_protobuf : tu.builtin_types()) {
224     BuiltinTypeIR builtin_type_ir;
225     ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir);
226     builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned());
227     builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral());
228     module_->AddBuiltinType(std::move(builtin_type_ir));
229   }
230 }
231 
ReadQualifiedTypes(const abi_dump::TranslationUnit & tu)232 void ProtobufIRReader::ReadQualifiedTypes(const abi_dump::TranslationUnit &tu) {
233   for (auto &&qualified_type_protobuf : tu.qualified_types()) {
234     QualifiedTypeIR qualified_type_ir;
235     ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir);
236     qualified_type_ir.SetConstness(qualified_type_protobuf.is_const());
237     qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile());
238     qualified_type_ir.SetRestrictedness(
239         qualified_type_protobuf.is_restricted());
240     module_->AddQualifiedType(std::move(qualified_type_ir));
241   }
242 }
243 
ReadArrayTypes(const abi_dump::TranslationUnit & tu)244 void ProtobufIRReader::ReadArrayTypes(const abi_dump::TranslationUnit &tu) {
245   for (auto &&array_type_protobuf : tu.array_types()) {
246     ArrayTypeIR array_type_ir;
247     ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir);
248     module_->AddArrayType(std::move(array_type_ir));
249   }
250 }
251 
ReadLvalueReferenceTypes(const abi_dump::TranslationUnit & tu)252 void ProtobufIRReader::ReadLvalueReferenceTypes(
253     const abi_dump::TranslationUnit &tu) {
254   for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) {
255     LvalueReferenceTypeIR lvalue_reference_type_ir;
256     ReadTypeInfo(lvalue_reference_type_protobuf.type_info(),
257                  &lvalue_reference_type_ir);
258     module_->AddLvalueReferenceType(std::move(lvalue_reference_type_ir));
259   }
260 }
261 
ReadRvalueReferenceTypes(const abi_dump::TranslationUnit & tu)262 void ProtobufIRReader::ReadRvalueReferenceTypes(
263     const abi_dump::TranslationUnit &tu) {
264   for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) {
265     RvalueReferenceTypeIR rvalue_reference_type_ir;
266     ReadTypeInfo(rvalue_reference_type_protobuf.type_info(),
267                  &rvalue_reference_type_ir);
268     module_->AddRvalueReferenceType(std::move(rvalue_reference_type_ir));
269   }
270 }
271 
ReadFunctions(const abi_dump::TranslationUnit & tu)272 void ProtobufIRReader::ReadFunctions(const abi_dump::TranslationUnit &tu) {
273   for (auto &&function_protobuf : tu.functions()) {
274     FunctionIR function_ir = FunctionProtobufToIR(function_protobuf);
275     module_->AddFunction(std::move(function_ir));
276   }
277 }
278 
ReadRecordTypes(const abi_dump::TranslationUnit & tu)279 void ProtobufIRReader::ReadRecordTypes(const abi_dump::TranslationUnit &tu) {
280   for (auto &&record_type_protobuf : tu.record_types()) {
281     RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf);
282     module_->AddRecordType(std::move(record_type_ir));
283   }
284 }
285 
ReadFunctionTypes(const abi_dump::TranslationUnit & tu)286 void ProtobufIRReader::ReadFunctionTypes(const abi_dump::TranslationUnit &tu) {
287   for (auto &&function_type_protobuf : tu.function_types()) {
288     FunctionTypeIR function_type_ir =
289         FunctionTypeProtobufToIR(function_type_protobuf);
290     module_->AddFunctionType(std::move(function_type_ir));
291   }
292 }
293 
ReadEnumTypes(const abi_dump::TranslationUnit & tu)294 void ProtobufIRReader::ReadEnumTypes(const abi_dump::TranslationUnit &tu) {
295   for (auto &&enum_type_protobuf : tu.enum_types()) {
296     EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf);
297     module_->AddEnumType(std::move(enum_type_ir));
298   }
299 }
300 
ReadElfFunctions(const abi_dump::TranslationUnit & tu)301 void ProtobufIRReader::ReadElfFunctions(const abi_dump::TranslationUnit &tu) {
302   for (auto &&elf_function : tu.elf_functions()) {
303     ElfFunctionIR elf_function_ir(
304         elf_function.name(),
305         ElfSymbolBindingProtobufToIR(elf_function.binding()));
306     module_->AddElfFunction(std::move(elf_function_ir));
307   }
308 }
309 
ReadElfObjects(const abi_dump::TranslationUnit & tu)310 void ProtobufIRReader::ReadElfObjects(const abi_dump::TranslationUnit &tu) {
311   for (auto &&elf_object : tu.elf_objects()) {
312     ElfObjectIR elf_object_ir(
313         elf_object.name(), ElfSymbolBindingProtobufToIR(elf_object.binding()));
314     module_->AddElfObject(std::move(elf_object_ir));
315   }
316 }
317 
CreateProtobufIRReader(const std::set<std::string> * exported_headers)318 std::unique_ptr<IRReader> CreateProtobufIRReader(
319     const std::set<std::string> *exported_headers) {
320   return std::make_unique<ProtobufIRReader>(exported_headers);
321 }
322 
323 
324 }  // namespace repr
325 }  // namespace header_checker
326