@@ -205,36 +205,67 @@ static bool hasInlineInfo(DWARFDie Die, uint32_t Depth) {
205
205
return false ;
206
206
}
207
207
208
+ static AddressRanges
209
+ ConvertDWARFRanges (const DWARFAddressRangesVector &DwarfRanges) {
210
+ AddressRanges Ranges;
211
+ for (const DWARFAddressRange &DwarfRange : DwarfRanges) {
212
+ if (DwarfRange.LowPC < DwarfRange.HighPC )
213
+ Ranges.insert ({DwarfRange.LowPC , DwarfRange.HighPC });
214
+ }
215
+ return Ranges;
216
+ }
217
+
208
218
static void parseInlineInfo (GsymCreator &Gsym, raw_ostream *Log, CUInfo &CUI,
209
219
DWARFDie Die, uint32_t Depth, FunctionInfo &FI,
210
- InlineInfo &parent) {
220
+ InlineInfo &Parent,
221
+ const AddressRanges &AllParentRanges,
222
+ bool &WarnIfEmpty) {
211
223
if (!hasInlineInfo (Die, Depth))
212
224
return ;
213
225
214
226
dwarf::Tag Tag = Die.getTag ();
215
227
if (Tag == dwarf::DW_TAG_inlined_subroutine) {
216
228
// create new InlineInfo and append to parent.children
217
229
InlineInfo II;
230
+ AddressRanges AllInlineRanges;
218
231
Expected<DWARFAddressRangesVector> RangesOrError = Die.getAddressRanges ();
219
232
if (RangesOrError) {
220
- for (const DWARFAddressRange &Range : RangesOrError.get ()) {
221
- // Check that the inlined function is within the any of the range the
222
- // parent InlineInfo. If it isn't remove it!
223
- AddressRange InlineRange (Range.LowPC , Range.HighPC );
233
+ AllInlineRanges = ConvertDWARFRanges (RangesOrError.get ());
234
+ uint32_t EmptyCount = 0 ;
235
+ for (const AddressRange &InlineRange : AllInlineRanges) {
224
236
// Check for empty inline range in case inline function was outlined
225
237
// or has not code
226
- if (!InlineRange.empty ()) {
227
- if (parent.Ranges .contains (InlineRange)) {
238
+ if (InlineRange.empty ()) {
239
+ ++EmptyCount;
240
+ } else {
241
+ if (Parent.Ranges .contains (InlineRange)) {
228
242
II.Ranges .insert (InlineRange);
229
- } else if (Log) {
230
- *Log << " error: inlined function DIE at " << HEX32 (Die.getOffset ())
231
- << " has a range [" << HEX64 (Range.LowPC ) << " - "
232
- << HEX64 (Range.HighPC ) << " ) that isn't contained in any "
233
- << " parent address ranges, this inline range will be "
234
- " removed.\n " ;
243
+ } else {
244
+ // Only warn if the current inline range is not within any of all
245
+ // of the parent ranges. If we have a DW_TAG_subpgram with multiple
246
+ // ranges we will emit a FunctionInfo for each range of that
247
+ // function that only emits information within the current range,
248
+ // so we only want to emit an error if the DWARF has issues, not
249
+ // when a range currently just isn't in the range we are currently
250
+ // parsing for.
251
+ if (AllParentRanges.contains (InlineRange)) {
252
+ WarnIfEmpty = false ;
253
+ } else if (Log) {
254
+ *Log << " error: inlined function DIE at "
255
+ << HEX32 (Die.getOffset ()) << " has a range ["
256
+ << HEX64 (InlineRange.start ()) << " - "
257
+ << HEX64 (InlineRange.end ()) << " ) that isn't contained in "
258
+ << " any parent address ranges, this inline range will be "
259
+ " removed.\n " ;
260
+ }
235
261
}
236
262
}
237
263
}
264
+ // If we have all empty ranges for the inlines, then don't warn if we
265
+ // have an empty InlineInfo at the top level as all inline functions
266
+ // were elided.
267
+ if (EmptyCount == AllInlineRanges.size ())
268
+ WarnIfEmpty = false ;
238
269
}
239
270
if (II.Ranges .empty ())
240
271
return ;
@@ -246,14 +277,16 @@ static void parseInlineInfo(GsymCreator &Gsym, raw_ostream *Log, CUInfo &CUI,
246
277
II.CallLine = dwarf::toUnsigned (Die.find (dwarf::DW_AT_call_line), 0 );
247
278
// parse all children and append to parent
248
279
for (DWARFDie ChildDie : Die.children ())
249
- parseInlineInfo (Gsym, Log, CUI, ChildDie, Depth + 1 , FI, II);
250
- parent.Children .emplace_back (std::move (II));
280
+ parseInlineInfo (Gsym, Log, CUI, ChildDie, Depth + 1 , FI, II,
281
+ AllInlineRanges, WarnIfEmpty);
282
+ Parent.Children .emplace_back (std::move (II));
251
283
return ;
252
284
}
253
285
if (Tag == dwarf::DW_TAG_subprogram || Tag == dwarf::DW_TAG_lexical_block) {
254
286
// skip this Die and just recurse down
255
287
for (DWARFDie ChildDie : Die.children ())
256
- parseInlineInfo (Gsym, Log, CUI, ChildDie, Depth + 1 , FI, parent);
288
+ parseInlineInfo (Gsym, Log, CUI, ChildDie, Depth + 1 , FI, Parent,
289
+ AllParentRanges, WarnIfEmpty);
257
290
}
258
291
}
259
292
@@ -381,6 +414,13 @@ void DwarfTransformer::handleDie(raw_ostream *OS, CUInfo &CUI, DWARFDie Die) {
381
414
}
382
415
break ;
383
416
}
417
+ // All ranges for the subprogram DIE in case it has multiple. We need to
418
+ // pass this down into parseInlineInfo so we don't warn about inline
419
+ // ranges that are not in the current subrange of a function when they
420
+ // actually are in another subgrange. We do this because when a function
421
+ // has discontiguos ranges, we create multiple function entries with only
422
+ // the info for that range contained inside of it.
423
+ AddressRanges AllSubprogramRanges = ConvertDWARFRanges (Ranges);
384
424
385
425
// Create a function_info for each range
386
426
for (const DWARFAddressRange &Range : Ranges) {
@@ -422,14 +462,16 @@ void DwarfTransformer::handleDie(raw_ostream *OS, CUInfo &CUI, DWARFDie Die) {
422
462
FunctionInfo FI;
423
463
FI.Range = {Range.LowPC , Range.HighPC };
424
464
FI.Name = *NameIndex;
425
- if (CUI.LineTable ) {
465
+ if (CUI.LineTable )
426
466
convertFunctionLineTable (OS, CUI, Die, Gsym, FI);
427
- }
467
+
428
468
if (hasInlineInfo (Die, 0 )) {
429
469
FI.Inline = InlineInfo ();
430
470
FI.Inline ->Name = *NameIndex;
431
471
FI.Inline ->Ranges .insert (FI.Range );
432
- parseInlineInfo (Gsym, OS, CUI, Die, 0 , FI, *FI.Inline );
472
+ bool WarnIfEmpty = true ;
473
+ parseInlineInfo (Gsym, OS, CUI, Die, 0 , FI, *FI.Inline ,
474
+ AllSubprogramRanges, WarnIfEmpty);
433
475
// Make sure we at least got some valid inline info other than just
434
476
// the top level function. If we didn't then remove the inline info
435
477
// from the function info. We have seen cases where LTO tries to modify
@@ -440,7 +482,7 @@ void DwarfTransformer::handleDie(raw_ostream *OS, CUInfo &CUI, DWARFDie Die) {
440
482
// information object, we will know if we got anything valid from the
441
483
// debug info.
442
484
if (FI.Inline ->Children .empty ()) {
443
- if (OS && !Gsym.isQuiet ()) {
485
+ if (WarnIfEmpty && OS && !Gsym.isQuiet ()) {
444
486
*OS << " warning: DIE contains inline function information that has "
445
487
" no valid ranges, removing inline information:\n " ;
446
488
Die.dump (*OS, 0 , DIDumpOptions::getForSingleDIE ());
0 commit comments