xref: /llvm-project-15.0.7/lld/ELF/Driver.cpp (revision d2793a03)
1 //===- Driver.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 #include "Driver.h"
11 #include "Config.h"
12 #include "Error.h"
13 #include "InputFiles.h"
14 #include "SymbolTable.h"
15 #include "Writer.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 
21 using namespace llvm;
22 
23 using namespace lld;
24 using namespace lld::elf2;
25 
26 Configuration *lld::elf2::Config;
27 LinkerDriver *lld::elf2::Driver;
28 
29 void lld::elf2::link(ArrayRef<const char *> Args) {
30   Configuration C;
31   LinkerDriver D;
32   Config = &C;
33   Driver = &D;
34   Driver->link(Args.slice(1));
35 }
36 
37 // Makes a path by concatenating Dir and File.
38 // If Dir starts with '=' the result will be preceded by Sysroot,
39 // which can be set with --sysroot command line switch.
40 static std::string buildSysrootedPath(StringRef Dir, StringRef File) {
41   SmallString<128> Path;
42   if (Dir.startswith("="))
43     sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
44   else
45     sys::path::append(Path, Dir, File);
46   return Path.str().str();
47 }
48 
49 // Searches a given library from input search paths, which are filled
50 // from -L command line switches. Returns a path to an existent library file.
51 static std::string searchLibrary(StringRef Path) {
52   std::vector<std::string> Names;
53   if (Path[0] == ':') {
54     Names.push_back(Path.drop_front().str());
55   } else {
56     if (!Config->Static)
57       Names.push_back((Twine("lib") + Path + ".so").str());
58     Names.push_back((Twine("lib") + Path + ".a").str());
59   }
60   for (StringRef Dir : Config->InputSearchPaths) {
61     for (const std::string &Name : Names) {
62       std::string FullPath = buildSysrootedPath(Dir, Name);
63       if (sys::fs::exists(FullPath))
64         return FullPath;
65     }
66   }
67   error(Twine("Unable to find library -l") + Path);
68 }
69 
70 // Opens and parses a file. Path has to be resolved already.
71 // Newly created memory buffers are owned by this driver.
72 void LinkerDriver::addFile(StringRef Path) {
73   using namespace llvm::sys::fs;
74   auto MBOrErr = MemoryBuffer::getFile(Path);
75   error(MBOrErr, Twine("cannot open ") + Path);
76   std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
77   MemoryBufferRef MBRef = MB->getMemBufferRef();
78   OwningMBs.push_back(std::move(MB)); // take MB ownership
79 
80   switch (identify_magic(MBRef.getBuffer())) {
81   case file_magic::unknown:
82     readLinkerScript(MBRef);
83     return;
84   case file_magic::archive:
85     Symtab.addFile(make_unique<ArchiveFile>(MBRef));
86     return;
87   case file_magic::elf_shared_object:
88     Symtab.addFile(createELFFile<SharedFile>(MBRef));
89     return;
90   default:
91     Symtab.addFile(createELFFile<ObjectFile>(MBRef));
92   }
93 }
94 
95 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
96   // Parse command line options.
97   opt::InputArgList Args = Parser.parse(ArgsArr);
98 
99   if (auto *Arg = Args.getLastArg(OPT_output))
100     Config->OutputFile = Arg->getValue();
101 
102   if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
103     Config->DynamicLinker = Arg->getValue();
104 
105   if (auto *Arg = Args.getLastArg(OPT_sysroot))
106     Config->Sysroot = Arg->getValue();
107 
108   std::vector<StringRef> RPaths;
109   for (auto *Arg : Args.filtered(OPT_rpath))
110     RPaths.push_back(Arg->getValue());
111   if (!RPaths.empty())
112     Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
113 
114   for (auto *Arg : Args.filtered(OPT_L))
115     Config->InputSearchPaths.push_back(Arg->getValue());
116 
117   if (auto *Arg = Args.getLastArg(OPT_entry))
118     Config->Entry = Arg->getValue();
119 
120   if (auto *Arg = Args.getLastArg(OPT_fini))
121     Config->Fini = Arg->getValue();
122 
123   if (auto *Arg = Args.getLastArg(OPT_init))
124     Config->Init = Arg->getValue();
125 
126   if (auto *Arg = Args.getLastArg(OPT_soname))
127     Config->SoName = Arg->getValue();
128 
129   Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
130   Config->DiscardAll = Args.hasArg(OPT_discard_all);
131   Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
132   Config->DiscardNone = Args.hasArg(OPT_discard_none);
133   Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
134   Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
135   Config->NoUndefined = Args.hasArg(OPT_no_undefined);
136   Config->Shared = Args.hasArg(OPT_shared);
137 
138   for (auto *Arg : Args) {
139     switch (Arg->getOption().getID()) {
140     case OPT_l:
141       addFile(searchLibrary(Arg->getValue()));
142       break;
143     case OPT_INPUT:
144       addFile(Arg->getValue());
145       break;
146     case OPT_Bstatic:
147       Config->Static = true;
148       break;
149     case OPT_Bdynamic:
150       Config->Static = false;
151       break;
152     case OPT_whole_archive:
153       Config->WholeArchive = true;
154       break;
155     case OPT_no_whole_archive:
156       Config->WholeArchive = false;
157       break;
158     default:
159       break;
160     }
161   }
162 
163   if (Symtab.getObjectFiles().empty())
164     error("no input files.");
165 
166   for (auto *Arg : Args.filtered(OPT_undefined))
167     Symtab.addUndefinedSym(Arg->getValue());
168 
169   // Write the result.
170   const ELFFileBase *FirstObj = Symtab.getFirstELF();
171   switch (FirstObj->getELFKind()) {
172   case ELF32LEKind:
173     writeResult<object::ELF32LE>(&Symtab);
174     return;
175   case ELF32BEKind:
176     writeResult<object::ELF32BE>(&Symtab);
177     return;
178   case ELF64LEKind:
179     writeResult<object::ELF64LE>(&Symtab);
180     return;
181   case ELF64BEKind:
182     writeResult<object::ELF64BE>(&Symtab);
183     return;
184   }
185 }
186