[PATCH][lld][PECOFF] Add Support for entry point symbol name

Jesús Serrano dagonoweda at gmail.com
Mon Aug 12 12:49:08 PDT 2013


On 31/07/2013 2:13, Reid Kleckner wrote:
> On Tue, Jul 30, 2013 at 4:12 PM, Chandler Carruth 
> <chandlerc at google.com <mailto:chandlerc at google.com>> wrote:
>
>
>     On Tue, Jul 30, 2013 at 3:46 PM, Jesús Serrano García
>     <dagonoweda at gmail.com <mailto:dagonoweda at gmail.com>> wrote:
>
>>         Looks like the entry function name should be _mainCRTStartup
>>         if subsystem is "console",
>>         _WinMainCRTStartup if subsystem is "windows", and
>>         "__DllMainCRTStartup" for DLL.
>>         See
>>         http://msdn.microsoft.com/en-us/library/f9t8842e(v=vs.80).aspx <http://msdn.microsoft.com/en-us/library/f9t8842e%28v=vs.80%29.aspx>.
>         I think this is rather a Visual Studio convention for its C
>         runtime library, and the PECOFF spec says nothing about it, so
>         I though that "_main" is a good default entry point name,
>         taking into account that there is currently no CRT guidelines
>         (or at least I'm unaware of them) in the lld project.
>
>
>     Sorry for the ambiguity, but the goal of all the PECOFF work in
>     LLD is to support linking in a compatible way for Windows. If you
>     have another usecase for linking PECOFF, you should raise that on
>     the discussion list (not the commit list) as it'll need a separate
>     design from what we're currently working on.
>
>     For now, as Rui has said, we should follow the MSDN spec he cited.
>
>
> Maybe the driver should call setEntrySymbolName() with a default if 
> the user didn't specify anything.  Then the link.exe driver could use 
> the Microsoft name and the GNU ld driver can use main / _main.
I've attached a new patch with this changes. Now the windows driver sets 
the entry symbol name according to the corresponding options. However, 
this won't work in all cases. Depending onwhether the crt is compiled as 
multibyte or unicode, the entry point symbol name changes from 
"mainCRTStartup" to "wmainCRTStartup", and the same for the windows 
subsystem. The problem with this is that the use of unicode is unknown 
at link time (or at least I don't know how to retrieve this option from 
object files). One possible solution would be to have two entry point 
names in the linking context, and find a symbol mathing any of them, but 
I don't like it so much. Any ideas on this?

Also, I'd like to add some tests for this feature, but I'm still 
learning how the test system works.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130812/8b811145/attachment.html>
-------------- next part --------------
diff --git include/lld/ReaderWriter/PECOFFLinkingContext.h include/lld/ReaderWriter/PECOFFLinkingContext.h
index 7112126..a6ea859 100644
--- include/lld/ReaderWriter/PECOFFLinkingContext.h
+++ include/lld/ReaderWriter/PECOFFLinkingContext.h
@@ -29,7 +29,8 @@ public:
         _heapReserve(1024 * 1024), _heapCommit(4096),
         _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), _minOSVersion(6, 0),
         _nxCompat(true), _largeAddressAware(false),
-        _baseRelocationEnabled(true), _terminalServerAware(true) {}
+        _baseRelocationEnabled(true), _terminalServerAware(true),
+        _imageType(ImageType::IMAGE_EXE) {}
 
   struct OSVersion {
     OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
@@ -37,6 +38,11 @@ public:
     int minorVersion;
   };
 
+  enum ImageType {
+    IMAGE_EXE,
+    IMAGE_DLL
+  };
+
   virtual error_code
   parseFile(std::unique_ptr<MemoryBuffer> &mb,
             std::vector<std::unique_ptr<File> > &result) const;
@@ -93,6 +99,9 @@ public:
   virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
   virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
 
