OSDN Git Service

[XRay] Define the library for XRay trace logs
[android-x86/external-llvm.git] / tools / llvm-xray / xray-converter.cc
1 //===- xray-converter.cc - XRay Trace Conversion --------------------------===//
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 // Implements the trace conversion functions.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "xray-converter.h"
14
15 #include "xray-extract.h"
16 #include "xray-registry.h"
17 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
18 #include "llvm/Support/EndianStream.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/YAMLTraits.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/XRay/Trace.h"
23 #include "llvm/XRay/YAMLXRayRecord.h"
24
25 using namespace llvm;
26 using namespace xray;
27
28 // llvm-xray convert
29 // ----------------------------------------------------------------------------
30 static cl::SubCommand Convert("convert", "Trace Format Conversion");
31 static cl::opt<std::string> ConvertInput(cl::Positional,
32                                          cl::desc("<xray log file>"),
33                                          cl::Required, cl::sub(Convert));
34 enum class ConvertFormats { BINARY, YAML };
35 static cl::opt<ConvertFormats> ConvertOutputFormat(
36     "output-format", cl::desc("output format"),
37     cl::values(clEnumValN(ConvertFormats::BINARY, "raw", "output in binary"),
38                clEnumValN(ConvertFormats::YAML, "yaml", "output in yaml")),
39     cl::sub(Convert));
40 static cl::alias ConvertOutputFormat2("f", cl::aliasopt(ConvertOutputFormat),
41                                       cl::desc("Alias for -output-format"),
42                                       cl::sub(Convert));
43 static cl::opt<std::string>
44     ConvertOutput("output", cl::value_desc("output file"), cl::init("-"),
45                   cl::desc("output file; use '-' for stdout"),
46                   cl::sub(Convert));
47 static cl::alias ConvertOutput2("o", cl::aliasopt(ConvertOutput),
48                                 cl::desc("Alias for -output"),
49                                 cl::sub(Convert));
50
51 static cl::opt<bool>
52     ConvertSymbolize("symbolize",
53                      cl::desc("symbolize function ids from the input log"),
54                      cl::init(false), cl::sub(Convert));
55 static cl::alias ConvertSymbolize2("y", cl::aliasopt(ConvertSymbolize),
56                                    cl::desc("Alias for -symbolize"),
57                                    cl::sub(Convert));
58
59 static cl::opt<std::string>
60     ConvertInstrMap("instr_map",
61                     cl::desc("binary with the instrumentation map, or "
62                              "a separate instrumentation map"),
63                     cl::value_desc("binary with xray_instr_map"),
64                     cl::sub(Convert), cl::init(""));
65 static cl::alias ConvertInstrMap2("m", cl::aliasopt(ConvertInstrMap),
66                                   cl::desc("Alias for -instr_map"),
67                                   cl::sub(Convert));
68 static cl::opt<bool> ConvertSortInput(
69     "sort",
70     cl::desc("determines whether to sort input log records by timestamp"),
71     cl::sub(Convert), cl::init(true));
72 static cl::alias ConvertSortInput2("s", cl::aliasopt(ConvertSortInput),
73                                    cl::desc("Alias for -sort"),
74                                    cl::sub(Convert));
75 static cl::opt<InstrumentationMapExtractor::InputFormats> InstrMapFormat(
76     "instr-map-format", cl::desc("format of instrumentation map"),
77     cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
78                           "instrumentation map in an ELF header"),
79                clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
80                           "yaml", "instrumentation map in YAML")),
81     cl::sub(Convert), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
82 static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
83                                  cl::desc("Alias for -instr-map-format"),
84                                  cl::sub(Convert));
85
86 using llvm::yaml::IO;
87 using llvm::yaml::Output;
88
89 void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) {
90   YAMLXRayTrace Trace;
91   const auto &FH = Records.getFileHeader();
92   Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC,
93                   FH.CycleFrequency};
94   Trace.Records.reserve(Records.size());
95   for (const auto &R : Records) {
96     Trace.Records.push_back({R.RecordType, R.CPU, R.Type, R.FuncId,
97                              Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
98                                        : std::to_string(R.FuncId),
99                              R.TSC, R.TId});
100   }
101   Output Out(OS);
102   Out << Trace;
103 }
104
105 void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
106   // First write out the file header, in the correct endian-appropriate format
107   // (XRay assumes currently little endian).
108   support::endian::Writer<support::endianness::little> Writer(OS);
109   const auto &FH = Records.getFileHeader();
110   Writer.write(FH.Version);
111   Writer.write(FH.Type);
112   uint32_t Bitfield{0};
113   if (FH.ConstantTSC)
114     Bitfield |= 1uL;
115   if (FH.NonstopTSC)
116     Bitfield |= 1uL << 1;
117   Writer.write(Bitfield);
118   Writer.write(FH.CycleFrequency);
119
120   // There's 16 bytes of padding at the end of the file header.
121   static constexpr uint32_t Padding4B = 0;
122   Writer.write(Padding4B);
123   Writer.write(Padding4B);
124   Writer.write(Padding4B);
125   Writer.write(Padding4B);
126
127   // Then write out the rest of the records, still in an endian-appropriate
128   // format.
129   for (const auto &R : Records) {
130     Writer.write(R.RecordType);
131     Writer.write(R.CPU);
132     switch (R.Type) {
133     case RecordTypes::ENTER:
134       Writer.write(uint8_t{0});
135       break;
136     case RecordTypes::EXIT:
137       Writer.write(uint8_t{1});
138       break;
139     }
140     Writer.write(R.FuncId);
141     Writer.write(R.TSC);
142     Writer.write(R.TId);
143     Writer.write(Padding4B);
144     Writer.write(Padding4B);
145     Writer.write(Padding4B);
146   }
147 }
148
149 namespace llvm {
150 namespace xray {
151
152 static CommandRegistration Unused(&Convert, []() -> Error {
153   // FIXME: Support conversion to BINARY when upgrading XRay trace versions.
154   int Fd;
155   auto EC = sys::fs::openFileForRead(ConvertInput, Fd);
156   if (EC)
157     return make_error<StringError>(
158         Twine("Cannot open file '") + ConvertInput + "'", EC);
159
160   Error Err = Error::success();
161   xray::InstrumentationMapExtractor Extractor(ConvertInstrMap, InstrMapFormat,
162                                               Err);
163   handleAllErrors(std::move(Err),
164                   [&](const ErrorInfoBase &E) { E.log(errs()); });
165
166   const auto &FunctionAddresses = Extractor.getFunctionAddresses();
167   symbolize::LLVMSymbolizer::Options Opts(
168       symbolize::FunctionNameKind::LinkageName, true, true, false, "");
169   symbolize::LLVMSymbolizer Symbolizer(Opts);
170   llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
171                                                   FunctionAddresses);
172   llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
173   raw_fd_ostream OS(ConvertOutput, EC,
174                     ConvertOutputFormat == ConvertFormats::BINARY
175                         ? sys::fs::OpenFlags::F_None
176                         : sys::fs::OpenFlags::F_Text);
177   if (EC)
178     return make_error<StringError>(
179         Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
180
181   if (auto TraceOrErr = loadTraceFile(ConvertInput, ConvertSortInput)) {
182     auto &T = *TraceOrErr;
183     switch (ConvertOutputFormat) {
184     case ConvertFormats::YAML:
185       TC.exportAsYAML(T, OS);
186       break;
187     case ConvertFormats::BINARY:
188       TC.exportAsRAWv1(T, OS);
189       break;
190     }
191   } else {
192     return joinErrors(
193         make_error<StringError>(
194             Twine("Failed loading input file '") + ConvertInput + "'.",
195             std::make_error_code(std::errc::protocol_error)),
196         TraceOrErr.takeError());
197   }
198   return Error::success();
199 });
200
201 } // namespace xray
202 } // namespace llvm