Home | History | Annotate | Download | only in include
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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:
    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 
    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 
    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:
    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 
    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