@@ -246,6 +246,12 @@ static cl::opt<unsigned> BatchSize(
246
246
" Specifies the size of batches for processing CUs. Higher number has "
247
247
" better performance, but more memory usage. Default value is 1." ),
248
248
cl::Hidden, cl::init(1 ), cl::cat(BoltCategory));
249
+
250
+ static cl::opt<bool > AlwaysConvertToRanges (
251
+ " always-convert-to-ranges" ,
252
+ cl::desc (" This option is for testing purposes only. It forces BOLT to "
253
+ " convert low_pc/high_pc to ranges always." ),
254
+ cl::ReallyHidden, cl::init(false ), cl::cat(BoltCategory));
249
255
} // namespace opts
250
256
251
257
static bool getLowAndHighPC (const DIE &Die, const DWARFUnit &DU,
@@ -693,6 +699,45 @@ void DWARFRewriter::updateUnitDebugInfo(
693
699
const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =
694
700
DIEBldr.getDIEsByUnit (Unit);
695
701
702
+ // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
703
+ auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,
704
+ const DIEValue &HighPCVal, uint64_t LowPC,
705
+ const uint64_t HighPC) {
706
+ dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;
707
+ dwarf::Form FormLowPC = dwarf::DW_FORM_addr;
708
+ dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;
709
+ dwarf::Form FormHighPC = dwarf::DW_FORM_data4;
710
+ const uint32_t Size = HighPC - LowPC;
711
+ // Whatever was generated is not low_pc/high_pc, so will reset to
712
+ // default for size 1.
713
+ if (!LowPCVal || !HighPCVal) {
714
+ if (Unit.getVersion () >= 5 )
715
+ FormLowPC = dwarf::DW_FORM_addrx;
716
+ else if (Unit.isDWOUnit ())
717
+ FormLowPC = dwarf::DW_FORM_GNU_addr_index;
718
+ } else {
719
+ AttrLowPC = LowPCVal.getAttribute ();
720
+ FormLowPC = LowPCVal.getForm ();
721
+ AttrHighPC = HighPCVal.getAttribute ();
722
+ FormHighPC = HighPCVal.getForm ();
723
+ }
724
+
725
+ if (FormLowPC == dwarf::DW_FORM_addrx ||
726
+ FormLowPC == dwarf::DW_FORM_GNU_addr_index)
727
+ LowPC = AddrWriter->getIndexFromAddress (LowPC, Unit);
728
+
729
+ if (LowPCVal)
730
+ DIEBldr.replaceValue (Die, AttrLowPC, FormLowPC, DIEInteger (LowPC));
731
+ else
732
+ DIEBldr.addValue (Die, AttrLowPC, FormLowPC, DIEInteger (LowPC));
733
+ if (HighPCVal) {
734
+ DIEBldr.replaceValue (Die, AttrHighPC, FormHighPC, DIEInteger (Size));
735
+ } else {
736
+ DIEBldr.deleteValue (Die, dwarf::DW_AT_ranges);
737
+ DIEBldr.addValue (Die, AttrHighPC, FormHighPC, DIEInteger (Size));
738
+ }
739
+ };
740
+
696
741
for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {
697
742
DIE *Die = DI->Die ;
698
743
switch (Die->getTag ()) {
@@ -726,7 +771,7 @@ void DWARFRewriter::updateUnitDebugInfo(
726
771
ARangesSectionWriter->addCURanges (Unit.getOffset (),
727
772
std::move (OutputRanges));
728
773
updateDWARFObjectAddressRanges (Unit, DIEBldr, *Die, RangesSectionOffset,
729
- 0 , RangesBase);
774
+ RangesBase);
730
775
DIEValue StmtListAttrVal = Die->findAttribute (dwarf::DW_AT_stmt_list);
731
776
if (LineTablePatchMap.count (&Unit))
732
777
DIEBldr.replaceValue (Die, dwarf::DW_AT_stmt_list,
@@ -737,8 +782,9 @@ void DWARFRewriter::updateUnitDebugInfo(
737
782
738
783
case dwarf::DW_TAG_subprogram: {
739
784
// Get function address either from ranges or [LowPC, HighPC) pair.
740
- uint64_t Address;
785
+ uint64_t Address = UINT64_MAX ;
741
786
uint64_t SectionIndex, HighPC;
787
+ DebugAddressRangesVector FunctionRanges;
742
788
if (!getLowAndHighPC (*Die, Unit, Address, HighPC, SectionIndex)) {
743
789
Expected<DWARFAddressRangesVector> RangesOrError =
744
790
getDIEAddressRanges (*Die, Unit);
@@ -751,23 +797,41 @@ void DWARFRewriter::updateUnitDebugInfo(
751
797
if (Ranges.empty ())
752
798
break ;
753
799
754
- Address = Ranges.front ().LowPC ;
800
+ for (const DWARFAddressRange &Range : Ranges) {
801
+ if (const BinaryFunction *Function =
802
+ BC.getBinaryFunctionAtAddress (Range.LowPC ))
803
+ FunctionRanges.append (Function->getOutputAddressRanges ());
804
+ }
805
+ } else {
806
+ if (const BinaryFunction *Function =
807
+ BC.getBinaryFunctionAtAddress (Address))
808
+ FunctionRanges = Function->getOutputAddressRanges ();
755
809
}
756
810
757
811
// Clear cached ranges as the new function will have its own set.
758
812
CachedRanges.clear ();
813
+ DIEValue LowPCVal = Die->findAttribute (dwarf::DW_AT_low_pc);
814
+ DIEValue HighPCVal = Die->findAttribute (dwarf::DW_AT_high_pc);
815
+ if (FunctionRanges.empty ()) {
816
+ if (LowPCVal && HighPCVal) {
817
+ FunctionRanges.push_back ({0 , HighPCVal.getDIEInteger ().getValue ()});
818
+ } else {
819
+ // I haven't seen this case, but who knows what other compilers
820
+ // generate.
821
+ FunctionRanges.push_back ({0 , 1 });
822
+ errs () << " BOLT-WARNING: [internal-dwarf-error]: subprogram got GCed "
823
+ " by the linker, DW_AT_ranges is used\n " ;
824
+ }
825
+ }
759
826
760
- DebugAddressRangesVector FunctionRanges;
761
- if (const BinaryFunction *Function =
762
- BC.getBinaryFunctionAtAddress (Address))
763
- FunctionRanges = Function->getOutputAddressRanges ();
764
-
765
- if (FunctionRanges.empty ())
766
- FunctionRanges.push_back ({0 , 0 });
827
+ if (FunctionRanges.size () == 1 && !opts::AlwaysConvertToRanges) {
828
+ updateLowPCHighPC (Die, LowPCVal, HighPCVal, FunctionRanges.back ().LowPC ,
829
+ FunctionRanges.back ().HighPC );
830
+ break ;
831
+ }
767
832
768
833
updateDWARFObjectAddressRanges (
769
- Unit, DIEBldr, *Die, RangesSectionWriter.addRanges (FunctionRanges),
770
- 0 );
834
+ Unit, DIEBldr, *Die, RangesSectionWriter.addRanges (FunctionRanges));
771
835
772
836
break ;
773
837
}
@@ -783,37 +847,33 @@ void DWARFRewriter::updateUnitDebugInfo(
783
847
? BC.getBinaryFunctionContainingAddress (
784
848
RangesOrError->front ().LowPC )
785
849
: nullptr ;
786
- bool ErrorState = false ;
787
- std::optional<uint64_t > NewLowPC;
850
+ DebugAddressRangesVector OutputRanges;
788
851
if (Function) {
789
- DebugAddressRangesVector OutputRanges =
790
- Function->translateInputToOutputRanges (*RangesOrError);
852
+ OutputRanges = Function->translateInputToOutputRanges (*RangesOrError);
791
853
LLVM_DEBUG (if (OutputRanges.empty () != RangesOrError->empty ()) {
792
854
dbgs () << " BOLT-DEBUG: problem with DIE at 0x"
793
855
<< Twine::utohexstr (Die->getOffset ()) << " in CU at 0x"
794
856
<< Twine::utohexstr (Unit.getOffset ()) << ' \n ' ;
795
857
});
796
- if (!OutputRanges.empty ())
797
- NewLowPC = OutputRanges.front ().LowPC ;
798
- RangesSectionOffset = RangesSectionWriter.addRanges (
799
- std::move (OutputRanges), CachedRanges);
858
+ if (opts::AlwaysConvertToRanges || OutputRanges.size () > 1 ) {
859
+ RangesSectionOffset = RangesSectionWriter.addRanges (
860
+ std::move (OutputRanges), CachedRanges);
861
+ OutputRanges.clear ();
862
+ } else if (OutputRanges.empty ()) {
863
+ OutputRanges.push_back ({RangesOrError.get ().front ().LowPC ,
864
+ RangesOrError.get ().front ().HighPC });
865
+ }
800
866
} else if (!RangesOrError) {
801
- ErrorState = true ;
802
867
consumeError (RangesOrError.takeError ());
803
868
}
804
-
805
- uint64_t LowPCToUse = 0 ;
806
- if (!ErrorState && RangesOrError.get ().size () == 1 &&
807
- RangesOrError.get ().begin ()->LowPC ==
808
- RangesOrError.get ().begin ()->HighPC ) {
809
- if (NewLowPC)
810
- LowPCToUse = NewLowPC.value ();
811
- else
812
- LowPCToUse = RangesOrError.get ().begin ()->LowPC ;
869
+ DIEValue LowPCVal = Die->findAttribute (dwarf::DW_AT_low_pc);
870
+ DIEValue HighPCVal = Die->findAttribute (dwarf::DW_AT_high_pc);
871
+ if (OutputRanges.size () == 1 ) {
872
+ updateLowPCHighPC (Die, LowPCVal, HighPCVal, OutputRanges.back ().LowPC ,
873
+ OutputRanges.back ().HighPC );
874
+ break ;
813
875
}
814
-
815
- updateDWARFObjectAddressRanges (Unit, DIEBldr, *Die, RangesSectionOffset,
816
- LowPCToUse);
876
+ updateDWARFObjectAddressRanges (Unit, DIEBldr, *Die, RangesSectionOffset);
817
877
break ;
818
878
}
819
879
case dwarf::DW_TAG_call_site: {
@@ -1147,7 +1207,7 @@ void DWARFRewriter::updateUnitDebugInfo(
1147
1207
1148
1208
void DWARFRewriter::updateDWARFObjectAddressRanges (
1149
1209
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
1150
- uint64_t LowPCToUse, std::optional<uint64_t > RangesBase) {
1210
+ std::optional<uint64_t > RangesBase) {
1151
1211
1152
1212
if (RangesBase) {
1153
1213
// If DW_AT_GNU_ranges_base is present, update it. No further modifications
@@ -1195,7 +1255,7 @@ void DWARFRewriter::updateDWARFObjectAddressRanges(
1195
1255
LowPCAttrInfo.getForm () != dwarf::DW_FORM_GNU_addr_index &&
1196
1256
LowPCAttrInfo.getForm () != dwarf::DW_FORM_addrx)
1197
1257
DIEBldr.replaceValue (&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm (),
1198
- DIEInteger (LowPCToUse ));
1258
+ DIEInteger (0 ));
1199
1259
return ;
1200
1260
}
1201
1261
@@ -1223,8 +1283,7 @@ void DWARFRewriter::updateDWARFObjectAddressRanges(
1223
1283
if (LowPCAttrInfo && HighPCAttrInfo) {
1224
1284
1225
1285
convertToRangesPatchDebugInfo (Unit, DIEBldr, Die, DebugRangesOffset,
1226
- LowPCAttrInfo, HighPCAttrInfo, LowPCToUse,
1227
- RangesBase);
1286
+ LowPCAttrInfo, HighPCAttrInfo, RangesBase);
1228
1287
} else if (!(Unit.isDWOUnit () &&
1229
1288
Die.getTag () == dwarf::DW_TAG_compile_unit)) {
1230
1289
if (opts::Verbosity >= 1 )
@@ -2086,8 +2145,7 @@ DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
2086
2145
void DWARFRewriter::convertToRangesPatchDebugInfo (
2087
2146
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
2088
2147
uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
2089
- DIEValue &HighPCAttrInfo, uint64_t LowPCToUse,
2090
- std::optional<uint64_t > RangesBase) {
2148
+ DIEValue &HighPCAttrInfo, std::optional<uint64_t > RangesBase) {
2091
2149
uint32_t BaseOffset = 0 ;
2092
2150
dwarf::Form LowForm = LowPCAttrInfo.getForm ();
2093
2151
dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
@@ -2120,12 +2178,12 @@ void DWARFRewriter::convertToRangesPatchDebugInfo(
2120
2178
// DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
2121
2179
// when it's absent.
2122
2180
if (LowForm == dwarf::DW_FORM_addrx) {
2123
- const uint32_t Index = AddrWriter->getIndexFromAddress (LowPCToUse , Unit);
2181
+ const uint32_t Index = AddrWriter->getIndexFromAddress (0 , Unit);
2124
2182
DIEBldr.replaceValue (&Die, LowPCAttrInfo.getAttribute (),
2125
2183
LowPCAttrInfo.getForm (), DIEInteger (Index));
2126
2184
} else
2127
2185
DIEBldr.replaceValue (&Die, LowPCAttrInfo.getAttribute (),
2128
- LowPCAttrInfo.getForm (), DIEInteger (LowPCToUse ));
2186
+ LowPCAttrInfo.getForm (), DIEInteger (0 ));
2129
2187
2130
2188
// Original CU didn't have DW_AT_*_base. We converted it's children (or
2131
2189
// dwo), so need to insert it into CU.
0 commit comments