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