diff options
| author | Fangrui Song <maskray@google.com> | 2019-06-26 08:09:08 +0000 |
|---|---|---|
| committer | Fangrui Song <maskray@google.com> | 2019-06-26 08:09:08 +0000 |
| commit | ba51fd5664e3e15fbc1d350acdb56b4d8fc52ebc (patch) | |
| tree | 85971b95475bea6bf976f1037ea986042d2c0f84 /lld/ELF/InputSection.cpp | |
| parent | 8bfe0fc1d9b52337baceb89ac39fb58498b17d71 (diff) | |
| download | bcm5719-llvm-ba51fd5664e3e15fbc1d350acdb56b4d8fc52ebc.tar.gz bcm5719-llvm-ba51fd5664e3e15fbc1d350acdb56b4d8fc52ebc.zip | |
Reland D61583 [ELF] Error on relocations to STT_SECTION symbols if the sections were discarded
This restores r361830 "[ELF] Error on relocations to STT_SECTION symbols if the sections were discarded"
and dependent commits (r362218, r362497) which were reverted by r364321, with a fix of a --gdb-index issue.
.rela.debug_ranges contains relocations of range list entries:
// start address of a range list entry
// old: 0; after r361830: 0
00000000000033a0 R_X86_64_64 .text._ZN2v88internal7Isolate7factoryEv + 0
// end address of a range list entry
// old: 0xe; after r361830: 0
00000000000033a8 R_X86_64_64 .text._ZN2v88internal7Isolate7factoryEv + e
If both start and end addresses of a range list entry resolve to 0,
DWARFDebugRangeList::isEndOfListEntry() will return true, then the
.debug_range decoding loop will terminate prematurely:
while (true) {
decode StartAddress
decode EndAddress
if (Entry.isEndOfListEntry()) // prematurely
break;
Entries.push_back(Entry);
}
In lld/ELF/SyntheticSections.cpp, readAddressAreas() will read
incomplete address ranges and the resulting .gdb_index will be
incomplete. For files that gdb hasn't loaded their debug info, gdb uses
.gdb_index to map addresses to CUs. The absent entries make gdb fail to
symbolize some addresses.
To address this issue, we simply allow relocations to undefined symbols
in DWARF.cpp:findAux() and let RelocationResolver resolve them.
This patch should fix:
[1] http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20190603/659848.html
[2] https://bugs.chromium.org/p/chromium/issues/detail?id=978067
llvm-svn: 364391
Diffstat (limited to 'lld/ELF/InputSection.cpp')
| -rw-r--r-- | lld/ELF/InputSection.cpp | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 3e8d093e6d2..d077c017ca7 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -412,7 +412,8 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { for (const RelTy &Rel : Rels) { RelType Type = Rel.getType(Config->IsMips64EL); - Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel); + const ObjFile<ELFT> *File = getFile<ELFT>(); + Symbol &Sym = File->getRelocTargetSym(Rel); auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); Buf += sizeof(RelTy); @@ -435,10 +436,23 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { // .eh_frame is horribly special and can reference discarded sections. To // avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which - // hopefully creates a frame that is ignored at runtime. + // hopefully creates a frame that is ignored at runtime. Also, don't warn + // on .gcc_except_table and debug sections. + // + // See the comment in maybeReportUndefined for PPC64 .toc . auto *D = dyn_cast<Defined>(&Sym); if (!D) { - error("STT_SECTION symbol should be defined"); + if (!Sec->Name.startswith(".debug") && + !Sec->Name.startswith(".zdebug") && Sec->Name != ".eh_frame" && + Sec->Name != ".gcc_except_table" && Sec->Name != ".toc") { + uint32_t SecIdx = cast<Undefined>(Sym).DiscardedSecIdx; + Elf_Shdr_Impl<ELFT> Sec = + CHECK(File->getObj().sections(), File)[SecIdx]; + warn("relocation refers to a discarded section: " + + CHECK(File->getObj().getSectionName(&Sec), File) + + "\n>>> referenced by " + getObjMsg(P->r_offset)); + } + P->setSymbolAndType(0, 0, false); continue; } SectionBase *Section = D->Section->Repl; |

