[BOLT] Strip debug sections by default

Summary:
We used to ignore debug sections by default, but we kept them in the
binary which led to invalid debug information in the output. It's better
to strip debug info and print a warning to the user.

Note: we are not updating debug info by default due to high memory
requirements for large applications.

(cherry picked from FBD15128947)
This commit is contained in:
Maksim Panchenko 2019-04-26 15:30:12 -07:00
parent 21ee0e98c7
commit 2b1523362e
3 changed files with 43 additions and 15 deletions

View File

@ -29,18 +29,16 @@ uint8_t *ExecutableFileMemoryManager::allocateSection(intptr_t Size,
StringRef SectionName,
bool IsCode,
bool IsReadOnly) {
// Register as note section (non-allocatable) if we recognize it as so
for (auto &OverwriteName : RewriteInstance::SectionsToOverwrite) {
if (SectionName == OverwriteName) {
uint8_t *DataCopy = new uint8_t[Size];
auto &Section = BC.registerOrUpdateNoteSection(SectionName,
DataCopy,
Size,
Alignment);
Section.setSectionID(SectionID);
assert(!Section.isAllocatable() && "note sections cannot be allocatable");
return DataCopy;
}
// Register a debug section as a note section.
if (RewriteInstance::isDebugSection(SectionName)) {
uint8_t *DataCopy = new uint8_t[Size];
auto &Section = BC.registerOrUpdateNoteSection(SectionName,
DataCopy,
Size,
Alignment);
Section.setSectionID(SectionID);
assert(!Section.isAllocatable() && "note sections cannot be allocatable");
return DataCopy;
}
uint8_t *Ret;

View File

@ -512,6 +512,7 @@ MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch,
}
constexpr const char *RewriteInstance::SectionsToOverwrite[];
constexpr const char *RewriteInstance::DebugSectionsToOverwrite[];
const std::string RewriteInstance::OrgSecPrefix = ".bolt.org";
@ -1720,6 +1721,7 @@ void RewriteInstance::readSpecialSections() {
TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
bool HasTextRelocations = false;
bool HasDebugInfo = false;
// Process special sections.
for (const auto &Section : InputFile->sections()) {
@ -1733,9 +1735,16 @@ void RewriteInstance::readSpecialSections() {
<< " @ 0x" << Twine::utohexstr(Section.getAddress()) << ":0x"
<< Twine::utohexstr(Section.getAddress() + Section.getSize())
<< "\n");
if (isDebugSection(SectionName))
HasDebugInfo = true;
}
}
if (HasDebugInfo && !opts::UpdateDebugSections) {
errs() << "BOLT-WARNING: debug info will be stripped from the binary. "
"Use -update-debug-sections to keep it.\n";
}
HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text");
LSDASection = BC->getUniqueSectionByName(".gcc_except_table");
EHFrameSection = BC->getUniqueSectionByName(".eh_frame");
@ -3763,8 +3772,7 @@ std::string RewriteInstance::getOutputSectionName(const ELFObjType *Obj,
StringRef SectionName =
cantFail(Obj->getSectionName(&Section), "cannot get section name");
if ((Section.sh_flags & ELF::SHF_ALLOC) &&
willOverwriteSection(SectionName))
if ((Section.sh_flags & ELF::SHF_ALLOC) && willOverwriteSection(SectionName))
return OrgSecPrefix + SectionName.str();
return SectionName;
@ -3868,6 +3876,10 @@ std::vector<ELFShdrTy> RewriteInstance::getOutputSections(
StringRef SectionName =
cantFail(Obj->getSectionName(&Section), "cannot get section name");
// Strip debug sections if not updating them.
if (isDebugSection(SectionName) && !opts::UpdateDebugSections)
continue;
auto BSec = BC->getUniqueSectionByName(SectionName);
assert(BSec && "missing section info for non-allocatable section");
@ -4789,7 +4801,18 @@ bool RewriteInstance::willOverwriteSection(StringRef SectionName) {
if (SectionName == OverwriteName)
return true;
}
for (auto &OverwriteName : DebugSectionsToOverwrite) {
if (SectionName == OverwriteName)
return true;
}
auto Section = BC->getUniqueSectionByName(SectionName);
return Section && Section->isAllocatable() && Section->isFinalized();
}
bool RewriteInstance::isDebugSection(StringRef SectionName) {
if (SectionName.startswith(".debug_") || SectionName == ".gdb_index")
return true;
return false;
}

View File

@ -259,11 +259,15 @@ private:
bool shouldDisassemble(BinaryFunction &BF) const;
public:
/// When updating debug info, these are the sections we overwrite.
/// Standard ELF sections we overwrite.
static constexpr const char *SectionsToOverwrite[] = {
".shstrtab",
".symtab",
".strtab",
};
/// Debug section to we overwrite while updating the debug info.
static constexpr const char *DebugSectionsToOverwrite[] = {
".debug_aranges",
".debug_line",
".debug_loc",
@ -271,6 +275,9 @@ public:
".gdb_index",
};
/// Return true if the section holds debug information.
static bool isDebugSection(StringRef SectionName);
using SectionPatchersType =
std::map<std::string, std::unique_ptr<BinaryPatcher>>;