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