diff options
author | Rui Ueyama <ruiu@google.com> | 2014-02-21 22:50:27 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2014-02-21 22:50:27 +0000 |
commit | a5dc335574b37be8ebeedb42c92651eac4b5fc1b (patch) | |
tree | ae7bf5e92ca65c0a01dc0c8751893478dc5468ed | |
parent | 27cfe10df89937bed1ab1cdab4d701398b05c6c9 (diff) | |
download | bcm5719-llvm-a5dc335574b37be8ebeedb42c92651eac4b5fc1b.tar.gz bcm5719-llvm-a5dc335574b37be8ebeedb42c92651eac4b5fc1b.zip |
[PECOFF] Implement /SAFESEH option.
LLD now prints an error message if /SAFESEH option is specified and one or
more input files are not compatible with SEH.
llvm-svn: 201900
-rw-r--r-- | lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp | 28 | ||||
-rw-r--r-- | lld/test/pecoff/safeseh.test | 9 |
2 files changed, 33 insertions, 4 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index 59b66bb7c2a..e2654be0eaf 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -68,6 +68,7 @@ public: error_code parse(StringMap &altNames); StringRef getLinkerDirectives() const { return _directives; } + bool isCompatibleWithSEH() const { return _compatibleWithSEH; } virtual const atom_collection<DefinedAtom> &defined() const { return _definedAtoms; @@ -136,6 +137,9 @@ private: // The contents of .drectve section. StringRef _directives; + // True if the object has "@feat.00" symbol. + bool _compatibleWithSEH; + // A map from symbol to its name. All symbols should be in this map except // unnamed ones. std::map<const coff_symbol *, StringRef> _symbolName; @@ -317,10 +321,18 @@ error_code FileCOFF::readSymbolTable(vector<const coff_symbol *> &result) { "Cannot atomize IMAGE_SYM_DEBUG!"); result.push_back(sym); - // Cache the name. StringRef name; if (error_code ec = _obj->getSymbolName(sym, name)) return ec; + + // Existence of the symbol @feat.00 indicates that object file is compatible + // with Safe Exception Handling. + if (name == "@feat.00") { + _compatibleWithSEH = true; + continue; + } + + // Cache the name. _symbolName[sym] = name; // Symbol may be followed by auxiliary symbol table records. The aux @@ -778,9 +790,8 @@ error_code FileCOFF::findSection(StringRef name, const coff_section *&result) { return error_code::success(); } } - // Section was not found, but it's not an error. This method returns an - // error - // only when there's a read error. + // Section was not found, but it's not an error. This method returns + // an error only when there's a read error. return error_code::success(); } @@ -930,6 +941,7 @@ public: parseFile(std::unique_ptr<MemoryBuffer> &mb, const Registry ®istry, std::vector<std::unique_ptr<File>> &result) const { // Parse the memory buffer as PECOFF file. + const char *mbName = mb->getBufferIdentifier(); error_code ec; std::unique_ptr<FileCOFF> file(new FileCOFF(std::move(mb), ec)); if (ec) @@ -943,6 +955,14 @@ public: if (error_code ec = file->parse(_context.alternateNames())) return ec; + + // Check for /SAFESEH. + if (_context.requireSEH() && !file->isCompatibleWithSEH()) { + llvm::errs() << "/SAFESEH is specified, but " << mbName + << " is not compatible with SEH.\n"; + return llvm::object::object_error::parse_failed; + } + result.push_back(std::move(file)); return error_code::success(); } diff --git a/lld/test/pecoff/safeseh.test b/lld/test/pecoff/safeseh.test new file mode 100644 index 00000000000..6a919a7026f --- /dev/null +++ b/lld/test/pecoff/safeseh.test @@ -0,0 +1,9 @@ +# "hello.obj" does not have the symbol "@feat.00", so it's not +# compatible with SEH. + +# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj +# RUN: not lld -flavor link /safeseh /out:%t.exe /subsystem:console \ +# RUN: -- %t.obj 2> %t.err +# RUN: FileCheck %s < %t.err + +CHECK: /SAFESEH is specified, but {{.*}} is not compatible with SEH. |