1 // Copyright (C) 2017 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 #ifndef IR_PROTOBUF_
15 #define IR_PROTOBUF_
16 
17 #include <ir_representation.h>
18 
19 #pragma clang diagnostic push
20 #pragma clang diagnostic ignored "-Wunused-parameter"
21 #pragma clang diagnostic ignored "-Wnested-anon-types"
22 #include "proto/abi_dump.pb.h"
23 #include "proto/abi_diff.pb.h"
24 #pragma clang diagnostic pop
25 
26 #include <google/protobuf/text_format.h>
27 #include <google/protobuf/io/zero_copy_stream_impl.h>
28 
29 
30 // Classes which act as middle-men between clang AST parsing routines and
31 // message format specific dumpers.
32 namespace abi_util {
33 
CompatibilityStatusIRToProtobuf(CompatibilityStatusIR status)34 inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf(
35     CompatibilityStatusIR status) {
36   switch(status) {
37     case CompatibilityStatusIR::Incompatible:
38       return abi_diff::CompatibilityStatus::INCOMPATIBLE;
39     case CompatibilityStatusIR::Extension:
40       return abi_diff::CompatibilityStatus::EXTENSION;
41     default:
42       break;
43   }
44   return abi_diff::CompatibilityStatus::COMPATIBLE;
45 }
46 
AccessIRToProtobuf(AccessSpecifierIR access)47 inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) {
48   switch (access) {
49     case AccessSpecifierIR::ProtectedAccess:
50       return abi_dump::AccessSpecifier::protected_access;
51     case AccessSpecifierIR::PrivateAccess:
52       return abi_dump::AccessSpecifier::private_access;
53     default:
54       return abi_dump::AccessSpecifier::public_access;
55   }
56   return abi_dump::AccessSpecifier::public_access;
57 }
58 
AccessProtobufToIR(abi_dump::AccessSpecifier access)59 inline AccessSpecifierIR AccessProtobufToIR(
60     abi_dump::AccessSpecifier access) {
61   switch (access) {
62     case abi_dump::AccessSpecifier::protected_access:
63       return AccessSpecifierIR::ProtectedAccess;
64     case abi_dump::AccessSpecifier::private_access:
65       return AccessSpecifierIR::PrivateAccess;
66     default:
67       return AccessSpecifierIR::PublicAccess;
68   }
69   return AccessSpecifierIR::PublicAccess;
70 }
71 
RecordKindIRToProtobuf(RecordTypeIR::RecordKind kind)72 inline abi_dump::RecordKind RecordKindIRToProtobuf(
73     RecordTypeIR::RecordKind kind) {
74   switch (kind) {
75     case RecordTypeIR::RecordKind::struct_kind:
76       return abi_dump::RecordKind::struct_kind;
77 
78     case RecordTypeIR::RecordKind::class_kind:
79       return abi_dump::RecordKind::class_kind;
80 
81     case RecordTypeIR::RecordKind::union_kind:
82       return abi_dump::RecordKind::union_kind;
83 
84     default:
85       return abi_dump::RecordKind::struct_kind;
86   }
87   // Should not be reached
88   assert(false);
89 }
90 
RecordKindProtobufToIR(abi_dump::RecordKind kind)91 inline RecordTypeIR::RecordKind RecordKindProtobufToIR(
92     abi_dump::RecordKind kind) {
93   switch (kind) {
94     case abi_dump::RecordKind::struct_kind:
95       return RecordTypeIR::struct_kind;
96 
97     case abi_dump::RecordKind::class_kind:
98       return RecordTypeIR::class_kind;
99 
100     case abi_dump::RecordKind::union_kind:
101       return RecordTypeIR::union_kind;
102 
103     default:
104       return RecordTypeIR::struct_kind;
105   }
106   // Should not be reached
107   assert(false);
108 }
109 
VTableComponentKindIRToProtobuf(VTableComponentIR::Kind kind)110 inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf(
111     VTableComponentIR::Kind kind) {
112   switch (kind) {
113     case VTableComponentIR::Kind::VCallOffset:
114       return abi_dump::VTableComponent_Kind_VCallOffset;
115 
116     case VTableComponentIR::Kind::VBaseOffset:
117       return abi_dump::VTableComponent_Kind_VBaseOffset;
118 
119     case VTableComponentIR::Kind::OffsetToTop:
120       return abi_dump::VTableComponent_Kind_OffsetToTop;
121 
122     case VTableComponentIR::Kind::RTTI:
123       return abi_dump::VTableComponent_Kind_RTTI;
124 
125     case VTableComponentIR::Kind::FunctionPointer:
126       return abi_dump::VTableComponent_Kind_FunctionPointer;
127 
128     case VTableComponentIR::Kind::CompleteDtorPointer:
129       return abi_dump::VTableComponent_Kind_CompleteDtorPointer;
130 
131     case VTableComponentIR::Kind::DeletingDtorPointer:
132       return abi_dump::VTableComponent_Kind_DeletingDtorPointer;
133 
134     default:
135       return abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
136   }
137   // Should not be reached
138   assert(false);
139 }
140 
VTableComponentKindProtobufToIR(abi_dump::VTableComponent_Kind kind)141 inline VTableComponentIR::Kind VTableComponentKindProtobufToIR(
142     abi_dump::VTableComponent_Kind kind) {
143   switch (kind) {
144     case abi_dump::VTableComponent_Kind_VCallOffset:
145       return VTableComponentIR::Kind::VCallOffset;
146 
147     case abi_dump::VTableComponent_Kind_VBaseOffset:
148       return VTableComponentIR::Kind::VBaseOffset;
149 
150     case abi_dump::VTableComponent_Kind_OffsetToTop:
151       return VTableComponentIR::Kind::OffsetToTop;
152 
153     case abi_dump::VTableComponent_Kind_RTTI:
154       return VTableComponentIR::Kind::RTTI;
155 
156     case abi_dump::VTableComponent_Kind_FunctionPointer:
157       return VTableComponentIR::Kind::FunctionPointer;
158 
159     case abi_dump::VTableComponent_Kind_CompleteDtorPointer:
160       return VTableComponentIR::Kind::CompleteDtorPointer;
161 
162     case abi_dump::VTableComponent_Kind_DeletingDtorPointer:
163       return VTableComponentIR::Kind::DeletingDtorPointer;
164 
165     default:
166       return VTableComponentIR::Kind::UnusedFunctionPointer;
167   }
168   // Should not be reached
169   assert(false);
170 }
171 
172 class IRToProtobufConverter {
173  private:
174   static bool AddTemplateInformation(
175     abi_dump::TemplateInfo *ti, const abi_util::TemplatedArtifactIR *ta);
176 
177   static bool AddTypeInfo(
178       abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep);
179 
180   static bool AddRecordFields(
181       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
182 
183   static bool AddBaseSpecifiers(
184       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
185 
186   static bool AddVTableLayout(
187       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
188 
189   static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf,
190                              const TagTypeIR *tag_type_ir);
191 
192   static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
193                             const EnumTypeIR *enum_ir);
194  public:
195   static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
196 
197   static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
198 
199   static abi_dump::FunctionType ConvertFunctionTypeIR (
200       const FunctionTypeIR *function_typep);
201 
202   template <typename CFunctionLikeMessage>
203   static bool AddFunctionParametersAndSetReturnType(
204       CFunctionLikeMessage *function_like_protobuf,
205       const CFunctionLikeIR *cfunction_like_ir);
206 
207   template <typename CFunctionLikeMessage>
208   static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
209                                     const CFunctionLikeIR *cfunction_like_ir);
210 
211   static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
212 
213   static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
214       const GlobalVarIR *global_varp);
215 
216   static abi_dump::PointerType ConvertPointerTypeIR(
217       const PointerTypeIR *pointerp);
218 
219   static abi_dump::QualifiedType ConvertQualifiedTypeIR(
220       const QualifiedTypeIR *qualtypep);
221 
222   static abi_dump::BuiltinType ConvertBuiltinTypeIR(
223       const BuiltinTypeIR *builtin_typep);
224 
225   static abi_dump::ArrayType ConvertArrayTypeIR(
226       const ArrayTypeIR *array_typep);
227 
228   static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
229       const LvalueReferenceTypeIR *lvalue_reference_typep);
230 
231   static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
232       const RvalueReferenceTypeIR *rvalue_reference_typep);
233 
234   static abi_dump::ElfFunction ConvertElfFunctionIR(
235       const ElfFunctionIR *elf_function_ir);
236 
237   static abi_dump::ElfObject ConvertElfObjectIR(
238       const ElfObjectIR *elf_object_ir);
239 };
240 
241 class IRDiffToProtobufConverter {
242  private:
243   static bool AddTypeInfoDiff(abi_diff::TypeInfoDiff *type_info_diff_protobuf,
244                               const TypeDiffIR *type_diff_ir);
245 
246   static bool AddVTableLayoutDiff(
247     abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
248     const VTableLayoutDiffIR *vtable_layout_diff_ir);
249 
250   static bool AddBaseSpecifierDiffs(
251     abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
252     const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
253 
254   static bool AddRecordFields(
255     abi_diff::RecordTypeDiff *record_diff_protobuf,
256     const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
257     bool removed);
258 
259   static bool AddRecordFieldDiffs(
260     abi_diff::RecordTypeDiff *record_diff_protobuf,
261     const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
262 
263   static bool AddEnumUnderlyingTypeDiff(
264     abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
265     const std::pair<std::string, std::string> *underlying_type_diff_ir);
266 
267  public:
268   static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
269       const RecordTypeDiffIR *record_type_diffp);
270 
271   static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
272       const EnumTypeDiffIR *enum_type_diffp);
273 
274   static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
275       const FunctionDiffIR *function_diffp);
276 
277   static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
278       const GlobalVarDiffIR *global_var_diffp);
279 };
280 
281 class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
282  private:
283   // Types
284   bool AddRecordTypeIR(const RecordTypeIR *);
285 
286   bool AddEnumTypeIR(const EnumTypeIR *);
287 
288   bool AddPointerTypeIR(const PointerTypeIR *);
289 
290   bool AddQualifiedTypeIR(const QualifiedTypeIR *);
291 
292   bool AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR *);
293 
294   bool AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR *);
295 
296   bool AddArrayTypeIR(const ArrayTypeIR *);
297 
298   bool AddBuiltinTypeIR(const BuiltinTypeIR *);
299 
300   bool AddFunctionTypeIR(const FunctionTypeIR *function_typep);
301 
302   // Functions and global variables.
303   bool AddFunctionIR(const FunctionIR *);
304 
305   bool AddGlobalVarIR(const GlobalVarIR *);
306 
307   bool AddElfFunctionIR(const ElfFunctionIR *);
308 
309   bool AddElfObjectIR(const ElfObjectIR *);
310 
311  public:
ProtobufIRDumper(const std::string & dump_path)312   ProtobufIRDumper(const std::string &dump_path)
313       : IRDumper(dump_path), tu_ptr_(new abi_dump::TranslationUnit()) { }
314 
315   bool AddLinkableMessageIR(const LinkableMessageIR *) override;
316 
317   bool AddElfSymbolMessageIR(const ElfSymbolIR *) override;
318 
319   bool Dump() override;
320 
~ProtobufIRDumper()321   ~ProtobufIRDumper() override { }
322 
323  private:
324   std::unique_ptr<abi_dump::TranslationUnit> tu_ptr_;
325 };
326 
327 
328 class ProtobufTextFormatToIRReader : public TextFormatToIRReader {
329  public:
330 
ProtobufTextFormatToIRReader(const std::set<std::string> * exported_headers)331   ProtobufTextFormatToIRReader(const std::set<std::string> *exported_headers)
332       : TextFormatToIRReader(exported_headers) { }
333 
334   bool ReadDump(const std::string &dump_file) override;
335 
336  private:
337   void ReadFunctions(const abi_dump::TranslationUnit &tu);
338 
339   void ReadGlobalVariables(const abi_dump::TranslationUnit &tu);
340 
341   void ReadEnumTypes(const abi_dump::TranslationUnit &tu);
342 
343   void ReadRecordTypes(const abi_dump::TranslationUnit &tu);
344 
345   void ReadFunctionTypes(const abi_dump::TranslationUnit &tu);
346 
347   void ReadPointerTypes(const abi_dump::TranslationUnit &tu);
348 
349   void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu);
350 
351   void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu);
352 
353   void ReadArrayTypes(const abi_dump::TranslationUnit &tu);
354 
355   void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
356 
357   void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
358 
359   void ReadElfFunctions (const abi_dump::TranslationUnit &tu);
360 
361   void ReadElfObjects (const abi_dump::TranslationUnit &tu);
362 
363   void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info,
364                     TypeIR *typep);
365 
366   FunctionIR FunctionProtobufToIR(const abi_dump::FunctionDecl &);
367 
368   FunctionTypeIR FunctionTypeProtobufToIR(
369       const abi_dump::FunctionType &function_type_protobuf);
370 
371   RecordTypeIR RecordTypeProtobufToIR(
372        const abi_dump::RecordType &record_type_protobuf);
373 
374   std::vector<RecordFieldIR> RecordFieldsProtobufToIR(
375     const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp);
376 
377   std::vector<CXXBaseSpecifierIR> RecordCXXBaseSpecifiersProtobufToIR(
378     const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs);
379 
380   std::vector<EnumFieldIR> EnumFieldsProtobufToIR(
381        const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp);
382 
383   EnumTypeIR EnumTypeProtobufToIR(
384        const abi_dump::EnumType &enum_type_protobuf);
385 
386   VTableLayoutIR VTableLayoutProtobufToIR(
387     const abi_dump::VTableLayout &vtable_layout_protobuf);
388 
389   TemplateInfoIR TemplateInfoProtobufToIR(
390        const abi_dump::TemplateInfo &template_info_protobuf);
391 };
392 
393 class ProtobufIRDiffDumper : public IRDiffDumper {
394  public:
ProtobufIRDiffDumper(const std::string & dump_path)395   ProtobufIRDiffDumper(const std::string &dump_path)
396       : IRDiffDumper(dump_path),
397         diff_tu_(new abi_diff::TranslationUnitDiff()) { }
398 
399   bool AddDiffMessageIR(const DiffMessageIR *, const std::string &type_stack,
400                         DiffKind diff_kind) override;
401 
402   bool AddLinkableMessageIR(const LinkableMessageIR *,
403                             DiffKind diff_kind) override;
404 
405   bool AddElfSymbolMessageIR(const ElfSymbolIR *, DiffKind diff_kind) override;
406 
407   void AddLibNameIR(const std::string &name) override;
408 
409   void AddArchIR(const std::string &arch) override;
410 
411   void AddCompatibilityStatusIR(CompatibilityStatusIR status) override;
412 
413   bool Dump() override;
414 
415    CompatibilityStatusIR GetCompatibilityStatusIR() override;
416 
~ProtobufIRDiffDumper()417    ~ProtobufIRDiffDumper() override { }
418 
419  private:
420   // User defined types.
421   bool AddRecordTypeDiffIR(const RecordTypeDiffIR *,
422                            const std::string &type_stack, DiffKind diff_kind);
423 
424   bool AddEnumTypeDiffIR(const EnumTypeDiffIR *,
425                          const std::string &type_stack, DiffKind diff_kind);
426 
427   // Functions and global variables.
428   bool AddFunctionDiffIR(const FunctionDiffIR *,
429                          const std::string &type_stack, DiffKind diff_kind);
430 
431   bool AddGlobalVarDiffIR(const GlobalVarDiffIR *,
432                           const std::string &type_stack, DiffKind diff_kind);
433 
434   bool AddLoneRecordTypeDiffIR(const RecordTypeIR *, DiffKind diff_kind);
435 
436   bool AddLoneEnumTypeDiffIR(const EnumTypeIR *, DiffKind diff_kind);
437 
438   // Functions and global variables.
439   bool AddLoneFunctionDiffIR(const FunctionIR *, DiffKind diff_kind);
440 
441   bool AddLoneGlobalVarDiffIR(const GlobalVarIR *, DiffKind diff_kind);
442 
443   bool AddElfObjectIR(const ElfObjectIR *elf_object_ir, DiffKind diff_kind);
444 
445   bool AddElfFunctionIR(const ElfFunctionIR *elf_function_ir,
446                         DiffKind diff_kind);
447 
448  protected:
449   std::unique_ptr<abi_diff::TranslationUnitDiff> diff_tu_;
450 };
451 
452 } // abi_util
453 
454 #endif // IR_PROTOBUF_
455