[BOLT] Fix memory leak in BinarySection (#82520)

The change in #80950 exposed a memory leak in BinarySection. Let
BinarySection manage memory passed via updateContents() unless a valid
SectionID is set indicating that the contents are managed by JITLink.
This commit is contained in:
Maksim Panchenko 2024-02-21 11:54:34 -08:00 committed by GitHub
parent baf6bd303b
commit 5daf2001a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 22 additions and 29 deletions

View File

@ -139,10 +139,7 @@ class BinarySection {
Alignment = NewAlignment;
ELFType = NewELFType;
ELFFlags = NewELFFlags;
OutputSize = NewSize;
OutputContents = StringRef(reinterpret_cast<const char *>(NewData),
NewData ? NewSize : 0);
IsFinalized = true;
updateContents(NewData, NewSize);
}
public:
@ -484,9 +481,18 @@ public:
void flushPendingRelocations(raw_pwrite_stream &OS,
SymbolResolverFuncTy Resolver);
/// Change contents of the section.
void updateContents(const uint8_t *Data, size_t NewSize) {
OutputContents = StringRef(reinterpret_cast<const char *>(Data), NewSize);
/// Change contents of the section. Unless the section has a valid SectionID,
/// the memory passed in \p NewData will be managed by the instance of
/// BinarySection.
void updateContents(const uint8_t *NewData, size_t NewSize) {
if (getOutputData() && !hasValidSectionID() &&
(!hasSectionRef() ||
OutputContents.data() != getContentsOrQuit(Section).data())) {
delete[] getOutputData();
}
OutputContents = StringRef(reinterpret_cast<const char *>(NewData),
NewData ? NewSize : 0);
OutputSize = NewSize;
IsFinalized = true;
}

View File

@ -190,18 +190,7 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
clearList(PendingRelocations);
}
BinarySection::~BinarySection() {
if (isReordered()) {
delete[] getData();
return;
}
if (!isAllocatable() && !hasValidSectionID() &&
(!hasSectionRef() ||
OutputContents.data() != getContentsOrQuit(Section).data())) {
delete[] getOutputData();
}
}
BinarySection::~BinarySection() { updateContents(nullptr, 0); }
void BinarySection::clearRelocations() { clearList(Relocations); }

View File

@ -4092,12 +4092,9 @@ void RewriteInstance::rewriteNoteSections() {
return getNewValueForSymbol(S->getName());
});
// Set/modify section info.
BinarySection &NewSection = BC->registerOrUpdateNoteSection(
SectionName, SectionData, Size, Section.sh_addralign,
!BSec->isWritable(), BSec->getELFType());
NewSection.setOutputAddress(0);
NewSection.setOutputFileOffset(NextAvailableOffset);
// Section contents are no longer needed, but we need to update the size so
// that it will be reflected in the section header table.
BSec->updateContents(nullptr, Size);
NextAvailableOffset += Size;
}

View File

@ -77,10 +77,11 @@ TEST_P(BinaryContextTester, FlushPendingRelocCALL26) {
// 12: bl func2
// 16: func2
char Data[20] = {};
constexpr size_t DataSize = 20;
uint8_t *Data = new uint8_t[DataSize];
BinarySection &BS = BC->registerOrUpdateSection(
".text", ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC,
(uint8_t *)Data, sizeof(Data), 4);
".text", ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, Data,
DataSize, 4);
MCSymbol *RelSymbol1 = BC->getOrCreateGlobalSymbol(4, "Func1");
ASSERT_TRUE(RelSymbol1);
BS.addRelocation(8, RelSymbol1, ELF::R_AARCH64_CALL26, 0, 0, true);
@ -89,7 +90,7 @@ TEST_P(BinaryContextTester, FlushPendingRelocCALL26) {
BS.addRelocation(12, RelSymbol2, ELF::R_AARCH64_CALL26, 0, 0, true);
std::error_code EC;
SmallVector<char> Vect(sizeof(Data));
SmallVector<char> Vect(DataSize);
raw_svector_ostream OS(Vect);
BS.flushPendingRelocations(OS, [&](const MCSymbol *S) {