@@ -413,33 +413,43 @@ Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
413413}
414414
415415static void writeNewOffsetsTo (MCStreamer &Out, DataExtractor &Data,
416- DenseMap<uint64_t , uint32_t > &OffsetRemapping,
417- uint64_t &Offset, uint64_t &Size) {
416+ DenseMap<uint64_t , uint64_t > &OffsetRemapping,
417+ uint64_t &Offset, const uint64_t Size,
418+ uint32_t OldOffsetSize, uint32_t NewOffsetSize) {
418419
419420 while (Offset < Size) {
420- auto OldOffset = Data.getU32 (&Offset);
421- auto NewOffset = OffsetRemapping[OldOffset];
422- Out.emitIntValue (NewOffset, 4 );
421+ const uint64_t OldOffset = Data.getUnsigned (&Offset, OldOffsetSize);
422+ const uint64_t NewOffset = OffsetRemapping[OldOffset];
423+ assert (NewOffsetSize == 8 || NewOffset <= UINT32_MAX);
424+ Out.emitIntValue (NewOffset, NewOffsetSize);
423425 }
424426}
425427
426428void writeStringsAndOffsets (MCStreamer &Out, DWPStringPool &Strings,
427429 MCSection *StrOffsetSection,
428430 StringRef CurStrSection,
429- StringRef CurStrOffsetSection, uint16_t Version) {
431+ StringRef CurStrOffsetSection, uint16_t Version,
432+ SectionLengths &SectionLength) {
430433 // Could possibly produce an error or warning if one of these was non-null but
431434 // the other was null.
432435 if (CurStrSection.empty () || CurStrOffsetSection.empty ())
433436 return ;
434437
435- DenseMap<uint64_t , uint32_t > OffsetRemapping;
438+ DenseMap<uint64_t , uint64_t > OffsetRemapping;
436439
437440 DataExtractor Data (CurStrSection, true , 0 );
438441 uint64_t LocalOffset = 0 ;
439442 uint64_t PrevOffset = 0 ;
443+
444+ // Keep track if any new string offsets exceed UINT32_MAX. If any do, we can
445+ // emit a DWARF64 .debug_str_offsets table for this compile unit.
446+ uint32_t OldOffsetSize = 4 ;
447+ uint32_t NewOffsetSize = 4 ;
440448 while (const char *S = Data.getCStr (&LocalOffset)) {
441- OffsetRemapping[PrevOffset] =
442- Strings.getOffset (S, LocalOffset - PrevOffset);
449+ uint64_t NewOffset = Strings.getOffset (S, LocalOffset - PrevOffset);
450+ OffsetRemapping[PrevOffset] = NewOffset;
451+ if (NewOffset > UINT32_MAX)
452+ NewOffsetSize = 8 ;
443453 PrevOffset = LocalOffset;
444454 }
445455
@@ -451,7 +461,7 @@ void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
451461 uint64_t Size = CurStrOffsetSection.size ();
452462 if (Version > 4 ) {
453463 while (Offset < Size) {
454- uint64_t HeaderSize = debugStrOffsetsHeaderSize (Data, Version);
464+ const uint64_t HeaderSize = debugStrOffsetsHeaderSize (Data, Version);
455465 assert (HeaderSize <= Size - Offset &&
456466 " StrOffsetSection size is less than its header" );
457467
@@ -461,16 +471,52 @@ void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
461471 if (HeaderSize == 8 ) {
462472 ContributionSize = Data.getU32 (&HeaderLengthOffset);
463473 } else if (HeaderSize == 16 ) {
474+ OldOffsetSize = 8 ;
464475 HeaderLengthOffset += 4 ; // skip the dwarf64 marker
465476 ContributionSize = Data.getU64 (&HeaderLengthOffset);
466477 }
467478 ContributionEnd = ContributionSize + HeaderLengthOffset;
468- Out.emitBytes (Data.getBytes (&Offset, HeaderSize));
469- writeNewOffsetsTo (Out, Data, OffsetRemapping, Offset, ContributionEnd);
479+
480+ StringRef HeaderBytes = Data.getBytes (&Offset, HeaderSize);
481+ if (OldOffsetSize == 4 && NewOffsetSize == 8 ) {
482+ // We had a DWARF32 .debug_str_offsets header, but we need to emit
483+ // some string offsets that require 64 bit offsets on the .debug_str
484+ // section. Emit the .debug_str_offsets header in DWARF64 format so we
485+ // can emit string offsets that exceed UINT32_MAX without truncating
486+ // the string offset.
487+
488+ // 2 bytes for DWARF version, 2 bytes pad.
489+ const uint64_t VersionPadSize = 4 ;
490+ const uint64_t NewLength =
491+ (ContributionSize - VersionPadSize) * 2 + VersionPadSize;
492+ // Emit the DWARF64 length that starts with a 4 byte DW_LENGTH_DWARF64
493+ // value followed by the 8 byte updated length.
494+ Out.emitIntValue (llvm::dwarf::DW_LENGTH_DWARF64, 4 );
495+ Out.emitIntValue (NewLength, 8 );
496+ // Emit DWARF version as a 2 byte integer.
497+ Out.emitIntValue (Version, 2 );
498+ // Emit 2 bytes of padding.
499+ Out.emitIntValue (0 , 2 );
500+ // Update the .debug_str_offsets section length contribution for the
501+ // this .dwo file.
502+ for (auto &Pair : SectionLength) {
503+ if (Pair.first == DW_SECT_STR_OFFSETS) {
504+ Pair.second = NewLength + 12 ;
505+ break ;
506+ }
507+ }
508+ } else {
509+ // Just emit the same .debug_str_offsets header.
510+ Out.emitBytes (HeaderBytes);
511+ }
512+ writeNewOffsetsTo (Out, Data, OffsetRemapping, Offset, ContributionEnd,
513+ OldOffsetSize, NewOffsetSize);
470514 }
471515
472516 } else {
473- writeNewOffsetsTo (Out, Data, OffsetRemapping, Offset, Size);
517+ assert (OldOffsetSize == NewOffsetSize);
518+ writeNewOffsetsTo (Out, Data, OffsetRemapping, Offset, Size, OldOffsetSize,
519+ NewOffsetSize);
474520 }
475521}
476522
@@ -562,7 +608,7 @@ Error handleSection(
562608 std::vector<StringRef> &CurTypesSection,
563609 std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
564610 StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
565- std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
611+ SectionLengths &SectionLength) {
566612 if (Section.isBSS ())
567613 return Error::success ();
568614
@@ -684,7 +730,7 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
684730 // This maps each section contained in this file to its length.
685731 // This information is later on used to calculate the contributions,
686732 // i.e. offset and length, of each compile/type unit to a section.
687- std::vector<std::pair<DWARFSectionKind, uint32_t >> SectionLength;
733+ SectionLengths SectionLength;
688734
689735 for (const auto &Section : Obj.sections ())
690736 if (auto Err = handleSection (
@@ -713,7 +759,7 @@ Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
713759 }
714760
715761 writeStringsAndOffsets (Out, Strings, StrOffsetSection, CurStrSection,
716- CurStrOffsetSection, Header.Version );
762+ CurStrOffsetSection, Header.Version , SectionLength );
717763
718764 for (auto Pair : SectionLength) {
719765 auto Index = getContributionIndex (Pair.first , IndexVersion);
0 commit comments