+  void setImageType(ImageType type) { _imageType = type; }
+  ImageType getImageType() const { return _imageType; }
+
   StringRef allocateString(const StringRef &ref) {
     char *x = _alloc.Allocate<char>(ref.size() + 1);
     memcpy(x, ref.data(), ref.size());
@@ -115,6 +124,7 @@ private:
   bool _largeAddressAware;
   bool _baseRelocationEnabled;
   bool _terminalServerAware;
+  ImageType _imageType;
 
   std::vector<StringRef> _inputSearchPaths;
   mutable std::unique_ptr<Reader> _reader;
diff --git lib/Driver/WinLinkDriver.cpp lib/Driver/WinLinkDriver.cpp
index d7ee924..9250267 100644
--- lib/Driver/WinLinkDriver.cpp
+++ lib/Driver/WinLinkDriver.cpp
@@ -270,6 +270,22 @@ void processLibEnv(PECOFFLinkingContext &context) {
       context.appendInputSearchPath(context.allocateString(path));
 }
 
+// Sets a default entry point symbol name depending on context image type and
+// subsystem. These default names are MS CRT compliant.
+void setDefaultEntrySymbolName(PECOFFLinkingContext &context)
+{
+  if (context.getImageType() == PECOFFLinkingContext::ImageType::IMAGE_DLL)
+    context.setEntrySymbolName("_DllMainCRTStartup");
+  else {
+    llvm::COFF::WindowsSubsystem subsystem = context.getSubsystem();
+    if (subsystem == llvm::COFF::WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_GUI)
+      context.setEntrySymbolName("WinMainCRTStartup");
+    else if (subsystem == 
+      llvm::COFF::WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_CUI)
+      context.setEntrySymbolName("mainCRTStartup");
+  }
+}
+
 // Parses the given command line options and returns the result. Returns NULL if
 // there's an error in the options.
 std::unique_ptr<llvm::opt::InputArgList> parseArgs(int argc, const char *argv[],
@@ -356,6 +372,8 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
   // handle /entry
   if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_entry))
     context.setEntrySymbolName(arg->getValue());
+  else
+    setDefaultEntrySymbolName(context);
 
   // handle /libpath
   for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_libpath),
diff --git lib/ReaderWriter/PECOFF/WriterPECOFF.cpp lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
index f9402e2..8a53ab7 100644
--- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -248,6 +248,10 @@ public:
 
   virtual void setSizeOfImage(uint32_t size) { _peHeader.SizeOfImage = size; }
 
+  virtual void setAddressOfEntryPoint(uint32_t address) { 
+    _peHeader.AddressOfEntryPoint = address; 
+  }
+
 private:
   llvm::object::coff_file_header _coffHeader;
   llvm::object::pe32_header _peHeader;
@@ -356,6 +360,13 @@ public:
       layout->_virtualAddr += rva;
   }
 
+  uint64_t getAtomVirtualAddress(StringRef name) {
+    for (auto atomLayout : _atomLayouts)
+      if (atomLayout->_atom->name() == name)
+        return atomLayout->_virtualAddr;
+    return 0;
+  }
+
   static bool classof(const Chunk *c) {
     Kind kind = c->getKind();
     return kind == kindSection || kind == kindDataDirectory;
@@ -794,6 +805,8 @@ public:
     peHeader->setSizeOfUninitializedData(bss->size());
     peHeader->setNumberOfSections(_numSections);
     peHeader->setSizeOfImage(_imageSizeInMemory);
+
+    setAddressOfEntryPoint(text, peHeader);
   }
 
   virtual error_code writeFile(const File &linkedFile, StringRef path) {
@@ -853,6 +866,21 @@ private:
     }
   }
 
+  void setAddressOfEntryPoint(TextSectionChunk *text, PEHeaderChunk *peHeader) {
+    // Find the virtual address of the entry point symbol if any.
+    // PECOFF spec says that entry point for dll images is optional, in which
+    // case it must be set to 0.
+    if (_PECOFFLinkingContext.entrySymbolName().empty() && 
+        _PECOFFLinkingContext.getImageType() == PECOFFLinkingContext::IMAGE_DLL)
+      peHeader->setAddressOfEntryPoint(0);
+    else {
+      uint64_t entryPointAddress = text->getAtomVirtualAddress(
+        _PECOFFLinkingContext.entrySymbolName()); 
+      if (entryPointAddress != 0)
+        peHeader->setAddressOfEntryPoint(entryPointAddress);
+    }
+  }
+
   std::vector<std::unique_ptr<Chunk>> _chunks;
   const PECOFFLinkingContext &_PECOFFLinkingContext;
   uint32_t _numSections;


More information about the llvm-commits mailing list