@@ -3086,11 +3086,48 @@ mccasformats::v1::loadDIETopLevel(DIETopLevelRef TopLevelRef) {
3086
3086
}
3087
3087
3088
3088
struct DIEVisitor {
3089
+
3090
+ struct AbbrevContent {
3091
+ dwarf::Attribute Attr;
3092
+ dwarf::Form Form;
3093
+ bool FormInDistinctData;
3094
+ std::optional<uint8_t > FormSize;
3095
+ };
3096
+
3097
+ struct AbbrevEntry {
3098
+ dwarf::Tag Tag;
3099
+ bool HasChildren;
3100
+ SmallVector<AbbrevContent> AbbrevContents;
3101
+ };
3102
+
3103
+ DIEVisitor () = delete ;
3104
+
3105
+ DIEVisitor (ArrayRef<StringRef> AbbrevEntries,
3106
+ BinaryStreamReader DistinctReader, StringRef DistinctData,
3107
+ std::function<void (StringRef)> HeaderCallback,
3108
+ std::function<void (dwarf::Tag, uint64_t )> StartTagCallback,
3109
+ std::function<void (dwarf::Attribute, dwarf::Form, StringRef, bool )>
3110
+ AttrCallback,
3111
+ std::function<void (bool )> EndTagCallback,
3112
+ std::function<void (StringRef)> NewBlockCallback)
3113
+ : AbbrevEntries(AbbrevEntries), DistinctReader(DistinctReader),
3114
+ DistinctData (DistinctData), HeaderCallback(HeaderCallback),
3115
+ StartTagCallback(StartTagCallback), AttrCallback(AttrCallback),
3116
+ EndTagCallback(EndTagCallback), NewBlockCallback(NewBlockCallback) {
3117
+ AbbrevEntryCache.reserve (AbbrevEntries.size ());
3118
+ for (unsigned I = 0 ; I < AbbrevEntries.size (); I++) {
3119
+ if (Error E = materializeAbbrevDIE (encodeAbbrevIndex (I)))
3120
+ report_fatal_error (std::move (E));
3121
+ }
3122
+ }
3123
+
3089
3124
Error visitDIERef (DIEDedupeTopLevelRef Ref);
3090
3125
Error visitDIERef (ArrayRef<DIEDataRef> &DIEChildrenStack);
3091
- Error visitDIEAttrs (AbbrevEntryReader &AbbrevReader,
3092
- BinaryStreamReader &Reader, StringRef DIEData);
3126
+ Error visitDIEAttrs (BinaryStreamReader &DataReader, StringRef DIEData,
3127
+ ArrayRef<AbbrevContent> DIEContents);
3128
+ Error materializeAbbrevDIE (unsigned AbbrevIdx);
3093
3129
3130
+ SmallVector<AbbrevEntry> AbbrevEntryCache;
3094
3131
ArrayRef<StringRef> AbbrevEntries;
3095
3132
BinaryStreamReader DistinctReader;
3096
3133
StringRef DistinctData;
@@ -3103,38 +3140,31 @@ struct DIEVisitor {
3103
3140
std::function<void (StringRef)> NewBlockCallback;
3104
3141
};
3105
3142
3106
- Error DIEVisitor::visitDIEAttrs (AbbrevEntryReader &AbbrevReader ,
3107
- BinaryStreamReader &DataReader ,
3108
- StringRef DIEData ) {
3143
+ Error DIEVisitor::visitDIEAttrs (BinaryStreamReader &DataReader ,
3144
+ StringRef DIEData ,
3145
+ ArrayRef<AbbrevContent> DIEContents ) {
3109
3146
constexpr auto IsLittleEndian = true ;
3110
3147
constexpr auto AddrSize = 8 ;
3111
3148
constexpr auto FormParams =
3112
3149
dwarf::FormParams{4 /* Version*/ , AddrSize, dwarf::DwarfFormat::DWARF32};
3113
3150
3114
- while (true ) {
3115
- Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr ();
3116
- if (!Attr)
3117
- return Attr.takeError ();
3118
- if (*Attr == getEndOfAttributesMarker ())
3119
- break ;
3120
-
3121
- Expected<dwarf::Form> Form = AbbrevReader.readForm ();
3122
- if (!Form)
3123
- return Form.takeError ();
3124
-
3125
- bool DataInDistinct = doesntDedup (*Form, *Attr);
3151
+ for (auto Contents : DIEContents) {
3152
+ bool DataInDistinct = Contents.FormInDistinctData ;
3126
3153
auto &ReaderForData = DataInDistinct ? DistinctReader : DataReader;
3127
3154
StringRef DataToUse = DataInDistinct ? DistinctData : DIEData;
3128
3155
Expected<uint64_t > FormSize =
3129
- getFormSize (*Form, FormParams, DataToUse, ReaderForData.getOffset (),
3130
- IsLittleEndian, AddrSize);
3156
+ Contents.FormSize
3157
+ ? *Contents.FormSize
3158
+ : getFormSize (Contents.Form , FormParams, DataToUse,
3159
+ ReaderForData.getOffset (), IsLittleEndian, AddrSize);
3131
3160
if (!FormSize)
3132
3161
return FormSize.takeError ();
3133
3162
3134
3163
ArrayRef<char > RawBytes;
3135
3164
if (auto E = ReaderForData.readArray (RawBytes, *FormSize))
3136
3165
return E;
3137
- AttrCallback (*Attr, *Form, toStringRef (RawBytes), DataInDistinct);
3166
+ AttrCallback (Contents.Attr , Contents.Form , toStringRef (RawBytes),
3167
+ DataInDistinct);
3138
3168
}
3139
3169
return Error::success ();
3140
3170
}
@@ -3153,6 +3183,111 @@ static AbbrevEntryReader getAbbrevEntryReader(ArrayRef<StringRef> AbbrevEntries,
3153
3183
return AbbrevEntryReader (AbbrevData);
3154
3184
}
3155
3185
3186
+ static std::optional<uint8_t > getNonULEBFormSize (dwarf::Form Form,
3187
+ dwarf::FormParams FP) {
3188
+ switch (Form) {
3189
+ case dwarf::DW_FORM_addr:
3190
+ return FP.AddrSize ;
3191
+ case dwarf::DW_FORM_ref_addr:
3192
+ return FP.getRefAddrByteSize ();
3193
+ case dwarf::DW_FORM_exprloc:
3194
+ case dwarf::DW_FORM_block:
3195
+ case dwarf::DW_FORM_block1:
3196
+ case dwarf::DW_FORM_block2:
3197
+ case dwarf::DW_FORM_block4:
3198
+ case dwarf::DW_FORM_sdata:
3199
+ case dwarf::DW_FORM_udata:
3200
+ case dwarf::DW_FORM_ref_udata:
3201
+ case dwarf::DW_FORM_ref4_cas:
3202
+ case dwarf::DW_FORM_strp_cas:
3203
+ case dwarf::DW_FORM_rnglistx:
3204
+ case dwarf::DW_FORM_loclistx:
3205
+ case dwarf::DW_FORM_GNU_addr_index:
3206
+ case dwarf::DW_FORM_GNU_str_index:
3207
+ case dwarf::DW_FORM_addrx:
3208
+ case dwarf::DW_FORM_strx:
3209
+ case dwarf::DW_FORM_LLVM_addrx_offset:
3210
+ case dwarf::DW_FORM_string:
3211
+ case dwarf::DW_FORM_indirect:
3212
+ return std::nullopt;
3213
+
3214
+ case dwarf::DW_FORM_implicit_const:
3215
+ case dwarf::DW_FORM_flag_present:
3216
+ return 0 ;
3217
+ case dwarf::DW_FORM_data1:
3218
+ case dwarf::DW_FORM_ref1:
3219
+ case dwarf::DW_FORM_flag:
3220
+ case dwarf::DW_FORM_strx1:
3221
+ case dwarf::DW_FORM_addrx1:
3222
+ return 1 ;
3223
+ case dwarf::DW_FORM_data2:
3224
+ case dwarf::DW_FORM_ref2:
3225
+ case dwarf::DW_FORM_strx2:
3226
+ case dwarf::DW_FORM_addrx2:
3227
+ return 2 ;
3228
+ case dwarf::DW_FORM_strx3:
3229
+ return 3 ;
3230
+ case dwarf::DW_FORM_data4:
3231
+ case dwarf::DW_FORM_ref4:
3232
+ case dwarf::DW_FORM_ref_sup4:
3233
+ case dwarf::DW_FORM_strx4:
3234
+ case dwarf::DW_FORM_addrx4:
3235
+ return 4 ;
3236
+ case dwarf::DW_FORM_ref_sig8:
3237
+ case dwarf::DW_FORM_data8:
3238
+ case dwarf::DW_FORM_ref8:
3239
+ case dwarf::DW_FORM_ref_sup8:
3240
+ return 8 ;
3241
+ case dwarf::DW_FORM_data16:
3242
+ return 16 ;
3243
+ case dwarf::DW_FORM_strp:
3244
+ case dwarf::DW_FORM_sec_offset:
3245
+ case dwarf::DW_FORM_GNU_ref_alt:
3246
+ case dwarf::DW_FORM_GNU_strp_alt:
3247
+ case dwarf::DW_FORM_line_strp:
3248
+ case dwarf::DW_FORM_strp_sup:
3249
+ return FP.getDwarfOffsetByteSize ();
3250
+ case dwarf::DW_FORM_addrx3:
3251
+ case dwarf::DW_FORM_lo_user:
3252
+ llvm_unreachable (" usupported form" );
3253
+ break ;
3254
+ }
3255
+ }
3256
+
3257
+ Error DIEVisitor::materializeAbbrevDIE (unsigned AbbrevIdx) {
3258
+ constexpr auto AddrSize = 8 ;
3259
+ constexpr auto FormParams =
3260
+ dwarf::FormParams{4 /* Version*/ , AddrSize, dwarf::DwarfFormat::DWARF32};
3261
+
3262
+ AbbrevEntryReader AbbrevReader =
3263
+ getAbbrevEntryReader (AbbrevEntries, AbbrevIdx);
3264
+ Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag ();
3265
+ if (!MaybeTag)
3266
+ return MaybeTag.takeError ();
3267
+
3268
+ Expected<bool > MaybeHasChildren = AbbrevReader.readHasChildren ();
3269
+ if (!MaybeHasChildren)
3270
+ return MaybeHasChildren.takeError ();
3271
+
3272
+ SmallVector<AbbrevContent> AbbrevVector;
3273
+ while (true ) {
3274
+ Expected<dwarf::Attribute> Attr = AbbrevReader.readAttr ();
3275
+ if (!Attr)
3276
+ return Attr.takeError ();
3277
+ if (*Attr == getEndOfAttributesMarker ())
3278
+ break ;
3279
+
3280
+ Expected<dwarf::Form> Form = AbbrevReader.readForm ();
3281
+ if (!Form)
3282
+ return Form.takeError ();
3283
+ AbbrevVector.push_back ({*Attr, *Form, doesntDedup (*Form, *Attr),
3284
+ getNonULEBFormSize (*Form, FormParams)});
3285
+ }
3286
+ AbbrevEntryCache.push_back (
3287
+ {*MaybeTag, *MaybeHasChildren, std::move (AbbrevVector)});
3288
+ return Error::success ();
3289
+ }
3290
+
3156
3291
// / Restores the state of the \p Reader and \p Data
3157
3292
// / arguments to a previous state. The algorithm in visitDIERefs is an iterative
3158
3293
// / implementation of a Depth First Search, and this function is used to
@@ -3205,25 +3340,18 @@ Error DIEVisitor::visitDIERef(ArrayRef<DIEDataRef> &DIEChildrenStack) {
3205
3340
}
3206
3341
3207
3342
// If we have a legitimate AbbrevIdx, materialize the current DIE.
3208
- AbbrevEntryReader AbbrevReader =
3209
- getAbbrevEntryReader (AbbrevEntries, AbbrevIdx);
3210
-
3211
- if (Expected<dwarf::Tag> MaybeTag = AbbrevReader.readTag ())
3212
- StartTagCallback (*MaybeTag, AbbrevIdx);
3213
- else
3214
- return MaybeTag.takeError ();
3215
-
3216
- Expected<bool > MaybeHasChildren = AbbrevReader.readHasChildren ();
3217
- if (!MaybeHasChildren)
3218
- return MaybeHasChildren.takeError ();
3343
+ auto &AbbrevEntryCacheVal =
3344
+ AbbrevEntryCache[decodeAbbrevIndexAsAbbrevSetIdx (AbbrevIdx)];
3345
+ StartTagCallback (AbbrevEntryCacheVal.Tag , AbbrevIdx);
3219
3346
3220
- if (auto E = visitDIEAttrs (AbbrevReader, Reader, Data))
3347
+ if (auto E =
3348
+ visitDIEAttrs (Reader, Data, AbbrevEntryCacheVal.AbbrevContents ))
3221
3349
return E;
3222
3350
3223
3351
// If the current DIE doesn't have any children, the current CAS Object will
3224
3352
// not contain any more data, pop the stack to continue materializing its
3225
3353
// parent's siblings that may exist.
3226
- if (!*MaybeHasChildren ) {
3354
+ if (!AbbrevEntryCacheVal. HasChildren ) {
3227
3355
if (!StackOfNodes.empty () && Reader.empty ())
3228
3356
popStack (Reader, Data, StackOfNodes);
3229
3357
EndTagCallback (false /* HadChildren*/ );
0 commit comments