annotate lld/docs/NewLLD.rst @ 154:f7e988d3e4cc

fix def file
author anatofuz
date Wed, 11 Mar 2020 19:23:03 +0900
parents 1d019706d866
children 0572611fdcc8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 The ELF, COFF and Wasm Linkers
anatofuz
parents:
diff changeset
2 ==============================
anatofuz
parents:
diff changeset
3
anatofuz
parents:
diff changeset
4 The ELF Linker as a Library
anatofuz
parents:
diff changeset
5 ---------------------------
anatofuz
parents:
diff changeset
6
anatofuz
parents:
diff changeset
7 You can embed LLD to your program by linking against it and calling the linker's
anatofuz
parents:
diff changeset
8 entry point function lld::elf::link.
anatofuz
parents:
diff changeset
9
anatofuz
parents:
diff changeset
10 The current policy is that it is your responsibility to give trustworthy object
anatofuz
parents:
diff changeset
11 files. The function is guaranteed to return as long as you do not pass corrupted
anatofuz
parents:
diff changeset
12 or malicious object files. A corrupted file could cause a fatal error or SEGV.
anatofuz
parents:
diff changeset
13 That being said, you don't need to worry too much about it if you create object
anatofuz
parents:
diff changeset
14 files in the usual way and give them to the linker. It is naturally expected to
anatofuz
parents:
diff changeset
15 work, or otherwise it's a linker's bug.
anatofuz
parents:
diff changeset
16
anatofuz
parents:
diff changeset
17 Design
anatofuz
parents:
diff changeset
18 ======
anatofuz
parents:
diff changeset
19
anatofuz
parents:
diff changeset
20 We will describe the design of the linkers in the rest of the document.
anatofuz
parents:
diff changeset
21
anatofuz
parents:
diff changeset
22 Key Concepts
anatofuz
parents:
diff changeset
23 ------------
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 Linkers are fairly large pieces of software.
anatofuz
parents:
diff changeset
26 There are many design choices you have to make to create a complete linker.
anatofuz
parents:
diff changeset
27
anatofuz
parents:
diff changeset
28 This is a list of design choices we've made for ELF and COFF LLD.
anatofuz
parents:
diff changeset
29 We believe that these high-level design choices achieved a right balance
anatofuz
parents:
diff changeset
30 between speed, simplicity and extensibility.
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 * Implement as native linkers
anatofuz
parents:
diff changeset
33
anatofuz
parents:
diff changeset
34 We implemented the linkers as native linkers for each file format.
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 The linkers share the same design but share very little code.
anatofuz
parents:
diff changeset
37 Sharing code makes sense if the benefit is worth its cost.
anatofuz
parents:
diff changeset
38 In our case, the object formats are different enough that we thought the layer
anatofuz
parents:
diff changeset
39 to abstract the differences wouldn't be worth its complexity and run-time
anatofuz
parents:
diff changeset
40 cost. Elimination of the abstract layer has greatly simplified the
anatofuz
parents:
diff changeset
41 implementation.
anatofuz
parents:
diff changeset
42
anatofuz
parents:
diff changeset
43 * Speed by design
anatofuz
parents:
diff changeset
44
anatofuz
parents:
diff changeset
45 One of the most important things in archiving high performance is to
anatofuz
parents:
diff changeset
46 do less rather than do it efficiently.
anatofuz
parents:
diff changeset
47 Therefore, the high-level design matters more than local optimizations.
anatofuz
parents:
diff changeset
48 Since we are trying to create a high-performance linker,
anatofuz
parents:
diff changeset
49 it is very important to keep the design as efficient as possible.
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 Broadly speaking, we do not do anything until we have to do it.
anatofuz
parents:
diff changeset
52 For example, we do not read section contents or relocations
anatofuz
parents:
diff changeset
53 until we need them to continue linking.
anatofuz
parents:
diff changeset
54 When we need to do some costly operation (such as looking up
anatofuz
parents:
diff changeset
55 a hash table for each symbol), we do it only once.
anatofuz
parents:
diff changeset
56 We obtain a handle (which is typically just a pointer to actual data)
anatofuz
parents:
diff changeset
57 on the first operation and use it throughout the process.
anatofuz
parents:
diff changeset
58
anatofuz
parents:
diff changeset
59 * Efficient archive file handling
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 LLD's handling of archive files (the files with ".a" file extension) is
anatofuz
parents:
diff changeset
62 different from the traditional Unix linkers and similar to Windows linkers.
anatofuz
parents:
diff changeset
63 We'll describe how the traditional Unix linker handles archive files, what the
anatofuz
parents:
diff changeset
64 problem is, and how LLD approached the problem.
anatofuz
parents:
diff changeset
65
anatofuz
parents:
diff changeset
66 The traditional Unix linker maintains a set of undefined symbols during
anatofuz
parents:
diff changeset
67 linking. The linker visits each file in the order as they appeared in the
anatofuz
parents:
diff changeset
68 command line until the set becomes empty. What the linker would do depends on
anatofuz
parents:
diff changeset
69 file type.
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 - If the linker visits an object file, the linker links object files to the
anatofuz
parents:
diff changeset
72 result, and undefined symbols in the object file are added to the set.
anatofuz
parents:
diff changeset
73
anatofuz
parents:
diff changeset
74 - If the linker visits an archive file, it checks for the archive file's
anatofuz
parents:
diff changeset
75 symbol table and extracts all object files that have definitions for any
anatofuz
parents:
diff changeset
76 symbols in the set.
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 This algorithm sometimes leads to a counter-intuitive behavior. If you give
anatofuz
parents:
diff changeset
79 archive files before object files, nothing will happen because when the linker
anatofuz
parents:
diff changeset
80 visits archives, there is no undefined symbols in the set. As a result, no
anatofuz
parents:
diff changeset
81 files are extracted from the first archive file, and the link is done at that
anatofuz
parents:
diff changeset
82 point because the set is empty after it visits one file.
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 You can fix the problem by reordering the files,
anatofuz
parents:
diff changeset
85 but that cannot fix the issue of mutually-dependent archive files.
anatofuz
parents:
diff changeset
86
anatofuz
parents:
diff changeset
87 Linking mutually-dependent archive files is tricky. You may specify the same
anatofuz
parents:
diff changeset
88 archive file multiple times to let the linker visit it more than once. Or,
anatofuz
parents:
diff changeset
89 you may use the special command line options, `--start-group` and
anatofuz
parents:
diff changeset
90 `--end-group`, to let the linker loop over the files between the options until
anatofuz
parents:
diff changeset
91 no new symbols are added to the set.
anatofuz
parents:
diff changeset
92
anatofuz
parents:
diff changeset
93 Visiting the same archive files multiple times makes the linker slower.
anatofuz
parents:
diff changeset
94
anatofuz
parents:
diff changeset
95 Here is how LLD approaches the problem. Instead of memorizing only undefined
anatofuz
parents:
diff changeset
96 symbols, we program LLD so that it memorizes all symbols. When it sees an
anatofuz
parents:
diff changeset
97 undefined symbol that can be resolved by extracting an object file from an
anatofuz
parents:
diff changeset
98 archive file it previously visited, it immediately extracts the file and links
anatofuz
parents:
diff changeset
99 it. It is doable because LLD does not forget symbols it has seen in archive
anatofuz
parents:
diff changeset
100 files.
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 We believe that LLD's way is efficient and easy to justify.
anatofuz
parents:
diff changeset
103
anatofuz
parents:
diff changeset
104 The semantics of LLD's archive handling are different from the traditional
anatofuz
parents:
diff changeset
105 Unix's. You can observe it if you carefully craft archive files to exploit
anatofuz
parents:
diff changeset
106 it. However, in reality, we don't know any program that cannot link with our
anatofuz
parents:
diff changeset
107 algorithm so far, so it's not going to cause trouble.
anatofuz
parents:
diff changeset
108
anatofuz
parents:
diff changeset
109 Numbers You Want to Know
anatofuz
parents:
diff changeset
110 ------------------------
anatofuz
parents:
diff changeset
111
anatofuz
parents:
diff changeset
112 To give you intuition about what kinds of data the linker is mainly working on,
anatofuz
parents:
diff changeset
113 I'll give you the list of objects and their numbers LLD has to read and process
anatofuz
parents:
diff changeset
114 in order to link a very large executable. In order to link Chrome with debug
anatofuz
parents:
diff changeset
115 info, which is roughly 2 GB in output size, LLD reads
anatofuz
parents:
diff changeset
116
anatofuz
parents:
diff changeset
117 - 17,000 files,
anatofuz
parents:
diff changeset
118 - 1,800,000 sections,
anatofuz
parents:
diff changeset
119 - 6,300,000 symbols, and
anatofuz
parents:
diff changeset
120 - 13,000,000 relocations.
anatofuz
parents:
diff changeset
121
anatofuz
parents:
diff changeset
122 LLD produces the 2 GB executable in 15 seconds.
anatofuz
parents:
diff changeset
123
anatofuz
parents:
diff changeset
124 These numbers vary depending on your program, but in general,
anatofuz
parents:
diff changeset
125 you have a lot of relocations and symbols for each file.
anatofuz
parents:
diff changeset
126 If your program is written in C++, symbol names are likely to be
anatofuz
parents:
diff changeset
127 pretty long because of name mangling.
anatofuz
parents:
diff changeset
128
anatofuz
parents:
diff changeset
129 It is important to not waste time on relocations and symbols.
anatofuz
parents:
diff changeset
130
anatofuz
parents:
diff changeset
131 In the above case, the total amount of symbol strings is 450 MB,
anatofuz
parents:
diff changeset
132 and inserting all of them to a hash table takes 1.5 seconds.
anatofuz
parents:
diff changeset
133 Therefore, if you causally add a hash table lookup for each symbol,
anatofuz
parents:
diff changeset
134 it would slow down the linker by 10%. So, don't do that.
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 On the other hand, you don't have to pursue efficiency
anatofuz
parents:
diff changeset
137 when handling files.
anatofuz
parents:
diff changeset
138
anatofuz
parents:
diff changeset
139 Important Data Structures
anatofuz
parents:
diff changeset
140 -------------------------
anatofuz
parents:
diff changeset
141
anatofuz
parents:
diff changeset
142 We will describe the key data structures in LLD in this section. The linker can
anatofuz
parents:
diff changeset
143 be understood as the interactions between them. Once you understand their
anatofuz
parents:
diff changeset
144 functions, the code of the linker should look obvious to you.
anatofuz
parents:
diff changeset
145
anatofuz
parents:
diff changeset
146 * Symbol
anatofuz
parents:
diff changeset
147
anatofuz
parents:
diff changeset
148 This class represents a symbol.
anatofuz
parents:
diff changeset
149 They are created for symbols in object files or archive files.
anatofuz
parents:
diff changeset
150 The linker creates linker-defined symbols as well.
anatofuz
parents:
diff changeset
151
anatofuz
parents:
diff changeset
152 There are basically three types of Symbols: Defined, Undefined, or Lazy.
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 - Defined symbols are for all symbols that are considered as "resolved",
anatofuz
parents:
diff changeset
155 including real defined symbols, COMDAT symbols, common symbols,
anatofuz
parents:
diff changeset
156 absolute symbols, linker-created symbols, etc.
anatofuz
parents:
diff changeset
157 - Undefined symbols represent undefined symbols, which need to be replaced by
anatofuz
parents:
diff changeset
158 Defined symbols by the resolver until the link is complete.
anatofuz
parents:
diff changeset
159 - Lazy symbols represent symbols we found in archive file headers
anatofuz
parents:
diff changeset
160 which can turn into Defined if we read archive members.
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 There's only one Symbol instance for each unique symbol name. This uniqueness
anatofuz
parents:
diff changeset
163 is guaranteed by the symbol table. As the resolver reads symbols from input
anatofuz
parents:
diff changeset
164 files, it replaces an existing Symbol with the "best" Symbol for its symbol
anatofuz
parents:
diff changeset
165 name using the placement new.
anatofuz
parents:
diff changeset
166
anatofuz
parents:
diff changeset
167 The above mechanism allows you to use pointers to Symbols as a very cheap way
anatofuz
parents:
diff changeset
168 to access name resolution results. Assume for example that you have a pointer
anatofuz
parents:
diff changeset
169 to an undefined symbol before name resolution. If the symbol is resolved to a
anatofuz
parents:
diff changeset
170 defined symbol by the resolver, the pointer will "automatically" point to the
anatofuz
parents:
diff changeset
171 defined symbol, because the undefined symbol the pointer pointed to will have
anatofuz
parents:
diff changeset
172 been replaced by the defined symbol in-place.
anatofuz
parents:
diff changeset
173
anatofuz
parents:
diff changeset
174 * SymbolTable
anatofuz
parents:
diff changeset
175
anatofuz
parents:
diff changeset
176 SymbolTable is basically a hash table from strings to Symbols
anatofuz
parents:
diff changeset
177 with logic to resolve symbol conflicts. It resolves conflicts by symbol type.
anatofuz
parents:
diff changeset
178
anatofuz
parents:
diff changeset
179 - If we add Defined and Undefined symbols, the symbol table will keep the
anatofuz
parents:
diff changeset
180 former.
anatofuz
parents:
diff changeset
181 - If we add Defined and Lazy symbols, it will keep the former.
anatofuz
parents:
diff changeset
182 - If we add Lazy and Undefined, it will keep the former,
anatofuz
parents:
diff changeset
183 but it will also trigger the Lazy symbol to load the archive member
anatofuz
parents:
diff changeset
184 to actually resolve the symbol.
anatofuz
parents:
diff changeset
185
anatofuz
parents:
diff changeset
186 * Chunk (COFF specific)
anatofuz
parents:
diff changeset
187
anatofuz
parents:
diff changeset
188 Chunk represents a chunk of data that will occupy space in an output.
anatofuz
parents:
diff changeset
189 Each regular section becomes a chunk.
anatofuz
parents:
diff changeset
190 Chunks created for common or BSS symbols are not backed by sections.
anatofuz
parents:
diff changeset
191 The linker may create chunks to append additional data to an output as well.
anatofuz
parents:
diff changeset
192
anatofuz
parents:
diff changeset
193 Chunks know about their size, how to copy their data to mmap'ed outputs,
anatofuz
parents:
diff changeset
194 and how to apply relocations to them.
anatofuz
parents:
diff changeset
195 Specifically, section-based chunks know how to read relocation tables
anatofuz
parents:
diff changeset
196 and how to apply them.
anatofuz
parents:
diff changeset
197
anatofuz
parents:
diff changeset
198 * InputSection (ELF specific)
anatofuz
parents:
diff changeset
199
anatofuz
parents:
diff changeset
200 Since we have less synthesized data for ELF, we don't abstract slices of
anatofuz
parents:
diff changeset
201 input files as Chunks for ELF. Instead, we directly use the input section
anatofuz
parents:
diff changeset
202 as an internal data type.
anatofuz
parents:
diff changeset
203
anatofuz
parents:
diff changeset
204 InputSection knows about their size and how to copy themselves to
anatofuz
parents:
diff changeset
205 mmap'ed outputs, just like COFF Chunks.
anatofuz
parents:
diff changeset
206
anatofuz
parents:
diff changeset
207 * OutputSection
anatofuz
parents:
diff changeset
208
anatofuz
parents:
diff changeset
209 OutputSection is a container of InputSections (ELF) or Chunks (COFF).
anatofuz
parents:
diff changeset
210 An InputSection or Chunk belongs to at most one OutputSection.
anatofuz
parents:
diff changeset
211
anatofuz
parents:
diff changeset
212 There are mainly three actors in this linker.
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 * InputFile
anatofuz
parents:
diff changeset
215
anatofuz
parents:
diff changeset
216 InputFile is a superclass of file readers.
anatofuz
parents:
diff changeset
217 We have a different subclass for each input file type,
anatofuz
parents:
diff changeset
218 such as regular object file, archive file, etc.
anatofuz
parents:
diff changeset
219 They are responsible for creating and owning Symbols and InputSections/Chunks.
anatofuz
parents:
diff changeset
220
anatofuz
parents:
diff changeset
221 * Writer
anatofuz
parents:
diff changeset
222
anatofuz
parents:
diff changeset
223 The writer is responsible for writing file headers and InputSections/Chunks to
anatofuz
parents:
diff changeset
224 a file. It creates OutputSections, put all InputSections/Chunks into them,
anatofuz
parents:
diff changeset
225 assign unique, non-overlapping addresses and file offsets to them, and then
anatofuz
parents:
diff changeset
226 write them down to a file.
anatofuz
parents:
diff changeset
227
anatofuz
parents:
diff changeset
228 * Driver
anatofuz
parents:
diff changeset
229
anatofuz
parents:
diff changeset
230 The linking process is driven by the driver. The driver:
anatofuz
parents:
diff changeset
231
anatofuz
parents:
diff changeset
232 - processes command line options,
anatofuz
parents:
diff changeset
233 - creates a symbol table,
anatofuz
parents:
diff changeset
234 - creates an InputFile for each input file and puts all symbols within into
anatofuz
parents:
diff changeset
235 the symbol table,
anatofuz
parents:
diff changeset
236 - checks if there's no remaining undefined symbols,
anatofuz
parents:
diff changeset
237 - creates a writer,
anatofuz
parents:
diff changeset
238 - and passes the symbol table to the writer to write the result to a file.
anatofuz
parents:
diff changeset
239
anatofuz
parents:
diff changeset
240 Link-Time Optimization
anatofuz
parents:
diff changeset
241 ----------------------
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 LTO is implemented by handling LLVM bitcode files as object files.
anatofuz
parents:
diff changeset
244 The linker resolves symbols in bitcode files normally. If all symbols
anatofuz
parents:
diff changeset
245 are successfully resolved, it then runs LLVM passes
anatofuz
parents:
diff changeset
246 with all bitcode files to convert them to one big regular ELF/COFF file.
anatofuz
parents:
diff changeset
247 Finally, the linker replaces bitcode symbols with ELF/COFF symbols,
anatofuz
parents:
diff changeset
248 so that they are linked as if they were in the native format from the beginning.
anatofuz
parents:
diff changeset
249
anatofuz
parents:
diff changeset
250 The details are described in this document.
anatofuz
parents:
diff changeset
251 http://llvm.org/docs/LinkTimeOptimization.html
anatofuz
parents:
diff changeset
252
anatofuz
parents:
diff changeset
253 Glossary
anatofuz
parents:
diff changeset
254 --------
anatofuz
parents:
diff changeset
255
anatofuz
parents:
diff changeset
256 * RVA (COFF)
anatofuz
parents:
diff changeset
257
anatofuz
parents:
diff changeset
258 Short for Relative Virtual Address.
anatofuz
parents:
diff changeset
259
anatofuz
parents:
diff changeset
260 Windows executables or DLLs are not position-independent; they are
anatofuz
parents:
diff changeset
261 linked against a fixed address called an image base. RVAs are
anatofuz
parents:
diff changeset
262 offsets from an image base.
anatofuz
parents:
diff changeset
263
anatofuz
parents:
diff changeset
264 Default image bases are 0x140000000 for executables and 0x18000000
anatofuz
parents:
diff changeset
265 for DLLs. For example, when we are creating an executable, we assume
anatofuz
parents:
diff changeset
266 that the executable will be loaded at address 0x140000000 by the
anatofuz
parents:
diff changeset
267 loader, so we apply relocations accordingly. Result texts and data
anatofuz
parents:
diff changeset
268 will contain raw absolute addresses.
anatofuz
parents:
diff changeset
269
anatofuz
parents:
diff changeset
270 * VA
anatofuz
parents:
diff changeset
271
anatofuz
parents:
diff changeset
272 Short for Virtual Address. For COFF, it is equivalent to RVA + image base.
anatofuz
parents:
diff changeset
273
anatofuz
parents:
diff changeset
274 * Base relocations (COFF)
anatofuz
parents:
diff changeset
275
anatofuz
parents:
diff changeset
276 Relocation information for the loader. If the loader decides to map
anatofuz
parents:
diff changeset
277 an executable or a DLL to a different address than their image
anatofuz
parents:
diff changeset
278 bases, it fixes up binaries using information contained in the base
anatofuz
parents:
diff changeset
279 relocation table. A base relocation table consists of a list of
anatofuz
parents:
diff changeset
280 locations containing addresses. The loader adds a difference between
anatofuz
parents:
diff changeset
281 RVA and actual load address to all locations listed there.
anatofuz
parents:
diff changeset
282
anatofuz
parents:
diff changeset
283 Note that this run-time relocation mechanism is much simpler than ELF.
anatofuz
parents:
diff changeset
284 There's no PLT or GOT. Images are relocated as a whole just
anatofuz
parents:
diff changeset
285 by shifting entire images in memory by some offsets. Although doing
anatofuz
parents:
diff changeset
286 this breaks text sharing, I think this mechanism is not actually bad
anatofuz
parents:
diff changeset
287 on today's computers.
anatofuz
parents:
diff changeset
288
anatofuz
parents:
diff changeset
289 * ICF
anatofuz
parents:
diff changeset
290
anatofuz
parents:
diff changeset
291 Short for Identical COMDAT Folding (COFF) or Identical Code Folding (ELF).
anatofuz
parents:
diff changeset
292
anatofuz
parents:
diff changeset
293 ICF is an optimization to reduce output size by merging read-only sections
anatofuz
parents:
diff changeset
294 by not only their names but by their contents. If two read-only sections
anatofuz
parents:
diff changeset
295 happen to have the same metadata, actual contents and relocations,
anatofuz
parents:
diff changeset
296 they are merged by ICF. It is known as an effective technique,
anatofuz
parents:
diff changeset
297 and it usually reduces C++ program's size by a few percent or more.
anatofuz
parents:
diff changeset
298
anatofuz
parents:
diff changeset
299 Note that this is not an entirely sound optimization. C/C++ require
anatofuz
parents:
diff changeset
300 different functions have different addresses. If a program depends on
anatofuz
parents:
diff changeset
301 that property, it would fail at runtime.
anatofuz
parents:
diff changeset
302
anatofuz
parents:
diff changeset
303 On Windows, that's not really an issue because MSVC link.exe enabled
anatofuz
parents:
diff changeset
304 the optimization by default. As long as your program works
anatofuz
parents:
diff changeset
305 with the linker's default settings, your program should be safe with ICF.
anatofuz
parents:
diff changeset
306
anatofuz
parents:
diff changeset
307 On Unix, your program is generally not guaranteed to be safe with ICF,
anatofuz
parents:
diff changeset
308 although large programs happen to work correctly.
anatofuz
parents:
diff changeset
309 LLD works fine with ICF for example.
anatofuz
parents:
diff changeset
310
anatofuz
parents:
diff changeset
311 Other Info
anatofuz
parents:
diff changeset
312 ----------
anatofuz
parents:
diff changeset
313
anatofuz
parents:
diff changeset
314 .. toctree::
anatofuz
parents:
diff changeset
315 :maxdepth: 1
anatofuz
parents:
diff changeset
316
anatofuz
parents:
diff changeset
317 missingkeyfunction