Skip to content

Commit 97376e9

Browse files
committed
[Bolt] Slice debug_str from DWP
1 parent 98ebb64 commit 97376e9

File tree

1 file changed

+100
-1
lines changed

1 file changed

+100
-1
lines changed

bolt/lib/Rewrite/DWARFRewriter.cpp

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,65 @@ StringRef getSectionName(const SectionRef &Section) {
17251725
return Name;
17261726
}
17271727

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

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

0 commit comments

Comments
 (0)