[PECOFF] Support -fixed command line option to disable base relocations.
authorRui Ueyama <ruiu@google.com>
Tue, 23 Jul 2013 01:29:50 +0000 (01:29 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 23 Jul 2013 01:29:50 +0000 (01:29 +0000)
llvm-svn: 186911

lld/include/lld/ReaderWriter/PECOFFTargetInfo.h
lld/lib/Driver/WinLinkDriver.cpp
lld/lib/Driver/WinLinkOptions.td
lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
lld/test/pecoff/base-reloc.test
lld/unittests/DriverTests/WinLinkDriverTest.cpp

index a7a7a8c..5194d1f 100644 (file)
@@ -28,7 +28,7 @@ public:
       : _baseAddress(0x400000), _stackReserve(1024 * 1024), _stackCommit(4096),
         _heapReserve(1024 * 1024), _heapCommit(4096),
         _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), _minOSVersion(6, 0),
-        _nxCompat(true), _largeAddressAware(false) {}
+        _nxCompat(true), _largeAddressAware(false), _baseRelocationEnabled(true) {}
 
   struct OSVersion {
     OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
@@ -78,9 +78,12 @@ public:
   void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
   bool getNxCompat() const { return _nxCompat; }
 
-  void setLargeAddressAware(bool option) { _largeAddressAware = option; }
+  void setLargeAddressAware(bool val) { _largeAddressAware = val; }
   bool getLargeAddressAware() const { return _largeAddressAware; }
 
+  void setBaseRelocationEnabled(bool val) { _baseRelocationEnabled = val; }
+  bool getBaseRelocationEnabled() const { return _baseRelocationEnabled; }
+
   virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
   virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
 
@@ -104,6 +107,7 @@ private:
   OSVersion _minOSVersion;
   bool _nxCompat;
   bool _largeAddressAware;
+  bool _baseRelocationEnabled;
 
   std::vector<StringRef> _inputSearchPaths;
   mutable std::unique_ptr<Reader> _reader;
index c7a73d1..33689b3 100644 (file)
@@ -324,7 +324,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
   if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_entry))
     info.setEntrySymbolName(arg->getValue());
 
-  // Hanlde -libpath
+  // Handle -libpath
   for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_libpath),
                                ie = parsedArgs->filtered_end();
        it != ie; ++it) {
@@ -335,15 +335,19 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
   if (parsedArgs->getLastArg(OPT_force))
     info.setAllowRemainingUndefines(true);
 
-  // Hanlde -nxcompat:no
+  // Handle -nxcompat:no
   if (parsedArgs->getLastArg(OPT_no_nxcompat))
     info.setNxCompat(false);
 
-  // Hanlde -largeaddressaware
+  // Handle -largeaddressaware
   if (parsedArgs->getLastArg(OPT_largeaddressaware))
     info.setLargeAddressAware(true);
 
-  // Hanlde -out
+  // Handle -fixed
+  if (parsedArgs->getLastArg(OPT_fixed))
+    info.setBaseRelocationEnabled(false);
+
+  // Handle -out
   if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_out))
     info.setOutputPath(outpath->getValue());
 
index e63f83f..f6ef1a8 100644 (file)
@@ -50,5 +50,10 @@ def largeaddressaware : Flag<["-", "/"], "largeaddressaware">,
 def no_largeaddressaware : Flag<["-", "/"], "largeaddressaware:no">,
     HelpText<"Disable large addresses">;
 
+def fixed : Flag<["-", "/"], "fixed">,
+    HelpText<"Disable base relocations">;
+def no_fixed : Flag<["-", "/"], "fixed:no">,
+    HelpText<"Enable base relocations">;
+
 def help : Flag<["-", "/"], "help">;
 def help_q : Flag<["-", "/"], "?">, Alias<help>;
index 89f6dbd..2c08b10 100644 (file)
@@ -698,7 +698,9 @@ public:
     auto *text = new TextSectionChunk(linkedFile);
     auto *rdata = new RDataSectionChunk(linkedFile);
     auto *data = new DataSectionChunk(linkedFile);
