• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dumper.h"
16 
17 #include "repr/protobuf/abi_dump.h"
18 #include "repr/protobuf/api.h"
19 
20 #include <fstream>
21 #include <memory>
22 
23 #include <llvm/Support/raw_ostream.h>
24 
25 #include <google/protobuf/io/zero_copy_stream_impl.h>
26 #include <google/protobuf/text_format.h>
27 
28 
29 namespace header_checker {
30 namespace repr {
31 
32 
AddTemplateInformation(abi_dump::TemplateInfo * ti,const TemplatedArtifactIR * ta)33 bool IRToProtobufConverter::AddTemplateInformation(
34     abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta) {
35   for (auto &&template_element : ta->GetTemplateElements()) {
36     abi_dump::TemplateElement *added_element = ti->add_elements();
37     if (!added_element) {
38       llvm::errs() << "Failed to add template element\n";
39       return false;
40     }
41     added_element->set_referenced_type(template_element.GetReferencedType());
42   }
43   return true;
44 }
45 
AddTypeInfo(abi_dump::BasicNamedAndTypedDecl * type_info,const TypeIR * typep)46 bool IRToProtobufConverter::AddTypeInfo(
47     abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep) {
48   if (!type_info || !typep) {
49     llvm::errs() << "Typeinfo not valid\n";
50     return false;
51   }
52   type_info->set_linker_set_key(typep->GetLinkerSetKey());
53   type_info->set_source_file(typep->GetSourceFile());
54   type_info->set_name(typep->GetName());
55   type_info->set_size(typep->GetSize());
56   type_info->set_alignment(typep->GetAlignment());
57   type_info->set_referenced_type(typep->GetReferencedType());
58   type_info->set_self_type(typep->GetSelfType());
59   return true;
60 }
61 
AddRecordFields(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)62 bool IRToProtobufConverter::AddRecordFields(
63     abi_dump::RecordType *record_protobuf,
64     const RecordTypeIR *record_ir) {
65   // Iterate through the fields and create corresponding ones for the protobuf
66   // record
67   for (auto &&field_ir : record_ir->GetFields()) {
68     abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields();
69     if (!added_field) {
70       llvm::errs() << "Couldn't add record field\n";
71     }
72     SetIRToProtobufRecordField(added_field, &field_ir);
73   }
74   return true;
75 }
76 
AddBaseSpecifiers(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)77 bool IRToProtobufConverter::AddBaseSpecifiers(
78     abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) {
79   for (auto &&base_ir : record_ir->GetBases()) {
80     abi_dump::CXXBaseSpecifier *added_base =
81         record_protobuf->add_base_specifiers();
82     if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) {
83       return false;
84     }
85   }
86   return true;
87 }
88 
AddVTableLayout(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)89 bool IRToProtobufConverter::AddVTableLayout(
90     abi_dump::RecordType *record_protobuf,
91     const RecordTypeIR *record_ir) {
92   // If there are no entries in the vtable, just return.
93   if (record_ir->GetVTableNumEntries() == 0) {
94     return true;
95   }
96   const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout();
97   abi_dump::VTableLayout *vtable_layout_protobuf =
98       record_protobuf->mutable_vtable_layout();
99   if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) {
100     return false;
101   }
102   return true;
103 }
104 
ConvertRecordTypeIR(const RecordTypeIR * recordp)105 abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR(
106     const RecordTypeIR *recordp) {
107   abi_dump::RecordType added_record_type;
108   added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess()));
109   added_record_type.set_record_kind(
110       RecordKindIRToProtobuf(recordp->GetRecordKind()));
111   if (recordp->IsAnonymous()) {
112     added_record_type.set_is_anonymous(true);
113   }
114   if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) ||
115       !AddRecordFields(&added_record_type, recordp) ||
116       !AddBaseSpecifiers(&added_record_type, recordp) ||
117       !AddVTableLayout(&added_record_type, recordp) ||
118       !(recordp->GetTemplateElements().size() ?
119         AddTemplateInformation(added_record_type.mutable_template_info(),
120                                recordp) : true)) {
121     llvm::errs() << "Template information could not be added\n";
122     ::exit(1);
123   }
124   return added_record_type;
125 }
126 
127 
ConvertElfObjectIR(const ElfObjectIR * elf_object_ir)128 abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR(
129     const ElfObjectIR *elf_object_ir) {
130   abi_dump::ElfObject elf_object_protobuf;
131   elf_object_protobuf.set_name(elf_object_ir->GetName());
132   return elf_object_protobuf;
133 }
134 
ConvertElfFunctionIR(const ElfFunctionIR * elf_function_ir)135 abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR(
136     const ElfFunctionIR *elf_function_ir) {
137   abi_dump::ElfFunction elf_function_protobuf;
138   elf_function_protobuf.set_name(elf_function_ir->GetName());
139   return elf_function_protobuf;
140 }
141 
142 template <typename CFunctionLikeMessage>
AddFunctionParametersAndSetReturnType(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)143 bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType(
144     CFunctionLikeMessage *function_like_protobuf,
145     const CFunctionLikeIR *cfunction_like_ir) {
146   function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType());
147   return AddFunctionParameters(function_like_protobuf, cfunction_like_ir);
148 }
149 
150 template <typename CFunctionLikeMessage>
AddFunctionParameters(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)151 bool IRToProtobufConverter::AddFunctionParameters(
152     CFunctionLikeMessage *function_like_protobuf,
153     const CFunctionLikeIR *cfunction_like_ir) {
154   for (auto &&parameter : cfunction_like_ir->GetParameters()) {
155     abi_dump::ParamDecl *added_parameter =
156         function_like_protobuf->add_parameters();
157     if (!added_parameter) {
158       return false;
159     }
160     added_parameter->set_referenced_type(
161         parameter.GetReferencedType());
162     added_parameter->set_default_arg(parameter.GetIsDefault());
163     added_parameter->set_is_this_ptr(parameter.GetIsThisPtr());
164   }
165   return true;
166 }
167 
ConvertFunctionTypeIR(const FunctionTypeIR * function_typep)168 abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR (
169     const FunctionTypeIR *function_typep) {
170   abi_dump::FunctionType added_function_type;
171   if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) ||
172       !AddFunctionParametersAndSetReturnType(&added_function_type,
173                                              function_typep)) {
174     llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n";
175     ::exit(1);
176   }
177   return added_function_type;
178 }
179 
ConvertFunctionIR(const FunctionIR * functionp)180 abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR(
181     const FunctionIR *functionp) {
182   abi_dump::FunctionDecl added_function;
183   added_function.set_access(AccessIRToProtobuf(functionp->GetAccess()));
184   added_function.set_linker_set_key(functionp->GetLinkerSetKey());
185   added_function.set_source_file(functionp->GetSourceFile());
186   added_function.set_function_name(functionp->GetName());
187   if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) ||
188       !(functionp->GetTemplateElements().size() ?
189       AddTemplateInformation(added_function.mutable_template_info(), functionp)
190       : true)) {
191     llvm::errs() << "Template information could not be added\n";
192     ::exit(1);
193   }
194   return added_function;
195 }
196 
AddEnumFields(abi_dump::EnumType * enum_protobuf,const EnumTypeIR * enum_ir)197 bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf,
198                                           const EnumTypeIR *enum_ir) {
199   for (auto &&field : enum_ir->GetFields()) {
200     abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields();
201     if (!SetIRToProtobufEnumField(enum_fieldp, &field)) {
202       return false;
203     }
204   }
205   return true;
206 }
207 
208 
ConvertEnumTypeIR(const EnumTypeIR * enump)209 abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR(
210     const EnumTypeIR *enump) {
211   abi_dump::EnumType added_enum_type;
212   added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess()));
213   added_enum_type.set_underlying_type(enump->GetUnderlyingType());
214   if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) ||
215       !AddEnumFields(&added_enum_type, enump)) {
216     llvm::errs() << "EnumTypeIR could not be converted\n";
217     ::exit(1);
218   }
219   return added_enum_type;
220 }
221 
ConvertGlobalVarIR(const GlobalVarIR * global_varp)222 abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR(
223     const GlobalVarIR *global_varp) {
224   abi_dump::GlobalVarDecl added_global_var;
225   added_global_var.set_referenced_type(global_varp->GetReferencedType());
226   added_global_var.set_source_file(global_varp->GetSourceFile());
227   added_global_var.set_name(global_varp->GetName());
228   added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey());
229   added_global_var.set_access(
230       AccessIRToProtobuf(global_varp->GetAccess()));
231   return added_global_var;
232 }
233 
ConvertPointerTypeIR(const PointerTypeIR * pointerp)234 abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR(
235     const PointerTypeIR *pointerp) {
236   abi_dump::PointerType added_pointer_type;
237   if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) {
238     llvm::errs() << "PointerTypeIR could not be converted\n";
239     ::exit(1);
240   }
241   return added_pointer_type;
242 }
243 
ConvertQualifiedTypeIR(const QualifiedTypeIR * qualtypep)244 abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR(
245     const QualifiedTypeIR *qualtypep) {
246   abi_dump::QualifiedType added_qualified_type;
247   if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) {
248     llvm::errs() << "QualifiedTypeIR could not be converted\n";
249     ::exit(1);
250   }
251   added_qualified_type.set_is_const(qualtypep->IsConst());
252   added_qualified_type.set_is_volatile(qualtypep->IsVolatile());
253   added_qualified_type.set_is_restricted(qualtypep->IsRestricted());
254   return added_qualified_type;
255 }
256 
ConvertBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)257 abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR(
258     const BuiltinTypeIR *builtin_typep) {
259   abi_dump::BuiltinType added_builtin_type;
260   added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned());
261   added_builtin_type.set_is_integral(builtin_typep->IsIntegralType());
262   if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) {
263     llvm::errs() << "BuiltinTypeIR could not be converted\n";
264     ::exit(1);
265   }
266   return added_builtin_type;
267 }
268 
ConvertArrayTypeIR(const ArrayTypeIR * array_typep)269 abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR(
270     const ArrayTypeIR *array_typep) {
271   abi_dump::ArrayType added_array_type;
272   added_array_type.set_is_of_unknown_bound(array_typep->IsOfUnknownBound());
273   if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) {
274     llvm::errs() << "ArrayTypeIR could not be converted\n";
275     ::exit(1);
276   }
277   return added_array_type;
278 }
279 
280 abi_dump::LvalueReferenceType
ConvertLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)281 IRToProtobufConverter::ConvertLvalueReferenceTypeIR(
282     const LvalueReferenceTypeIR *lvalue_reference_typep) {
283   abi_dump::LvalueReferenceType added_lvalue_reference_type;
284   if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(),
285                    lvalue_reference_typep)) {
286     llvm::errs() << "LvalueReferenceTypeIR could not be converted\n";
287     ::exit(1);
288   }
289   return added_lvalue_reference_type;
290 }
291 
292 abi_dump::RvalueReferenceType
ConvertRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)293 IRToProtobufConverter::ConvertRvalueReferenceTypeIR(
294     const RvalueReferenceTypeIR *rvalue_reference_typep) {
295   abi_dump::RvalueReferenceType added_rvalue_reference_type;
296   if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(),
297                    rvalue_reference_typep)) {
298     llvm::errs() << "RvalueReferenceTypeIR could not be converted\n";
299     ::exit(1);
300   }
301   return added_rvalue_reference_type;
302 }
303 
AddLinkableMessageIR(const LinkableMessageIR * lm)304 bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
305   // No RTTI
306   switch (lm->GetKind()) {
307     case RecordTypeKind:
308       return AddRecordTypeIR(static_cast<const RecordTypeIR *>(lm));
309     case EnumTypeKind:
310       return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm));
311     case PointerTypeKind:
312       return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm));
313     case QualifiedTypeKind:
314       return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm));
315     case ArrayTypeKind:
316       return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm));
317     case LvalueReferenceTypeKind:
318       return AddLvalueReferenceTypeIR(
319           static_cast<const LvalueReferenceTypeIR *>(lm));
320     case RvalueReferenceTypeKind:
321       return AddRvalueReferenceTypeIR(
322           static_cast<const RvalueReferenceTypeIR*>(lm));
323     case BuiltinTypeKind:
324       return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm));
325     case FunctionTypeKind:
326       return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm));
327     case GlobalVarKind:
328       return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm));
329     case FunctionKind:
330       return AddFunctionIR(static_cast<const FunctionIR*>(lm));
331   }
332   return false;
333 }
334 
AddElfFunctionIR(const ElfFunctionIR * elf_function)335 bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
336   abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
337   if (!added_elf_function) {
338     return false;
339   }
340   added_elf_function->set_name(elf_function->GetName());
341   added_elf_function->set_binding(
342       ElfSymbolBindingIRToProtobuf(elf_function->GetBinding()));
343   return true;
344 }
345 
AddElfObjectIR(const ElfObjectIR * elf_object)346 bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
347   abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
348   if (!added_elf_object) {
349     return false;
350   }
351   added_elf_object->set_name(elf_object->GetName());
352   added_elf_object->set_binding(
353       ElfSymbolBindingIRToProtobuf(elf_object->GetBinding()));
354   return true;
355 }
356 
AddElfSymbolMessageIR(const ElfSymbolIR * em)357 bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
358   switch (em->GetKind()) {
359     case ElfSymbolIR::ElfFunctionKind:
360       return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
361     case ElfSymbolIR::ElfObjectKind:
362       return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
363   }
364   return false;
365 }
366 
AddRecordTypeIR(const RecordTypeIR * recordp)367 bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
368   abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
369   if (!added_record_type) {
370     return false;
371   }
372   *added_record_type = ConvertRecordTypeIR(recordp);
373   return true;
374 }
375 
AddFunctionTypeIR(const FunctionTypeIR * function_typep)376 bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) {
377   abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types();
378   if (!added_function_type) {
379     return false;
380   }
381   *added_function_type = ConvertFunctionTypeIR(function_typep);
382   return true;
383 }
384 
AddFunctionIR(const FunctionIR * functionp)385 bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) {
386   abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions();
387   if (!added_function) {
388     return false;
389   }
390   *added_function = ConvertFunctionIR(functionp);
391   return true;
392 }
393 
AddEnumTypeIR(const EnumTypeIR * enump)394 bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) {
395   abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types();
396   if (!added_enum_type) {
397     return false;
398   }
399   *added_enum_type = ConvertEnumTypeIR(enump);
400   return true;
401 }
402 
AddGlobalVarIR(const GlobalVarIR * global_varp)403 bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) {
404   abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars();
405   if (!added_global_var) {
406     return false;
407   }
408   *added_global_var = ConvertGlobalVarIR(global_varp);
409   return true;
410 }
411 
AddPointerTypeIR(const PointerTypeIR * pointerp)412 bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) {
413   abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types();
414   if (!added_pointer_type) {
415     return false;
416   }
417   *added_pointer_type = ConvertPointerTypeIR(pointerp);
418   return true;
419 }
420 
AddQualifiedTypeIR(const QualifiedTypeIR * qualtypep)421 bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) {
422   abi_dump::QualifiedType *added_qualified_type =
423       tu_ptr_->add_qualified_types();
424   if (!added_qualified_type) {
425     return false;
426   }
427   *added_qualified_type = ConvertQualifiedTypeIR(qualtypep);
428   return true;
429 }
430 
AddBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)431 bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
432   abi_dump::BuiltinType *added_builtin_type =
433       tu_ptr_->add_builtin_types();
434   if (!added_builtin_type) {
435     return false;
436   }
437   *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep);
438   return true;
439 }
440 
AddArrayTypeIR(const ArrayTypeIR * array_typep)441 bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) {
442   abi_dump::ArrayType *added_array_type =
443       tu_ptr_->add_array_types();
444   if (!added_array_type) {
445     return false;
446   }
447   *added_array_type = ConvertArrayTypeIR(array_typep);
448   return true;
449 }
450 
AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)451 bool ProtobufIRDumper::AddLvalueReferenceTypeIR(
452     const LvalueReferenceTypeIR *lvalue_reference_typep) {
453   abi_dump::LvalueReferenceType *added_lvalue_reference_type =
454       tu_ptr_->add_lvalue_reference_types();
455   if (!added_lvalue_reference_type) {
456     return false;
457   }
458   *added_lvalue_reference_type =
459       ConvertLvalueReferenceTypeIR(lvalue_reference_typep);
460   return true;
461 }
462 
AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)463 bool ProtobufIRDumper::AddRvalueReferenceTypeIR(
464     const RvalueReferenceTypeIR *rvalue_reference_typep) {
465   abi_dump::RvalueReferenceType *added_rvalue_reference_type =
466       tu_ptr_->add_rvalue_reference_types();
467   if (!added_rvalue_reference_type) {
468     return false;
469   }
470   *added_rvalue_reference_type =
471       ConvertRvalueReferenceTypeIR(rvalue_reference_typep);
472   return true;
473 }
474 
Dump(const ModuleIR & module)475 bool ProtobufIRDumper::Dump(const ModuleIR &module) {
476   GOOGLE_PROTOBUF_VERIFY_VERSION;
477   DumpModule(module);
478   assert( tu_ptr_.get() != nullptr);
479   std::ofstream text_output(dump_path_);
480   google::protobuf::io::OstreamOutputStream text_os(&text_output);
481   return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os);
482 }
483 
CreateProtobufIRDumper(const std::string & dump_path)484 std::unique_ptr<IRDumper> CreateProtobufIRDumper(const std::string &dump_path) {
485   return std::make_unique<ProtobufIRDumper>(dump_path);
486 }
487 
488 
489 }  // namespace repr
490 }  // namespace header_checker
491