Skip to content

Commit cda8046

Browse files
committed
[Bolt] Slice debug_str from DWP
1 parent 9a46060 commit cda8046

File tree

1 file changed

+101
-2
lines changed

1 file changed

+101
-2
lines changed

bolt/lib/Rewrite/DWARFRewriter.cpp

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,66 @@ StringRef getSectionName(const SectionRef &Section) {
17231723
return Name;
17241724
}
17251725

1726-
// Extracts an appropriate slice if input is DWP.
1726+
// Exctracts some appropriate slices of .debug_str.dwo from DWP.
1727+
// Updates the .debug_str_offets.dwo for CUs.
1728+
void UpdateStrAndStrOffsets(StringRef StrDWOContent,
1729+
StringRef StrOffsetsContent,
1730+
SmallVectorImpl<StringRef> &StrDWOOutData,
1731+
std::string &StrOffsetsOutData,
1732+
unsigned DwarfVersion, bool IsLittleEndian) {
1733+
const llvm::endianness Endian =
1734+
IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;
1735+
// ignore DWARF64
1736+
const uint64_t HeaderOffset = (DwarfVersion >= 5) ? 8 : 0;
1737+
const uint64_t NumOffsets = (StrOffsetsContent.size() - HeaderOffset) / 4;
1738+
1739+
DataExtractor Extractor(StrOffsetsContent, IsLittleEndian, 0);
1740+
uint64_t ExtractionOffset = HeaderOffset;
1741+
1742+
using StringFragment = DWARFUnitIndex::Entry::SectionContribution;
1743+
auto getStringLength = [](StringRef Content, uint64_t Offset) -> uint64_t {
1744+
size_t NullPos = Content.find('\0', Offset);
1745+
return (NullPos != StringRef::npos) ? (NullPos - Offset + 1) : 0;
1746+
};
1747+
auto isContiguous = [](const StringFragment &Fragment,
1748+
uint64_t NextOffset) -> bool {
1749+
return NextOffset == Fragment.getOffset() + Fragment.getLength();
1750+
};
1751+
std::optional<StringFragment> CurrentFragment;
1752+
uint64_t AccumulatedStrLen = 0;
1753+
for (uint64_t I = 0; I < NumOffsets; ++I) {
1754+
const uint64_t StrOffset = Extractor.getU32(&ExtractionOffset);
1755+
const uint64_t StringLength = getStringLength(StrDWOContent, StrOffset);
1756+
if (!CurrentFragment) {
1757+
// first init
1758+
CurrentFragment = StringFragment(StrOffset, StringLength);
1759+
} else {
1760+
if (isContiguous(*CurrentFragment, StrOffset)) {
1761+
// expand the current fragment
1762+
CurrentFragment->setLength(CurrentFragment->getLength() + StringLength);
1763+
} else {
1764+
// save the current fragment and start a new one
1765+
StrDWOOutData.push_back(StrDWOContent.substr(
1766+
CurrentFragment->getOffset(), CurrentFragment->getLength()));
1767+
CurrentFragment = StringFragment(StrOffset, StringLength);
1768+
}
1769+
}
1770+
if (AccumulatedStrLen != StrOffset) {
1771+
// update str offsets
1772+
if (StrOffsetsOutData.empty())
1773+
StrOffsetsOutData = StrOffsetsContent.str();
1774+
llvm::support::endian::write32(&StrOffsetsOutData[HeaderOffset + I * 4],
1775+
static_cast<uint32_t>(AccumulatedStrLen),
1776+
Endian);
1777+
}
1778+
AccumulatedStrLen += StringLength;
1779+
}
1780+
if (CurrentFragment)
1781+
StrDWOOutData.push_back(StrDWOContent.substr(CurrentFragment->getOffset(),
1782+
CurrentFragment->getLength()));
1783+
}
1784+
1785+
// Exctracts an appropriate slice if input is DWP.
17271786
// Applies patches or overwrites the section.
17281787
std::optional<StringRef> updateDebugData(
17291788
DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
@@ -1888,18 +1947,58 @@ void DWARFRewriter::writeDWOFiles(
18881947
}
18891948
}
18901949

1950+
StringRef StrDWOContent;
1951+
StringRef StrOffsetsContent;
1952+
llvm::SmallVector<StringRef, 3> StrDWOOutData;
1953+
std::string StrOffsetsOutData;
18911954
for (const SectionRef &Section : File->sections()) {
18921955
std::unique_ptr<DebugBufferVector> OutputData;
18931956
StringRef SectionName = getSectionName(Section);
18941957
if (SectionName == "debug_rnglists.dwo")
18951958
continue;
18961959
Expected<StringRef> ContentsExp = Section.getContents();
18971960
assert(ContentsExp && "Invalid contents.");
1961+
if (IsDWP && SectionName == "debug_str.dwo") {
1962+
StrDWOContent = *ContentsExp;
1963+
continue;
1964+
}
18981965
if (std::optional<StringRef> OutData = updateDebugData(
18991966
(*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
19001967
*Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
1901-
LocWriter, StrOffstsWriter, StrWriter, OverridenSections))
1968+
LocWriter, StrOffstsWriter, StrWriter, OverridenSections)) {
1969+
if (IsDWP && SectionName == "debug_str_offsets.dwo") {
1970+
StrOffsetsContent = *OutData;
1971+
continue;
1972+
}
19021973
Streamer->emitBytes(*OutData);
1974+
}
1975+
}
1976+
1977+
if (IsDWP) {
1978+
// Handling both .debug_str.dwo and .debug_str_offsets.dwo concurrently. In
1979+
// the original DWP, .debug_str is a deduplicated global table, and the
1980+
// .debug_str.dwo slice for a single CU needs to be extracted according to
1981+
// .debug_str_offsets.dwo.
1982+
UpdateStrAndStrOffsets(StrDWOContent, StrOffsetsContent, StrDWOOutData,
1983+
StrOffsetsOutData, CU.getVersion(),
1984+
(*DWOCU)->getContext().isLittleEndian());
1985+
auto SectionIter = KnownSections.find("debug_str.dwo");
1986+
if (SectionIter != KnownSections.end()) {
1987+
Streamer->switchSection(SectionIter->second.first);
1988+
for (size_t i = 0; i < StrDWOOutData.size(); ++i) {
1989+
StringRef OutData = StrDWOOutData[i];
1990+
if (!OutData.empty())
1991+
Streamer->emitBytes(OutData);
1992+
}
1993+
}
1994+
SectionIter = KnownSections.find("debug_str_offsets.dwo");
1995+
if (SectionIter != KnownSections.end()) {
1996+
Streamer->switchSection(SectionIter->second.first);
1997+
if (!StrOffsetsOutData.empty())
1998+
Streamer->emitBytes(StrOffsetsOutData);
1999+
else
2000+
Streamer->emitBytes(StrOffsetsContent);
2001+
}
19032002
}
19042003
Streamer->finish();
19052004
TempOut->keep();

0 commit comments

Comments
 (0)