<div dir="ltr"><div dir="ltr">On Mon, Mar 18, 2019 at 8:02 PM Rui Ueyama <<a href="mailto:ruiu@google.com">ruiu@google.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Thu, Mar 14, 2019 at 1:05 PM bd1976 llvm via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Thu, Mar 14, 2019 at 6:27 PM Peter Collingbourne <<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 14, 2019 at 6:08 AM bd1976 llvm via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>At Sony we offer autolinking as a feature in our ELF toolchain. We would like to see full support for this feature upstream as there is anecdotal evidence that it would find use beyond Sony.</div><div><br></div><div>In general autolinking (<a href="https://en.wikipedia.org/wiki/Auto-linking" target="_blank">https://en.wikipedia.org/wiki/Auto-linking</a>) allows developers to specify inputs to the linker in their source code. LLVM and Clang already have support for autolinking on ELF via embedding strings, which specify linker behavior, into a .linker-options section in relocatable object files, see:</div><div><br></div><div>RFC - <a href="http://lists.llvm.org/pipermail/llvm-dev/2018-January/120101.html" target="_blank">http://lists.llvm.org/pipermail/llvm-dev/2018-January/120101.html</a></div><div>LLVM -  <a href="https://llvm.org/docs/Extensions.html#linker-options-section-linker-options" target="_blank">https://llvm.org/docs/Extensions.html#linker-options-section-linker-options</a>, <a href="https://reviews.llvm.org/D40849" target="_blank">https://reviews.llvm.org/D40849</a> </div><div>Clang - <a href="https://clang.llvm.org/docs/LanguageExtensions.html#specifying-linker-options-on-elf-targets" target="_blank">https://clang.llvm.org/docs/LanguageExtensions.html#specifying-linker-options-on-elf-targets</a>, <a href="https://reviews.llvm.org/D42758" target="_blank">https://reviews.llvm.org/D42758</a> </div><div><br></div><div>However, although support was added to Clang and LLVM, no support has been implemented in LLD; and, I get the sense, from reading the reviews, that there wasn't agreement on the implementation when the changes landed. The original motivation seems to have been to remove the "autolink-extract" mechanism used by Swift to workaround the lack of autolinking support for ELF. However, looking at the Swift source code, Swift still seems to be using the "autolink-extract" method.</div><div><br></div><div>So my first question: Are there any users of the current implementation for ELF?</div><div><br></div><div>Assuming that no one is using the current code, I would like to suggest a different mechanism for autolinking.</div><div><br></div><div>For ELF we need limited autolinking support. Specifically, we only need support for "comment lib" pragmas (<a href="https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=vs-2017" target="_blank">https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=vs-2017</a>) in C/C++ e.g. #pragma comment(lib, "foo"). My suggestion that we keep the implementation as lean as possible.</div><div><br></div><div>Principles to guide the implementation:</div><div>- Developers should be able to easily understand autolinking behavior.</div><div>- Developers should be able to override autolinking from the linker command line.</div><div>- Inputs specified via pragmas should be handled in a general way to allow the same source code to work in different environments.</div><div><br></div><div>I would like to propose that we focus on autolinking exclusively and that we divorce the implementation from the idea of "linker options" which, by nature, would tie source code to the vagaries of particular linkers. I don't see much value in supporting other linker operations so I suggest that the binary representation be a mergable string section (SHF_MERGE, SHF_STRINGS), called .autolink, with custom type SHT_LLVM_AUTOLINK (0x6fff4c04), and SHF_EXCLUDE set (to avoid the contents appearing in the output). The compiler can form this section by concatenating the arguments of the "comment lib" pragmas in the order they are encountered. Partial (-r, -Ur) links can be handled by concatenating .autolink sections with the normal mergeable string section rules. The current .linker-options can remain (or be removed); but, "comment lib" pragmas for ELF should be lowered to .autolink not to .linker-options. This makes sense as there is no linker option that "comment lib" pragmas map directly to. As an example, #pragma comment(lib, "foo") would result in:</div><div><br></div><div>.section ".autolink","eMS",@llvm_autolink,1</div><div>        .asciz "foo"</div><div><br></div><div>For LTO, equivalent information to the contents of a the .autolink section will be written to the IRSymtab so that it is available to the linker for symbol resolution.</div><div><br></div><div>The linker will process the .autolink strings in the following way:</div><div><br></div><div>1. Inputs from the .autolink sections of a relocatable object file are added when the linker decides to include that file (which could itself be in a library) in the link. Autolinked inputs behave as if they were appended to the command line as a group after all other options. As a consequence the set of autolinked libraries are searched last to resolve symbols.</div></div></div></blockquote><div><br></div><div>If we want this to be compatible with GNU linkers, doesn't the autolinked input need to appear at the point immediately after the object file appears in the link? I'm imagining the case where you have a statically linked libc as well as a libbar.a autolinked from a foo.o. The link command line would look like this:</div><div><br></div><div>ld foo.o -lc</div><div><br></div><div>Now foo.o autolinks against bar. The command line becomes:</div><div><br></div><div>ld foo.o -lc -lbar</div></div></div></blockquote><div><br></div><div>Actually, I was thinking that on a GNU linker the command line would become "ld foo.o -lc -( -lbar )-"; but, this doesn't affect your point.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><div>If libbar.a requires an additional object file from libc.a, it will not be added to the link.</div><div><br></div></div></div></blockquote><div><br></div><div>As it stands all the dependencies of an autolinked library must themselves be autolinked. I had imagined that this is a reasonable limitation. If not we need another scheme. I try to think about some motivating examples for this.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>2. It is an error if a file cannot be found for a given string.</div><div>3. Any command line options in effect at the end of the command line parsing apply to autolinked inputs, e.g. --whole-archive.</div><div>4. Duplicate autolinked inputs are ignored.</div></div></div></blockquote><div><br></div><div>This seems like it would work in GNU linkers, as long as the autolinked file is added to the link immediately after the last mention, rather than the first. Otherwise a command line like:</div><div><br></div><div>ld foo1.o foo2.o</div><div><br></div><div>(where foo1.o and foo2.o both autolink bar) could end up looking like:</div><div><br></div><div>ld foo1.o -lbar foo2.o</div><div><br></div><div>and you will not link anything from libbar.a that only foo2.o requires. It may end up being simpler to not ignore duplicates.</div></div></div></blockquote><div><br></div><div>Correct; but, given that the proposal was to handle the libraries as if they are appended to the link line after everything on the command line then I think this will work. With deduplication (and the use of SHF_MERGE) developers get no ordering guarantees. I claim that this is a feature! My rationale is that the order in which libraries are linked affects different linkers in different ways (e.g. LLD does not resolve symbols from archives in a compatible manner with either the Microsoft linker or the GNU linkers.), by not allowing the user to control the order I am essentially saying that autolinking is not suitable for libraries that offer competing copies of the same symbol. This ties into my argument that "comment lib" pragmas should be handled in as "general" a way as possible.</div></div></div></div></div></div></div></div></div></blockquote><div><br></div><div>Right. I think if you need a fine control over the link order, autolinking is not a feature you want to use. Or, in general, if your program is sensitive to a link order because its source object files have competing symbols of the same name, it's perhaps unnecessarily fragile.</div><div><br></div><div>That being said, I think you need to address the issue that pcc pointed out. If you statically link a program `foo` with the following command line</div><div><br></div><div>  ld -o foo foo.o -lc</div><div><br></div><div>, `foo.o` auto-imports libbar.a, and libbar.a depends on libc.a, can your proposed feature pull out object files needed for libbar.a?</div></div></div></blockquote><div><br></div><div>It won't work on GNU linkers. It will work with LLD as LLD has MSVC-like archive handling. However, I would like to make sure that whatever we come up with can be supported in the GNU toolchain.</div><div><br></div><div>I had thought that it would be acceptable that all the dependencies of an autolinked library must themselves be autolinked in order to work on GNU style linkers. Having thought more, I don't like this limitation - especially as it doesn't exist for Microsoft style linkers. One possible resolution could be that GNU linkers might have to implement another command line option e.g. --auto-dep=<file> to allow injection into the group of autolinked libraries.<br></div><div><br></div><div>i.e In pcc's example you would need to do: "ld foo.o --auto-dep=libc.a" which would become "ld --start-group libbar.a libc.a --end-group" with autolinking.</div><div><br></div><div>I wanted to avoid the approach of inserting autolinked libraries after the object that autolinks them. In LLD (and MSVC) it becomes hard to reason about "where" the linker is in the command line and it would also mean that we can't have the nice separation between parsing the command line and doing the rest of the link that we currently have. Also, if you give people a way to have a fine grained control over the link order with autolinking you risk ending up with source code that will link on GNU style linkers but not with LLD (assuming GNU ever implemented support for autolinking).</div><div><br></div><div>Scenario:</div><div><br></div><div>libbar.a(bar.o) - defines symbol bar</div><div>libfoo.a(foo.o) - defines foo and autolinks libbar.a</div><div>main.o - references foo</div><div>another.o - does not reference foo</div><div>No references to bar exist</div><div><br></div><div>lld -lfoo another.o --whole-archive main.o with autolinking becomes lld -lfoo another.o --whole-archive main.o -lbar result: bar.o gets added to the link.<br></div><div class="gmail_quote">But, if a change is made so that another.o references bar then the link line with autolinking becomes lld -lfoo another.o -lbar --whole-archive main.o result: bar.o is not added to the link.</div><div><br></div><div>Hopefully the above scenario demonstrates why I think that it becomes too complicated to reason about the effects of autolinking with pcc's proposed insertion scheme.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>5. The linker tries to add a library or relocatable object file from each of the strings in a .autolink section by; first, handling the string as if it was specified on the commandline; second, by looking for the string in each of the library search paths in turn; third, by looking for a lib<string>.a or lib<string>.so (depending on the current mode of the linker) in each of the library search paths. </div></div></div></blockquote><div><br></div><div>Is the second part necessary? "-l:foo" causes the linker to search for a file named "foo" in the library search path, so it seems that allowing the autolink string to look like ":foo" would satisfy this use case.</div></div></div></blockquote><div><br></div><div><br></div><div>I worded the proposal to avoid mapping "comment lib" pragmas to --library command line options. My reasons:<br></div><div><br></div><div>1. I find the requirement that the user put ':' in their lib strings slightly awkward. It means that the source code is now coupled to a GNU-style linker. So then this isn't merely an ELF linking proposal, it's a proposal for ELF toolchains with GNU-like linkers (e.g. the arm linker doesn't support the colon prefix <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474c/Cjahbdei.html" target="_blank">http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474c/Cjahbdei.html</a>).</div><div><br></div><div>2. The syntax is #pragma comment(lib, ...) not #pragma linker-option(library, ...) i.e. the only thing this (frankly rather bizarre) syntax definitely implies is that the argument is related to libraries (and comments ¯\_(ツ)_/¯); it is a bit of a stretch to interpret "comment lib" pragmas as mapping directly to "specifying an additional --library command line option".</div><div><br></div><div>AFAIK all linkers support two ways of specifying inputs; firstly, directly on the command line; secondly, with an option with very similar semantics to GNU's --library option. I choose a method of finding a input files that encompasses both methods of specifying a library on the command line. I think that this method is actually more intuitive than either the method used by the linker script INPUT command or by --library. FWIW, I looked into the history of the colon prefix. It was added in <a href="https://www.sourceware.org/ml/binutils/2007-03/msg00421.html" target="_blank">https://www.sourceware.org/ml/binutils/2007-03/msg00421.html</a>. Unfortunately, the rationale given is that it was merely a port of a vxworks linker extension. I couldn't trace the history any further than that to find the actual design discussion. The linker script command INPUT uses a different scheme and the command already had this search order 20 years ago, which is the earliest version of the GNU linker I have history for; again, the rationale is not available.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>6. A new command line option --no-llvm-autolink will tell LLD to ignore the .autolink sections.</div><div><br></div><div>Rationale for the above points:</div><div><br></div><div>1. Adding the autolinked inputs last makes the process simple to understand from a developers perspective. All linkers are able to implement this scheme.</div><div>2. Error-ing for libraries that are not found seems like better behavior than failing the link during symbol resolution.</div><div>3. It seems useful for the user to be able to apply command line options which will affect all of the autolinked input files. There is a potential problem of surprise for developers, who might not realize that these options would apply to the "invisible" autolinked input files; however, despite the potential for surprise, this is easy for developers to reason about and gives developers the control that they may require.</div><div>4. Unlike on the command line it is probably easy to include the same input file twice via pragmas and might be a pain to fix; think of Third-party libraries supplied as binaries.</div><div>5. This algorithm takes into account all of the different ways that ELF linkers find input files. The different search methods are tried by the linker in most obvious to least obvious order.</div><div>6. I considered adding finer grained control over which .autolink inputs were ignored (e.g. MSVC has /nodefaultlib:<library>); however, I concluded that this is not necessary: if finer control is required developers can recreate the same effect autolinking would have had using command line options.</div><div><br></div><div>Thoughts?</div><div><br></div></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail-m_2221753019524292884gmail-m_3655744095190252507gmail-m_-5762841330346382240gmail_signature"><div dir="ltr">-- <div>Peter</div></div></div></div>
</blockquote></div></div></div></div></div></div></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>
</blockquote></div></div>