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 15 #include <ir_representation_protobuf.h> 16 17 #include <llvm/Support/raw_ostream.h> 18 19 #include <fstream> 20 #include <iostream> 21 #include <string> 22 #include <memory> 23 24 namespace abi_util { 25 26 static bool IsPresentInExportedHeaders( 27 const LinkableMessageIR &linkable_message, 28 const std::set<std::string> *exported_headers) { 29 if (exported_headers == nullptr || exported_headers->empty()) { 30 return true; 31 } 32 return exported_headers->find(linkable_message.GetSourceFile()) 33 != exported_headers->end(); 34 } 35 36 void ProtobufTextFormatToIRReader::ReadTypeInfo( 37 const abi_dump::BasicNamedAndTypedDecl &type_info, 38 TypeIR *typep) { 39 typep->SetLinkerSetKey(type_info.linker_set_key()); 40 typep->SetName(type_info.name()); 41 typep->SetSourceFile(type_info.source_file()); 42 typep->SetReferencedType(type_info.referenced_type()); 43 typep->SetSelfType(type_info.self_type()); 44 typep->SetSize(type_info.size()); 45 typep->SetAlignment(type_info.alignment()); 46 } 47 48 bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) { 49 abi_dump::TranslationUnit tu; 50 std::ifstream input(dump_file); 51 google::protobuf::io::IstreamInputStream text_is(&input); 52 53 if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) { 54 llvm::errs() << "Failed to parse protobuf TextFormat file\n"; 55 return false; 56 } 57 ReadFunctions(tu); 58 ReadGlobalVariables(tu); 59 60 ReadEnumTypes(tu); 61 ReadRecordTypes(tu); 62 ReadFunctionTypes(tu); 63 ReadArrayTypes(tu); 64 ReadPointerTypes(tu); 65 ReadQualifiedTypes(tu); 66 ReadBuiltinTypes(tu); 67 ReadLvalueReferenceTypes(tu); 68 ReadRvalueReferenceTypes(tu); 69 70 ReadElfFunctions(tu); 71 ReadElfObjects(tu); 72 return true; 73 } 74 75 TemplateInfoIR ProtobufTextFormatToIRReader::TemplateInfoProtobufToIR( 76 const abi_dump::TemplateInfo &template_info_protobuf) { 77 TemplateInfoIR template_info_ir; 78 for (auto &&template_element : template_info_protobuf.elements()) { 79 TemplateElementIR template_element_ir(template_element.referenced_type()); 80 template_info_ir.AddTemplateElement(std::move(template_element_ir)); 81 } 82 return template_info_ir; 83 } 84 85 template< typename T> 86 static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf, 87 CFunctionLikeIR *cfunction_like_ir) { 88 cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type()); 89 for (auto &¶meter: cfunction_like_protobuf.parameters()) { 90 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), 91 false); 92 cfunction_like_ir->AddParameter(std::move(param_ir)); 93 } 94 } 95 96 FunctionIR ProtobufTextFormatToIRReader::FunctionProtobufToIR( 97 const abi_dump::FunctionDecl &function_protobuf) { 98 FunctionIR function_ir; 99 function_ir.SetReturnType(function_protobuf.return_type()); 100 function_ir.SetLinkerSetKey(function_protobuf.linker_set_key()); 101 function_ir.SetName(function_protobuf.function_name()); 102 function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access())); 103 function_ir.SetSourceFile(function_protobuf.source_file()); 104 // Set parameters 105 for (auto &¶meter: function_protobuf.parameters()) { 106 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), 107 parameter.is_this_ptr()); 108 function_ir.AddParameter(std::move(param_ir)); 109 } 110 // Set Template info 111 function_ir.SetTemplateInfo( 112 TemplateInfoProtobufToIR(function_protobuf.template_info())); 113 return function_ir; 114 } 115 116 FunctionTypeIR ProtobufTextFormatToIRReader::FunctionTypeProtobufToIR( 117 const abi_dump::FunctionType &function_type_protobuf) { 118 FunctionTypeIR function_type_ir; 119 ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir); 120 SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir); 121 return function_type_ir; 122 } 123 124 VTableLayoutIR ProtobufTextFormatToIRReader::VTableLayoutProtobufToIR( 125 const abi_dump::VTableLayout &vtable_layout_protobuf) { 126 VTableLayoutIR vtable_layout_ir; 127 for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) { 128 VTableComponentIR vtable_component_ir( 129 vtable_component.mangled_component_name(), 130 VTableComponentKindProtobufToIR(vtable_component.kind()), 131 vtable_component.component_value()); 132 vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir)); 133 } 134 return vtable_layout_ir; 135 } 136 137 std::vector<RecordFieldIR> 138 ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR( 139 const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) { 140 std::vector<RecordFieldIR> record_type_fields_ir; 141 for (auto &&field : rfp) { 142 RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(), 143 field.field_offset(), 144 AccessProtobufToIR(field.access())); 145 record_type_fields_ir.emplace_back(std::move(record_field_ir)); 146 } 147 return record_type_fields_ir; 148 } 149 150 std::vector<CXXBaseSpecifierIR> 151 ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR( 152 const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) { 153 std::vector<CXXBaseSpecifierIR> record_type_bases_ir; 154 for (auto &&base : rbs) { 155 CXXBaseSpecifierIR record_base_ir( 156 base.referenced_type(), base.is_virtual(), 157 AccessProtobufToIR(base.access())); 158 record_type_bases_ir.emplace_back(std::move(record_base_ir)); 159 } 160 return record_type_bases_ir; 161 } 162 163 RecordTypeIR ProtobufTextFormatToIRReader::RecordTypeProtobufToIR( 164 const abi_dump::RecordType &record_type_protobuf) { 165 RecordTypeIR record_type_ir; 166 ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir); 167 record_type_ir.SetTemplateInfo( 168 TemplateInfoProtobufToIR(record_type_protobuf.template_info())); 169 record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access())); 170 record_type_ir.SetVTableLayout( 171 VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout())); 172 // Get fields 173 record_type_ir.SetRecordFields(RecordFieldsProtobufToIR( 174 record_type_protobuf.fields())); 175 // Base Specifiers 176 record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR( 177 record_type_protobuf.base_specifiers())); 178 record_type_ir.SetRecordKind( 179 RecordKindProtobufToIR(record_type_protobuf.record_kind())); 180 record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous()); 181 record_type_ir.SetUniqueId(record_type_protobuf.tag_info().unique_id()); 182 return record_type_ir; 183 } 184 185 std::vector<EnumFieldIR> 186 ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR( 187 const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) { 188 std::vector<EnumFieldIR> enum_type_fields_ir; 189 for (auto &&field : efp) { 190 EnumFieldIR enum_field_ir(field.name(), field.enum_field_value()); 191 enum_type_fields_ir.emplace_back(std::move(enum_field_ir)); 192 } 193 return enum_type_fields_ir; 194 } 195 196 EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR( 197 const abi_dump::EnumType &enum_type_protobuf) { 198 EnumTypeIR enum_type_ir; 199 ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir); 200 enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type()); 201 enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access())); 202 enum_type_ir.SetFields( 203 EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields())); 204 enum_type_ir.SetUniqueId(enum_type_protobuf.tag_info().unique_id()); 205 return enum_type_ir; 206 } 207 208 void ProtobufTextFormatToIRReader::ReadGlobalVariables( 209 const abi_dump::TranslationUnit &tu) { 210 for (auto &&global_variable_protobuf : tu.global_vars()) { 211 GlobalVarIR global_variable_ir; 212 global_variable_ir.SetName(global_variable_protobuf.name()); 213 global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access())); 214 global_variable_ir.SetSourceFile(global_variable_protobuf.source_file()); 215 global_variable_ir.SetReferencedType( 216 global_variable_protobuf.referenced_type()); 217 global_variable_ir.SetLinkerSetKey( 218 global_variable_protobuf.linker_set_key()); 219 if (!IsPresentInExportedHeaders(global_variable_ir, exported_headers_)) { 220 continue; 221 } 222 global_variables_.insert( 223 {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)}); 224 } 225 } 226 227 void ProtobufTextFormatToIRReader::ReadPointerTypes( 228 const abi_dump::TranslationUnit &tu) { 229 for (auto &&pointer_type_protobuf : tu.pointer_types()) { 230 PointerTypeIR pointer_type_ir; 231 ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir); 232 if (!IsPresentInExportedHeaders(pointer_type_ir, exported_headers_)) { 233 continue; 234 } 235 AddToMapAndTypeGraph(std::move(pointer_type_ir), &pointer_types_, 236 &type_graph_); 237 } 238 } 239 240 void ProtobufTextFormatToIRReader::ReadBuiltinTypes( 241 const abi_dump::TranslationUnit &tu) { 242 for (auto &&builtin_type_protobuf : tu.builtin_types()) { 243 BuiltinTypeIR builtin_type_ir; 244 ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir); 245 builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned()); 246 builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral()); 247 AddToMapAndTypeGraph(std::move(builtin_type_ir), &builtin_types_, 248 &type_graph_); 249 } 250 } 251 252 void ProtobufTextFormatToIRReader::ReadQualifiedTypes( 253 const abi_dump::TranslationUnit &tu) { 254 for (auto &&qualified_type_protobuf : tu.qualified_types()) { 255 QualifiedTypeIR qualified_type_ir; 256 ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir); 257 qualified_type_ir.SetConstness(qualified_type_protobuf.is_const()); 258 qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile()); 259 qualified_type_ir.SetRestrictedness( 260 qualified_type_protobuf.is_restricted()); 261 if (!IsPresentInExportedHeaders(qualified_type_ir, exported_headers_)) { 262 continue; 263 } 264 AddToMapAndTypeGraph(std::move(qualified_type_ir), &qualified_types_, 265 &type_graph_); 266 } 267 } 268 269 void ProtobufTextFormatToIRReader::ReadArrayTypes( 270 const abi_dump::TranslationUnit &tu) { 271 for (auto &&array_type_protobuf : tu.array_types()) { 272 ArrayTypeIR array_type_ir; 273 ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir); 274 if (!IsPresentInExportedHeaders(array_type_ir, exported_headers_)) { 275 continue; 276 } 277 AddToMapAndTypeGraph(std::move(array_type_ir), &array_types_, 278 &type_graph_); 279 } 280 } 281 282 void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes( 283 const abi_dump::TranslationUnit &tu) { 284 for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) { 285 LvalueReferenceTypeIR lvalue_reference_type_ir; 286 ReadTypeInfo(lvalue_reference_type_protobuf.type_info(), 287 &lvalue_reference_type_ir); 288 if (!IsPresentInExportedHeaders(lvalue_reference_type_ir, 289 exported_headers_)) { 290 continue; 291 } 292 AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir), 293 &lvalue_reference_types_, &type_graph_); 294 } 295 } 296 297 void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes( 298 const abi_dump::TranslationUnit &tu) { 299 for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) { 300 RvalueReferenceTypeIR rvalue_reference_type_ir; 301 ReadTypeInfo(rvalue_reference_type_protobuf.type_info(), 302 &rvalue_reference_type_ir); 303 if (!IsPresentInExportedHeaders(rvalue_reference_type_ir, 304 exported_headers_)) { 305 continue; 306 } 307 AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir), 308 &rvalue_reference_types_, &type_graph_); 309 } 310 } 311 312 void ProtobufTextFormatToIRReader::ReadFunctions( 313 const abi_dump::TranslationUnit &tu) { 314 for (auto &&function_protobuf : tu.functions()) { 315 FunctionIR function_ir = FunctionProtobufToIR(function_protobuf); 316 if (!IsPresentInExportedHeaders(function_ir, exported_headers_)) { 317 continue; 318 } 319 functions_.insert({function_ir.GetLinkerSetKey(), std::move(function_ir)}); 320 } 321 } 322 323 void ProtobufTextFormatToIRReader::ReadRecordTypes( 324 const abi_dump::TranslationUnit &tu) { 325 for (auto &&record_type_protobuf : tu.record_types()) { 326 RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf); 327 if (!IsPresentInExportedHeaders(record_type_ir, exported_headers_)) { 328 continue; 329 } 330 auto it = AddToMapAndTypeGraph(std::move(record_type_ir), &record_types_, 331 &type_graph_); 332 const std::string &key = GetODRListMapKey(&(it->second)); 333 AddToODRListMap(key, &(it->second)); 334 } 335 } 336 337 void ProtobufTextFormatToIRReader::ReadFunctionTypes( 338 const abi_dump::TranslationUnit &tu) { 339 for (auto &&function_type_protobuf : tu.function_types()) { 340 FunctionTypeIR function_type_ir = 341 FunctionTypeProtobufToIR(function_type_protobuf); 342 if (!IsPresentInExportedHeaders(function_type_ir, exported_headers_)) { 343 continue; 344 } 345 auto it = AddToMapAndTypeGraph(std::move(function_type_ir), 346 &function_types_, &type_graph_); 347 const std::string &key = GetODRListMapKey(&(it->second)); 348 AddToODRListMap(key, &(it->second)); 349 } 350 } 351 352 void ProtobufTextFormatToIRReader::ReadEnumTypes( 353 const abi_dump::TranslationUnit &tu) { 354 for (auto &&enum_type_protobuf : tu.enum_types()) { 355 EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf); 356 if (!IsPresentInExportedHeaders(enum_type_ir, exported_headers_)) { 357 continue; 358 } 359 auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), &enum_types_, 360 &type_graph_); 361 AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(), 362 (&it->second)); 363 } 364 } 365 366 void ProtobufTextFormatToIRReader::ReadElfFunctions( 367 const abi_dump::TranslationUnit &tu) { 368 for (auto &&elf_function : tu.elf_functions()) { 369 ElfFunctionIR elf_function_ir(elf_function.name()); 370 elf_functions_.insert( 371 {elf_function_ir.GetName(), std::move(elf_function_ir)}); 372 } 373 } 374 375 void ProtobufTextFormatToIRReader::ReadElfObjects( 376 const abi_dump::TranslationUnit &tu) { 377 for (auto &&elf_object : tu.elf_objects()) { 378 ElfObjectIR elf_object_ir(elf_object.name()); 379 elf_objects_.insert( 380 {elf_object_ir.GetName(), std::move(elf_object_ir)}); 381 } 382 } 383 384 bool IRToProtobufConverter::AddTemplateInformation( 385 abi_dump::TemplateInfo *ti, const abi_util::TemplatedArtifactIR *ta) { 386 for (auto &&template_element : ta->GetTemplateElements()) { 387 abi_dump::TemplateElement *added_element = ti->add_elements(); 388 if (!added_element) { 389 llvm::errs() << "Failed to add template element\n"; 390 return false; 391 } 392 added_element->set_referenced_type(template_element.GetReferencedType()); 393 } 394 return true; 395 } 396 397 bool IRToProtobufConverter::AddTypeInfo( 398 abi_dump::BasicNamedAndTypedDecl *type_info, 399 const TypeIR *typep) { 400 if (!type_info || !typep) { 401 llvm::errs() << "Typeinfo not valid\n"; 402 return false; 403 } 404 type_info->set_linker_set_key(typep->GetLinkerSetKey()); 405 type_info->set_source_file(typep->GetSourceFile()); 406 type_info->set_name(typep->GetName()); 407 type_info->set_size(typep->GetSize()); 408 type_info->set_alignment(typep->GetAlignment()); 409 type_info->set_referenced_type(typep->GetReferencedType()); 410 type_info->set_self_type(typep->GetSelfType()); 411 return true; 412 } 413 414 static void SetIRToProtobufRecordField( 415 abi_dump::RecordFieldDecl *record_field_protobuf, 416 const RecordFieldIR *record_field_ir) { 417 record_field_protobuf->set_field_name(record_field_ir->GetName()); 418 record_field_protobuf->set_referenced_type( 419 record_field_ir->GetReferencedType()); 420 record_field_protobuf->set_access( 421 AccessIRToProtobuf(record_field_ir->GetAccess())); 422 record_field_protobuf->set_field_offset(record_field_ir->GetOffset()); 423 } 424 425 bool IRToProtobufConverter::AddRecordFields( 426 abi_dump::RecordType *record_protobuf, 427 const RecordTypeIR *record_ir) { 428 // Iterate through the fields and create corresponding ones for the protobuf 429 // record 430 for (auto &&field_ir : record_ir->GetFields()) { 431 abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields(); 432 if (!added_field) { 433 llvm::errs() << "Couldn't add record field\n"; 434 } 435 SetIRToProtobufRecordField(added_field, &field_ir); 436 } 437 return true; 438 } 439 440 static bool SetIRToProtobufBaseSpecifier( 441 abi_dump::CXXBaseSpecifier *base_specifier_protobuf, 442 const CXXBaseSpecifierIR &base_specifier_ir) { 443 if (!base_specifier_protobuf) { 444 llvm::errs() << "Protobuf base specifier not valid\n"; 445 return false; 446 } 447 base_specifier_protobuf->set_referenced_type( 448 base_specifier_ir.GetReferencedType()); 449 base_specifier_protobuf->set_is_virtual( 450 base_specifier_ir.IsVirtual()); 451 base_specifier_protobuf->set_access( 452 AccessIRToProtobuf(base_specifier_ir.GetAccess())); 453 return true; 454 } 455 456 bool IRToProtobufConverter::AddBaseSpecifiers( 457 abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) { 458 for (auto &&base_ir : record_ir->GetBases()) { 459 abi_dump::CXXBaseSpecifier *added_base = 460 record_protobuf->add_base_specifiers(); 461 if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { 462 return false; 463 } 464 } 465 return true; 466 } 467 468 static bool SetIRToProtobufVTableLayout( 469 abi_dump::VTableLayout *vtable_layout_protobuf, 470 const VTableLayoutIR &vtable_layout_ir) { 471 if (vtable_layout_protobuf == nullptr) { 472 llvm::errs() << "vtable layout protobuf not valid\n"; 473 return false; 474 } 475 for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) { 476 abi_dump::VTableComponent *added_vtable_component = 477 vtable_layout_protobuf->add_vtable_components(); 478 if (!added_vtable_component) { 479 llvm::errs() << "Couldn't add vtable component\n"; 480 return false; 481 } 482 added_vtable_component->set_kind( 483 VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind())); 484 added_vtable_component->set_component_value(vtable_component_ir.GetValue()); 485 added_vtable_component->set_mangled_component_name( 486 vtable_component_ir.GetName()); 487 } 488 return true; 489 } 490 491 bool IRToProtobufConverter::AddVTableLayout( 492 abi_dump::RecordType *record_protobuf, 493 const RecordTypeIR *record_ir) { 494 // If there are no entries in the vtable, just return. 495 if (record_ir->GetVTableNumEntries() == 0) { 496 return true; 497 } 498 const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout(); 499 abi_dump::VTableLayout *vtable_layout_protobuf = 500 record_protobuf->mutable_vtable_layout(); 501 if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) { 502 return false; 503 } 504 return true; 505 } 506 507 bool IRToProtobufConverter::AddTagTypeInfo( 508 abi_dump::TagType *tag_type_protobuf, 509 const abi_util::TagTypeIR *tag_type_ir) { 510 if (!tag_type_protobuf || !tag_type_ir) { 511 return false; 512 } 513 tag_type_protobuf->set_unique_id(tag_type_ir->GetUniqueId()); 514 return true; 515 } 516 517 abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR( 518 const RecordTypeIR *recordp) { 519 abi_dump::RecordType added_record_type; 520 added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess())); 521 added_record_type.set_record_kind( 522 RecordKindIRToProtobuf(recordp->GetRecordKind())); 523 if (recordp->IsAnonymous()) { 524 added_record_type.set_is_anonymous(true); 525 } 526 if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) || 527 !AddRecordFields(&added_record_type, recordp) || 528 !AddBaseSpecifiers(&added_record_type, recordp) || 529 !AddVTableLayout(&added_record_type, recordp) || 530 !AddTagTypeInfo(added_record_type.mutable_tag_info(), recordp) || 531 !(recordp->GetTemplateElements().size() ? 532 AddTemplateInformation(added_record_type.mutable_template_info(), 533 recordp) : true)) { 534 llvm::errs() << "Template information could not be added\n"; 535 ::exit(1); 536 } 537 return added_record_type; 538 } 539 540 541 abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR( 542 const ElfObjectIR *elf_object_ir) { 543 abi_dump::ElfObject elf_object_protobuf; 544 elf_object_protobuf.set_name(elf_object_ir->GetName()); 545 return elf_object_protobuf; 546 } 547 548 abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR( 549 const ElfFunctionIR *elf_function_ir) { 550 abi_dump::ElfFunction elf_function_protobuf; 551 elf_function_protobuf.set_name(elf_function_ir->GetName()); 552 return elf_function_protobuf; 553 } 554 555 template <typename CFunctionLikeMessage> 556 bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType( 557 CFunctionLikeMessage *function_like_protobuf, 558 const CFunctionLikeIR *cfunction_like_ir) { 559 function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType()); 560 return AddFunctionParameters(function_like_protobuf, cfunction_like_ir); 561 } 562 563 template <typename CFunctionLikeMessage> 564 bool IRToProtobufConverter::AddFunctionParameters( 565 CFunctionLikeMessage *function_like_protobuf, 566 const CFunctionLikeIR *cfunction_like_ir) { 567 for (auto &¶meter : cfunction_like_ir->GetParameters()) { 568 abi_dump::ParamDecl *added_parameter = 569 function_like_protobuf->add_parameters(); 570 if (!added_parameter) { 571 return false; 572 } 573 added_parameter->set_referenced_type( 574 parameter.GetReferencedType()); 575 added_parameter->set_default_arg(parameter.GetIsDefault()); 576 added_parameter->set_is_this_ptr(parameter.GetIsThisPtr()); 577 } 578 return true; 579 } 580 581 abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR ( 582 const FunctionTypeIR *function_typep) { 583 abi_dump::FunctionType added_function_type; 584 if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) || 585 !AddFunctionParametersAndSetReturnType(&added_function_type, 586 function_typep)) { 587 llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n"; 588 ::exit(1); 589 } 590 return added_function_type; 591 } 592 593 abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR( 594 const FunctionIR *functionp) { 595 abi_dump::FunctionDecl added_function; 596 added_function.set_access(AccessIRToProtobuf(functionp->GetAccess())); 597 added_function.set_linker_set_key(functionp->GetLinkerSetKey()); 598 added_function.set_source_file(functionp->GetSourceFile()); 599 added_function.set_function_name(functionp->GetName()); 600 if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) || 601 !(functionp->GetTemplateElements().size() ? 602 AddTemplateInformation(added_function.mutable_template_info(), functionp) 603 : true)) { 604 llvm::errs() << "Template information could not be added\n"; 605 ::exit(1); 606 } 607 return added_function; 608 } 609 610 static bool SetIRToProtobufEnumField( 611 abi_dump::EnumFieldDecl *enum_field_protobuf, 612 const EnumFieldIR *enum_field_ir) { 613 if (enum_field_protobuf == nullptr) { 614 return true; 615 } 616 enum_field_protobuf->set_name(enum_field_ir->GetName()); 617 enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue()); 618 return true; 619 } 620 621 bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf, 622 const EnumTypeIR *enum_ir) { 623 for (auto &&field : enum_ir->GetFields()) { 624 abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields(); 625 if (!SetIRToProtobufEnumField(enum_fieldp, &field)) { 626 return false; 627 } 628 } 629 return true; 630 } 631 632 633 abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR( 634 const EnumTypeIR *enump) { 635 abi_dump::EnumType added_enum_type; 636 added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess())); 637 added_enum_type.set_underlying_type(enump->GetUnderlyingType()); 638 if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) || 639 !AddEnumFields(&added_enum_type, enump) || 640 !AddTagTypeInfo(added_enum_type.mutable_tag_info(), enump)) { 641 llvm::errs() << "EnumTypeIR could not be converted\n"; 642 ::exit(1); 643 } 644 return added_enum_type; 645 } 646 647 abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR( 648 const GlobalVarIR *global_varp) { 649 abi_dump::GlobalVarDecl added_global_var; 650 added_global_var.set_referenced_type(global_varp->GetReferencedType()); 651 added_global_var.set_source_file(global_varp->GetSourceFile()); 652 added_global_var.set_name(global_varp->GetName()); 653 added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey()); 654 added_global_var.set_access( 655 AccessIRToProtobuf(global_varp->GetAccess())); 656 return added_global_var; 657 } 658 659 abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR( 660 const PointerTypeIR *pointerp) { 661 abi_dump::PointerType added_pointer_type; 662 if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) { 663 llvm::errs() << "PointerTypeIR could not be converted\n"; 664 ::exit(1); 665 } 666 return added_pointer_type; 667 } 668 669 abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR( 670 const QualifiedTypeIR *qualtypep) { 671 abi_dump::QualifiedType added_qualified_type; 672 if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) { 673 llvm::errs() << "QualifiedTypeIR could not be converted\n"; 674 ::exit(1); 675 } 676 added_qualified_type.set_is_const(qualtypep->IsConst()); 677 added_qualified_type.set_is_volatile(qualtypep->IsVolatile()); 678 added_qualified_type.set_is_restricted(qualtypep->IsRestricted()); 679 return added_qualified_type; 680 } 681 682 abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR( 683 const BuiltinTypeIR *builtin_typep) { 684 abi_dump::BuiltinType added_builtin_type; 685 added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned()); 686 added_builtin_type.set_is_integral(builtin_typep->IsIntegralType()); 687 if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) { 688 llvm::errs() << "BuiltinTypeIR could not be converted\n"; 689 ::exit(1); 690 } 691 return added_builtin_type; 692 } 693 694 abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR( 695 const ArrayTypeIR *array_typep) { 696 abi_dump::ArrayType added_array_type; 697 if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) { 698 llvm::errs() << "ArrayTypeIR could not be converted\n"; 699 ::exit(1); 700 } 701 return added_array_type; 702 } 703 704 abi_dump::LvalueReferenceType 705 IRToProtobufConverter::ConvertLvalueReferenceTypeIR( 706 const LvalueReferenceTypeIR *lvalue_reference_typep) { 707 abi_dump::LvalueReferenceType added_lvalue_reference_type; 708 if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(), 709 lvalue_reference_typep)) { 710 llvm::errs() << "LvalueReferenceTypeIR could not be converted\n"; 711 ::exit(1); 712 } 713 return added_lvalue_reference_type; 714 } 715 716 abi_dump::RvalueReferenceType 717 IRToProtobufConverter::ConvertRvalueReferenceTypeIR( 718 const RvalueReferenceTypeIR *rvalue_reference_typep) { 719 abi_dump::RvalueReferenceType added_rvalue_reference_type; 720 if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(), 721 rvalue_reference_typep)) { 722 llvm::errs() << "RvalueReferenceTypeIR could not be converted\n"; 723 ::exit(1); 724 } 725 return added_rvalue_reference_type; 726 } 727 728 729 bool IRDiffToProtobufConverter::AddTypeInfoDiff( 730 abi_diff::TypeInfoDiff *type_info_diff_protobuf, 731 const TypeDiffIR *type_diff_ir) { 732 abi_diff::TypeInfo *old_type_info_protobuf = 733 type_info_diff_protobuf->mutable_old_type_info(); 734 abi_diff::TypeInfo *new_type_info_protobuf = 735 type_info_diff_protobuf->mutable_new_type_info(); 736 if (old_type_info_protobuf == nullptr || new_type_info_protobuf == nullptr) { 737 return false; 738 } 739 const std::pair<uint64_t, uint64_t> &sizes = type_diff_ir->GetSizes(); 740 const std::pair<uint32_t, uint32_t> &alignments = 741 type_diff_ir->GetAlignments(); 742 old_type_info_protobuf->set_size(sizes.first); 743 new_type_info_protobuf->set_size(sizes.second); 744 745 old_type_info_protobuf->set_alignment(alignments.first); 746 new_type_info_protobuf->set_alignment(alignments.second); 747 return true; 748 } 749 750 bool IRDiffToProtobufConverter::AddVTableLayoutDiff( 751 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf, 752 const VTableLayoutDiffIR *vtable_layout_diff_ir) { 753 abi_dump:: VTableLayout *old_vtable = 754 vtable_layout_diff_protobuf->mutable_old_vtable(); 755 abi_dump:: VTableLayout *new_vtable = 756 vtable_layout_diff_protobuf->mutable_new_vtable(); 757 if (old_vtable == nullptr || new_vtable == nullptr || 758 !SetIRToProtobufVTableLayout(old_vtable, 759 vtable_layout_diff_ir->GetOldVTable()) || 760 !SetIRToProtobufVTableLayout(new_vtable, 761 vtable_layout_diff_ir->GetNewVTable())) { 762 return false; 763 } 764 return true; 765 } 766 767 template <typename T> 768 static bool CopyBaseSpecifiersDiffIRToProtobuf( 769 google::protobuf::RepeatedPtrField<T> *dst, 770 const std::vector<CXXBaseSpecifierIR> &bases_ir) { 771 for (auto &&base_ir : bases_ir) { 772 T *added_base = dst->Add(); 773 if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { 774 return false; 775 } 776 } 777 return true; 778 } 779 780 bool IRDiffToProtobufConverter::AddBaseSpecifierDiffs( 781 abi_diff::CXXBaseSpecifierDiff *base_specifiers_diff_protobuf, 782 const CXXBaseSpecifierDiffIR *base_specifiers_diff_ir) { 783 if (!CopyBaseSpecifiersDiffIRToProtobuf( 784 base_specifiers_diff_protobuf->mutable_old_bases(), 785 base_specifiers_diff_ir->GetOldBases()) || 786 !CopyBaseSpecifiersDiffIRToProtobuf( 787 base_specifiers_diff_protobuf->mutable_new_bases(), 788 base_specifiers_diff_ir->GetNewBases())) { 789 return false; 790 } 791 return true; 792 } 793 794 bool IRDiffToProtobufConverter::AddRecordFields( 795 abi_diff::RecordTypeDiff *record_diff_protobuf, 796 const std::vector<const RecordFieldIR *> &record_fields_ir, 797 bool field_removed) { 798 for (auto &&record_field_ir : record_fields_ir) { 799 abi_dump::RecordFieldDecl *field = nullptr; 800 if (field_removed) { 801 field = record_diff_protobuf->add_fields_removed(); 802 } else { 803 field = record_diff_protobuf->add_fields_added(); 804 } 805 if (field == nullptr) { 806 return false; 807 } 808 SetIRToProtobufRecordField(field, record_field_ir); 809 } 810 return true; 811 } 812 813 bool IRDiffToProtobufConverter::AddRecordFieldDiffs( 814 abi_diff::RecordTypeDiff *record_diff_protobuf, 815 const std::vector<RecordFieldDiffIR> &record_field_diffs_ir) { 816 for (auto &&record_field_diff_ir : record_field_diffs_ir) { 817 abi_diff::RecordFieldDeclDiff *record_field_diff = 818 record_diff_protobuf->add_fields_diff(); 819 if (record_field_diff == nullptr) { 820 return false; 821 } 822 abi_dump::RecordFieldDecl *old_field = 823 record_field_diff->mutable_old_field(); 824 abi_dump::RecordFieldDecl *new_field = 825 record_field_diff->mutable_new_field(); 826 if (old_field == nullptr || new_field == nullptr) { 827 return false; 828 } 829 SetIRToProtobufRecordField(old_field, 830 record_field_diff_ir.GetOldField()); 831 SetIRToProtobufRecordField(new_field, 832 record_field_diff_ir.GetNewField()); 833 } 834 return true; 835 } 836 837 abi_diff::RecordTypeDiff IRDiffToProtobufConverter::ConvertRecordTypeDiffIR( 838 const RecordTypeDiffIR *record_type_diff_ir) { 839 abi_diff::RecordTypeDiff record_type_diff_protobuf; 840 record_type_diff_protobuf.set_name(record_type_diff_ir->GetName()); 841 const TypeDiffIR *type_diff_ir = record_type_diff_ir->GetTypeDiff(); 842 // If a type_info diff exists 843 if (type_diff_ir != nullptr) { 844 abi_diff::TypeInfoDiff *type_info_diff = 845 record_type_diff_protobuf.mutable_type_info_diff(); 846 if (!AddTypeInfoDiff(type_info_diff, type_diff_ir)) { 847 llvm::errs() << "RecordType could not be converted\n"; 848 ::exit(1); 849 } 850 } 851 // If vtables differ. 852 const VTableLayoutDiffIR *vtable_layout_diff_ir = 853 record_type_diff_ir->GetVTableLayoutDiff(); 854 if (vtable_layout_diff_ir != nullptr) { 855 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf = 856 record_type_diff_protobuf.mutable_vtable_layout_diff(); 857 if (!AddVTableLayoutDiff(vtable_layout_diff_protobuf, 858 vtable_layout_diff_ir)) { 859 llvm::errs() << "VTable layout diff could not be added\n"; 860 ::exit(1); 861 } 862 } 863 // If base specifiers differ. 864 const CXXBaseSpecifierDiffIR *base_specifier_diff_ir = 865 record_type_diff_ir->GetBaseSpecifiers(); 866 if ( base_specifier_diff_ir != nullptr) { 867 abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf = 868 record_type_diff_protobuf.mutable_bases_diff(); 869 if (!AddBaseSpecifierDiffs(base_specifier_diff_protobuf, 870 base_specifier_diff_ir)) { 871 llvm::errs() << "Base Specifier diff could not be added\n"; 872 ::exit(1); 873 } 874 } 875 // Field diffs 876 if (!AddRecordFields(&record_type_diff_protobuf, 877 record_type_diff_ir->GetFieldsRemoved(), true) || 878 !AddRecordFields(&record_type_diff_protobuf, 879 record_type_diff_ir->GetFieldsAdded(), false) || 880 !AddRecordFieldDiffs(&record_type_diff_protobuf, 881 record_type_diff_ir->GetFieldDiffs())) { 882 llvm::errs() << "Record Field diff could not be added\n"; 883 ::exit(1); 884 } 885 return record_type_diff_protobuf; 886 } 887 888 bool IRDiffToProtobufConverter::AddEnumUnderlyingTypeDiff( 889 abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf, 890 const std::pair<std::string, std::string> *underlying_type_diff_ir) { 891 if (underlying_type_diff_protobuf == nullptr) { 892 return false; 893 } 894 underlying_type_diff_protobuf->set_old_type(underlying_type_diff_ir->first); 895 underlying_type_diff_protobuf->set_new_type(underlying_type_diff_ir->second); 896 return true; 897 } 898 899 static bool AddEnumFields( 900 google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> *dst, 901 const std::vector<const EnumFieldIR *> &enum_fields) { 902 for (auto &&enum_field : enum_fields) { 903 abi_dump::EnumFieldDecl *added_enum_field = dst->Add(); 904 if (!SetIRToProtobufEnumField(added_enum_field, enum_field)) { 905 return false; 906 } 907 } 908 return true; 909 } 910 911 static bool AddEnumFieldDiffs( 912 google::protobuf::RepeatedPtrField<abi_diff::EnumFieldDeclDiff> *dst, 913 const std::vector<EnumFieldDiffIR> &fields_diff_ir) { 914 for (auto &&field_diff_ir : fields_diff_ir) { 915 abi_diff::EnumFieldDeclDiff *field_diff_protobuf = dst->Add(); 916 if (field_diff_protobuf == nullptr) { 917 return false; 918 } 919 if (!SetIRToProtobufEnumField(field_diff_protobuf->mutable_old_field(), 920 field_diff_ir.GetOldField()) || 921 !SetIRToProtobufEnumField(field_diff_protobuf->mutable_new_field(), 922 field_diff_ir.GetNewField())) { 923 return false; 924 } 925 } 926 return true; 927 } 928 929 abi_diff::EnumTypeDiff IRDiffToProtobufConverter::ConvertEnumTypeDiffIR( 930 const EnumTypeDiffIR *enum_type_diff_ir) { 931 abi_diff::EnumTypeDiff enum_type_diff_protobuf; 932 enum_type_diff_protobuf.set_name(enum_type_diff_ir->GetName()); 933 const std::pair<std::string, std::string> *underlying_type_diff = 934 enum_type_diff_ir->GetUnderlyingTypeDiff(); 935 if ((underlying_type_diff != nullptr && 936 !AddEnumUnderlyingTypeDiff( 937 enum_type_diff_protobuf.mutable_underlying_type_diff(), 938 underlying_type_diff)) || 939 !AddEnumFields(enum_type_diff_protobuf.mutable_fields_removed(), 940 enum_type_diff_ir->GetFieldsRemoved()) || 941 !AddEnumFields(enum_type_diff_protobuf.mutable_fields_added(), 942 enum_type_diff_ir->GetFieldsAdded()) || 943 !AddEnumFieldDiffs(enum_type_diff_protobuf.mutable_fields_diff(), 944 enum_type_diff_ir->GetFieldsDiff())) { 945 llvm::errs() << "Enum field diff could not be added\n"; 946 ::exit(1); 947 } 948 return enum_type_diff_protobuf; 949 } 950 951 abi_diff::GlobalVarDeclDiff IRDiffToProtobufConverter::ConvertGlobalVarDiffIR( 952 const GlobalVarDiffIR *global_var_diff_ir) { 953 abi_diff::GlobalVarDeclDiff global_var_diff; 954 global_var_diff.set_name(global_var_diff_ir->GetName()); 955 abi_dump::GlobalVarDecl *old_global_var = global_var_diff.mutable_old(); 956 abi_dump::GlobalVarDecl *new_global_var = global_var_diff.mutable_new_(); 957 if (old_global_var == nullptr || new_global_var == nullptr) { 958 llvm::errs() << "Globar Var diff could not be added\n"; 959 ::exit(1); 960 } 961 *old_global_var = 962 IRToProtobufConverter::ConvertGlobalVarIR( 963 global_var_diff_ir->GetOldGlobalVar()); 964 *new_global_var = 965 IRToProtobufConverter::ConvertGlobalVarIR( 966 global_var_diff_ir->GetNewGlobalVar()); 967 return global_var_diff; 968 } 969 970 abi_diff::FunctionDeclDiff IRDiffToProtobufConverter::ConvertFunctionDiffIR( 971 const FunctionDiffIR *function_diff_ir) { 972 abi_diff::FunctionDeclDiff function_diff; 973 function_diff.set_name(function_diff_ir->GetName()); 974 abi_dump::FunctionDecl *old_function = function_diff.mutable_old(); 975 abi_dump::FunctionDecl *new_function = function_diff.mutable_new_(); 976 if (old_function == nullptr || new_function == nullptr) { 977 llvm::errs() << "Function diff could not be added\n"; 978 ::exit(1); 979 } 980 *old_function = 981 IRToProtobufConverter::ConvertFunctionIR( 982 function_diff_ir->GetOldFunction()); 983 *new_function = 984 IRToProtobufConverter::ConvertFunctionIR( 985 function_diff_ir->GetNewFunction()); 986 return function_diff; 987 } 988 989 bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) { 990 // No RTTI 991 switch (lm->GetKind()) { 992 case RecordTypeKind: 993 return AddRecordTypeIR(static_cast<const RecordTypeIR *>(lm)); 994 case EnumTypeKind: 995 return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm)); 996 case PointerTypeKind: 997 return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm)); 998 case QualifiedTypeKind: 999 return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm)); 1000 case ArrayTypeKind: 1001 return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm)); 1002 case LvalueReferenceTypeKind: 1003 return AddLvalueReferenceTypeIR( 1004 static_cast<const LvalueReferenceTypeIR *>(lm)); 1005 case RvalueReferenceTypeKind: 1006 return AddRvalueReferenceTypeIR( 1007 static_cast<const RvalueReferenceTypeIR*>(lm)); 1008 case BuiltinTypeKind: 1009 return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm)); 1010 case FunctionTypeKind: 1011 return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm)); 1012 case GlobalVarKind: 1013 return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm)); 1014 case FunctionKind: 1015 return AddFunctionIR(static_cast<const FunctionIR*>(lm)); 1016 } 1017 return false; 1018 } 1019 1020 bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) { 1021 abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions(); 1022 if (!added_elf_function) { 1023 return false; 1024 } 1025 added_elf_function->set_name(elf_function->GetName()); 1026 return true; 1027 } 1028 1029 bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) { 1030 abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects(); 1031 if (!added_elf_object) { 1032 return false; 1033 } 1034 added_elf_object->set_name(elf_object->GetName()); 1035 return true; 1036 } 1037 1038 bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) { 1039 switch (em->GetKind()) { 1040 case ElfSymbolIR::ElfFunctionKind: 1041 return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em)); 1042 case ElfSymbolIR::ElfObjectKind: 1043 return AddElfObjectIR(static_cast<const ElfObjectIR *>(em)); 1044 } 1045 return false; 1046 } 1047 1048 bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) { 1049 abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types(); 1050 if (!added_record_type) { 1051 return false; 1052 } 1053 *added_record_type = ConvertRecordTypeIR(recordp); 1054 return true; 1055 } 1056 1057 bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) { 1058 abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types(); 1059 if (!added_function_type) { 1060 return false; 1061 } 1062 *added_function_type = ConvertFunctionTypeIR(function_typep); 1063 return true; 1064 } 1065 1066 bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) { 1067 abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions(); 1068 if (!added_function) { 1069 return false; 1070 } 1071 *added_function = ConvertFunctionIR(functionp); 1072 return true; 1073 } 1074 1075 bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) { 1076 abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types(); 1077 if (!added_enum_type) { 1078 return false; 1079 } 1080 *added_enum_type = ConvertEnumTypeIR(enump); 1081 return true; 1082 } 1083 1084 bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) { 1085 abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars(); 1086 if (!added_global_var) { 1087 return false; 1088 } 1089 *added_global_var = ConvertGlobalVarIR(global_varp); 1090 return true; 1091 } 1092 1093 bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) { 1094 abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types(); 1095 if (!added_pointer_type) { 1096 return false; 1097 } 1098 *added_pointer_type = ConvertPointerTypeIR(pointerp); 1099 return true; 1100 } 1101 1102 bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) { 1103 abi_dump::QualifiedType *added_qualified_type = 1104 tu_ptr_->add_qualified_types(); 1105 if (!added_qualified_type) { 1106 return false; 1107 } 1108 *added_qualified_type = ConvertQualifiedTypeIR(qualtypep); 1109 return true; 1110 } 1111 1112 bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) { 1113 abi_dump::BuiltinType *added_builtin_type = 1114 tu_ptr_->add_builtin_types(); 1115 if (!added_builtin_type) { 1116 return false; 1117 } 1118 *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep); 1119 return true; 1120 } 1121 1122 bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) { 1123 abi_dump::ArrayType *added_array_type = 1124 tu_ptr_->add_array_types(); 1125 if (!added_array_type) { 1126 return false; 1127 } 1128 *added_array_type = ConvertArrayTypeIR(array_typep); 1129 return true; 1130 } 1131 1132 bool ProtobufIRDumper::AddLvalueReferenceTypeIR( 1133 const LvalueReferenceTypeIR *lvalue_reference_typep) { 1134 abi_dump::LvalueReferenceType *added_lvalue_reference_type = 1135 tu_ptr_->add_lvalue_reference_types(); 1136 if (!added_lvalue_reference_type) { 1137 return false; 1138 } 1139 *added_lvalue_reference_type = 1140 ConvertLvalueReferenceTypeIR(lvalue_reference_typep); 1141 return true; 1142 } 1143 1144 bool ProtobufIRDumper::AddRvalueReferenceTypeIR( 1145 const RvalueReferenceTypeIR *rvalue_reference_typep) { 1146 abi_dump::RvalueReferenceType *added_rvalue_reference_type = 1147 tu_ptr_->add_rvalue_reference_types(); 1148 if (!added_rvalue_reference_type) { 1149 return false; 1150 } 1151 *added_rvalue_reference_type = 1152 ConvertRvalueReferenceTypeIR(rvalue_reference_typep); 1153 return true; 1154 } 1155 1156 bool ProtobufIRDumper::Dump() { 1157 GOOGLE_PROTOBUF_VERIFY_VERSION; 1158 assert( tu_ptr_.get() != nullptr); 1159 std::ofstream text_output(dump_path_); 1160 google::protobuf::io::OstreamOutputStream text_os(&text_output); 1161 return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os); 1162 } 1163 1164 void ProtobufIRDiffDumper::AddLibNameIR(const std::string &name) { 1165 diff_tu_->set_lib_name(name); 1166 } 1167 1168 void ProtobufIRDiffDumper::AddArchIR(const std::string &arch) { 1169 diff_tu_->set_arch(arch); 1170 } 1171 1172 CompatibilityStatusIR ProtobufIRDiffDumper::GetCompatibilityStatusIR() { 1173 if (diff_tu_->functions_removed().size() != 0 || 1174 diff_tu_->global_vars_removed().size() != 0 || 1175 diff_tu_->function_diffs().size() != 0 || 1176 diff_tu_->global_var_diffs().size() != 0 || 1177 diff_tu_->enum_type_diffs().size() != 0 || 1178 diff_tu_->record_type_diffs().size() != 0) { 1179 return CompatibilityStatusIR::Incompatible; 1180 } 1181 1182 CompatibilityStatusIR combined_status = CompatibilityStatusIR::Compatible; 1183 1184 if (diff_tu_->enum_type_extension_diffs().size() != 0 || 1185 diff_tu_->functions_added().size() != 0 || 1186 diff_tu_->global_vars_added().size() != 0) { 1187 combined_status = combined_status | CompatibilityStatusIR::Extension; 1188 } 1189 1190 if (diff_tu_->unreferenced_enum_type_diffs().size() != 0 || 1191 diff_tu_->unreferenced_enum_types_removed().size() != 0 || 1192 diff_tu_->unreferenced_record_types_removed().size() != 0 || 1193 diff_tu_->unreferenced_record_type_diffs().size() != 0 || 1194 diff_tu_->unreferenced_enum_type_extension_diffs().size() != 0 || 1195 diff_tu_->unreferenced_record_types_added().size() != 0 || 1196 diff_tu_->unreferenced_enum_types_added().size()) { 1197 combined_status = 1198 combined_status | CompatibilityStatusIR::UnreferencedChanges; 1199 } 1200 1201 if(diff_tu_->removed_elf_functions().size() != 0 || 1202 diff_tu_->removed_elf_objects().size() != 0) { 1203 combined_status = combined_status | CompatibilityStatusIR::ElfIncompatible; 1204 } 1205 1206 return combined_status; 1207 } 1208 1209 void ProtobufIRDiffDumper::AddCompatibilityStatusIR( 1210 CompatibilityStatusIR status) { 1211 diff_tu_->set_compatibility_status(CompatibilityStatusIRToProtobuf(status)); 1212 } 1213 1214 bool ProtobufIRDiffDumper::AddDiffMessageIR( 1215 const DiffMessageIR *message, 1216 const std::string &type_stack, 1217 DiffKind diff_kind) { 1218 switch (message->Kind()) { 1219 case RecordTypeKind: 1220 return AddRecordTypeDiffIR( 1221 static_cast<const RecordTypeDiffIR *>(message), 1222 type_stack, diff_kind); 1223 case EnumTypeKind: 1224 return AddEnumTypeDiffIR( 1225 static_cast<const EnumTypeDiffIR *>(message), 1226 type_stack, diff_kind); 1227 case GlobalVarKind: 1228 return AddGlobalVarDiffIR( 1229 static_cast<const GlobalVarDiffIR*>(message), 1230 type_stack, diff_kind); 1231 case FunctionKind: 1232 return AddFunctionDiffIR( 1233 static_cast<const FunctionDiffIR*>(message), 1234 type_stack, diff_kind); 1235 default: 1236 break; 1237 } 1238 llvm::errs() << "Dump Diff attempted on something not a user defined type" << 1239 "/ function / global variable\n"; 1240 return false; 1241 } 1242 1243 bool ProtobufIRDiffDumper::AddLinkableMessageIR( 1244 const LinkableMessageIR *message, 1245 DiffKind diff_kind) { 1246 switch (message->GetKind()) { 1247 case RecordTypeKind: 1248 return AddLoneRecordTypeDiffIR( 1249 static_cast<const RecordTypeIR *>(message), diff_kind); 1250 case EnumTypeKind: 1251 return AddLoneEnumTypeDiffIR( 1252 static_cast<const EnumTypeIR *>(message), diff_kind); 1253 case GlobalVarKind: 1254 return AddLoneGlobalVarDiffIR( 1255 static_cast<const GlobalVarIR*>(message), diff_kind); 1256 case FunctionKind: 1257 return AddLoneFunctionDiffIR( 1258 static_cast<const FunctionIR*>(message), diff_kind); 1259 default: 1260 break; 1261 } 1262 llvm::errs() << "Dump Diff attempted on something not a user defined type" << 1263 "/ function / global variable\n"; 1264 return false; 1265 } 1266 1267 bool ProtobufIRDiffDumper::AddElfSymbolMessageIR (const ElfSymbolIR *elf_symbol, 1268 DiffKind diff_kind) { 1269 switch (elf_symbol->GetKind()) { 1270 case ElfSymbolIR::ElfFunctionKind: 1271 return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(elf_symbol), 1272 diff_kind); 1273 break; 1274 case ElfSymbolIR::ElfObjectKind: 1275 return AddElfObjectIR(static_cast<const ElfObjectIR *>(elf_symbol), 1276 diff_kind); 1277 break; 1278 } 1279 // Any other kind is invalid 1280 return false; 1281 } 1282 1283 bool ProtobufIRDiffDumper::AddElfFunctionIR( 1284 const ElfFunctionIR *elf_function_ir, DiffKind diff_kind) { 1285 abi_dump::ElfFunction *added_elf_function = nullptr; 1286 switch(diff_kind) { 1287 case DiffKind::Removed: 1288 added_elf_function = diff_tu_->add_removed_elf_functions(); 1289 break; 1290 case DiffKind::Added: 1291 added_elf_function = diff_tu_->add_added_elf_functions(); 1292 break; 1293 default: 1294 llvm::errs() << "Invalid call to AddElfFunctionIR\n"; 1295 return false; 1296 } 1297 if (added_elf_function == nullptr) { 1298 return false; 1299 } 1300 *added_elf_function = 1301 IRToProtobufConverter::ConvertElfFunctionIR(elf_function_ir); 1302 return true; 1303 } 1304 1305 bool ProtobufIRDiffDumper::AddElfObjectIR( 1306 const ElfObjectIR *elf_object_ir, DiffKind diff_kind) { 1307 abi_dump::ElfObject *added_elf_object = nullptr; 1308 switch(diff_kind) { 1309 case DiffKind::Removed: 1310 added_elf_object = diff_tu_->add_removed_elf_objects(); 1311 break; 1312 case DiffKind::Added: 1313 added_elf_object = diff_tu_->add_added_elf_objects(); 1314 break; 1315 default: 1316 llvm::errs() << "Invalid call to AddElfObjectIR\n"; 1317 return false; 1318 } 1319 if (added_elf_object == nullptr) { 1320 return false; 1321 } 1322 *added_elf_object = 1323 IRToProtobufConverter::ConvertElfObjectIR(elf_object_ir); 1324 return true; 1325 } 1326 1327 bool ProtobufIRDiffDumper::AddLoneRecordTypeDiffIR( 1328 const RecordTypeIR *record_type_ir, 1329 DiffKind diff_kind) { 1330 abi_dump::RecordType *added_record_type = nullptr; 1331 switch (diff_kind) { 1332 case DiffKind::Removed: 1333 // Referenced record types do not get reported as added / removed, 1334 // the diff shows up in the parent type / function/ global variable 1335 // referencing the record. 1336 added_record_type = diff_tu_->add_unreferenced_record_types_removed(); 1337 break; 1338 case DiffKind::Added: 1339 added_record_type = diff_tu_->add_unreferenced_record_types_added(); 1340 break; 1341 default: 1342 llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; 1343 return false; 1344 } 1345 if (added_record_type == nullptr) { 1346 return false; 1347 } 1348 *added_record_type = 1349 IRToProtobufConverter::ConvertRecordTypeIR(record_type_ir); 1350 return true; 1351 } 1352 1353 bool ProtobufIRDiffDumper::AddLoneFunctionDiffIR( 1354 const FunctionIR *function_ir, 1355 DiffKind diff_kind) { 1356 abi_dump::FunctionDecl *added_function = nullptr; 1357 switch (diff_kind) { 1358 case DiffKind::Removed: 1359 added_function = diff_tu_->add_functions_removed(); 1360 break; 1361 case DiffKind::Added: 1362 added_function = diff_tu_->add_functions_added(); 1363 break; 1364 default: 1365 llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; 1366 return false; 1367 } 1368 *added_function = IRToProtobufConverter::ConvertFunctionIR(function_ir); 1369 return true; 1370 } 1371 1372 bool ProtobufIRDiffDumper::AddLoneEnumTypeDiffIR( 1373 const EnumTypeIR *enum_type_ir, DiffKind diff_kind) { 1374 abi_dump::EnumType *added_enum_type = nullptr; 1375 switch (diff_kind) { 1376 case DiffKind::Removed: 1377 // Referenced enum types do not get reported as added / removed, 1378 // the diff shows up in the parent type / function/ global variable 1379 // referencing the enum. 1380 added_enum_type = diff_tu_->add_unreferenced_enum_types_removed(); 1381 break; 1382 case DiffKind::Added: 1383 added_enum_type = diff_tu_->add_unreferenced_enum_types_added(); 1384 break; 1385 default: 1386 llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; 1387 return false; 1388 } 1389 if (added_enum_type == nullptr) { 1390 return false; 1391 } 1392 *added_enum_type = IRToProtobufConverter::ConvertEnumTypeIR(enum_type_ir); 1393 return true; 1394 } 1395 1396 bool ProtobufIRDiffDumper::AddLoneGlobalVarDiffIR( 1397 const GlobalVarIR *global_var_ir, DiffKind diff_kind) { 1398 abi_dump::GlobalVarDecl *added_global_var = nullptr; 1399 switch (diff_kind) { 1400 case DiffKind::Removed: 1401 added_global_var = diff_tu_->add_global_vars_removed(); 1402 break; 1403 case DiffKind::Added: 1404 added_global_var = diff_tu_->add_global_vars_added(); 1405 break; 1406 default: 1407 llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; 1408 return false; 1409 } 1410 *added_global_var = IRToProtobufConverter::ConvertGlobalVarIR(global_var_ir); 1411 return true; 1412 } 1413 1414 bool ProtobufIRDiffDumper::AddRecordTypeDiffIR( 1415 const RecordTypeDiffIR *record_diff_ir, 1416 const std::string &type_stack, 1417 DiffKind diff_kind) { 1418 abi_diff::RecordTypeDiff *added_record_type_diff = nullptr; 1419 switch (diff_kind) { 1420 case DiffKind::Unreferenced: 1421 added_record_type_diff = diff_tu_->add_unreferenced_record_type_diffs(); 1422 break; 1423 case DiffKind::Referenced: 1424 added_record_type_diff = diff_tu_->add_record_type_diffs(); 1425 break; 1426 default: 1427 break; 1428 } 1429 if (!added_record_type_diff) { 1430 return false; 1431 } 1432 1433 *added_record_type_diff = 1434 IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(record_diff_ir); 1435 added_record_type_diff->set_type_stack(type_stack); 1436 return true; 1437 } 1438 1439 bool ProtobufIRDiffDumper::AddFunctionDiffIR( 1440 const FunctionDiffIR *function_diff_ir, const std::string &type_stack, 1441 DiffKind diff_kind) { 1442 abi_diff::FunctionDeclDiff *added_function_diff = 1443 diff_tu_->add_function_diffs(); 1444 if (!added_function_diff) { 1445 return false; 1446 } 1447 *added_function_diff = 1448 IRDiffToProtobufConverter::ConvertFunctionDiffIR(function_diff_ir); 1449 return true; 1450 } 1451 1452 bool ProtobufIRDiffDumper::AddEnumTypeDiffIR(const EnumTypeDiffIR *enum_diff_ir, 1453 const std::string &type_stack, 1454 DiffKind diff_kind) { 1455 abi_diff::EnumTypeDiff *added_enum_type_diff = nullptr; 1456 switch (diff_kind) { 1457 case DiffKind::Unreferenced: 1458 if (enum_diff_ir->IsExtended()) { 1459 added_enum_type_diff = 1460 diff_tu_->add_unreferenced_enum_type_extension_diffs(); 1461 } else { 1462 added_enum_type_diff = 1463 diff_tu_->add_unreferenced_enum_type_diffs(); 1464 } 1465 break; 1466 case DiffKind::Referenced: 1467 if (enum_diff_ir->IsExtended()) { 1468 added_enum_type_diff = 1469 diff_tu_->add_enum_type_extension_diffs(); 1470 } else { 1471 added_enum_type_diff = 1472 diff_tu_->add_enum_type_diffs(); 1473 } 1474 break; 1475 default: 1476 break; 1477 } 1478 if (!added_enum_type_diff) { 1479 return false; 1480 } 1481 *added_enum_type_diff = 1482 IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(enum_diff_ir); 1483 added_enum_type_diff->set_type_stack(type_stack); 1484 return true; 1485 } 1486 1487 bool ProtobufIRDiffDumper::AddGlobalVarDiffIR( 1488 const GlobalVarDiffIR *global_var_diff_ir, 1489 const std::string &type_stack, 1490 DiffKind diff_kind) { 1491 abi_diff::GlobalVarDeclDiff *added_global_var_diff = 1492 diff_tu_->add_global_var_diffs(); 1493 if (!added_global_var_diff) { 1494 return false; 1495 } 1496 *added_global_var_diff = 1497 IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(global_var_diff_ir); 1498 return true; 1499 } 1500 1501 bool ProtobufIRDiffDumper::Dump() { 1502 GOOGLE_PROTOBUF_VERIFY_VERSION; 1503 assert(diff_tu_.get() != nullptr); 1504 std::ofstream text_output(dump_path_); 1505 google::protobuf::io::OstreamOutputStream text_os(&text_output); 1506 return google::protobuf::TextFormat::Print(*diff_tu_.get(), &text_os); 1507 } 1508 1509 } //abi_util 1510