Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 1 | //===- yaml2obj - Convert YAML to a binary object file --------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This program takes a YAML description of an object file and outputs the |
| 11 | // binary equivalent. |
| 12 | // |
| 13 | // This is used for writing tests that require binary files. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
Sean Silva | 3b76e40 | 2013-06-05 19:56:47 +0000 | [diff] [blame] | 17 | #include "yaml2obj.h" |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/StringExtras.h" |
Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 19 | #include "llvm/Support/CommandLine.h" |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 20 | #include "llvm/Support/FileSystem.h" |
Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 21 | #include "llvm/Support/ManagedStatic.h" |
| 22 | #include "llvm/Support/MemoryBuffer.h" |
| 23 | #include "llvm/Support/PrettyStackTrace.h" |
Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Signals.h" |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 25 | #include "llvm/Support/ToolOutputFile.h" |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 26 | #include "llvm/Support/YAMLTraits.h" |
Rafael Espindola | a6e9c3e | 2014-06-12 17:38:55 +0000 | [diff] [blame] | 27 | #include "llvm/Support/raw_ostream.h" |
| 28 | #include <system_error> |
Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 29 | |
| 30 | using namespace llvm; |
| 31 | |
| 32 | static cl::opt<std::string> |
| 33 | Input(cl::Positional, cl::desc("<input>"), cl::init("-")); |
| 34 | |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 35 | // TODO: The "right" way to tell what kind of object file a given YAML file |
| 36 | // corresponds to is to look at YAML "tags" (e.g. `!Foo`). Then, different |
| 37 | // tags (`!ELF`, `!COFF`, etc.) would be used to discriminate between them. |
| 38 | // Interpreting the tags is needed eventually for when writing test cases, |
| 39 | // so that we can e.g. have `!Archive` contain a sequence of `!ELF`, and |
| 40 | // just Do The Right Thing. However, interpreting these tags and acting on |
| 41 | // them appropriately requires some work in the YAML parser and the YAMLIO |
| 42 | // library. |
| 43 | enum YAMLObjectFormat { |
Sean Silva | f99309c | 2013-06-10 23:44:15 +0000 | [diff] [blame] | 44 | YOF_COFF, |
| 45 | YOF_ELF |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 46 | }; |
| 47 | |
| 48 | cl::opt<YAMLObjectFormat> Format( |
| 49 | "format", |
| 50 | cl::desc("Interpret input as this type of object file"), |
| 51 | cl::values( |
| 52 | clEnumValN(YOF_COFF, "coff", "COFF object file format"), |
Sean Silva | f99309c | 2013-06-10 23:44:15 +0000 | [diff] [blame] | 53 | clEnumValN(YOF_ELF, "elf", "ELF object file format"), |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 54 | clEnumValEnd)); |
| 55 | |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 56 | cl::opt<unsigned> |
| 57 | DocNum("docnum", cl::init(1), |
| 58 | cl::desc("Read specified document from input (default = 1)")); |
| 59 | |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 60 | static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), |
| 61 | cl::value_desc("filename")); |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 62 | |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 63 | typedef int (*ConvertFuncPtr)(yaml::Input & YIn, raw_ostream &Out); |
| 64 | |
Benjamin Kramer | f044d3f | 2015-03-09 16:23:46 +0000 | [diff] [blame] | 65 | static int convertYAML(yaml::Input &YIn, raw_ostream &Out, |
| 66 | ConvertFuncPtr Convert) { |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 67 | unsigned CurDocNum = 0; |
| 68 | do { |
| 69 | if (++CurDocNum == DocNum) |
| 70 | return Convert(YIn, Out); |
| 71 | } while (YIn.nextDocument()); |
| 72 | |
| 73 | errs() << "yaml2obj: Cannot find the " << DocNum |
| 74 | << llvm::getOrdinalSuffix(DocNum) << " document\n"; |
| 75 | return 1; |
| 76 | } |
| 77 | |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 78 | int main(int argc, char **argv) { |
| 79 | cl::ParseCommandLineOptions(argc, argv); |
| 80 | sys::PrintStackTraceOnErrorSignal(); |
| 81 | PrettyStackTraceProgram X(argc, argv); |
| 82 | llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. |
| 83 | |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 84 | if (OutputFilename.empty()) |
| 85 | OutputFilename = "-"; |
| 86 | |
Rafael Espindola | 3fd1e99 | 2014-08-25 18:16:47 +0000 | [diff] [blame] | 87 | std::error_code EC; |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 88 | std::unique_ptr<tool_output_file> Out( |
Rafael Espindola | 3fd1e99 | 2014-08-25 18:16:47 +0000 | [diff] [blame] | 89 | new tool_output_file(OutputFilename, EC, sys::fs::F_None)); |
| 90 | if (EC) { |
| 91 | errs() << EC.message() << '\n'; |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 92 | return 1; |
| 93 | } |
| 94 | |
Rafael Espindola | adf21f2 | 2014-07-06 17:43:13 +0000 | [diff] [blame] | 95 | ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = |
| 96 | MemoryBuffer::getFileOrSTDIN(Input); |
| 97 | if (!Buf) |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 98 | return 1; |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 99 | |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 100 | ConvertFuncPtr Convert = nullptr; |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 101 | if (Format == YOF_COFF) |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 102 | Convert = yaml2coff; |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 103 | else if (Format == YOF_ELF) |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 104 | Convert = yaml2elf; |
| 105 | else { |
Sean Silva | 741cebb | 2013-06-05 18:51:34 +0000 | [diff] [blame] | 106 | errs() << "Not yet implemented\n"; |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 107 | return 1; |
| 108 | } |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 109 | |
Rafael Espindola | adf21f2 | 2014-07-06 17:43:13 +0000 | [diff] [blame] | 110 | yaml::Input YIn(Buf.get()->getBuffer()); |
Simon Atanasyan | f97af8a | 2014-05-31 04:51:07 +0000 | [diff] [blame] | 111 | |
| 112 | int Res = convertYAML(YIn, Out->os(), Convert); |
Simon Atanasyan | 73e047e | 2014-05-15 16:14:02 +0000 | [diff] [blame] | 113 | if (Res == 0) |
| 114 | Out->keep(); |
| 115 | |
| 116 | return Res; |
Michael J. Spencer | 1ffd9de | 2012-08-02 19:16:56 +0000 | [diff] [blame] | 117 | } |