-    auto *baseReloc = new BaseRelocChunk(linkedFile);
+    BaseRelocChunk *baseReloc = nullptr;
+    if (_PECOFFTargetInfo.getBaseRelocationEnabled())
+      baseReloc = new BaseRelocChunk(linkedFile);
 
     addChunk(dosStub);
     addChunk(peHeader);
@@ -717,11 +719,13 @@ public:
     // Now that we know the addresses of all defined atoms that needs to be
     // relocated. So we can create the ".reloc" section which contains all the
     // relocation sites.
-    baseReloc->setContents(_chunks);
-    if (baseReloc->size()) {
-      dataDirectory->setBaseRelocField(baseReloc->getSectionRva(),
-                                       baseReloc->rawSize());
-      addSectionChunk(baseReloc, sectionTable);
+    if (baseReloc) {
+      baseReloc->setContents(_chunks);
+      if (baseReloc->size()) {
+        dataDirectory->setBaseRelocField(baseReloc->getSectionRva(),
+                                         baseReloc->rawSize());
+        addSectionChunk(baseReloc, sectionTable);
+      }
     }
 
     setImageSizeOnDisk();
index 55377c3..a1161de 100644 (file)
@@ -1,7 +1,10 @@
 # RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
 #
 # RUN: lld -flavor link -out %t1 -subsystem console -force -- %t.obj \
-# RUN:   && llvm-objdump -s %t1 | FileCheck %s
+# RUN:   && llvm-objdump -s %t1 | FileCheck %s --check-prefix=BASEREL
+#
+# RUN: lld -flavor link -out %t1 -subsystem console -force -fixed -- %t.obj \
+# RUN:   && llvm-objdump -s %t1 | FileCheck %s --check-prefix=NOBASEREL
 
 # Because llvm-objdump cannot pretty-print the contents of .reloc section, we
 # have no choice other than comparing the result with this binary blob.
@@ -9,5 +12,7 @@
 # TODO: Improve llvm-objdump to pretty print .reloc section as GNU binutil
 # objdump does.
 
-CHECK: Contents of section .reloc:
-CHECK-NEXT:  3000 00100000 0c000000 07300c30 00000000  .........0.0....
+BASEREL: Contents of section .reloc:
+BASEREL-NEXT:  3000 00100000 0c000000 07300c30 00000000  .........0.0....
+
+NOBASEREL-NOT: Contents of section .reloc:
index ebf5771..1070399 100644 (file)
@@ -42,6 +42,8 @@ TEST_F(WinLinkParserTest, Basic) {
   EXPECT_EQ("b.obj", inputFile(1));
   EXPECT_EQ("c.obj", inputFile(2));
   EXPECT_TRUE(_info.getInputSearchPaths().empty());
+
+  // Unspecified flags will have default values.
   EXPECT_EQ(6, _info.getMinOSVersion().majorVersion);
   EXPECT_EQ(0, _info.getMinOSVersion().minorVersion);
   EXPECT_EQ((uint64_t)0x400000, _info.getBaseAddress());
@@ -50,6 +52,7 @@ TEST_F(WinLinkParserTest, Basic) {
   EXPECT_FALSE(_info.allowRemainingUndefines());
   EXPECT_TRUE(_info.getNxCompat());
   EXPECT_FALSE(_info.getLargeAddressAware());
+  EXPECT_TRUE(_info.getBaseRelocationEnabled());
 }
 
 TEST_F(WinLinkParserTest, WindowsStyleOption) {
@@ -148,6 +151,15 @@ TEST_F(WinLinkParserTest, NoLargeAddressAware) {
   EXPECT_FALSE(_info.getLargeAddressAware());
 }
 
+TEST_F(WinLinkParserTest, Fixed) {
+  EXPECT_FALSE(parse("link.exe", "-fixed", "a.out", nullptr));
+  EXPECT_FALSE(_info.getBaseRelocationEnabled());
+}
+
+TEST_F(WinLinkParserTest, NoFixed) {
+  EXPECT_FALSE(parse("link.exe", "-fixed:no", "a.out", nullptr));
+  EXPECT_TRUE(_info.getBaseRelocationEnabled());
+}
 
 TEST_F(WinLinkParserTest, NoInputFiles) {
   EXPECT_TRUE(parse("link.exe", nullptr));