@@ -420,6 +420,281 @@ TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) {
420420 ASSERT_EQ (type_as_string, " void (*__ptrauth(0,0,42))(...)" );
421421}
422422
423+ TEST_F (DWARFASTParserClangTests, TestVTablePtrAuthParsing) {
424+ // Tests parsing dynamic structure types with explicit vtable pointer
425+ // authentication
426+
427+ // This is Dwarf for the following C++ code:
428+ // ```
429+ // struct [[clang::ptrauth_vtable_pointer(process_dependent,
430+ // address_discrimination,
431+ // custom_discrimination, 42)]] A {
432+ // virtual void foo() {}
433+ // };
434+ // A a;
435+ // ```
436+
437+ const char *yamldata = R"(
438+ --- !ELF
439+ FileHeader:
440+ Class: ELFCLASS64
441+ Data: ELFDATA2LSB
442+ Type: ET_EXEC
443+ Machine: EM_AARCH64
444+ DWARF:
445+ debug_str:
446+ - a
447+ - A
448+ - _vptr$A
449+ - foo
450+ - __vtbl_ptr_type
451+ - int
452+ debug_abbrev:
453+ - ID: 0
454+ Table:
455+ - Code: 0x1
456+ Tag: DW_TAG_compile_unit
457+ Children: DW_CHILDREN_yes
458+ Attributes:
459+ - Attribute: DW_AT_language
460+ Form: DW_FORM_data2
461+ - Code: 0x2
462+ Tag: DW_TAG_variable
463+ Children: DW_CHILDREN_no
464+ Attributes:
465+ - Attribute: DW_AT_name
466+ Form: DW_FORM_strp
467+ - Attribute: DW_AT_type
468+ Form: DW_FORM_ref4
469+ - Attribute: DW_AT_external
470+ Form: DW_FORM_flag_present
471+ - Code: 0x3
472+ Tag: DW_TAG_structure_type
473+ Children: DW_CHILDREN_yes
474+ Attributes:
475+ - Attribute: DW_AT_containing_type
476+ Form: DW_FORM_ref4
477+ - Attribute: DW_AT_name
478+ Form: DW_FORM_strp
479+ - Code: 0x4
480+ Tag: DW_TAG_member
481+ Children: DW_CHILDREN_no
482+ Attributes:
483+ - Attribute: DW_AT_name
484+ Form: DW_FORM_strp
485+ - Attribute: DW_AT_type
486+ Form: DW_FORM_ref4
487+ - Attribute: DW_AT_artificial
488+ Form: DW_FORM_flag_present
489+ - Code: 0x5
490+ Tag: DW_TAG_subprogram
491+ Children: DW_CHILDREN_yes
492+ Attributes:
493+ - Attribute: DW_AT_name
494+ Form: DW_FORM_strp
495+ - Attribute: DW_AT_virtuality
496+ Form: DW_FORM_data1
497+ - Attribute: DW_AT_containing_type
498+ Form: DW_FORM_ref4
499+ - Code: 0x6
500+ Tag: DW_TAG_formal_parameter
501+ Children: DW_CHILDREN_no
502+ Attributes:
503+ - Attribute: DW_AT_type
504+ Form: DW_FORM_ref4
505+ - Attribute: DW_AT_artificial
506+ Form: DW_FORM_flag_present
507+ - Code: 0x7
508+ Tag: DW_TAG_LLVM_ptrauth_type
509+ Children: DW_CHILDREN_no
510+ Attributes:
511+ - Attribute: DW_AT_type
512+ Form: DW_FORM_ref4
513+ - Attribute: DW_AT_LLVM_ptrauth_key
514+ Form: DW_FORM_data1
515+ - Attribute: DW_AT_LLVM_ptrauth_extra_discriminator
516+ Form: DW_FORM_data2
517+ - Attribute: DW_AT_LLVM_ptrauth_address_discriminated
518+ Form: DW_FORM_flag_present
519+ - Code: 0x8
520+ Tag: DW_TAG_pointer_type
521+ Children: DW_CHILDREN_no
522+ Attributes:
523+ - Attribute: DW_AT_type
524+ Form: DW_FORM_ref4
525+ - Code: 0x9
526+ Tag: DW_TAG_pointer_type
527+ Children: DW_CHILDREN_no
528+ Attributes:
529+ - Attribute: DW_AT_type
530+ Form: DW_FORM_ref4
531+ - Attribute: DW_AT_name
532+ Form: DW_FORM_strp
533+ - Code: 0xA
534+ Tag: DW_TAG_subroutine_type
535+ Children: DW_CHILDREN_no
536+ Attributes:
537+ - Attribute: DW_AT_type
538+ Form: DW_FORM_ref4
539+ - Code: 0xB
540+ Tag: DW_TAG_base_type
541+ Children: DW_CHILDREN_no
542+ Attributes:
543+ - Attribute: DW_AT_name
544+ Form: DW_FORM_strp
545+ - Attribute: DW_AT_encoding
546+ Form: DW_FORM_data1
547+ - Attribute: DW_AT_byte_size
548+ Form: DW_FORM_data1
549+ - Code: 0xC
550+ Tag: DW_TAG_pointer_type
551+ Children: DW_CHILDREN_no
552+ Attributes:
553+ - Attribute: DW_AT_type
554+ Form: DW_FORM_ref4
555+
556+ debug_info:
557+ - Version: 5
558+ UnitType: DW_UT_compile
559+ AddrSize: 8
560+ Entries:
561+ # 0x0c: DW_TAG_compile_unit
562+ # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus_11)
563+ - AbbrCode: 0x1
564+ Values:
565+ - Value: 0x1A
566+
567+ # 0x0f: DW_TAG_variable
568+ # DW_AT_name [DW_FORM_strp] (\"a\")
569+ # DW_AT_type [DW_FORM_ref4] (0x00000018 \"A\")
570+ # DW_AT_external [DW_FORM_flag_present] (true)
571+ - AbbrCode: 0x2
572+ Values:
573+ - Value: 0x00
574+ - Value: 0x18
575+
576+ # 0x18: DW_TAG_structure_type
577+ # DW_AT_containing_type [DW_FORM_ref4] (0x00000018 \"A\")
578+ # DW_AT_name [DW_FORM_strp] (\"A\")
579+ - AbbrCode: 0x3
580+ Values:
581+ - Value: 0x18
582+ - Value: 0x02
583+
584+ # 0x21: DW_TAG_member
585+ # DW_AT_name [DW_FORM_strp] (\"_vptr$A\")
586+ # DW_AT_type [DW_FORM_ref4] (0x0000002f)
587+ # DW_AT_artificial [DW_FORM_flag_present] (true)
588+ - AbbrCode: 0x4
589+ Values:
590+ - Value: 0x04
591+ - Value: 0x3B
592+
593+ # 0x2a: DW_TAG_subprogram
594+ # DW_AT_name [DW_FORM_strp] (\"foo\")
595+ # DW_AT_virtuality [DW_FORM_data1] (DW_VIRTUALITY_virtual)
596+ # DW_AT_containing_type [DW_FORM_ref4] (0x00000018 \"A\")
597+ - AbbrCode: 0x5
598+ Values:
599+ - Value: 0x0C
600+ - Value: 0x01
601+ - Value: 0x18
602+
603+ # 0x34: DW_TAG_formal_parameter
604+ # DW_AT_type [DW_FORM_ref4] (0x0000005d \"A *\")
605+ # DW_AT_artificial [DW_FORM_flag_present] (true)
606+ - AbbrCode: 0x6
607+ Values:
608+ - Value: 0x5D
609+
610+ - AbbrCode: 0x0 # end of child tags of 0x2a
611+ - AbbrCode: 0x0 # end of child tags of 0x18
612+
613+ # 0x3b: DW_TAG_LLVM_ptrauth_type
614+ # DW_AT_type [DW_FORM_ref4] (0x00000043 \"int (**)()\")
615+ # DW_AT_LLVM_ptrauth_key [DW_FORM_data1] (0x02)
616+ # DW_AT_LLVM_ptrauth_extra_discriminator [DW_FORM_data2] (0x002a)
617+ # DW_AT_LLVM_ptrauth_address_discriminated [DW_FORM_flag_present] (true)
618+ - AbbrCode: 0x7
619+ Values:
620+ - Value: 0x43
621+ - Value: 0x02
622+ - Value: 0x2A
623+
624+ # 0x43: DW_TAG_pointer_type
625+ # DW_AT_type [DW_FORM_ref4] (0x00000048 \"int (*)()\")
626+ - AbbrCode: 0x8
627+ Values:
628+ - Value: 0x48
629+
630+ # 0x48: DW_TAG_pointer_type
631+ # DW_AT_type [DW_FORM_ref4] (0x00000051 \"int ()\")
632+ # DW_AT_name [DW_FORM_strp] (\"__vtbl_ptr_type\")
633+ - AbbrCode: 0x9
634+ Values:
635+ - Value: 0x51
636+ - Value: 0x10
637+
638+ # 0x51: DW_TAG_subroutine_type
639+ # DW_AT_type [DW_FORM_ref4] (0x00000056 \"int\")
640+ - AbbrCode: 0xA
641+ Values:
642+ - Value: 0x56
643+
644+ # 0x56: DW_TAG_base_type
645+ # DW_AT_name [DW_FORM_strp] (\"int\")
646+ # DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
647+ # DW_AT_byte_size [DW_FORM_data1] (0x04)
648+ - AbbrCode: 0xB
649+ Values:
650+ - Value: 0x20
651+ - Value: 0x05
652+ - Value: 0x04
653+
654+ # 0x5d: DW_TAG_pointer_type
655+ # DW_AT_type [DW_FORM_ref4] (0x00000018 \"A\")
656+ - AbbrCode: 0xC
657+ Values:
658+ - Value: 0x18
659+
660+ - AbbrCode: 0x0 # end of child tags of 0x0c
661+ ...
662+ )" ;
663+ YAMLModuleTester t (yamldata);
664+
665+ DWARFUnit *unit = t.GetDwarfUnit ();
666+ ASSERT_NE (unit, nullptr );
667+ const DWARFDebugInfoEntry *cu_entry = unit->DIE ().GetDIE ();
668+ ASSERT_EQ (cu_entry->Tag (), DW_TAG_compile_unit);
669+ DWARFDIE cu_die (unit, cu_entry);
670+
671+ auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>(" ast" );
672+ auto &ast_ctx = *holder->GetAST ();
673+ DWARFASTParserClangStub ast_parser (ast_ctx);
674+
675+ DWARFDIE struct_object = cu_die.GetFirstChild ();
676+ ASSERT_EQ (struct_object.Tag (), DW_TAG_variable);
677+ DWARFDIE structure_type =
678+ struct_object.GetAttributeValueAsReferenceDIE (DW_AT_type);
679+ ASSERT_EQ (structure_type.Tag (), DW_TAG_structure_type);
680+
681+ SymbolContext sc;
682+ bool new_type = false ;
683+ lldb::TypeSP type =
684+ ast_parser.ParseTypeFromDWARF (sc, structure_type, &new_type);
685+ clang::RecordDecl *record_decl =
686+ TypeSystemClang::GetAsRecordDecl (type->GetForwardCompilerType ());
687+ auto *attr = record_decl->getAttr <clang::VTablePointerAuthenticationAttr>();
688+ ASSERT_NE (attr, nullptr );
689+ ASSERT_EQ (attr->getKey (),
690+ clang::VTablePointerAuthenticationAttr::ProcessDependent);
691+ ASSERT_EQ (attr->getAddressDiscrimination (),
692+ clang::VTablePointerAuthenticationAttr::AddressDiscrimination);
693+ ASSERT_EQ (attr->getExtraDiscrimination (),
694+ clang::VTablePointerAuthenticationAttr::CustomDiscrimination);
695+ ASSERT_EQ (attr->getCustomDiscriminationValue (), 42 );
696+ }
697+
423698struct ExtractIntFromFormValueTest : public testing ::Test {
424699 SubsystemRAII<FileSystem, HostInfo> subsystems;
425700 clang_utils::TypeSystemClangHolder holder;
0 commit comments