• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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