diff options
Diffstat (limited to 'COFF/Writer.cpp')
| -rw-r--r-- | COFF/Writer.cpp | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp index fb1f3cae5bb2..d32577b361fa 100644 --- a/COFF/Writer.cpp +++ b/COFF/Writer.cpp @@ -181,7 +181,7 @@ void OutputSection::addChunk(Chunk *C) { uint64_t Off = Header.VirtualSize; Off = alignTo(Off, C->getAlign()); C->setRVA(Off); - C->setOutputSectionOff(Off); + C->OutputSectionOff = Off; Off += C->getSize(); Header.VirtualSize = Off; if (C->hasData()) @@ -210,16 +210,46 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { } } -uint64_t Defined::getSecrel() { - if (auto *D = dyn_cast<DefinedRegular>(this)) - return getRVA() - D->getChunk()->getOutputSection()->getRVA(); - fatal("SECREL relocation points to a non-regular symbol"); +uint32_t Defined::getSecrel() { + assert(this); + switch (kind()) { + case DefinedRegularKind: + return cast<DefinedRegular>(this)->getSecrel(); + case DefinedCommonKind: + return cast<DefinedCommon>(this)->getSecrel(); + case DefinedSyntheticKind: + return cast<DefinedSynthetic>(this)->getSecrel(); + default: + break; + } + fatal("SECREL relocation points to a non-regular symbol: " + toString(*this)); +} + +uint32_t DefinedRegular::getSecrel() { + assert(getChunk()->isLive() && "relocation against discarded section"); + uint64_t Diff = getRVA() - getChunk()->getOutputSection()->getRVA(); + assert(Diff < UINT32_MAX && "section offset too large"); + return (uint32_t)Diff; } -uint64_t Defined::getSectionIndex() { +uint16_t Defined::getSectionIndex() { if (auto *D = dyn_cast<DefinedRegular>(this)) return D->getChunk()->getOutputSection()->SectionIndex; - fatal("SECTION relocation points to a non-regular symbol"); + if (isa<DefinedAbsolute>(this)) + return DefinedAbsolute::OutputSectionIndex; + if (auto *D = dyn_cast<DefinedCommon>(this)) + return D->getSectionIndex(); + if (auto *D = dyn_cast<DefinedSynthetic>(this)) { + if (!D->getChunk()) + return 0; + return D->getChunk()->getOutputSection()->SectionIndex; + } + fatal("SECTION relocation points to a non-regular symbol: " + + toString(*this)); +} + +uint16_t DefinedCommon::getSectionIndex() { + return Data->getOutputSection()->SectionIndex; } bool Defined::isExecutable() { @@ -345,12 +375,19 @@ void Writer::createMiscChunks() { for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) { if (!File->SEHCompat) return; - for (SymbolBody *B : File->SEHandlers) - Handlers.insert(cast<Defined>(B)); + for (SymbolBody *B : File->SEHandlers) { + // Make sure the handler is still live. Assume all handlers are regular + // symbols. + auto *D = dyn_cast<DefinedRegular>(B); + if (D && D->getChunk()->isLive()) + Handlers.insert(D); + } } - SEHTable = make<SEHTableChunk>(Handlers); - RData->addChunk(SEHTable); + if (!Handlers.empty()) { + SEHTable = make<SEHTableChunk>(Handlers); + RData->addChunk(SEHTable); + } } // Create .idata section for the DLL-imported symbol table. @@ -442,12 +479,15 @@ size_t Writer::addEntryToStringTable(StringRef Str) { Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { // Relative symbols are unrepresentable in a COFF symbol table. - if (isa<DefinedRelative>(Def)) + if (isa<DefinedSynthetic>(Def)) return None; - if (auto *D = dyn_cast<DefinedRegular>(Def)) - if (!D->getChunk()->isLive()) + if (auto *D = dyn_cast<DefinedRegular>(Def)) { + // Don't write dead symbols or symbols in codeview sections to the symbol + // table. + if (!D->getChunk()->isLive() || D->getChunk()->isCodeView()) return None; + } if (auto *Sym = dyn_cast<DefinedImportData>(Def)) if (!Sym->File->Live) @@ -599,6 +639,15 @@ template <typename PEHeaderTy> void Writer::writeHeader() { auto *PE = reinterpret_cast<PEHeaderTy *>(Buf); Buf += sizeof(*PE); PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32; + + // If {Major,Minor}LinkerVersion is left at 0.0, then for some + // reason signing the resulting PE file with Authenticode produces a + // signature that fails to validate on Windows 7 (but is OK on 10). + // Set it to 14.0, which is what VS2015 outputs, and which avoids + // that problem. + PE->MajorLinkerVersion = 14; + PE->MinorLinkerVersion = 0; + PE->ImageBase = Config->ImageBase; PE->SectionAlignment = PageSize; PE->FileAlignment = SectorSize; @@ -743,10 +792,13 @@ void Writer::openFile(StringRef Path) { void Writer::fixSafeSEHSymbols() { if (!SEHTable) return; - if (auto *T = dyn_cast<DefinedRelative>(Config->SEHTable->body())) - T->setRVA(SEHTable->getRVA()); - if (auto *C = dyn_cast<DefinedAbsolute>(Config->SEHCount->body())) - C->setVA(SEHTable->getSize() / 4); + // Replace the absolute table symbol with a synthetic symbol pointing to the + // SEHTable chunk so that we can emit base relocations for it and resolve + // section relative relocations. + Symbol *T = Symtab->find("___safe_se_handler_table"); + Symbol *C = Symtab->find("___safe_se_handler_count"); + replaceBody<DefinedSynthetic>(T, T->body()->getName(), SEHTable); + cast<DefinedAbsolute>(C->body())->setVA(SEHTable->getSize() / 4); } // Handles /section options to allow users to overwrite @@ -762,6 +814,10 @@ void Writer::setSectionPermissions() { // Write section contents to a mmap'ed file. void Writer::writeSections() { + // Record the section index that should be used when resolving a section + // relocation against an absolute symbol. + DefinedAbsolute::OutputSectionIndex = OutputSections.size() + 1; + uint8_t *Buf = Buffer->getBufferStart(); for (OutputSection *Sec : OutputSections) { uint8_t *SecBuf = Buf + Sec->getFileOff(); |
