1 //===- OutputFormatOptions.cpp --------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <mcld/OutputFormatOptions.h>
10 #include <mcld/Module.h>
11 #include <mcld/Support/MsgHandling.h>
12
13 namespace {
14
15 llvm::cl::opt<mcld::sys::fs::Path,
16 false,
17 llvm::cl::parser<mcld::sys::fs::Path> > ArgOutputFilename("o",
18 llvm::cl::desc("Output filename"),
19 llvm::cl::value_desc("filename"));
20
21 llvm::cl::alias AliasOutputFilename("output",
22 llvm::cl::desc("alias for -o"),
23 llvm::cl::aliasopt(ArgOutputFilename));
24
25 llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgFileType("filetype",
26 llvm::cl::init(mcld::LinkerConfig::Exec),
27 llvm::cl::desc("Choose a file type\n"
28 "(not all types are supported by all targets):"),
29 llvm::cl::values(
30 clEnumValN(mcld::LinkerConfig::Object, "obj",
31 "Emit a relocatable object ('.o') file"),
32 clEnumValN(mcld::LinkerConfig::DynObj, "dso",
33 "Emit an dynamic shared object ('.so') file"),
34 clEnumValN(mcld::LinkerConfig::Exec, "exe",
35 "Emit an executable ('.exe') file"),
36 clEnumValN(mcld::LinkerConfig::Binary, "bin",
37 "Emit a binary file"),
38 clEnumValN(mcld::LinkerConfig::External, "null",
39 "Emit nothing for performance testing"),
40 clEnumValEnd));
41
42 llvm::cl::opt<mcld::LinkerConfig::CodeGenType> ArgOFormat("oformat",
43 llvm::cl::value_desc("Format"),
44 llvm::cl::desc("set output format"),
45 llvm::cl::init(mcld::LinkerConfig::Unknown),
46 llvm::cl::values(
47 clEnumValN(mcld::LinkerConfig::Binary, "binary",
48 "generate binary machine code."),
49 clEnumValEnd));
50
51 llvm::cl::opt<bool> ArgShared("shared",
52 llvm::cl::ZeroOrMore,
53 llvm::cl::desc("Create a shared library."),
54 llvm::cl::init(false));
55
56 llvm::cl::alias ArgSharedAlias("Bshareable",
57 llvm::cl::desc("alias for -shared"),
58 llvm::cl::aliasopt(ArgShared));
59
60 llvm::cl::opt<bool> ArgPIE("pie",
61 llvm::cl::desc("Emit a position-independent executable file"),
62 llvm::cl::init(false));
63
64 llvm::cl::opt<bool> ArgRelocatable("relocatable",
65 llvm::cl::desc("Generate relocatable output"),
66 llvm::cl::init(false));
67
68 llvm::cl::alias ArgRelocatableAlias("r",
69 llvm::cl::desc("alias for --relocatable"),
70 llvm::cl::aliasopt(ArgRelocatable));
71
72 llvm::cl::opt<mcld::Input::Type> ArgFormat("b",
73 llvm::cl::value_desc("Format"),
74 llvm::cl::desc("set input format"),
75 llvm::cl::init(mcld::Input::Unknown),
76 llvm::cl::values(
77 clEnumValN(mcld::Input::Binary, "binary",
78 "read in binary machine code."),
79 clEnumValEnd));
80
81 llvm::cl::alias ArgFormatAlias("format",
82 llvm::cl::desc("alias for -b"),
83 llvm::cl::aliasopt(ArgFormat));
84
85 llvm::cl::opt<bool> ArgStripDebug("strip-debug",
86 llvm::cl::desc("Omit debugger symbol information from the output file."),
87 llvm::cl::init(false));
88
89 llvm::cl::alias ArgStripDebugAlias("S",
90 llvm::cl::desc("alias for --strip-debug"),
91 llvm::cl::aliasopt(ArgStripDebug));
92
93 llvm::cl::opt<bool> ArgStripAll("strip-all",
94 llvm::cl::desc("Omit all symbol information from the output file."),
95 llvm::cl::init(false));
96
97 llvm::cl::alias ArgStripAllAlias("s",
98 llvm::cl::desc("alias for --strip-all"),
99 llvm::cl::aliasopt(ArgStripAll));
100
101 llvm::cl::opt<bool> ArgDiscardAll("discard-all",
102 llvm::cl::desc("Delete all local symbols."),
103 llvm::cl::init(false));
104
105 llvm::cl::alias ArgDiscardAllAlias("x",
106 llvm::cl::desc("alias for --discard-all"),
107 llvm::cl::aliasopt(ArgDiscardAll));
108
109 llvm::cl::opt<bool> ArgDiscardLocals("discard-locals",
110 llvm::cl::desc("Delete all temporary local symbols."),
111 llvm::cl::init(false));
112
113 llvm::cl::alias ArgDiscardLocalsAlias("X",
114 llvm::cl::desc("alias for --discard-locals"),
115 llvm::cl::aliasopt(ArgDiscardLocals));
116
117 llvm::cl::opt<bool> ArgEhFrameHdr("eh-frame-hdr",
118 llvm::cl::ZeroOrMore,
119 llvm::cl::desc("Request creation of \".eh_frame_hdr\" section and\n"
120 "ELF \"PT_GNU_EH_FRAME\" segment header."),
121 llvm::cl::init(false));
122
123 llvm::cl::opt<bool> ArgNMagic("nmagic",
124 llvm::cl::desc("Do not page align data"),
125 llvm::cl::init(false));
126
127 llvm::cl::alias ArgNMagicAlias("n",
128 llvm::cl::desc("alias for --nmagic"),
129 llvm::cl::aliasopt(ArgNMagic));
130
131 llvm::cl::opt<bool> ArgOMagic("omagic",
132 llvm::cl::desc("Do not page align data, do not make text readonly"),
133 llvm::cl::init(false));
134
135 llvm::cl::alias ArgOMagicAlias("N",
136 llvm::cl::desc("alias for --omagic"),
137 llvm::cl::aliasopt(ArgOMagic));
138
139 llvm::cl::opt<mcld::GeneralOptions::HashStyle> ArgHashStyle("hash-style",
140 llvm::cl::init(mcld::GeneralOptions::SystemV),
141 llvm::cl::desc("Set the type of linker's hash table(s)."),
142 llvm::cl::values(
143 clEnumValN(mcld::GeneralOptions::SystemV, "sysv",
144 "classic ELF .hash section"),
145 clEnumValN(mcld::GeneralOptions::GNU, "gnu",
146 "new style GNU .gnu.hash section"),
147 clEnumValN(mcld::GeneralOptions::Both, "both",
148 "both the classic ELF and new style GNU hash tables"),
149 clEnumValEnd));
150
151 llvm::cl::opt<bool> ArgNoWarnMismatch("no-warn-mismatch",
152 llvm::cl::desc("Allow linking together mismatched input files."),
153 llvm::cl::init(false));
154
155 // Not supported yet {
156 llvm::cl::opt<bool> ArgExportDynamic("export-dynamic",
157 llvm::cl::desc("Export all dynamic symbols"),
158 llvm::cl::init(false));
159
160 llvm::cl::alias ArgExportDynamicAlias("E",
161 llvm::cl::desc("alias for --export-dynamic"),
162 llvm::cl::aliasopt(ArgExportDynamic));
163
164 llvm::cl::opt<std::string> ArgBuildID("build-id",
165 llvm::cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."),
166 llvm::cl::value_desc("style"),
167 llvm::cl::ValueOptional);
168
169 llvm::cl::list<std::string> ArgExcludeLIBS("exclude-libs",
170 llvm::cl::CommaSeparated,
171 llvm::cl::desc("Exclude libraries from automatic export"),
172 llvm::cl::value_desc("lib1,lib2,..."));
173
174 // } Not supported yet
175
176 } // anonymous namespace
177
178 using namespace mcld;
179
180 //===----------------------------------------------------------------------===//
181 // OutputFormatOptions
182 //===----------------------------------------------------------------------===//
OutputFormatOptions()183 OutputFormatOptions::OutputFormatOptions()
184 : m_OutputFilename(ArgOutputFilename),
185 m_FileType(ArgFileType),
186 m_OFormat(ArgOFormat),
187 m_Shared(ArgShared),
188 m_PIE(ArgPIE),
189 m_Relocatable(ArgRelocatable),
190 m_Format(ArgFormat),
191 m_StripDebug(ArgStripDebug),
192 m_StripAll(ArgStripAll),
193 m_DiscardAll(ArgDiscardAll),
194 m_DiscardLocals(ArgDiscardLocals),
195 m_EhFrameHdr(ArgEhFrameHdr),
196 m_NMagic(ArgNMagic),
197 m_OMagic(ArgOMagic),
198 m_HashStyle(ArgHashStyle),
199 m_ExportDynamic(ArgExportDynamic),
200 m_BuildID(ArgBuildID),
201 m_ExcludeLIBS(ArgExcludeLIBS),
202 m_NoWarnMismatch(ArgNoWarnMismatch) {
203 }
204
parse(mcld::Module & pModule,LinkerConfig & pConfig)205 bool OutputFormatOptions::parse(mcld::Module& pModule, LinkerConfig& pConfig)
206 {
207 if (!parseOutput(pModule, pConfig)) {
208 mcld::unreachable(mcld::diag::unrecognized_output_file) << pModule.name();
209 return false;
210 }
211
212 if (mcld::Input::Binary == m_Format)
213 pConfig.options().setBinaryInput();
214
215 pConfig.options().setStripDebug(m_StripDebug || m_StripAll);
216 if (m_StripAll)
217 pConfig.options().setStripSymbols(mcld::GeneralOptions::StripAllSymbols);
218 else if (m_DiscardAll)
219 pConfig.options().setStripSymbols(mcld::GeneralOptions::StripLocals);
220 else if (m_DiscardLocals)
221 pConfig.options().setStripSymbols(mcld::GeneralOptions::StripTemporaries);
222 else
223 pConfig.options().setStripSymbols(mcld::GeneralOptions::KeepAllSymbols);
224
225 pConfig.options().setEhFrameHdr(m_EhFrameHdr);
226 pConfig.options().setPIE(m_PIE);
227 pConfig.options().setNMagic(m_NMagic);
228 pConfig.options().setOMagic(m_OMagic);
229 pConfig.options().setHashStyle(m_HashStyle);
230 pConfig.options().setExportDynamic(m_ExportDynamic);
231
232 // --exclude-libs
233 llvm::cl::list<std::string>::iterator exclude,
234 excludeEnd = m_ExcludeLIBS.end();
235 for (exclude = m_ExcludeLIBS.begin(); exclude != excludeEnd; ++exclude) {
236 pConfig.options().excludeLIBS().insert(*exclude);
237 }
238
239 if (m_NoWarnMismatch)
240 pConfig.options().setWarnMismatch(false);
241 else
242 pConfig.options().setWarnMismatch(true);
243 // build-id
244 // exclude-libs
245
246 return true;
247 }
248
249 /// configure the output filename
parseOutput(Module & pModule,LinkerConfig & pConfig)250 bool OutputFormatOptions::parseOutput(Module& pModule, LinkerConfig& pConfig)
251 {
252 if (true == m_Shared || true == m_PIE) {
253 // -shared or -pie
254 m_FileType = mcld::LinkerConfig::DynObj;
255 }
256 else if (true == m_Relocatable) {
257 // partial linking
258 m_FileType = mcld::LinkerConfig::Object;
259 }
260 else if (mcld::LinkerConfig::Binary == m_OFormat) {
261 // binary output
262 m_FileType = mcld::LinkerConfig::Binary;
263 }
264
265 pConfig.setCodeGenType(m_FileType);
266
267 std::string output_filename(m_OutputFilename.native());
268
269 if (m_OutputFilename.empty()) {
270
271 if (llvm::Triple::Win32 == pConfig.targets().triple().getOS()) {
272 output_filename.assign("_out");
273 switch (m_FileType) {
274 case mcld::LinkerConfig::Object: {
275 output_filename += ".obj";
276 break;
277 }
278 case mcld::LinkerConfig::DynObj: {
279 output_filename += ".dll";
280 break;
281 }
282 case mcld::LinkerConfig::Exec: {
283 output_filename += ".exe";
284 break;
285 }
286 case mcld::LinkerConfig::External:
287 break;
288 default: {
289 return false;
290 break;
291 }
292 } // switch
293 }
294 else {
295 if (mcld::LinkerConfig::Object == m_FileType ||
296 mcld::LinkerConfig::DynObj == m_FileType ||
297 mcld::LinkerConfig::Exec == m_FileType ||
298 mcld::LinkerConfig::External == m_FileType) {
299 output_filename.assign("a.out");
300 }
301 else {
302 return false;
303 }
304 }
305 } // end of if empty m_OutputFilename
306
307 pModule.setName(output_filename);
308 return true;
309 }
310