1 //===-- llvm-mc.cpp - Machine Code Hacking Driver ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This utility is a simple driver that allows command line hacking on machine
10 // code.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Disassembler.h"
15 #include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameAnalyzer.h"
16 #include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h"
17 #include "llvm/MC/MCAsmBackend.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCInstPrinter.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCObjectFileInfo.h"
24 #include "llvm/MC/MCObjectWriter.h"
25 #include "llvm/MC/MCParser/AsmLexer.h"
26 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
27 #include "llvm/MC/MCRegisterInfo.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSubtargetInfo.h"
30 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
31 #include "llvm/MC/TargetRegistry.h"
32 #include "llvm/Support/CommandLine.h"
33 #include "llvm/Support/Compression.h"
34 #include "llvm/Support/FileUtilities.h"
35 #include "llvm/Support/FormattedStream.h"
36 #include "llvm/Support/InitLLVM.h"
37 #include "llvm/Support/MemoryBuffer.h"
38 #include "llvm/Support/SourceMgr.h"
39 #include "llvm/Support/TargetSelect.h"
40 #include "llvm/Support/ToolOutputFile.h"
41 #include "llvm/Support/WithColor.h"
42 #include "llvm/TargetParser/Host.h"
43 #include <memory>
44
45 using namespace llvm;
46
47 static mc::RegisterMCTargetOptionsFlags MOF;
48
49 static cl::OptionCategory MCCategory("MC Options");
50
51 static cl::opt<std::string> InputFilename(cl::Positional,
52 cl::desc("<input file>"),
53 cl::init("-"), cl::cat(MCCategory));
54
55 static cl::list<std::string> InstPrinterOptions("M",
56 cl::desc("InstPrinter options"),
57 cl::cat(MCCategory));
58
59 static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
60 cl::value_desc("filename"),
61 cl::init("-"), cl::cat(MCCategory));
62
63 static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
64 cl::desc("DWO output filename"),
65 cl::value_desc("filename"),
66 cl::cat(MCCategory));
67
68 static cl::opt<bool> ShowEncoding("show-encoding",
69 cl::desc("Show instruction encodings"),
70 cl::cat(MCCategory));
71
72 static cl::opt<DebugCompressionType> CompressDebugSections(
73 "compress-debug-sections", cl::ValueOptional,
74 cl::init(DebugCompressionType::None),
75 cl::desc("Choose DWARF debug sections compression:"),
76 cl::values(clEnumValN(DebugCompressionType::None, "none", "No compression"),
77 clEnumValN(DebugCompressionType::Zlib, "zlib", "Use zlib"),
78 clEnumValN(DebugCompressionType::Zstd, "zstd", "Use zstd")),
79 cl::cat(MCCategory));
80
81 static cl::opt<bool>
82 ShowInst("show-inst", cl::desc("Show internal instruction representation"),
83 cl::cat(MCCategory));
84
85 static cl::opt<bool>
86 ShowInstOperands("show-inst-operands",
87 cl::desc("Show instructions operands as parsed"),
88 cl::cat(MCCategory));
89
90 static cl::opt<unsigned>
91 OutputAsmVariant("output-asm-variant",
92 cl::desc("Syntax variant to use for output printing"),
93 cl::cat(MCCategory));
94
95 static cl::opt<bool>
96 PrintImmHex("print-imm-hex", cl::init(false),
97 cl::desc("Prefer hex format for immediate values"),
98 cl::cat(MCCategory));
99
100 static cl::opt<bool>
101 HexBytes("hex",
102 cl::desc("Take raw hexadecimal bytes as input for disassembly. "
103 "Whitespace is ignored"),
104 cl::cat(MCCategory));
105
106 static cl::list<std::string>
107 DefineSymbol("defsym",
108 cl::desc("Defines a symbol to be an integer constant"),
109 cl::cat(MCCategory));
110
111 static cl::opt<bool>
112 PreserveComments("preserve-comments",
113 cl::desc("Preserve Comments in outputted assembly"),
114 cl::cat(MCCategory));
115
116 static cl::opt<unsigned> CommentColumn("comment-column",
117 cl::desc("Asm comments indentation"),
118 cl::init(40));
119
120 enum OutputFileType {
121 OFT_Null,
122 OFT_AssemblyFile,
123 OFT_ObjectFile
124 };
125 static cl::opt<OutputFileType>
126 FileType("filetype", cl::init(OFT_AssemblyFile),
127 cl::desc("Choose an output file type:"),
128 cl::values(clEnumValN(OFT_AssemblyFile, "asm",
129 "Emit an assembly ('.s') file"),
130 clEnumValN(OFT_Null, "null",
131 "Don't emit anything (for timing purposes)"),
132 clEnumValN(OFT_ObjectFile, "obj",
133 "Emit a native object ('.o') file")),
134 cl::cat(MCCategory));
135
136 static cl::list<std::string> IncludeDirs("I",
137 cl::desc("Directory of include files"),
138 cl::value_desc("directory"),
139 cl::Prefix, cl::cat(MCCategory));
140
141 static cl::opt<std::string>
142 ArchName("arch",
143 cl::desc("Target arch to assemble for, "
144 "see -version for available targets"),
145 cl::cat(MCCategory));
146
147 static cl::opt<std::string>
148 TripleName("triple",
149 cl::desc("Target triple to assemble for, "
150 "see -version for available targets"),
151 cl::cat(MCCategory));
152
153 static cl::opt<std::string>
154 MCPU("mcpu",
155 cl::desc("Target a specific cpu type (-mcpu=help for details)"),
156 cl::value_desc("cpu-name"), cl::init(""), cl::cat(MCCategory));
157
158 static cl::list<std::string>
159 MAttrs("mattr", cl::CommaSeparated,
160 cl::desc("Target specific attributes (-mattr=help for details)"),
161 cl::value_desc("a1,+a2,-a3,..."), cl::cat(MCCategory));
162
163 static cl::opt<bool> PIC("position-independent",
164 cl::desc("Position independent"), cl::init(false),
165 cl::cat(MCCategory));
166
167 static cl::opt<bool>
168 LargeCodeModel("large-code-model",
169 cl::desc("Create cfi directives that assume the code might "
170 "be more than 2gb away"),
171 cl::cat(MCCategory));
172
173 static cl::opt<bool>
174 NoInitialTextSection("n",
175 cl::desc("Don't assume assembly file starts "
176 "in the text section"),
177 cl::cat(MCCategory));
178
179 static cl::opt<bool>
180 GenDwarfForAssembly("g",
181 cl::desc("Generate dwarf debugging info for assembly "
182 "source files"),
183 cl::cat(MCCategory));
184
185 static cl::opt<std::string>
186 DebugCompilationDir("fdebug-compilation-dir",
187 cl::desc("Specifies the debug info's compilation dir"),
188 cl::cat(MCCategory));
189
190 static cl::list<std::string> DebugPrefixMap(
191 "fdebug-prefix-map", cl::desc("Map file source paths in debug info"),
192 cl::value_desc("= separated key-value pairs"), cl::cat(MCCategory));
193
194 static cl::opt<std::string> MainFileName(
195 "main-file-name",
196 cl::desc("Specifies the name we should consider the input file"),
197 cl::cat(MCCategory));
198
199 static cl::opt<bool> LexMasmIntegers(
200 "masm-integers",
201 cl::desc("Enable binary and hex masm integers (0b110 and 0ABCh)"),
202 cl::cat(MCCategory));
203
204 static cl::opt<bool> LexMasmHexFloats(
205 "masm-hexfloats",
206 cl::desc("Enable MASM-style hex float initializers (3F800000r)"),
207 cl::cat(MCCategory));
208
209 static cl::opt<bool> LexMotorolaIntegers(
210 "motorola-integers",
211 cl::desc("Enable binary and hex Motorola integers (%110 and $ABC)"),
212 cl::cat(MCCategory));
213
214 static cl::opt<bool> NoExecStack("no-exec-stack",
215 cl::desc("File doesn't need an exec stack"),
216 cl::cat(MCCategory));
217
218 static cl::opt<bool> ValidateCFI("validate-cfi",
219 cl::desc("Validate the CFI directives"),
220 cl::cat(MCCategory));
221
222 enum ActionType {
223 AC_AsLex,
224 AC_Assemble,
225 AC_Disassemble,
226 AC_MDisassemble,
227 AC_CDisassemble,
228 };
229
230 static cl::opt<ActionType> Action(
231 cl::desc("Action to perform:"), cl::init(AC_Assemble),
232 cl::values(clEnumValN(AC_AsLex, "as-lex", "Lex tokens from a .s file"),
233 clEnumValN(AC_Assemble, "assemble",
234 "Assemble a .s file (default)"),
235 clEnumValN(AC_Disassemble, "disassemble",
236 "Disassemble strings of hex bytes"),
237 clEnumValN(AC_MDisassemble, "mdis",
238 "Marked up disassembly of strings of hex bytes"),
239 clEnumValN(AC_CDisassemble, "cdis",
240 "Colored disassembly of strings of hex bytes")),
241 cl::cat(MCCategory));
242
GetTarget(const char * ProgName)243 static const Target *GetTarget(const char *ProgName) {
244 // Figure out the target triple.
245 if (TripleName.empty())
246 TripleName = sys::getDefaultTargetTriple();
247 Triple TheTriple(Triple::normalize(TripleName));
248
249 // Get the target specific parser.
250 std::string Error;
251 const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
252 Error);
253 if (!TheTarget) {
254 WithColor::error(errs(), ProgName) << Error;
255 return nullptr;
256 }
257
258 // Update the triple name and return the found target.
259 TripleName = TheTriple.getTriple();
260 return TheTarget;
261 }
262
GetOutputStream(StringRef Path,sys::fs::OpenFlags Flags)263 static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path,
264 sys::fs::OpenFlags Flags) {
265 std::error_code EC;
266 auto Out = std::make_unique<ToolOutputFile>(Path, EC, Flags);
267 if (EC) {
268 WithColor::error() << EC.message() << '\n';
269 return nullptr;
270 }
271
272 return Out;
273 }
274
275 static std::string DwarfDebugFlags;
setDwarfDebugFlags(int argc,char ** argv)276 static void setDwarfDebugFlags(int argc, char **argv) {
277 if (!getenv("RC_DEBUG_OPTIONS"))
278 return;
279 for (int i = 0; i < argc; i++) {
280 DwarfDebugFlags += argv[i];
281 if (i + 1 < argc)
282 DwarfDebugFlags += " ";
283 }
284 }
285
286 static std::string DwarfDebugProducer;
setDwarfDebugProducer()287 static void setDwarfDebugProducer() {
288 if(!getenv("DEBUG_PRODUCER"))
289 return;
290 DwarfDebugProducer += getenv("DEBUG_PRODUCER");
291 }
292
AsLexInput(SourceMgr & SrcMgr,MCAsmInfo & MAI,raw_ostream & OS)293 static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI,
294 raw_ostream &OS) {
295
296 AsmLexer Lexer(MAI);
297 Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer());
298
299 bool Error = false;
300 while (Lexer.Lex().isNot(AsmToken::Eof)) {
301 Lexer.getTok().dump(OS);
302 OS << "\n";
303 if (Lexer.getTok().getKind() == AsmToken::Error)
304 Error = true;
305 }
306
307 return Error;
308 }
309
fillCommandLineSymbols(MCAsmParser & Parser)310 static int fillCommandLineSymbols(MCAsmParser &Parser) {
311 for (auto &I: DefineSymbol) {
312 auto Pair = StringRef(I).split('=');
313 auto Sym = Pair.first;
314 auto Val = Pair.second;
315
316 if (Sym.empty() || Val.empty()) {
317 WithColor::error() << "defsym must be of the form: sym=value: " << I
318 << "\n";
319 return 1;
320 }
321 int64_t Value;
322 if (Val.getAsInteger(0, Value)) {
323 WithColor::error() << "value is not an integer: " << Val << "\n";
324 return 1;
325 }
326 Parser.getContext().setSymbolValue(Parser.getStreamer(), Sym, Value);
327 }
328 return 0;
329 }
330
AssembleInput(const char * ProgName,const Target * TheTarget,SourceMgr & SrcMgr,MCContext & Ctx,MCStreamer & Str,MCAsmInfo & MAI,MCSubtargetInfo & STI,MCInstrInfo & MCII,MCTargetOptions const & MCOptions)331 static int AssembleInput(const char *ProgName, const Target *TheTarget,
332 SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
333 MCAsmInfo &MAI, MCSubtargetInfo &STI,
334 MCInstrInfo &MCII, MCTargetOptions const &MCOptions) {
335 std::unique_ptr<MCAsmParser> Parser(
336 createMCAsmParser(SrcMgr, Ctx, Str, MAI));
337 std::unique_ptr<MCTargetAsmParser> TAP(
338 TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
339
340 if (!TAP) {
341 WithColor::error(errs(), ProgName)
342 << "this target does not support assembly parsing.\n";
343 return 1;
344 }
345
346 int SymbolResult = fillCommandLineSymbols(*Parser);
347 if(SymbolResult)
348 return SymbolResult;
349 Parser->setShowParsedOperands(ShowInstOperands);
350 Parser->setTargetParser(*TAP);
351 Parser->getLexer().setLexMasmIntegers(LexMasmIntegers);
352 Parser->getLexer().setLexMasmHexFloats(LexMasmHexFloats);
353 Parser->getLexer().setLexMotorolaIntegers(LexMotorolaIntegers);
354
355 int Res = Parser->Run(NoInitialTextSection);
356
357 return Res;
358 }
359
main(int argc,char ** argv)360 int main(int argc, char **argv) {
361 InitLLVM X(argc, argv);
362
363 // Initialize targets and assembly printers/parsers.
364 llvm::InitializeAllTargetInfos();
365 llvm::InitializeAllTargetMCs();
366 llvm::InitializeAllAsmParsers();
367 llvm::InitializeAllDisassemblers();
368
369 // Register the target printer for --version.
370 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
371
372 cl::HideUnrelatedOptions({&MCCategory, &getColorCategory()});
373 cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
374 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
375 MCOptions.CompressDebugSections = CompressDebugSections.getValue();
376 MCOptions.ShowMCInst = ShowInst;
377 MCOptions.AsmVerbose = true;
378 MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;
379 MCOptions.InstPrinterOptions = InstPrinterOptions;
380
381 setDwarfDebugFlags(argc, argv);
382 setDwarfDebugProducer();
383
384 const char *ProgName = argv[0];
385 const Target *TheTarget = GetTarget(ProgName);
386 if (!TheTarget)
387 return 1;
388 // Now that GetTarget() has (potentially) replaced TripleName, it's safe to
389 // construct the Triple object.
390 Triple TheTriple(TripleName);
391
392 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
393 MemoryBuffer::getFileOrSTDIN(InputFilename, /*IsText=*/true);
394 if (std::error_code EC = BufferPtr.getError()) {
395 WithColor::error(errs(), ProgName)
396 << InputFilename << ": " << EC.message() << '\n';
397 return 1;
398 }
399 MemoryBuffer *Buffer = BufferPtr->get();
400
401 SourceMgr SrcMgr;
402
403 // Tell SrcMgr about this buffer, which is what the parser will pick up.
404 SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
405
406 // Record the location of the include directories so that the lexer can find
407 // it later.
408 SrcMgr.setIncludeDirs(IncludeDirs);
409
410 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
411 assert(MRI && "Unable to create target register info!");
412
413 std::unique_ptr<MCAsmInfo> MAI(
414 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
415 assert(MAI && "Unable to create target asm info!");
416
417 if (CompressDebugSections != DebugCompressionType::None) {
418 if (const char *Reason = compression::getReasonIfUnsupported(
419 compression::formatFor(CompressDebugSections))) {
420 WithColor::error(errs(), ProgName)
421 << "--compress-debug-sections: " << Reason;
422 return 1;
423 }
424 }
425 MAI->setPreserveAsmComments(PreserveComments);
426 MAI->setCommentColumn(CommentColumn);
427
428 // Package up features to be passed to target/subtarget
429 std::string FeaturesStr;
430 if (MAttrs.size()) {
431 SubtargetFeatures Features;
432 for (unsigned i = 0; i != MAttrs.size(); ++i)
433 Features.AddFeature(MAttrs[i]);
434 FeaturesStr = Features.getString();
435 }
436
437 std::unique_ptr<MCSubtargetInfo> STI(
438 TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
439 assert(STI && "Unable to create subtarget info!");
440
441 // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
442 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
443 MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr,
444 &MCOptions);
445 std::unique_ptr<MCObjectFileInfo> MOFI(
446 TheTarget->createMCObjectFileInfo(Ctx, PIC, LargeCodeModel));
447 Ctx.setObjectFileInfo(MOFI.get());
448
449 Ctx.setGenDwarfForAssembly(GenDwarfForAssembly);
450 // Default to 4 for dwarf version.
451 unsigned DwarfVersion = MCOptions.DwarfVersion ? MCOptions.DwarfVersion : 4;
452 if (DwarfVersion < 2 || DwarfVersion > 5) {
453 errs() << ProgName << ": Dwarf version " << DwarfVersion
454 << " is not supported." << '\n';
455 return 1;
456 }
457 Ctx.setDwarfVersion(DwarfVersion);
458 if (MCOptions.Dwarf64) {
459 // The 64-bit DWARF format was introduced in DWARFv3.
460 if (DwarfVersion < 3) {
461 errs() << ProgName
462 << ": the 64-bit DWARF format is not supported for DWARF versions "
463 "prior to 3\n";
464 return 1;
465 }
466 // 32-bit targets don't support DWARF64, which requires 64-bit relocations.
467 if (MAI->getCodePointerSize() < 8) {
468 errs() << ProgName
469 << ": the 64-bit DWARF format is only supported for 64-bit "
470 "targets\n";
471 return 1;
472 }
473 // If needsDwarfSectionOffsetDirective is true, we would eventually call
474 // MCStreamer::emitSymbolValue() with IsSectionRelative = true, but that
475 // is supported only for 4-byte long references.
476 if (MAI->needsDwarfSectionOffsetDirective()) {
477 errs() << ProgName << ": the 64-bit DWARF format is not supported for "
478 << TheTriple.normalize() << "\n";
479 return 1;
480 }
481 Ctx.setDwarfFormat(dwarf::DWARF64);
482 }
483 if (!DwarfDebugFlags.empty())
484 Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags));
485 if (!DwarfDebugProducer.empty())
486 Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer));
487 if (!DebugCompilationDir.empty())
488 Ctx.setCompilationDir(DebugCompilationDir);
489 else {
490 // If no compilation dir is set, try to use the current directory.
491 SmallString<128> CWD;
492 if (!sys::fs::current_path(CWD))
493 Ctx.setCompilationDir(CWD);
494 }
495 for (const auto &Arg : DebugPrefixMap) {
496 const auto &KV = StringRef(Arg).split('=');
497 Ctx.addDebugPrefixMapEntry(std::string(KV.first), std::string(KV.second));
498 }
499 if (!MainFileName.empty())
500 Ctx.setMainFileName(MainFileName);
501 if (GenDwarfForAssembly)
502 Ctx.setGenDwarfRootFile(InputFilename, Buffer->getBuffer());
503
504 sys::fs::OpenFlags Flags = (FileType == OFT_AssemblyFile)
505 ? sys::fs::OF_TextWithCRLF
506 : sys::fs::OF_None;
507 std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename, Flags);
508 if (!Out)
509 return 1;
510
511 std::unique_ptr<ToolOutputFile> DwoOut;
512 if (!SplitDwarfFile.empty()) {
513 if (FileType != OFT_ObjectFile) {
514 WithColor::error() << "dwo output only supported with object files\n";
515 return 1;
516 }
517 DwoOut = GetOutputStream(SplitDwarfFile, sys::fs::OF_None);
518 if (!DwoOut)
519 return 1;
520 }
521
522 std::unique_ptr<buffer_ostream> BOS;
523 raw_pwrite_stream *OS = &Out->os();
524 std::unique_ptr<MCStreamer> Str;
525
526 std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
527 assert(MCII && "Unable to create instruction info!");
528
529 std::unique_ptr<MCInstPrinter> IP;
530 if (ValidateCFI) {
531 // TODO: The DWARF CFI checker support for emitting anything other than
532 // errors and warnings has not been implemented yet. Because of this, it is
533 // assert-checked that the filetype output is null.
534 assert(FileType == OFT_Null);
535 auto FFA = std::make_unique<CFIFunctionFrameAnalyzer>(Ctx, *MCII);
536 auto FFS = std::make_unique<CFIFunctionFrameStreamer>(Ctx, std::move(FFA));
537 TheTarget->createNullTargetStreamer(*FFS);
538 Str = std::move(FFS);
539 } else if (FileType == OFT_AssemblyFile) {
540 IP.reset(TheTarget->createMCInstPrinter(
541 Triple(TripleName), OutputAsmVariant, *MAI, *MCII, *MRI));
542
543 if (!IP) {
544 WithColor::error()
545 << "unable to create instruction printer for target triple '"
546 << TheTriple.normalize() << "' with assembly variant "
547 << OutputAsmVariant << ".\n";
548 return 1;
549 }
550
551 for (StringRef Opt : InstPrinterOptions)
552 if (!IP->applyTargetSpecificCLOption(Opt)) {
553 WithColor::error() << "invalid InstPrinter option '" << Opt << "'\n";
554 return 1;
555 }
556
557 // Set the display preference for hex vs. decimal immediates.
558 IP->setPrintImmHex(PrintImmHex);
559
560 switch (Action) {
561 case AC_MDisassemble:
562 IP->setUseMarkup(true);
563 break;
564 case AC_CDisassemble:
565 IP->setUseColor(true);
566 break;
567 default:
568 break;
569 }
570
571 // Set up the AsmStreamer.
572 std::unique_ptr<MCCodeEmitter> CE;
573 if (ShowEncoding)
574 CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
575
576 std::unique_ptr<MCAsmBackend> MAB(
577 TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
578 auto FOut = std::make_unique<formatted_raw_ostream>(*OS);
579 Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), std::move(IP),
580 std::move(CE), std::move(MAB)));
581
582 } else if (FileType == OFT_Null) {
583 Str.reset(TheTarget->createNullStreamer(Ctx));
584 } else {
585 assert(FileType == OFT_ObjectFile && "Invalid file type!");
586
587 if (!Out->os().supportsSeeking()) {
588 BOS = std::make_unique<buffer_ostream>(Out->os());
589 OS = BOS.get();
590 }
591
592 MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, Ctx);
593 MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
594 Str.reset(TheTarget->createMCObjectStreamer(
595 TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
596 DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os())
597 : MAB->createObjectWriter(*OS),
598 std::unique_ptr<MCCodeEmitter>(CE), *STI));
599 if (NoExecStack)
600 Str->switchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
601 Str->emitVersionForTarget(TheTriple, VersionTuple(), nullptr,
602 VersionTuple());
603 }
604
605 int Res = 1;
606 bool disassemble = false;
607 switch (Action) {
608 case AC_AsLex:
609 Res = AsLexInput(SrcMgr, *MAI, Out->os());
610 break;
611 case AC_Assemble:
612 Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI,
613 *MCII, MCOptions);
614 break;
615 case AC_MDisassemble:
616 case AC_CDisassemble:
617 case AC_Disassemble:
618 disassemble = true;
619 break;
620 }
621 if (disassemble)
622 Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
623 SrcMgr, Ctx, MCOptions, HexBytes);
624
625 // Keep output if no errors.
626 if (Res == 0) {
627 Out->keep();
628 if (DwoOut)
629 DwoOut->keep();
630 }
631 return Res;
632 }
633