llvm.org GIT mirror llvm / 6e1f066
[XRay] Implement `llvm-xray convert` -- trace file conversion This is the second part of a multi-part change to define additional subcommands to the `llvm-xray` tool. This change defines a conversion subcommand to take XRay log files, and turns them from one format to another (binary or YAML). This currently only supports the first version of the log file format, defined in the compiler-rt runtime. Depends on D21987. Reviewers: dblaikie, echristo Subscribers: mehdi_amini, dberris, beanz, llvm-commits Differential Revision: https://reviews.llvm.org/D24376 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291529 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 3 years ago
21 changed file(s) with 950 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
0 ---
1 - { id: 1, address: 0x000000000041CA40, function: 0x000000000041CA40, kind: function-enter,
2 always-instrument: true }
3 - { id: 1, address: 0x000000000041CA50, function: 0x000000000041CA40, kind: tail-exit,
4 always-instrument: true }
5 - { id: 2, address: 0x000000000041CA70, function: 0x000000000041CA70, kind: function-enter,
6 always-instrument: true }
7 - { id: 2, address: 0x000000000041CA7C, function: 0x000000000041CA70, kind: tail-exit,
8 always-instrument: true }
9 - { id: 3, address: 0x000000000041CAA0, function: 0x000000000041CAA0, kind: function-enter,
10 always-instrument: true }
11 - { id: 3, address: 0x000000000041CAB4, function: 0x000000000041CAA0, kind: function-exit,
12 always-instrument: true }
13 ...
+0
-3
test/tools/llvm-xray/X86/bad-instrmap-sizes.bin less more
None ; RUN: not llvm-xray extract %S/Inputs/elf64-badentrysizes.bin 2>&1 | FileCheck %s
1 ; CHECK: llvm-xray: Cannot extract instrumentation map from '{{.*}}elf64-badentrysizes.bin'.
2 ; CHECK-NEXT: Instrumentation map entries not evenly divisible by size of an XRay sled entry in ELF64.
0 ; RUN: not llvm-xray extract %S/Inputs/elf64-badentrysizes.bin 2>&1 | FileCheck %s
1 ; CHECK: llvm-xray: Cannot extract instrumentation map from '{{.*}}elf64-badentrysizes.bin'.
2 ; CHECK-NEXT: Instrumentation map entries not evenly divisible by size of an XRay sled entry in ELF64.
0 #RUN: llvm-xray convert %s -i=yaml -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
1 ---
2 header:
3 version: 1
4 type: 0
5 constant-tsc: true
6 nonstop-tsc: true
7 cycle-frequency: 2601000000
8 records:
9 - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-enter,
10 tsc: 10001 }
11 - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-exit,
12 tsc: 10100 }
13 ...
14
15 #CHECK: ---
16 #CHECK-NEXT: header:
17 #CHECK-NEXT: version: 1
18 #CHECK-NEXT: type: 0
19 #CHECK-NEXT: constant-tsc: true
20 #CHECK-NEXT: nonstop-tsc: true
21 #CHECK-NEXT: cycle-frequency: 2601000000
22 #CHECK-NEXT: records:
23 #CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-enter,
24 #CHECK-NEXT: tsc: 10001 }
25 #CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-exit,
26 #CHECK-NEXT: tsc: 10100 }
27 #CHECK-NEXT: ...
0 ; RUN: llvm-xray convert %S/Inputs/naive-log-simple.xray -f=yaml -o - | FileCheck %s
1
2 ; CHECK: ---
3 ; CHECK-NEXT: header:
4 ; CHECK-NEXT: version: 1
5 ; CHECK-NEXT: type: 0
6 ; CHECK-NEXT: constant-tsc: true
7 ; CHECK-NEXT: nonstop-tsc: true
8 ; CHECK-NEXT: cycle-frequency: 2601000000
9 ; CHECK-NEXT: records:
10 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '3', cpu: 37, thread: 84697, kind: function-enter,
11 ; CHECK-NEXT: tsc: 3315356841453914 }
12 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 37, thread: 84697, kind: function-enter,
13 ; CHECK-NEXT: tsc: 3315356841454542 }
14 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 37, thread: 84697, kind: function-exit,
15 ; CHECK-NEXT: tsc: 3315356841454670 }
16 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 37, thread: 84697, kind: function-enter,
17 ; CHECK-NEXT: tsc: 3315356841454762 }
18 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 37, thread: 84697, kind: function-exit,
19 ; CHECK-NEXT: tsc: 3315356841454802 }
20 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '3', cpu: 37, thread: 84697, kind: function-exit,
21 ; CHECK-NEXT: tsc: 3315356841494828 }
22 ; CHECK-NEXT: ...
0 ; RUN: llvm-xray convert -m %S/Inputs/elf64-sample-o2.bin -y %S/Inputs/naive-log-simple.xray -f=yaml -o - 2>&1 | FileCheck %s
1
2 ; CHECK: ---
3 ; CHECK-NEXT: header:
4 ; CHECK-NEXT: version: 1
5 ; CHECK-NEXT: type: 0
6 ; CHECK-NEXT: constant-tsc: true
7 ; CHECK-NEXT: nonstop-tsc: true
8 ; CHECK-NEXT: cycle-frequency: 2601000000
9 ; CHECK-NEXT: records:
10 ; CHECK-NEXT: - { type: 0, func-id: 3, function: main, cpu: 37, thread: 84697, kind: function-enter,
11 ; CHECK-NEXT: tsc: 3315356841453914 }
12 ; CHECK-NEXT: - { type: 0, func-id: 2, function: 'foo()', cpu: 37, thread: 84697, kind: function-enter,
13 ; CHECK-NEXT: tsc: 3315356841454542 }
14 ; CHECK-NEXT: - { type: 0, func-id: 2, function: 'foo()', cpu: 37, thread: 84697, kind: function-exit,
15 ; CHECK-NEXT: tsc: 3315356841454670 }
16 ; CHECK-NEXT: - { type: 0, func-id: 1, function: 'bar()', cpu: 37, thread: 84697, kind: function-enter,
17 ; CHECK-NEXT: tsc: 3315356841454762 }
18 ; CHECK-NEXT: - { type: 0, func-id: 1, function: 'bar()', cpu: 37, thread: 84697, kind: function-exit,
19 ; CHECK-NEXT: tsc: 3315356841454802 }
20 ; CHECK-NEXT: - { type: 0, func-id: 3, function: main, cpu: 37, thread: 84697, kind: function-exit,
21 ; CHECK-NEXT: tsc: 3315356841494828 }
22 ; CHECK-NEXT: ...
0 ; RUN: llvm-xray convert -m %S/Inputs/elf64-objcopied-instrmap.bin -y %S/Inputs/naive-log-simple.xray -f=yaml -o - 2>&1 | FileCheck %s
1
2 ; CHECK: ---
3 ; CHECK-NEXT: header:
4 ; CHECK-NEXT: version: 1
5 ; CHECK-NEXT: type: 0
6 ; CHECK-NEXT: constant-tsc: true
7 ; CHECK-NEXT: nonstop-tsc: true
8 ; CHECK-NEXT: cycle-frequency: 2601000000
9 ; CHECK-NEXT: records:
10 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '@(41caa0)', cpu: 37, thread: 84697,
11 ; CHECK-NEXT: kind: function-enter, tsc: 3315356841453914 }
12 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '@(41ca70)', cpu: 37, thread: 84697,
13 ; CHECK-NEXT: kind: function-enter, tsc: 3315356841454542 }
14 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '@(41ca70)', cpu: 37, thread: 84697,
15 ; CHECK-NEXT: kind: function-exit, tsc: 3315356841454670 }
16 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '@(41ca40)', cpu: 37, thread: 84697,
17 ; CHECK-NEXT: kind: function-enter, tsc: 3315356841454762 }
18 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '@(41ca40)', cpu: 37, thread: 84697,
19 ; CHECK-NEXT: kind: function-exit, tsc: 3315356841454802 }
20 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '@(41caa0)', cpu: 37, thread: 84697,
21 ; CHECK-NEXT: kind: function-exit, tsc: 3315356841494828 }
22 ; CHECK-NEXT: ...
0 ; RUN: llvm-xray convert -m %S/Inputs/simple-xray-instrmap.yaml -t yaml %S/Inputs/naive-log-simple.xray -f=yaml -o - | FileCheck %s
1
2 ; CHECK: ---
3 ; CHECK-NEXT: header:
4 ; CHECK-NEXT: version: 1
5 ; CHECK-NEXT: type: 0
6 ; CHECK-NEXT: constant-tsc: true
7 ; CHECK-NEXT: nonstop-tsc: true
8 ; CHECK-NEXT: cycle-frequency: 2601000000
9 ; CHECK-NEXT: records:
10 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '3', cpu: 37, thread: 84697, kind: function-enter,
11 ; CHECK-NEXT: tsc: 3315356841453914 }
12 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 37, thread: 84697, kind: function-enter,
13 ; CHECK-NEXT: tsc: 3315356841454542 }
14 ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 37, thread: 84697, kind: function-exit,
15 ; CHECK-NEXT: tsc: 3315356841454670 }
16 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 37, thread: 84697, kind: function-enter,
17 ; CHECK-NEXT: tsc: 3315356841454762 }
18 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 37, thread: 84697, kind: function-exit,
19 ; CHECK-NEXT: tsc: 3315356841454802 }
20 ; CHECK-NEXT: - { type: 0, func-id: 3, function: '3', cpu: 37, thread: 84697, kind: function-exit,
21 ; CHECK-NEXT: tsc: 3315356841494828 }
22 ; CHECK-NEXT: ...
0 set(LLVM_LINK_COMPONENTS
11 ${LLVM_TARGETS_TO_BUILD}
2 DebugInfoDWARF
3 Object
24 Support
3 Object)
5 Symbolize)
46
57 set(LLVM_XRAY_TOOLS
8 func-id-helper.cc
9 xray-converter.cc
610 xray-extract.cc
11 xray-extract.cc
12 xray-log-reader.cc
713 xray-registry.cc)
814
915 add_llvm_tool(llvm-xray llvm-xray.cc ${LLVM_XRAY_TOOLS})
0 //===- xray-fc-account.cc - XRay Function Call Accounting Tool ------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implementation of the helper tools dealing with XRay-generated function ids.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "func-id-helper.h"
14 #include "llvm/Support/Path.h"
15 #include
16
17 using namespace llvm;
18 using namespace xray;
19
20 std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const {
21 std::ostringstream F;
22 auto It = FunctionAddresses.find(FuncId);
23 if (It == FunctionAddresses.end()) {
24 F << "#" << FuncId;
25 return F.str();
26 }
27
28 if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second)) {
29 auto &DI = *ResOrErr;
30 if (DI.FunctionName == "")
31 F << "@(" << std::hex << It->second << ")";
32 else
33 F << DI.FunctionName;
34 } else
35 handleAllErrors(ResOrErr.takeError(), [&](const ErrorInfoBase &) {
36 F << "@(" << std::hex << It->second << ")";
37 });
38
39 return F.str();
40 }
41
42 std::string FuncIdConversionHelper::FileLineAndColumn(int32_t FuncId) const {
43 auto It = FunctionAddresses.find(FuncId);
44 if (It == FunctionAddresses.end())
45 return "(unknown)";
46
47 std::ostringstream F;
48 auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second);
49 if (!ResOrErr) {
50 consumeError(ResOrErr.takeError());
51 return "(unknown)";
52 }
53
54 auto &DI = *ResOrErr;
55 F << sys::path::filename(DI.FileName).str() << ":" << DI.Line << ":"
56 << DI.Column;
57
58 return F.str();
59 }
0 //===- func-id-helper.h - XRay Function ID Conversion Helpers -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines helper tools dealing with XRay-generated function ids.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
13 #define LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
14
15 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
16 #include
17
18 namespace llvm {
19 namespace xray {
20
21 // This class consolidates common operations related to Function IDs.
22 class FuncIdConversionHelper {
23 public:
24 using FunctionAddressMap = std::unordered_map;
25
26 private:
27 std::string BinaryInstrMap;
28 symbolize::LLVMSymbolizer &Symbolizer;
29 const FunctionAddressMap &FunctionAddresses;
30
31 public:
32 FuncIdConversionHelper(std::string BinaryInstrMap,
33 symbolize::LLVMSymbolizer &Symbolizer,
34 const FunctionAddressMap &FunctionAddresses)
35 : BinaryInstrMap(std::move(BinaryInstrMap)), Symbolizer(Symbolizer),
36 FunctionAddresses(FunctionAddresses) {}
37
38 // Returns the symbol or a string representation of the function id.
39 std::string SymbolOrNumber(int32_t FuncId) const;
40
41 // Returns the file and column from debug info for the given function id.
42 std::string FileLineAndColumn(int32_t FuncId) const;
43 };
44
45 } // namespace xray
46 } // namespace llvm
47
48 #endif // LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
0 //===- xray-converter.cc - XRay Trace Conversion --------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implements the trace conversion functions.
10 //
11 //===----------------------------------------------------------------------===//
12 #include "xray-converter.h"
13
14 #include "xray-extract.h"
15 #include "xray-record-yaml.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
23
24 using namespace llvm;
25 using namespace xray;
26
27 // llvm-xray convert
28 // ----------------------------------------------------------------------------
29 static cl::SubCommand Convert("convert", "Trace Format Conversion");
30 static cl::opt ConvertInput(cl::Positional,
31 cl::desc(""),
32 cl::Required, cl::sub(Convert));
33 enum class ConvertFormats { BINARY, YAML };
34 static cl::opt ConvertInputFormat(
35 "input-format", cl::desc("input format"),
36 cl::values(clEnumValN(ConvertFormats::BINARY, "raw",
37 "input is in raw binary"),
38 clEnumValN(ConvertFormats::YAML, "yaml", "input is in yaml")),
39 cl::sub(Convert));
40 static cl::alias ConvertInputFormat2("i", cl::aliasopt(ConvertInputFormat),
41 cl::desc("Alias for -input-format"),
42 cl::sub(Convert));
43 static cl::opt ConvertOutputFormat(
44 "output-format", cl::desc("output format"),
45 cl::values(clEnumValN(ConvertFormats::BINARY, "raw", "output in binary"),
46 clEnumValN(ConvertFormats::YAML, "yaml", "output in yaml")),
47 cl::sub(Convert));
48 static cl::alias ConvertOutputFormat2("f", cl::aliasopt(ConvertOutputFormat),
49 cl::desc("Alias for -output-format"),
50 cl::sub(Convert));
51 static cl::opt
52 ConvertOutput("output", cl::value_desc("output file"), cl::init("-"),
53 cl::desc("output file; use '-' for stdout"),
54 cl::sub(Convert));
55 static cl::alias ConvertOutput2("o", cl::aliasopt(ConvertOutput),
56 cl::desc("Alias for -output"),
57 cl::sub(Convert));
58
59 static cl::opt
60 ConvertSymbolize("symbolize",
61 cl::desc("symbolize function ids from the input log"),
62 cl::init(false), cl::sub(Convert));
63 static cl::alias ConvertSymbolize2("y", cl::aliasopt(ConvertSymbolize),
64 cl::desc("Alias for -symbolize"),
65 cl::sub(Convert));
66
67 static cl::opt
68 ConvertInstrMap("instr_map",
69 cl::desc("binary with the instrumentation map, or "
70 "a separate instrumentation map"),
71 cl::value_desc("binary with xray_instr_map"),
72 cl::sub(Convert), cl::init(""));
73 static cl::alias ConvertInstrMap2("m", cl::aliasopt(ConvertInstrMap),
74 cl::desc("Alias for -instr_map"),
75 cl::sub(Convert));
76 static cl::opt ConvertSortInput(
77 "sort",
78 cl::desc("determines whether to sort input log records by timestamp"),
79 cl::sub(Convert), cl::init(true));
80 static cl::alias ConvertSortInput2("s", cl::aliasopt(ConvertSortInput),
81 cl::desc("Alias for -sort"),
82 cl::sub(Convert));
83 static cl::opt InstrMapFormat(
84 "instr-map-format", cl::desc("format of instrumentation map"),
85 cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
86 "instrumentation map in an ELF header"),
87 clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
88 "yaml", "instrumentation map in YAML")),
89 cl::sub(Convert), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
90 static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
91 cl::desc("Alias for -instr-map-format"),
92 cl::sub(Convert));
93
94 using llvm::yaml::MappingTraits;
95 using llvm::yaml::ScalarEnumerationTraits;
96 using llvm::yaml::IO;
97 using llvm::yaml::Output;
98
99 void TraceConverter::exportAsYAML(const LogReader &Records, raw_ostream &OS) {
100 YAMLXRayTrace Trace;
101 const auto &FH = Records.getFileHeader();
102 Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC,
103 FH.CycleFrequency};
104 Trace.Records.reserve(Records.size());
105 for (const auto &R : Records) {
106 Trace.Records.push_back({R.RecordType, R.CPU, R.Type, R.FuncId,
107 Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
108 : std::to_string(R.FuncId),
109 R.TSC, R.TId});
110 }
111 Output Out(OS);
112 Out << Trace;
113 }
114
115 void TraceConverter::exportAsRAWv1(const LogReader &Records, raw_ostream &OS) {
116 // First write out the file header, in the correct endian-appropriate format
117 // (XRay assumes currently little endian).
118 support::endian::Writer Writer(OS);
119 const auto &FH = Records.getFileHeader();
120 Writer.write(FH.Version);
121 Writer.write(FH.Type);
122 uint32_t Bitfield{0};
123 if (FH.ConstantTSC)
124 Bitfield |= 1uL;
125 if (FH.NonstopTSC)
126 Bitfield |= 1uL << 1;
127 Writer.write(Bitfield);
128 Writer.write(FH.CycleFrequency);
129
130 // There's 16 bytes of padding at the end of the file header.
131 static constexpr uint32_t Padding4B = 0;
132 Writer.write(Padding4B);
133 Writer.write(Padding4B);
134 Writer.write(Padding4B);
135 Writer.write(Padding4B);
136
137 // Then write out the rest of the records, still in an endian-appropriate
138 // format.
139 for (const auto &R : Records) {
140 Writer.write(R.RecordType);
141 Writer.write(R.CPU);
142 switch (R.Type) {
143 case RecordTypes::ENTER:
144 Writer.write(uint8_t{0});
145 break;
146 case RecordTypes::EXIT:
147 Writer.write(uint8_t{1});
148 break;
149 }
150 Writer.write(R.FuncId);
151 Writer.write(R.TSC);
152 Writer.write(R.TId);
153 Writer.write(Padding4B);
154 Writer.write(Padding4B);
155 Writer.write(Padding4B);
156 }
157 }
158
159 namespace llvm {
160 namespace xray {
161
162 static CommandRegistration Unused(&Convert, []() -> Error {
163 // FIXME: Support conversion to BINARY when upgrading XRay trace versions.
164 int Fd;
165 auto EC = sys::fs::openFileForRead(ConvertInput, Fd);
166 if (EC)
167 return make_error(
168 Twine("Cannot open file '") + ConvertInput + "'", EC);
169
170 Error Err = Error::success();
171 xray::InstrumentationMapExtractor Extractor(ConvertInstrMap, InstrMapFormat,
172 Err);
173 handleAllErrors(std::move(Err),
174 [&](const ErrorInfoBase &E) { E.log(errs()); });
175
176 const auto &FunctionAddresses = Extractor.getFunctionAddresses();
177 symbolize::LLVMSymbolizer::Options Opts(
178 symbolize::FunctionNameKind::LinkageName, true, true, false, "");
179 symbolize::LLVMSymbolizer Symbolizer(Opts);
180 llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
181 FunctionAddresses);
182 llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
183 LogReader::LoaderFunction Loader;
184 switch (ConvertInputFormat) {
185 case ConvertFormats::BINARY:
186 Loader = NaiveLogLoader;
187 break;
188 case ConvertFormats::YAML:
189 Loader = YAMLLogLoader;
190 break;
191 }
192
193 LogReader Reader(ConvertInput, Err, ConvertSortInput, Loader);
194 if (Err)
195 return joinErrors(
196 make_error(
197 Twine("Failed loading input file '") + ConvertInput + "'.",
198 std::make_error_code(std::errc::protocol_error)),
199 std::move(Err));
200
201 raw_fd_ostream OS(ConvertOutput, EC,
202 ConvertOutputFormat == ConvertFormats::BINARY
203 ? sys::fs::OpenFlags::F_None
204 : sys::fs::OpenFlags::F_Text);
205 if (EC)
206 return make_error(
207 Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
208
209 switch (ConvertOutputFormat) {
210 case ConvertFormats::YAML:
211 TC.exportAsYAML(Reader, OS);
212 break;
213 case ConvertFormats::BINARY:
214 TC.exportAsRAWv1(Reader, OS);
215 break;
216 }
217 return Error::success();
218 });
219
220 } // namespace xray
221 } // namespace llvm
0 //===- xray-converter.h - XRay Trace Conversion ---------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the TraceConverter class for turning binary traces into
10 // human-readable text and vice versa.
11 //
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
14 #define LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
15
16 #include "func-id-helper.h"
17 #include "xray-log-reader.h"
18 #include "xray-record.h"
19
20 namespace llvm {
21 namespace xray {
22
23 class TraceConverter {
24 FuncIdConversionHelper &FuncIdHelper;
25 bool Symbolize;
26
27 public:
28 TraceConverter(FuncIdConversionHelper &FuncIdHelper, bool Symbolize = false)
29 : FuncIdHelper(FuncIdHelper), Symbolize(Symbolize) {}
30
31 void exportAsYAML(const LogReader &Records, raw_ostream &OS);
32 void exportAsRAWv1(const LogReader &Records, raw_ostream &OS);
33 };
34
35 } // namespace xray
36 } // namespace llvm
37
38 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
161161 "'.",
162162 std::make_error_code(std::errc::executable_format_error));
163163 }
164 auto AlwaysInstrument = Extractor.getU8(&OffsetPtr);
165 Entry.AlwaysInstrument = AlwaysInstrument != 0;
164 Entry.AlwaysInstrument = Extractor.getU8(&OffsetPtr) != 0;
166165
167166 // We replicate the function id generation scheme implemented in the runtime
168167 // here. Ideally we should be able to break it out, or output this map from
184183 return llvm::Error::success();
185184 }
186185
186 Error LoadYAMLInstrMap(
187 StringRef Filename, std::deque &Sleds,
188 InstrumentationMapExtractor::FunctionAddressMap &InstrMap,
189 InstrumentationMapExtractor::FunctionAddressReverseMap &FunctionIds) {
190 int Fd;
191 if (auto EC = sys::fs::openFileForRead(Filename, Fd))
192 return make_error(
193 Twine("Failed opening file '") + Filename + "' for reading.", EC);
194
195 uint64_t FileSize;
196 if (auto EC = sys::fs::file_size(Filename, FileSize))
197 return make_error(
198 Twine("Failed getting size of file '") + Filename + "'.", EC);
199
200 std::error_code EC;
201 sys::fs::mapped_file_region MappedFile(
202 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
203 if (EC)
204 return make_error(
205 Twine("Failed memory-mapping file '") + Filename + "'.", EC);
206
207 std::vector YAMLSleds;
208 Input In(StringRef(MappedFile.data(), MappedFile.size()));
209 In >> YAMLSleds;
210 if (In.error())
211 return make_error(
212 Twine("Failed loading YAML document from '") + Filename + "'.",
213 In.error());
214
215 for (const auto &Y : YAMLSleds) {
216 InstrMap[Y.FuncId] = Y.Function;
217 FunctionIds[Y.Function] = Y.FuncId;
218 Sleds.push_back(
219 SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument});
220 }
221 return Error::success();
222 }
223
187224 } // namespace
188225
189226 InstrumentationMapExtractor::InstrumentationMapExtractor(std::string Filename,
190227 InputFormats Format,
191228 Error &EC) {
192229 ErrorAsOutParameter ErrAsOutputParam(&EC);
230 if (Filename.empty()) {
231 EC = Error::success();
232 return;
233 }
193234 switch (Format) {
194235 case InputFormats::ELF: {
195236 EC = handleErrors(
196237 LoadBinaryInstrELF(Filename, Sleds, FunctionAddresses, FunctionIds),
197 [](std::unique_ptr E) {
238 [&](std::unique_ptr E) {
198239 return joinErrors(
199240 make_error(
200241 Twine("Cannot extract instrumentation map from '") +
201 ExtractInput + "'.",
242 Filename + "'.",
202243 std::make_error_code(std::errc::executable_format_error)),
203244 std::move(E));
204245 });
205246 break;
206247 }
207 default:
208 llvm_unreachable("Input format type not supported yet.");
248 case InputFormats::YAML: {
249 EC = handleErrors(
250 LoadYAMLInstrMap(Filename, Sleds, FunctionAddresses, FunctionIds),
251 [&](std::unique_ptr E) {
252 return joinErrors(
253 make_error(
254 Twine("Cannot load YAML instrumentation map from '") +
255 Filename + "'.",
256 std::make_error_code(std::errc::wrong_protocol_type)),
257 std::move(E));
258 });
209259 break;
260 }
210261 }
211262 }
212263
0 //===- xray-log-reader.cc - XRay Log Reader Implementation ----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // XRay log reader implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 #include
13
14 #include "xray-log-reader.h"
15 #include "xray-record-yaml.h"
16 #include "llvm/Support/DataExtractor.h"
17 #include "llvm/Support/FileSystem.h"
18
19 using namespace llvm;
20 using namespace llvm::xray;
21 using llvm::yaml::Input;
22
23 LogReader::LogReader(
24 StringRef Filename, Error &Err, bool Sort,
25 std::function &)>
26 Loader) {
27 ErrorAsOutParameter Guard(&Err);
28 int Fd;
29 if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
30 Err = make_error(
31 Twine("Cannot read log from '") + Filename + "'", EC);
32 return;
33 }
34 uint64_t FileSize;
35 if (auto EC = sys::fs::file_size(Filename, FileSize)) {
36 Err = make_error(
37 Twine("Cannot read log from '") + Filename + "'", EC);
38 return;
39 }
40
41 std::error_code EC;
42 sys::fs::mapped_file_region MappedFile(
43 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
44 if (EC) {
45 Err = make_error(
46 Twine("Cannot read log from '") + Filename + "'", EC);
47 return;
48 }
49
50 if (auto E = Loader(StringRef(MappedFile.data(), MappedFile.size()),
51 FileHeader, Records)) {
52 Err = std::move(E);
53 return;
54 }
55
56 if (Sort)
57 std::sort(
58 Records.begin(), Records.end(),
59 [](const XRayRecord &L, const XRayRecord &R) { return L.TSC < R.TSC; });
60 }
61
62 Error llvm::xray::NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
63 std::vector &Records) {
64 // FIXME: Maybe deduce whether the data is little or big-endian using some
65 // magic bytes in the beginning of the file?
66
67 // First 32 bytes of the file will always be the header. We assume a certain
68 // format here:
69 //
70 // (2) uint16 : version
71 // (2) uint16 : type
72 // (4) uint32 : bitfield
73 // (8) uint64 : cycle frequency
74 // (16) - : padding
75 //
76 if (Data.size() < 32)
77 return make_error(
78 "Not enough bytes for an XRay log.",
79 std::make_error_code(std::errc::invalid_argument));
80
81 if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
82 return make_error(
83 "Invalid-sized XRay data.",
84 std::make_error_code(std::errc::invalid_argument));
85
86 DataExtractor HeaderExtractor(Data, true, 8);
87 uint32_t OffsetPtr = 0;
88 FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
89 FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
90 uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
91 FileHeader.ConstantTSC = Bitfield & 1uL;
92 FileHeader.NonstopTSC = Bitfield & 1uL << 1;
93 FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
94
95 if (FileHeader.Version != 1)
96 return make_error(
97 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
98 std::make_error_code(std::errc::invalid_argument));
99
100 // Each record after the header will be 32 bytes, in the following format:
101 //
102 // (2) uint16 : record type
103 // (1) uint8 : cpu id
104 // (1) uint8 : type
105 // (4) sint32 : function id
106 // (8) uint64 : tsc
107 // (4) uint32 : thread id
108 // (12) - : padding
109 for (auto S = Data.drop_front(32); !S.empty(); S = S.drop_front(32)) {
110 DataExtractor RecordExtractor(S, true, 8);
111 uint32_t OffsetPtr = 0;
112 Records.emplace_back();
113 auto &Record = Records.back();
114 Record.RecordType = RecordExtractor.getU16(&OffsetPtr);
115 Record.CPU = RecordExtractor.getU8(&OffsetPtr);
116 auto Type = RecordExtractor.getU8(&OffsetPtr);
117 switch (Type) {
118 case 0:
119 Record.Type = RecordTypes::ENTER;
120 break;
121 case 1:
122 Record.Type = RecordTypes::EXIT;
123 break;
124 default:
125 return make_error(
126 Twine("Unknown record type '") + Twine(int{Type}) + "'",
127 std::make_error_code(std::errc::protocol_error));
128 }
129 Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t));
130 Record.TSC = RecordExtractor.getU64(&OffsetPtr);
131 Record.TId = RecordExtractor.getU32(&OffsetPtr);
132 }
133 return Error::success();
134 }
135
136 Error llvm::xray::YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
137 std::vector &Records) {
138
139 // Load the documents from the MappedFile.
140 YAMLXRayTrace Trace;
141 Input In(Data);
142 In >> Trace;
143 if (In.error())
144 return make_error("Failed loading YAML Data.", In.error());
145
146 FileHeader.Version = Trace.Header.Version;
147 FileHeader.Type = Trace.Header.Type;
148 FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
149 FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
150 FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
151
152 if (FileHeader.Version != 1)
153 return make_error(
154 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
155 std::make_error_code(std::errc::invalid_argument));
156
157 Records.clear();
158 std::transform(Trace.Records.begin(), Trace.Records.end(),
159 std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
160 return XRayRecord{R.RecordType, R.CPU, R.Type,
161 R.FuncId, R.TSC, R.TId};
162 });
163 return Error::success();
164 }
0 //===- xray-log-reader.h - XRay Log Reader Interface ----------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Define the interface for an XRay log reader. Currently we only support one
10 // version of the log (naive log) with fixed-sized records.
11 //
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
14 #define LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
15
16 #include
17 #include
18 #include
19
20 #include "xray-record-yaml.h"
21 #include "xray-record.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/FileSystem.h"
24
25 namespace llvm {
26 namespace xray {
27
28 class LogReader {
29 XRayFileHeader FileHeader;
30 std::vector Records;
31
32 typedef std::vector::const_iterator citerator;
33
34 public:
35 typedef std::function
36 std::vector &)>
37 LoaderFunction;
38
39 LogReader(StringRef Filename, Error &Err, bool Sort, LoaderFunction Loader);
40
41 const XRayFileHeader &getFileHeader() const { return FileHeader; }
42
43 citerator begin() const { return Records.begin(); }
44 citerator end() const { return Records.end(); }
45 size_t size() const { return Records.size(); }
46 };
47
48 Error NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
49 std::vector &Records);
50 Error YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
51 std::vector &Records);
52
53 } // namespace xray
54 } // namespace llvm
55
56 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
0 //===- xray-record-yaml.h - XRay Record YAML Support Definitions ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Types and traits specialisations for YAML I/O of XRay log entries.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
13 #define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
14
15 #include
16
17 #include "xray-record.h"
18 #include "llvm/Support/YAMLTraits.h"
19
20 namespace llvm {
21 namespace xray {
22
23 struct YAMLXRayFileHeader {
24 uint16_t Version;
25 uint16_t Type;
26 bool ConstantTSC;
27 bool NonstopTSC;
28 uint64_t CycleFrequency;
29 };
30
31 struct YAMLXRayRecord {
32 uint16_t RecordType;
33 uint8_t CPU;
34 RecordTypes Type;
35 int32_t FuncId;
36 std::string Function;
37 uint64_t TSC;
38 uint32_t TId;
39 };
40
41 struct YAMLXRayTrace {
42 YAMLXRayFileHeader Header;
43 std::vector Records;
44 };
45
46 using XRayRecordStorage =
47 std::aligned_storage::type;
48
49 } // namespace xray
50
51 namespace yaml {
52
53 // YAML Traits
54 // -----------
55 template <> struct ScalarEnumerationTraits {
56 static void enumeration(IO &IO, xray::RecordTypes &Type) {
57 IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
58 IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
59 }
60 };
61
62 template <> struct MappingTraits {
63 static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) {
64 IO.mapRequired("version", Header.Version);
65 IO.mapRequired("type", Header.Type);
66 IO.mapRequired("constant-tsc", Header.ConstantTSC);
67 IO.mapRequired("nonstop-tsc", Header.NonstopTSC);
68 IO.mapRequired("cycle-frequency", Header.CycleFrequency);
69 }
70 };
71
72 template <> struct MappingTraits {
73 static void mapping(IO &IO, xray::YAMLXRayRecord &Record) {
74 // FIXME: Make this type actually be descriptive
75 IO.mapRequired("type", Record.RecordType);
76 IO.mapRequired("func-id", Record.FuncId);
77 IO.mapOptional("function", Record.Function);
78 IO.mapRequired("cpu", Record.CPU);
79 IO.mapRequired("thread", Record.TId);
80 IO.mapRequired("kind", Record.Type);
81 IO.mapRequired("tsc", Record.TSC);
82 }
83
84 static constexpr bool flow = true;
85 };
86
87 template <> struct MappingTraits {
88 static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) {
89 // A trace file contains two parts, the header and the list of all the
90 // trace records.
91 IO.mapRequired("header", Trace.Header);
92 IO.mapRequired("records", Trace.Records);
93 }
94 };
95
96 } // namespace yaml
97 } // namespace llvm
98
99 LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord)
100
101 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
0 //===- xray-record.h - XRay Trace Record ----------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file replicates the record definition for XRay log entries. This should
10 // follow the evolution of the log record versions supported in the compiler-rt
11 // xray project.
12 //
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H
15 #define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H
16
17 #include
18
19 namespace llvm {
20 namespace xray {
21
22 struct XRayFileHeader {
23 uint16_t Version = 0;
24 uint16_t Type = 0;
25 bool ConstantTSC;
26 bool NonstopTSC;
27 uint64_t CycleFrequency = 0;
28 };
29
30 enum class RecordTypes { ENTER, EXIT };
31
32 struct XRayRecord {
33 uint16_t RecordType;
34
35 // The CPU where the thread is running. We assume number of CPUs <= 256.
36 uint8_t CPU;
37
38 // Identifies the type of record.
39 RecordTypes Type;
40
41 // The function ID for the record.
42 int32_t FuncId;
43
44 // Get the full 8 bytes of the TSC when we get the log record.
45 uint64_t TSC;
46
47 // The thread ID for the currently running thread.
48 uint32_t TId;
49 };
50
51 } // namespace xray
52 } // namespace llvm
53
54 #endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H