summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2014-02-21 22:50:27 +0000
committerRui Ueyama <ruiu@google.com>2014-02-21 22:50:27 +0000
commita5dc335574b37be8ebeedb42c92651eac4b5fc1b (patch)
treeae7bf5e92ca65c0a01dc0c8751893478dc5468ed
parent27cfe10df89937bed1ab1cdab4d701398b05c6c9 (diff)
downloadbcm5719-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.cpp28
-rw-r--r--lld/test/pecoff/safeseh.test9
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 &registry,
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.
OpenPOWER on IntegriCloud