diff options
Diffstat (limited to 'lld/COFF/InputFiles.cpp')
-rw-r--r-- | lld/COFF/InputFiles.cpp | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index d9312f633f3..4e5e34c3405 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -25,6 +25,7 @@ using namespace llvm::object; using namespace llvm::support::endian; using llvm::RoundUpToAlignment; using llvm::Triple; +using llvm::support::ulittle32_t; using llvm::sys::fs::file_magic; using llvm::sys::fs::identify_magic; @@ -112,7 +113,9 @@ std::error_code ObjectFile::parse() { // Read section and symbol tables. if (auto EC = initializeChunks()) return EC; - return initializeSymbols(); + if (auto EC = initializeSymbols()) + return EC; + return initializeSEH(); } std::error_code ObjectFile::initializeChunks() { @@ -132,6 +135,10 @@ std::error_code ObjectFile::initializeChunks() { << EC.message() << "\n"; return make_error_code(LLDError::BrokenFile); } + if (Name == ".sxdata") { + SXData = Sec; + continue; + } if (Name == ".drectve") { ArrayRef<uint8_t> Data; COFFObj->getSectionContents(Sec, Data); @@ -214,8 +221,14 @@ Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, if (Sym.isAbsolute()) { COFFObj->getSymbolName(Sym, Name); // Skip special symbols. - if (Name == "@comp.id" || Name == "@feat.00") + if (Name == "@comp.id") return nullptr; + // COFF spec 5.10.1. The .sxdata section. + if (Name == "@feat.00") { + if (Sym.getValue() & 1) + SEHCompat = true; + return nullptr; + } return new (Alloc) DefinedAbsolute(Name, Sym); } if (Sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG) @@ -242,6 +255,22 @@ Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, return B; } +std::error_code ObjectFile::initializeSEH() { + if (!SEHCompat || !SXData) + return std::error_code(); + ArrayRef<uint8_t> A; + COFFObj->getSectionContents(SXData, A); + if (A.size() % 4 != 0) { + llvm::errs() << ".sxdata must be an array of symbol table indices\n"; + return make_error_code(LLDError::BrokenFile); + } + auto *I = reinterpret_cast<const ulittle32_t *>(A.data()); + auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size()); + for (; I != E; ++I) + SEHandlers.insert(SparseSymbolBodies[*I]); + return std::error_code(); +} + MachineTypes ObjectFile::getMachineType() { if (COFFObj) return static_cast<MachineTypes>(COFFObj->getMachine()); |