This is an archive of the discontinued LLVM Phabricator instance.

lld-link: Take /SUBSYSTEM into account for automatic /ENTRY detection.
ClosedPublic

Authored by thakis on Aug 5 2018, 1:21 PM.

Details

Reviewers
ruiu
Summary

If /subsystem:windows is passed, link.exe only looks for WinMain and wWinMain, and if /subsystem:console is passed it only looks for main and wmain. lld-link used to look for all 4 in both cases. This patch makes lld-link match link.exe's behavior.

This requires that the subsystem is known by the time findDefaultEntry() gets called. findDefaultEntry() is called before the main link loop, so that the loop can mark the entry point as undefined. That means inferSubsystem() has to be called above the main loop as well. This in turn means /subsystem: from .drectve sections only has an effect on entry point inference for obj files passed to lld-link directly (and not in obj files found later in .lib files). link.exe seems to ignore /subsystem: for obj files from lib files completely (while in lld it's ignored only for entry point detection but it still overrides /subsystem: flags passed on the command line for the value that gets written in the output file).

Also, if the subsytem isn't needed (e.g. when only writing a /def: lib file and not writing a coff file), link.exe doesn't complain if the subsystem isn't known, so both subsystem and entry point handling should be below the early return lld has for that case.

Fixes PR36523.

Diff Detail

Event Timeline

thakis created this revision.Aug 5 2018, 1:21 PM
ruiu added inline comments.Aug 6 2018, 3:21 PM
lld/COFF/Driver.cpp
428–429

This function seems a bit tricky to me especially where a boolean value is used as 0 or 1 to access an array. Maybe something like this would work:

auto Find = [](StringRef X, StringRef Y) {
  return findUnderscoreMangle(Config->NoDefaultLibAll ? Y : X);
};

if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
  if (find("main", "mainCRTStartup"))
    return mangle("main");
  if (find("wmain", "wmainCRTStartup"))
    return mangle("wmain");
}

if (find("WinMain", "WinMainCRTStartup"))
  return mangle("WinMain");
if (find("wWinMain", "wWinMainCRTStartup"))
  return mangle("wWinMain");
return "";
thakis updated this revision to Diff 159513.Aug 7 2018, 8:05 AM
thakis added inline comments.
lld/COFF/Driver.cpp
428–429

I agree the current function is overly clever. Thank you for your suggestion, it much easier tor read. On the other hand it looks a bit repetitive (the entry points each repeat once, and the overall structure is repeated a few times). Since link.exe prints a warning if both main and wmain or both WinMain and wWinMain are present and that's nicer to implement in your version, I went with that (without the lambda, which makes things a bit clever again). Please take another look.

ruiu accepted this revision.Aug 7 2018, 11:23 AM

LGTM

This revision is now accepted and ready to land.Aug 7 2018, 11:23 AM
thakis closed this revision.Aug 7 2018, 12:11 PM

339165, thanks!