llvm.org GIT mirror llvm / 441b4ee
Revert r308329: llvm: add llvm-dlltool support to the archiver This reverts commit r308329 because it broke buildbots. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308374 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 3 years ago
17 changed file(s) with 27 addition(s) and 411 deletion(s). Raw diff Collapse all Expand all
1414 // https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
1515 //
1616 //===----------------------------------------------------------------------===//
17
1718
1819 #ifndef LLVM_OBJECT_COFF_MODULE_DEFINITION_H
1920 #define LLVM_OBJECT_COFF_MODULE_DEFINITION_H
3839 uint32_t MinorOSVersion = 0;
3940 };
4041
41 // mingw and wine def files do not mangle _ for x86 which
42 // is a consequence of legacy binutils' dlltool functionality.
43 // This MingwDef flag should be removed once mingw stops this pratice.
4442 Expected
45 parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine,
46 bool MingwDef = false);
43 parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine);
4744
4845 } // End namespace object.
4946 } // End namespace llvm.
+0
-24
include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h less more
None //===- DlltoolDriver.h - dlltool.exe-compatible driver ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines an interface to a dlltool.exe-compatible driver.
10 // Used by llvm-dlltool.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TOOLDRIVERS_LLVM_DLLTOOL_DLLTOOLDRIVER_H
15 #define LLVM_TOOLDRIVERS_LLVM_DLLTOOL_DLLTOOLDRIVER_H
16
17 namespace llvm {
18 template class ArrayRef;
19
20 int dlltoolDriverMain(ArrayRef ArgsArr);
21 } // namespace llvm
22
23 #endif
317317 continue;
318318 if (!(Symflags & object::SymbolRef::SF_Global))
319319 continue;
320 if (Symflags & object::SymbolRef::SF_Undefined &&
321 !(Symflags & object::SymbolRef::SF_Indirect))
320 if (Symflags & object::SymbolRef::SF_Undefined)
322321 continue;
323322
324323 unsigned NameOffset = NameOS.tell();
161161 // Library Format.
162162 NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
163163 ImportType Type, ImportNameType NameType);
164
165 // Create a weak external file which is described in PE/COFF Aux Format 3.
166 NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp);
167164 };
168165 } // namespace
169166
170167 NewArchiveMember
171168 ObjectFactory::createImportDescriptor(std::vector &Buffer) {
172 const uint32_t NumberOfSections = 2;
173 const uint32_t NumberOfSymbols = 7;
174 const uint32_t NumberOfRelocations = 3;
169 static const uint32_t NumberOfSections = 2;
170 static const uint32_t NumberOfSymbols = 7;
171 static const uint32_t NumberOfRelocations = 3;
175172
176173 // COFF Header
177174 coff_file_header Header{
191188 append(Buffer, Header);
192189
193190 // Section Header Table
194 const coff_section SectionTable[NumberOfSections] = {
191 static const coff_section SectionTable[NumberOfSections] = {
195192 {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
196193 u32(0),
197194 u32(0),
221218 append(Buffer, SectionTable);
222219
223220 // .idata$2
224 const coff_import_directory_table_entry ImportDescriptor{
221 static const coff_import_directory_table_entry ImportDescriptor{
225222 u32(0), u32(0), u32(0), u32(0), u32(0),
226223 };
227224 append(Buffer, ImportDescriptor);
228225
229 const coff_relocation RelocationTable[NumberOfRelocations] = {
226 static const coff_relocation RelocationTable[NumberOfRelocations] = {
230227 {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
231228 u16(getImgRelRelocation(Machine))},
232229 {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
309306
310307 NewArchiveMember
311308 ObjectFactory::createNullImportDescriptor(std::vector &Buffer) {
312 const uint32_t NumberOfSections = 1;
313 const uint32_t NumberOfSymbols = 1;
309 static const uint32_t NumberOfSections = 1;
310 static const uint32_t NumberOfSymbols = 1;
314311
315312 // COFF Header
316313 coff_file_header Header{
327324 append(Buffer, Header);
328325
329326 // Section Header Table
330 const coff_section SectionTable[NumberOfSections] = {
327 static const coff_section SectionTable[NumberOfSections] = {
331328 {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
332329 u32(0),
333330 u32(0),
344341 append(Buffer, SectionTable);
345342
346343 // .idata$3
347 const coff_import_directory_table_entry ImportDescriptor{
344 static const coff_import_directory_table_entry ImportDescriptor{
348345 u32(0), u32(0), u32(0), u32(0), u32(0),
349346 };
350347 append(Buffer, ImportDescriptor);
369366 }
370367
371368 NewArchiveMember ObjectFactory::createNullThunk(std::vector &Buffer) {
372 const uint32_t NumberOfSections = 2;
373 const uint32_t NumberOfSymbols = 1;
369 static const uint32_t NumberOfSections = 2;
370 static const uint32_t NumberOfSymbols = 1;
374371 uint32_t VASize = is32bit(Machine) ? 4 : 8;
375372
376373 // COFF Header
390387 append(Buffer, Header);
391388
392389 // Section Header Table
393 const coff_section SectionTable[NumberOfSections] = {
390 static const coff_section SectionTable[NumberOfSections] = {
394391 {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
395392 u32(0),
396393 u32(0),
478475 return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
479476 }
480477
481 NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
482 StringRef Weak, bool Imp) {
483 std::vector Buffer;
484 const uint32_t NumberOfSections = 1;
485 const uint32_t NumberOfSymbols = 5;
486
487 // COFF Header
488 coff_file_header Header{
489 u16(0),
490 u16(NumberOfSections),
491 u32(0),
492 u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
493 u32(NumberOfSymbols),
494 u16(0),
495 u16(0),
496 };
497 append(Buffer, Header);
498
499 // Section Header Table
500 const coff_section SectionTable[NumberOfSections] = {
501 {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
502 u32(0),
503 u32(0),
504 u32(0),
505 u32(0),
506 u32(0),
507 u32(0),
508 u16(0),
509 u16(0),
510 u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
511 append(Buffer, SectionTable);
512
513 // Symbol Table
514 coff_symbol16 SymbolTable[NumberOfSymbols] = {
515 {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
516 u32(0),
517 u16(0xFFFF),
518 u16(0),
519 IMAGE_SYM_CLASS_STATIC,
520 0},
521 {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
522 u32(0),
523 u16(0xFFFF),
524 u16(0),
525 IMAGE_SYM_CLASS_STATIC,
526 0},
527 {{{0, 0, 0, 0, 0, 0, 0, 0}},
528 u32(0),
529 u16(0),
530 u16(0),
531 IMAGE_SYM_CLASS_EXTERNAL,
532 0},
533 {{{0, 0, 0, 0, 0, 0, 0, 0}},
534 u32(0),
535 u16(0),
536 u16(0),
537 IMAGE_SYM_CLASS_WEAK_EXTERNAL,
538 1},
539 {{{2, 0, 0, 0, 3, 0, 0, 0}}, u32(0), u16(0), u16(0), uint8_t(0), 0},
540 };
541 SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
542
543 //__imp_ String Table
544 if (Imp) {
545 SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 7;
546 writeStringTable(Buffer, {std::string("__imp_").append(Sym),
547 std::string("__imp_").append(Weak)});
548 } else {
549 SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 1;
550 writeStringTable(Buffer, {Sym, Weak});
551 }
552 append(Buffer, SymbolTable);
553
554 // Copied here so we can still use writeStringTable
555 char *Buf = Alloc.Allocate(Buffer.size());
556 memcpy(Buf, Buffer.data(), Buffer.size());
557 return {MemoryBufferRef(StringRef(Buf, Buffer.size()), DLLName)};
558 }
559
560478 std::error_code writeImportLibrary(StringRef DLLName, StringRef Path,
561479 ArrayRef Exports,
562480 MachineTypes Machine) {
576494 for (COFFShortExport E : Exports) {
577495 if (E.Private)
578496 continue;
579
580 if (E.isWeak()) {
581 Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, false));
582 Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, true));
583 continue;
584 }
585497
586498 ImportType ImportType = IMPORT_CODE;
587499 if (E.Data)
5454 StringRef Value;
5555 };
5656
57 static bool isDecorated(StringRef Sym, bool MingwDef) {
58 // mingw does not prepend "_".
59 return (!MingwDef && Sym.startswith("_")) || Sym.startswith("@") ||
60 Sym.startswith("?");
57 static bool isDecorated(StringRef Sym) {
58 return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
6159 }
6260
6361 static Error createError(const Twine &Err) {
8482 }
8583 case '=':
8684 Buf = Buf.drop_front();
87 // GNU dlltool accepts both = and ==.
88 if (Buf.startswith("="))
89 Buf = Buf.drop_front();
9085 return Token(Equal, "=");
9186 case ',':
9287 Buf = Buf.drop_front();
124119
125120 class Parser {
126121 public:
127 explicit Parser(StringRef S, MachineTypes M, bool B)
128 : Lex(S), Machine(M), MingwDef(B) {}
122 explicit Parser(StringRef S, MachineTypes M) : Lex(S), Machine(M) {}
129123
130124 Expected parse() {
131125 do {
218212 }
219213
220214 if (Machine == IMAGE_FILE_MACHINE_I386) {
221 if (!isDecorated(E.Name, MingwDef))
215 if (!isDecorated(E.Name))
222216 E.Name = (std::string("_").append(E.Name));
223 if (!E.ExtName.empty() && !isDecorated(E.ExtName, MingwDef))
217 if (!E.ExtName.empty() && !isDecorated(E.ExtName))
224218 E.ExtName = (std::string("_").append(E.ExtName));
225219 }
226220
313307 std::vector Stack;
314308 MachineTypes Machine;
315309 COFFModuleDefinition Info;
316 bool MingwDef;
317310 };
318311
319312 Expected parseCOFFModuleDefinition(MemoryBufferRef MB,
320 MachineTypes Machine,
321 bool MingwDef) {
322 return Parser(MB.getBuffer(), Machine, MingwDef).parse();
313 MachineTypes Machine) {
314 return Parser(MB.getBuffer(), Machine).parse();
323315 }
324316
325317 } // namespace object
226226 if (Symb.isExternal() || Symb.isWeakExternal())
227227 Result |= SymbolRef::SF_Global;
228228
229 if (Symb.isWeakExternal()) {
229 if (Symb.isWeakExternal())
230230 Result |= SymbolRef::SF_Weak;
231 // We use indirect to allow the archiver to write weak externs
232 Result |= SymbolRef::SF_Indirect;
233 }
234231
235232 if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
236233 Result |= SymbolRef::SF_Absolute;
None add_subdirectory(llvm-dlltool)
1 add_subdirectory(llvm-lib)
1515 ;===------------------------------------------------------------------------===;
1616
1717 [common]
18 subdirectories = llvm-dlltool llvm-lib
18 subdirectories = llvm-lib
1919
2020 [component_0]
2121 type = Group
+0
-9
lib/ToolDrivers/llvm-dlltool/CMakeLists.txt less more
None set(LLVM_TARGET_DEFINITIONS Options.td)
1 tablegen(LLVM Options.inc -gen-opt-parser-defs)
2 add_public_tablegen_target(DllOptionsTableGen)
3
4 add_llvm_library(LLVMDlltoolDriver
5 DlltoolDriver.cpp
6 )
7
8 add_dependencies(LLVMDlltoolDriver DllOptionsTableGen)
+0
-160
lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp less more
None //===- DlltoolDriver.cpp - dlltool.exe-compatible driver ------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines an interface to a dlltool.exe-compatible driver.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
14 #include "llvm/Object/ArchiveWriter.h"
15 #include "llvm/Object/COFF.h"
16 #include "llvm/Object/COFFImportFile.h"
17 #include "llvm/Object/COFFModuleDefinition.h"
18 #include "llvm/Option/Arg.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Option/Option.h"
21 #include "llvm/Support/Path.h"
22
23 #include
24 #include
25
26 using namespace llvm;
27 using namespace llvm::object;
28 using namespace llvm::COFF;
29
30 namespace {
31
32 enum {
33 OPT_INVALID = 0,
34 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
35 #include "Options.inc"
36 #undef OPTION
37 };
38
39 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
40 #include "Options.inc"
41 #undef PREFIX
42
43 static const llvm::opt::OptTable::Info infoTable[] = {
44 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
45 {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \
46 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
47 #include "Options.inc"
48 #undef OPTION
49 };
50
51 class DllOptTable : public llvm::opt::OptTable {
52 public:
53 DllOptTable() : OptTable(infoTable, false) {}
54 };
55
56 } // namespace
57
58 std::vector> OwningMBs;
59
60 // Opens a file. Path has to be resolved already.
61 // Newly created memory buffers are owned by this driver.
62 MemoryBufferRef openFile(StringRef Path) {
63 ErrorOr> MB = MemoryBuffer::getFile(Path);
64
65 if (std::error_code EC = MB.getError())
66 llvm::errs() << "fail openFile: " << EC.message() << "\n";
67
68 MemoryBufferRef MBRef = MB.get()->getMemBufferRef();
69 OwningMBs.push_back(std::move(MB.get())); // take ownership
70 return MBRef;
71 }
72
73 static MachineTypes getEmulation(StringRef S) {
74 return StringSwitch(S)
75 .Case("i386", IMAGE_FILE_MACHINE_I386)
76 .Case("i386:x86-64", IMAGE_FILE_MACHINE_AMD64)
77 .Case("arm", IMAGE_FILE_MACHINE_ARMNT)
78 .Default(IMAGE_FILE_MACHINE_UNKNOWN);
79 }
80
81 static std::string getImplibPath(std::string Path) {
82 SmallString<128> Out = StringRef("lib");
83 Out.append(Path);
84 sys::path::replace_extension(Out, ".a");
85 return Out.str();
86 }
87
88 int llvm::dlltoolDriverMain(llvm::ArrayRef ArgsArr) {
89 DllOptTable Table;
90 unsigned MissingIndex;
91 unsigned MissingCount;
92 llvm::opt::InputArgList Args =
93 Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);
94 if (MissingCount) {
95 llvm::errs() << Args.getArgString(MissingIndex) << ": missing argument\n";
96 return 1;
97 }
98
99 // Handle when no input or output is specified
100 if (Args.hasArgNoClaim(OPT_INPUT) ||
101 (!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l))) {
102 Table.PrintHelp(outs(), ArgsArr[0], "dlltool", false);
103 llvm::outs() << "\nTARGETS: i386, i386:x86-64, arm\n";
104 return 1;
105 }
106
107 if (!Args.hasArgNoClaim(OPT_m) && Args.hasArgNoClaim(OPT_d)) {
108 llvm::errs() << "error: no target machine specified\n"
109 << "supported targets: i386, i386:x86-64, arm\n";
110 return 1;
111 }
112
113 for (auto *Arg : Args.filtered(OPT_UNKNOWN))
114 llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
115
116 MemoryBufferRef MB;
117 if (auto *Arg = Args.getLastArg(OPT_d))
118 MB = openFile(Arg->getValue());
119
120 if (!MB.getBufferSize()) {
121 llvm::errs() << "definition file empty\n";
122 return 1;
123 }
124
125 COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
126 if (auto *Arg = Args.getLastArg(OPT_m))
127 Machine = getEmulation(Arg->getValue());
128
129 if (Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
130 llvm::errs() << "unknown target\n";
131 return 1;
132 }
133
134 Expected Def =
135 parseCOFFModuleDefinition(MB, Machine, true);
136
137 if (!Def) {
138 llvm::errs() << "error parsing definition\n"
139 << errorToErrorCode(Def.takeError()).message();
140 return 1;
141 }
142
143 // Do this after the parser because parseCOFFModuleDefinition sets OutputFile.
144 if (auto *Arg = Args.getLastArg(OPT_D))
145 Def->OutputFile = Arg->getValue();
146
147 if (Def->OutputFile.empty()) {
148 llvm::errs() << "no output file specified\n";
149 return 1;
150 }
151
152 std::string Path = Args.getLastArgValue(OPT_l);
153 if (Path.empty())
154 Path = getImplibPath(Def->OutputFile);
155
156 if (writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine))
157 return 1;
158 return 0;
159 }
+0
-22
lib/ToolDrivers/llvm-dlltool/LLVMBuild.txt less more
None ;===- ./lib/ToolDrivers/llvm-dlltool/LLVMBuild.txt -------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = DlltoolDriver
20 parent = Libraries
21 required_libraries = Object Option Support
+0
-26
lib/ToolDrivers/llvm-dlltool/Options.td less more
None include "llvm/Option/OptParser.td"
1
2 def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target machine">;
3 def m_long : JoinedOrSeparate<["--"], "machine">, Alias;
4
5 def l: JoinedOrSeparate<["-"], "l">, HelpText<"Generate an import lib">;
6 def l_long : JoinedOrSeparate<["--"], "output-lib">, Alias;
7
8 def D: JoinedOrSeparate<["-"], "D">, HelpText<"Specify the input DLL Name">;
9 def D_long : JoinedOrSeparate<["--"], "dllname">, Alias;
10
11 def d: JoinedOrSeparate<["-"], "d">, HelpText<"Input .def File">;
12 def d_long : JoinedOrSeparate<["--"], "input-def">, Alias;
13
14 //==============================================================================
15 // The flags below do nothing. They are defined only for dlltool compatibility.
16 //==============================================================================
17
18 def k: Flag<["-"], "k">, HelpText<"Kill @n Symbol from export">;
19 def k_alias: Flag<["--"], "kill-at">, Alias;
20
21 def S: JoinedOrSeparate<["-"], "S">, HelpText<"Assembler">;
22 def S_alias: JoinedOrSeparate<["--"], "as">, Alias;
23
24 def f: JoinedOrSeparate<["-"], "f">, HelpText<"Assembler Flags">;
25 def f_alias: JoinedOrSeparate<["--"], "as-flags">, Alias;
+0
-13
test/DllTool/coff-exports.def less more
None ; RUN: llvm-dlltool -m i386:x86-64 --input-def %s --output-lib %t.a
1 ; RUN: llvm-readobj -coff-exports %t.a | FileCheck %s
2
3 LIBRARY test.dll
4 EXPORTS
5 TestFunction
6
7 ; CHECK: File: test.dll
8 ; CHECK: Format: COFF-import-file
9 ; CHECK: Type: code
10 ; CHECK: Name type: name
11 ; CHECK: Symbol: __imp_TestFunction
12 ; CHECK: Symbol: TestFunction
+0
-19
test/DllTool/coff-weak-exports.def less more
None ; RUN: llvm-dlltool -m i386:x86-64 --input-def %s --output-lib %t.a
1 ; RUN: llvm-readobj -coff-exports %t.a | FileCheck %s
2
3 LIBRARY test.dll
4 EXPORTS
5 TestFunction==AltTestFunction
6
7 ; CHECK: File: test.dll
8 ; CHECK: Format: COFF-x86-64
9 ; CHECK: Arch: x86_64
10 ; CHECK: AddressSize: 64bit
11 ; CHECK: File: test.dll
12 ; CHECK: Format: COFF-x86-64
13 ; CHECK: Arch: x86_64
14 ; CHECK: AddressSize: 64bit
15 ; CHECK: File: test.dll
16 ; CHECK: Format: COFF-x86-64
17 ; CHECK: Arch: x86_64
18 ; CHECK: AddressSize: 64bit
+0
-1
test/DllTool/lit.local.cfg less more
None config.suffixes = ['.def']
0 set(LLVM_LINK_COMPONENTS
11 ${LLVM_TARGETS_TO_BUILD}
22 Core
3 DlltoolDriver
43 LibDriver
54 Object
65 Support
1514
1615 add_llvm_tool_symlink(llvm-ranlib llvm-ar)
1716 add_llvm_tool_symlink(llvm-lib llvm-ar)
18 add_llvm_tool_symlink(llvm-dlltool llvm-ar)
1515 #include "llvm/ADT/Triple.h"
1616 #include "llvm/IR/LLVMContext.h"
1717 #include "llvm/IR/Module.h"
18 #include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
1918 #include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
2019 #include "llvm/Object/Archive.h"
2120 #include "llvm/Object/ArchiveWriter.h"
863862 llvm::InitializeAllAsmParsers();
864863
865864 StringRef Stem = sys::path::stem(ToolName);
866 if (Stem.find("dlltool") != StringRef::npos)
867 return dlltoolDriverMain(makeArrayRef(argv, argc));
868
869865 if (Stem.find("ranlib") == StringRef::npos &&
870866 Stem.find("lib") != StringRef::npos)
871867 return libDriverMain(makeArrayRef(argv, argc));
881877 return ranlib_main();
882878 if (Stem.find("ar") != StringRef::npos)
883879 return ar_main();
884 fail("Not ranlib, ar, lib or dlltool!");
885 }
880 fail("Not ranlib, ar or lib!");
881 }