8
8
// ===----------------------------------------------------------------------===//
9
9
10
10
#include " llvm/DebugInfo/DWARF/DWARFVerifier.h"
11
+ #include " llvm/ADT/SmallSet.h"
11
12
#include " llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
12
13
#include " llvm/DebugInfo/DWARF/DWARFContext.h"
13
14
#include " llvm/DebugInfo/DWARF/DWARFDebugLine.h"
@@ -939,6 +940,89 @@ DWARFVerifier::verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
939
940
return NumErrors;
940
941
}
941
942
943
+ unsigned DWARFVerifier::verifyNameIndexAttribute (
944
+ const DWARFDebugNames::NameIndex &NI, const DWARFDebugNames::Abbrev &Abbr,
945
+ DWARFDebugNames::AttributeEncoding AttrEnc) {
946
+ StringRef FormName = dwarf::FormEncodingString (AttrEnc.Form );
947
+ if (FormName.empty ()) {
948
+ error () << formatv (" NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
949
+ " unknown form: {3}.\n " ,
950
+ NI.getUnitOffset (), Abbr.Code , AttrEnc.Index ,
951
+ AttrEnc.Form );
952
+ return 1 ;
953
+ }
954
+
955
+ if (AttrEnc.Index == DW_IDX_type_hash) {
956
+ if (AttrEnc.Form != dwarf::DW_FORM_data8) {
957
+ error () << formatv (
958
+ " NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
959
+ " uses an unexpected form {2} (should be {3}).\n " ,
960
+ NI.getUnitOffset (), Abbr.Code , AttrEnc.Form , dwarf::DW_FORM_data8);
961
+ return 1 ;
962
+ }
963
+ }
964
+
965
+ // A list of known index attributes and their expected form classes.
966
+ // DW_IDX_type_hash is handled specially in the check above, as it has a
967
+ // specific form (not just a form class) we should expect.
968
+ struct FormClassTable {
969
+ dwarf::Index Index;
970
+ DWARFFormValue::FormClass Class;
971
+ StringLiteral ClassName;
972
+ };
973
+ static constexpr FormClassTable Table[] = {
974
+ {dwarf::DW_IDX_compile_unit, DWARFFormValue::FC_Constant, {" constant" }},
975
+ {dwarf::DW_IDX_type_unit, DWARFFormValue::FC_Constant, {" constant" }},
976
+ {dwarf::DW_IDX_die_offset, DWARFFormValue::FC_Reference, {" reference" }},
977
+ {dwarf::DW_IDX_parent, DWARFFormValue::FC_Constant, {" constant" }},
978
+ };
979
+
980
+ ArrayRef<FormClassTable> TableRef (Table);
981
+ auto Iter = find_if (TableRef, [AttrEnc](const FormClassTable &T) {
982
+ return T.Index == AttrEnc.Index ;
983
+ });
984
+ if (Iter == TableRef.end ()) {
985
+ warn () << formatv (" NameIndex @ {0:x}: Abbreviation {1:x} contains an "
986
+ " unknown index attribute: {2}.\n " ,
987
+ NI.getUnitOffset (), Abbr.Code , AttrEnc.Index );
988
+ return 0 ;
989
+ }
990
+
991
+ if (!DWARFFormValue (AttrEnc.Form ).isFormClass (Iter->Class )) {
992
+ error () << formatv (" NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
993
+ " unexpected form {3} (expected form class {4}).\n " ,
994
+ NI.getUnitOffset (), Abbr.Code , AttrEnc.Index ,
995
+ AttrEnc.Form , Iter->ClassName );
996
+ return 1 ;
997
+ }
998
+ return 0 ;
999
+ }
1000
+
1001
+ unsigned
1002
+ DWARFVerifier::verifyNameIndexAbbrevs (const DWARFDebugNames::NameIndex &NI) {
1003
+ unsigned NumErrors = 0 ;
1004
+ for (const auto &Abbrev : NI.getAbbrevs ()) {
1005
+ StringRef TagName = dwarf::TagString (Abbrev.Tag );
1006
+ if (TagName.empty ()) {
1007
+ warn () << formatv (" NameIndex @ {0:x}: Abbreviation {1:x} references an "
1008
+ " unknown tag: {2}.\n " ,
1009
+ NI.getUnitOffset (), Abbrev.Code , Abbrev.Tag );
1010
+ }
1011
+ SmallSet<unsigned , 5 > Attributes;
1012
+ for (const auto &AttrEnc : Abbrev.Attributes ) {
1013
+ if (!Attributes.insert (AttrEnc.Index ).second ) {
1014
+ error () << formatv (" NameIndex @ {0:x}: Abbreviation {1:x} contains "
1015
+ " multiple {2} attributes.\n " ,
1016
+ NI.getUnitOffset (), Abbrev.Code , AttrEnc.Index );
1017
+ ++NumErrors;
1018
+ continue ;
1019
+ }
1020
+ NumErrors += verifyNameIndexAttribute (NI, Abbrev, AttrEnc);
1021
+ }
1022
+ }
1023
+ return NumErrors;
1024
+ }
1025
+
942
1026
unsigned DWARFVerifier::verifyDebugNames (const DWARFSection &AccelSection,
943
1027
const DataExtractor &StrData) {
944
1028
unsigned NumErrors = 0 ;
@@ -958,6 +1042,8 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
958
1042
NumErrors += verifyDebugNamesCULists (AccelTable);
959
1043
for (const auto &NI : AccelTable)
960
1044
NumErrors += verifyNameIndexBuckets (NI, StrData);
1045
+ for (const auto &NI : AccelTable)
1046
+ NumErrors += verifyNameIndexAbbrevs (NI);
961
1047
962
1048
return NumErrors;
963
1049
}
0 commit comments