]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/COFF/Librarian.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r301441, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / COFF / Librarian.cpp
1 //===- Librarian.cpp ------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains functions for the Librarian.  The librarian creates and
11 // manages libraries of the Common Object File Format (COFF) object files.  It
12 // primarily is used for creating static libraries and import libraries.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "Config.h"
17 #include "Driver.h"
18 #include "Error.h"
19 #include "Symbols.h"
20 #include "llvm/Object/Archive.h"
21 #include "llvm/Object/ArchiveWriter.h"
22 #include "llvm/Object/COFF.h"
23 #include "llvm/Support/Path.h"
24
25 #include <vector>
26
27 using namespace lld::coff;
28 using namespace llvm::COFF;
29 using namespace llvm::object;
30 using namespace llvm;
31
32 static bool is32bit() {
33   switch (Config->Machine) {
34   default:
35     llvm_unreachable("unsupported machine");
36   case IMAGE_FILE_MACHINE_AMD64:
37     return false;
38   case IMAGE_FILE_MACHINE_ARMNT:
39   case IMAGE_FILE_MACHINE_I386:
40     return true;
41   }
42 }
43
44 static uint16_t getImgRelRelocation() {
45   switch (Config->Machine) {
46   default:
47     llvm_unreachable("unsupported machine");
48   case IMAGE_FILE_MACHINE_AMD64:
49     return IMAGE_REL_AMD64_ADDR32NB;
50   case IMAGE_FILE_MACHINE_ARMNT:
51     return IMAGE_REL_ARM_ADDR32NB;
52   case IMAGE_FILE_MACHINE_I386:
53     return IMAGE_REL_I386_DIR32NB;
54   }
55 }
56
57 template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
58   size_t S = B.size();
59   B.resize(S + sizeof(T));
60   memcpy(&B[S], &Data, sizeof(T));
61 }
62
63 static void writeStringTable(std::vector<uint8_t> &B,
64                              ArrayRef<const std::string> Strings) {
65   // The COFF string table consists of a 4-byte value which is the size of the
66   // table, including the length field itself.  This value is followed by the
67   // string content itself, which is an array of null-terminated C-style
68   // strings.  The termination is important as they are referenced to by offset
69   // by the symbol entity in the file format.
70
71   std::vector<uint8_t>::size_type Pos = B.size();
72   std::vector<uint8_t>::size_type Offset = B.size();
73
74   // Skip over the length field, we will fill it in later as we will have
75   // computed the length while emitting the string content itself.
76   Pos += sizeof(uint32_t);
77
78   for (const auto &S : Strings) {
79     B.resize(Pos + S.length() + 1);
80     strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
81     Pos += S.length() + 1;
82   }
83
84   // Backfill the length of the table now that it has been computed.
85   support::ulittle32_t Length(B.size() - Offset);
86   memcpy(&B[Offset], &Length, sizeof(Length));
87 }
88
89 static std::string getImplibPath() {
90   if (!Config->Implib.empty())
91     return Config->Implib;
92   SmallString<128> Out = StringRef(Config->OutputFile);
93   sys::path::replace_extension(Out, ".lib");
94   return Out.str();
95 }
96
97 static ImportNameType getNameType(StringRef Sym, StringRef ExtName) {
98   if (Sym != ExtName)
99     return IMPORT_NAME_UNDECORATE;
100   if (Config->Machine == I386 && Sym.startswith("_"))
101     return IMPORT_NAME_NOPREFIX;
102   return IMPORT_NAME;
103 }
104
105 static std::string replace(StringRef S, StringRef From, StringRef To) {
106   size_t Pos = S.find(From);
107
108   // From and To may be mangled, but substrings in S may not.
109   if (Pos == StringRef::npos && From.startswith("_") && To.startswith("_")) {
110     From = From.substr(1);
111     To = To.substr(1);
112     Pos = S.find(From);
113   }
114
115   if (Pos == StringRef::npos) {
116     error(S + ": replacing '" + From + "' with '" + To + "' failed");
117     return "";
118   }
119   return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
120 }
121
122 static const std::string NullImportDescriptorSymbolName =
123     "__NULL_IMPORT_DESCRIPTOR";
124
125 namespace {
126 // This class constructs various small object files necessary to support linking
127 // symbols imported from a DLL.  The contents are pretty strictly defined and
128 // nearly entirely static.  The details of the structures files are defined in
129 // WINNT.h and the PE/COFF specification.
130 class ObjectFactory {
131   using u16 = support::ulittle16_t;
132   using u32 = support::ulittle32_t;
133
134   BumpPtrAllocator Alloc;
135   StringRef DLLName;
136   StringRef Library;
137   std::string ImportDescriptorSymbolName;
138   std::string NullThunkSymbolName;
139
140 public:
141   ObjectFactory(StringRef S)
142       : DLLName(S), Library(S.drop_back(4)),
143         ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
144         NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
145
146   // Creates an Import Descriptor.  This is a small object file which contains a
147   // reference to the terminators and contains the library name (entry) for the
148   // import name table.  It will force the linker to construct the necessary
149   // structure to import symbols from the DLL.
150   NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
151
152   // Creates a NULL import descriptor.  This is a small object file whcih
153   // contains a NULL import descriptor.  It is used to terminate the imports
154   // from a specific DLL.
155   NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
156
157   // Create a NULL Thunk Entry.  This is a small object file which contains a
158   // NULL Import Address Table entry and a NULL Import Lookup Table Entry.  It
159   // is used to terminate the IAT and ILT.
160   NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
161
162   // Create a short import file which is described in PE/COFF spec 7. Import
163   // Library Format.
164   NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
165                                      ImportType Type, ImportNameType NameType);
166 };
167 }
168
169 NewArchiveMember
170 ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
171   static const uint32_t NumberOfSections = 2;
172   static const uint32_t NumberOfSymbols = 7;
173   static const uint32_t NumberOfRelocations = 3;
174
175   // COFF Header
176   coff_file_header Header{
177       u16(Config->Machine), u16(NumberOfSections), u32(0),
178       u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
179           // .idata$2
180           sizeof(coff_import_directory_table_entry) +
181           NumberOfRelocations * sizeof(coff_relocation) +
182           // .idata$4
183           (DLLName.size() + 1)),
184       u32(NumberOfSymbols), u16(0),
185       u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
186   };
187   append(Buffer, Header);
188
189   // Section Header Table
190   static const coff_section SectionTable[NumberOfSections] = {
191       {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
192        u32(0),
193        u32(0),
194        u32(sizeof(coff_import_directory_table_entry)),
195        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
196        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
197            sizeof(coff_import_directory_table_entry)),
198        u32(0),
199        u16(NumberOfRelocations),
200        u16(0),
201        u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
202            IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
203       {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
204        u32(0),
205        u32(0),
206        u32(DLLName.size() + 1),
207        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
208            sizeof(coff_import_directory_table_entry) +
209            NumberOfRelocations * sizeof(coff_relocation)),
210        u32(0),
211        u32(0),
212        u16(0),
213        u16(0),
214        u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
215            IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
216   };
217   append(Buffer, SectionTable);
218
219   // .idata$2
220   static const coff_import_directory_table_entry ImportDescriptor{
221       u32(0), u32(0), u32(0), u32(0), u32(0),
222   };
223   append(Buffer, ImportDescriptor);
224
225   static const coff_relocation RelocationTable[NumberOfRelocations] = {
226       {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
227        u16(getImgRelRelocation())},
228       {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
229        u32(3), u16(getImgRelRelocation())},
230       {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
231        u32(4), u16(getImgRelRelocation())},
232   };
233   append(Buffer, RelocationTable);
234
235   // .idata$6
236   auto S = Buffer.size();
237   Buffer.resize(S + DLLName.size() + 1);
238   memcpy(&Buffer[S], DLLName.data(), DLLName.size());
239   Buffer[S + DLLName.size()] = '\0';
240
241   // Symbol Table
242   coff_symbol16 SymbolTable[NumberOfSymbols] = {
243       {{{0, 0, 0, 0, 0, 0, 0, 0}},
244        u32(0),
245        u16(1),
246        u16(0),
247        IMAGE_SYM_CLASS_EXTERNAL,
248        0},
249       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
250        u32(0),
251        u16(1),
252        u16(0),
253        IMAGE_SYM_CLASS_SECTION,
254        0},
255       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
256        u32(0),
257        u16(2),
258        u16(0),
259        IMAGE_SYM_CLASS_STATIC,
260        0},
261       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
262        u32(0),
263        u16(0),
264        u16(0),
265        IMAGE_SYM_CLASS_SECTION,
266        0},
267       {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
268        u32(0),
269        u16(0),
270        u16(0),
271        IMAGE_SYM_CLASS_SECTION,
272        0},
273       {{{0, 0, 0, 0, 0, 0, 0, 0}},
274        u32(0),
275        u16(0),
276        u16(0),
277        IMAGE_SYM_CLASS_EXTERNAL,
278        0},
279       {{{0, 0, 0, 0, 0, 0, 0, 0}},
280        u32(0),
281        u16(0),
282        u16(0),
283        IMAGE_SYM_CLASS_EXTERNAL,
284        0},
285   };
286   reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
287       sizeof(uint32_t);
288   reinterpret_cast<StringTableOffset &>(SymbolTable[5].Name).Offset =
289       sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
290   reinterpret_cast<StringTableOffset &>(SymbolTable[6].Name).Offset =
291       sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
292       NullImportDescriptorSymbolName.length() + 1;
293   append(Buffer, SymbolTable);
294
295   // String Table
296   writeStringTable(Buffer,
297                    {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
298                     NullThunkSymbolName});
299
300   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
301   return {MemoryBufferRef(F, DLLName)};
302 }
303
304 NewArchiveMember
305 ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
306   static const uint32_t NumberOfSections = 1;
307   static const uint32_t NumberOfSymbols = 1;
308
309   // COFF Header
310   coff_file_header Header{
311       u16(Config->Machine), u16(NumberOfSections), u32(0),
312       u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
313           // .idata$3
314           sizeof(coff_import_directory_table_entry)),
315       u32(NumberOfSymbols), u16(0),
316       u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
317   };
318   append(Buffer, Header);
319
320   // Section Header Table
321   static const coff_section SectionTable[NumberOfSections] = {
322       {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
323        u32(0),
324        u32(0),
325        u32(sizeof(coff_import_directory_table_entry)),
326        u32(sizeof(coff_file_header) +
327            (NumberOfSections * sizeof(coff_section))),
328        u32(0),
329        u32(0),
330        u16(0),
331        u16(0),
332        u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
333            IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
334   };
335   append(Buffer, SectionTable);
336
337   // .idata$3
338   static const coff_import_directory_table_entry ImportDescriptor{
339       u32(0), u32(0), u32(0), u32(0), u32(0),
340   };
341   append(Buffer, ImportDescriptor);
342
343   // Symbol Table
344   coff_symbol16 SymbolTable[NumberOfSymbols] = {
345       {{{0, 0, 0, 0, 0, 0, 0, 0}},
346        u32(0),
347        u16(1),
348        u16(0),
349        IMAGE_SYM_CLASS_EXTERNAL,
350        0},
351   };
352   reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
353       sizeof(uint32_t);
354   append(Buffer, SymbolTable);
355
356   // String Table
357   writeStringTable(Buffer, {NullImportDescriptorSymbolName});
358
359   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
360   return {MemoryBufferRef(F, DLLName)};
361 }
362
363 NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
364   static const uint32_t NumberOfSections = 2;
365   static const uint32_t NumberOfSymbols = 1;
366   uint32_t VASize = is32bit() ? 4 : 8;
367
368   // COFF Header
369   coff_file_header Header{
370       u16(Config->Machine), u16(NumberOfSections), u32(0),
371       u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
372           // .idata$5
373           VASize +
374           // .idata$4
375           VASize),
376       u32(NumberOfSymbols), u16(0),
377       u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
378   };
379   append(Buffer, Header);
380
381   // Section Header Table
382   static const coff_section SectionTable[NumberOfSections] = {
383       {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
384        u32(0),
385        u32(0),
386        u32(VASize),
387        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
388        u32(0),
389        u32(0),
390        u16(0),
391        u16(0),
392        u32((is32bit() ? IMAGE_SCN_ALIGN_4BYTES : IMAGE_SCN_ALIGN_8BYTES) |
393            IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
394            IMAGE_SCN_MEM_WRITE)},
395       {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
396        u32(0),
397        u32(0),
398        u32(VASize),
399        u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
400            VASize),
401        u32(0),
402        u32(0),
403        u16(0),
404        u16(0),
405        u32((is32bit() ? IMAGE_SCN_ALIGN_4BYTES : IMAGE_SCN_ALIGN_8BYTES) |
406            IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
407            IMAGE_SCN_MEM_WRITE)},
408   };
409   append(Buffer, SectionTable);
410
411   // .idata$5, ILT
412   append(Buffer, u32(0));
413   if (!is32bit())
414     append(Buffer, u32(0));
415
416   // .idata$4, IAT
417   append(Buffer, u32(0));
418   if (!is32bit())
419     append(Buffer, u32(0));
420
421   // Symbol Table
422   coff_symbol16 SymbolTable[NumberOfSymbols] = {
423       {{{0, 0, 0, 0, 0, 0, 0, 0}},
424        u32(0),
425        u16(1),
426        u16(0),
427        IMAGE_SYM_CLASS_EXTERNAL,
428        0},
429   };
430   reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
431       sizeof(uint32_t);
432   append(Buffer, SymbolTable);
433
434   // String Table
435   writeStringTable(Buffer, {NullThunkSymbolName});
436
437   StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
438   return {MemoryBufferRef{F, DLLName}};
439 }
440
441 NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
442                                                   uint16_t Ordinal,
443                                                   ImportType ImportType,
444                                                   ImportNameType NameType) {
445   size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
446   size_t Size = sizeof(coff_import_header) + ImpSize;
447   char *Buf = Alloc.Allocate<char>(Size);
448   memset(Buf, 0, Size);
449   char *P = Buf;
450
451   // Write short import library.
452   auto *Imp = reinterpret_cast<coff_import_header *>(P);
453   P += sizeof(*Imp);
454   Imp->Sig2 = 0xFFFF;
455   Imp->Machine = Config->Machine;
456   Imp->SizeOfData = ImpSize;
457   if (Ordinal > 0)
458     Imp->OrdinalHint = Ordinal;
459   Imp->TypeInfo = (NameType << 2) | ImportType;
460
461   // Write symbol name and DLL name.
462   memcpy(P, Sym.data(), Sym.size());
463   P += Sym.size() + 1;
464   memcpy(P, DLLName.data(), DLLName.size());
465
466   return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
467 }
468
469 // Creates an import library for a DLL. In this function, we first
470 // create an empty import library using lib.exe and then adds short
471 // import files to that file.
472 void lld::coff::writeImportLibrary() {
473   std::vector<NewArchiveMember> Members;
474
475   std::string Path = getImplibPath();
476   std::string DLLName = sys::path::filename(Config->OutputFile);
477   ObjectFactory OF(DLLName);
478
479   std::vector<uint8_t> ImportDescriptor;
480   Members.push_back(OF.createImportDescriptor(ImportDescriptor));
481
482   std::vector<uint8_t> NullImportDescriptor;
483   Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
484
485   std::vector<uint8_t> NullThunk;
486   Members.push_back(OF.createNullThunk(NullThunk));
487
488   for (Export &E : Config->Exports) {
489     if (E.Private)
490       continue;
491
492     ImportType ImportType = IMPORT_CODE;
493     if (E.Data)
494       ImportType = IMPORT_DATA;
495     if (E.Constant)
496       ImportType = IMPORT_CONST;
497
498     ImportNameType NameType = getNameType(E.SymbolName, E.Name);
499     std::string Name = E.ExtName.empty()
500                            ? std::string(E.SymbolName)
501                            : replace(E.SymbolName, E.Name, E.ExtName);
502     Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
503                                            NameType));
504   }
505
506   std::pair<StringRef, std::error_code> Result =
507       writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
508                    /*Deterministic*/ true, /*Thin*/ false);
509   if (auto EC = Result.second)
510     fatal(EC, "failed to write " + Path);
511 }