llvm.org GIT mirror llvm / 14cdbca
[XRay] Define the library for XRay trace logs Summary: In this change we move the definition of the log reading routines from the tools directory in LLVM to {include/llvm,lib}/XRay. We improve the documentation a little bit for the publicly accessible headers, and adjust the top-matter. This also leads to some refactoring and cleanup in the tooling code. In particular, we do the following: - Rename the class from LogReader to Trace, as it better represents the logical set of records as opposed to a log. - Use file type detection instead of asking the user to say what format the input file is. This allows us to keep the interface simple and encapsulate the logic of loading the data appropriately. In future changes we increase the API surface and write dedicated unit tests for the XRay library. Depends on D24376. Reviewers: dblaikie, echristo Subscribers: mehdi_amini, mgorny, llvm-commits, varno Differential Revision: https://reviews.llvm.org/D28345 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291652 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 3 years ago
14 changed file(s) with 483 addition(s) and 423 deletion(s). Raw diff Collapse all Expand all
0 //===- Trace.h - XRay Trace Abstraction -----------------------------------===//
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 XRay Trace class representing records in an XRay trace file.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_XRAY_TRACE_H
13 #define LLVM_XRAY_TRACE_H
14
15 #include
16 #include
17
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/XRay/XRayRecord.h"
22
23 namespace llvm {
24 namespace xray {
25
26 /// A Trace object represents the records that have been loaded from XRay
27 /// log files generated by instrumented binaries. We encapsulate the logic of
28 /// reading the traces in factory functions that populate the Trace object
29 /// appropriately.
30 ///
31 /// Trace objects provide an accessor to an XRayFileHeader which says more about
32 /// details of the file from which the XRay trace was loaded from.
33 ///
34 /// Usage:
35 ///
36 /// if (auto TraceOrErr = loadTraceFile("xray-log.something.xray")) {
37 /// auto& T = *TraceOrErr;
38 /// // T.getFileHeader() will provide information from the trace header.
39 /// for (const XRayRecord &R : T) {
40 /// // ... do something with R here.
41 /// }
42 /// } else {
43 /// // Handle the error here.
44 /// }
45 ///
46 class Trace {
47 XRayFileHeader FileHeader;
48 std::vector Records;
49
50 typedef std::vector::const_iterator citerator;
51
52 friend Expected loadTraceFile(StringRef, bool);
53
54 public:
55 /// Provides access to the loaded XRay trace file header.
56 const XRayFileHeader &getFileHeader() const { return FileHeader; }
57
58 citerator begin() const { return Records.begin(); }
59 citerator end() const { return Records.end(); }
60 size_t size() const { return Records.size(); }
61 };
62
63 /// This function will attempt to load XRay trace records from the provided
64 /// |Filename|.
65 Expected loadTraceFile(StringRef Filename, bool Sort = false);
66
67 } // namespace xray
68 } // namespace llvm
69
70 #endif // LLVM_XRAY_TRACE_H
0 //===- XRayRecord.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_XRAY_XRAY_RECORD_H
15 #define LLVM_XRAY_XRAY_RECORD_H
16
17 #include
18
19 namespace llvm {
20 namespace xray {
21
22 /// XRay traces all have a header providing some top-matter information useful
23 /// to help tools determine how to interpret the information available in the
24 /// trace.
25 struct XRayFileHeader {
26 /// Version of the XRay implementation that produced this file.
27 uint16_t Version = 0;
28
29 /// A numeric identifier for the type of file this is. Best used in
30 /// combination with Version.
31 uint16_t Type = 0;
32
33 /// Whether the CPU that produced the timestamp counters (TSC) move at a
34 /// constant rate.
35 bool ConstantTSC;
36
37 /// Whether the CPU that produced the timestamp counters (TSC) do not stop.
38 bool NonstopTSC;
39
40 /// The number of cycles per second for the CPU that produced the timestamp
41 /// counter (TSC) values. Useful for estimating the amount of time that
42 /// elapsed between two TSCs on some platforms.
43 uint64_t CycleFrequency = 0;
44 };
45
46 /// Determines the supported types of records that could be seen in XRay traces.
47 /// This may or may not correspond to actual record types in the raw trace (as
48 /// the loader implementation may synthesize this information in the process of
49 /// of loading).
50 enum class RecordTypes { ENTER, EXIT };
51
52 struct XRayRecord {
53 /// The type of record.
54 uint16_t RecordType;
55
56 /// The CPU where the thread is running. We assume number of CPUs <= 256.
57 uint8_t CPU;
58
59 /// Identifies the type of record.
60 RecordTypes Type;
61
62 /// The function ID for the record.
63 int32_t FuncId;
64
65 /// Get the full 8 bytes of the TSC when we get the log record.
66 uint64_t TSC;
67
68 /// The thread ID for the currently running thread.
69 uint32_t TId;
70 };
71
72 } // namespace xray
73 } // namespace llvm
74
75 #endif // LLVM_XRAY_XRAY_RECORD_H
0 //===- YAMLXRayRecord.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_XRAY_YAML_XRAY_RECORD_H
13 #define LLVM_XRAY_YAML_XRAY_RECORD_H
14
15 #include
16
17 #include "llvm/Support/YAMLTraits.h"
18 #include "llvm/XRay/XRayRecord.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 } // namespace xray
47
48 namespace yaml {
49
50 // YAML Traits
51 // -----------
52 template <> struct ScalarEnumerationTraits {
53 static void enumeration(IO &IO, xray::RecordTypes &Type) {
54 IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
55 IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
56 }
57 };
58
59 template <> struct MappingTraits {
60 static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) {
61 IO.mapRequired("version", Header.Version);
62 IO.mapRequired("type", Header.Type);
63 IO.mapRequired("constant-tsc", Header.ConstantTSC);
64 IO.mapRequired("nonstop-tsc", Header.NonstopTSC);
65 IO.mapRequired("cycle-frequency", Header.CycleFrequency);
66 }
67 };
68
69 template <> struct MappingTraits {
70 static void mapping(IO &IO, xray::YAMLXRayRecord &Record) {
71 // FIXME: Make this type actually be descriptive
72 IO.mapRequired("type", Record.RecordType);
73 IO.mapRequired("func-id", Record.FuncId);
74 IO.mapOptional("function", Record.Function);
75 IO.mapRequired("cpu", Record.CPU);
76 IO.mapRequired("thread", Record.TId);
77 IO.mapRequired("kind", Record.Type);
78 IO.mapRequired("tsc", Record.TSC);
79 }
80
81 static constexpr bool flow = true;
82 };
83
84 template <> struct MappingTraits {
85 static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) {
86 // A trace file contains two parts, the header and the list of all the
87 // trace records.
88 IO.mapRequired("header", Trace.Header);
89 IO.mapRequired("records", Trace.Records);
90 }
91 };
92
93 } // namespace yaml
94 } // namespace llvm
95
96 LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord)
97
98 #endif // LLVM_XRAY_YAML_XRAY_RECORD_H
2121 add_subdirectory(Fuzzer)
2222 add_subdirectory(Passes)
2323 add_subdirectory(LibDriver)
24 add_subdirectory(XRay)
0 add_llvm_library(LLVMXRay
1 Trace.cpp
2
3 ADDITIONAL_HEADER_DIRS
4 ${LLVM_MAIN_INCLUDE_DIR}/llvm/ADT
5 ${LLVM_MAIN_INCLUDE_DIR}/llvm/XRay
6
7 DEPENDS
8 LLVMSupport
9
10 LINK_LIBS
11 LLVMSupport
12 )
0 //===- Trace.cpp - XRay Trace Loading 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 "llvm/XRay/Trace.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/Support/DataExtractor.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/XRay/YAMLXRayRecord.h"
18
19 using namespace llvm;
20 using namespace llvm::xray;
21 using llvm::yaml::Input;
22
23 using XRayRecordStorage =
24 std::aligned_storage::type;
25
26 Error NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
27 std::vector &Records) {
28 // FIXME: Maybe deduce whether the data is little or big-endian using some
29 // magic bytes in the beginning of the file?
30
31 // First 32 bytes of the file will always be the header. We assume a certain
32 // format here:
33 //
34 // (2) uint16 : version
35 // (2) uint16 : type
36 // (4) uint32 : bitfield
37 // (8) uint64 : cycle frequency
38 // (16) - : padding
39 //
40 if (Data.size() < 32)
41 return make_error(
42 "Not enough bytes for an XRay log.",
43 std::make_error_code(std::errc::invalid_argument));
44
45 if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
46 return make_error(
47 "Invalid-sized XRay data.",
48 std::make_error_code(std::errc::invalid_argument));
49
50 DataExtractor HeaderExtractor(Data, true, 8);
51 uint32_t OffsetPtr = 0;
52 FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
53 FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
54 uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
55 FileHeader.ConstantTSC = Bitfield & 1uL;
56 FileHeader.NonstopTSC = Bitfield & 1uL << 1;
57 FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
58
59 if (FileHeader.Version != 1)
60 return make_error(
61 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
62 std::make_error_code(std::errc::invalid_argument));
63
64 // Each record after the header will be 32 bytes, in the following format:
65 //
66 // (2) uint16 : record type
67 // (1) uint8 : cpu id
68 // (1) uint8 : type
69 // (4) sint32 : function id
70 // (8) uint64 : tsc
71 // (4) uint32 : thread id
72 // (12) - : padding
73 for (auto S = Data.drop_front(32); !S.empty(); S = S.drop_front(32)) {
74 DataExtractor RecordExtractor(S, true, 8);
75 uint32_t OffsetPtr = 0;
76 Records.emplace_back();
77 auto &Record = Records.back();
78 Record.RecordType = RecordExtractor.getU16(&OffsetPtr);
79 Record.CPU = RecordExtractor.getU8(&OffsetPtr);
80 auto Type = RecordExtractor.getU8(&OffsetPtr);
81 switch (Type) {
82 case 0:
83 Record.Type = RecordTypes::ENTER;
84 break;
85 case 1:
86 Record.Type = RecordTypes::EXIT;
87 break;
88 default:
89 return make_error(
90 Twine("Unknown record type '") + Twine(int{Type}) + "'",
91 std::make_error_code(std::errc::executable_format_error));
92 }
93 Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t));
94 Record.TSC = RecordExtractor.getU64(&OffsetPtr);
95 Record.TId = RecordExtractor.getU32(&OffsetPtr);
96 }
97 return Error::success();
98 }
99
100 Error YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
101 std::vector &Records) {
102
103 // Load the documents from the MappedFile.
104 YAMLXRayTrace Trace;
105 Input In(Data);
106 In >> Trace;
107 if (In.error())
108 return make_error("Failed loading YAML Data.", In.error());
109
110 FileHeader.Version = Trace.Header.Version;
111 FileHeader.Type = Trace.Header.Type;
112 FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
113 FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
114 FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
115
116 if (FileHeader.Version != 1)
117 return make_error(
118 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
119 std::make_error_code(std::errc::invalid_argument));
120
121 Records.clear();
122 std::transform(Trace.Records.begin(), Trace.Records.end(),
123 std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
124 return XRayRecord{R.RecordType, R.CPU, R.Type,
125 R.FuncId, R.TSC, R.TId};
126 });
127 return Error::success();
128 }
129
130 Expected llvm::xray::loadTraceFile(StringRef Filename, bool Sort) {
131 int Fd;
132 if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
133 return make_error(
134 Twine("Cannot read log from '") + Filename + "'", EC);
135 }
136
137 // Attempt to get the filesize.
138 uint64_t FileSize;
139 if (auto EC = sys::fs::file_size(Filename, FileSize)) {
140 return make_error(
141 Twine("Cannot read log from '") + Filename + "'", EC);
142 }
143 if (FileSize < 4) {
144 return make_error(
145 Twine("File '") + Filename + "' too small for XRay.",
146 std::make_error_code(std::errc::protocol_error));
147 }
148
149 // Attempt to mmap the file.
150 std::error_code EC;
151 sys::fs::mapped_file_region MappedFile(
152 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
153 if (EC) {
154 return make_error(
155 Twine("Cannot read log from '") + Filename + "'", EC);
156 }
157
158 // Attempt to detect the file type using file magic. We have a slight bias
159 // towards the binary format, and we do this by making sure that the first 4
160 // bytes of the binary file is some combination of the following byte
161 // patterns:
162 //
163 // 0x0001 0x0000 - version 1, "naive" format
164 // 0x0001 0x0001 - version 1, "flight data recorder" format
165 //
166 // YAML files dont' typically have those first four bytes as valid text so we
167 // try loading assuming YAML if we don't find these bytes.
168 //
169 // Only if we can't load either the binary or the YAML format will we yield an
170 // error.
171 StringRef Magic(MappedFile.data(), 4);
172 DataExtractor HeaderExtractor(Magic, true, 8);
173 uint32_t OffsetPtr = 0;
174 uint16_t Version = HeaderExtractor.getU16(&OffsetPtr);
175 uint16_t Type = HeaderExtractor.getU16(&OffsetPtr);
176
177 Trace T;
178 if (Version == 1 && (Type == 0 || Type == 1)) {
179 if (auto E = NaiveLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
180 T.FileHeader, T.Records))
181 return std::move(E);
182 } else {
183 if (auto E = YAMLLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
184 T.FileHeader, T.Records))
185 return std::move(E);
186 }
187
188 if (Sort)
189 std::sort(T.Records.begin(), T.Records.end(),
190 [&](const XRayRecord &L, const XRayRecord &R) {
191 return L.TSC < R.TSC;
192 });
193
194 return std::move(T);
195 }
None #RUN: llvm-xray convert %s -i=yaml -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
0 #RUN: llvm-xray convert %s -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
11 ---
22 header:
33 version: 1
22 DebugInfoDWARF
33 Object
44 Support
5 Symbolize)
5 Symbolize
6 XRay)
67
78 set(LLVM_XRAY_TOOLS
89 func-id-helper.cc
910 xray-converter.cc
1011 xray-extract.cc
1112 xray-extract.cc
12 xray-log-reader.cc
1313 xray-registry.cc)
1414
1515 add_llvm_tool(llvm-xray llvm-xray.cc ${LLVM_XRAY_TOOLS})
1212 #include "xray-converter.h"
1313
1414 #include "xray-extract.h"
15 #include "xray-record-yaml.h"
1615 #include "xray-registry.h"
1716 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
1817 #include "llvm/Support/EndianStream.h"
1918 #include "llvm/Support/FileSystem.h"
2019 #include "llvm/Support/YAMLTraits.h"
2120 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/XRay/Trace.h"
22 #include "llvm/XRay/YAMLXRayRecord.h"
2223
2324 using namespace llvm;
2425 using namespace xray;
3031 cl::desc(""),
3132 cl::Required, cl::sub(Convert));
3233 enum class ConvertFormats { BINARY, YAML };
33 static cl::opt ConvertInputFormat(
34 "input-format", cl::desc("input format"),
35 cl::values(clEnumValN(ConvertFormats::BINARY, "raw",
36 "input is in raw binary"),
37 clEnumValN(ConvertFormats::YAML, "yaml", "input is in yaml")),
38 cl::sub(Convert));
39 static cl::alias ConvertInputFormat2("i", cl::aliasopt(ConvertInputFormat),
40 cl::desc("Alias for -input-format"),
41 cl::sub(Convert));
4234 static cl::opt ConvertOutputFormat(
4335 "output-format", cl::desc("output format"),
4436 cl::values(clEnumValN(ConvertFormats::BINARY, "raw", "output in binary"),
9082 cl::desc("Alias for -instr-map-format"),
9183 cl::sub(Convert));
9284
93 using llvm::yaml::MappingTraits;
94 using llvm::yaml::ScalarEnumerationTraits;
9585 using llvm::yaml::IO;
9686 using llvm::yaml::Output;
9787
98 void TraceConverter::exportAsYAML(const LogReader &Records, raw_ostream &OS) {
88 void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) {
9989 YAMLXRayTrace Trace;
10090 const auto &FH = Records.getFileHeader();
10191 Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC,
111101 Out << Trace;
112102 }
113103
114 void TraceConverter::exportAsRAWv1(const LogReader &Records, raw_ostream &OS) {
104 void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
115105 // First write out the file header, in the correct endian-appropriate format
116106 // (XRay assumes currently little endian).
117107 support::endian::Writer Writer(OS);
179169 llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
180170 FunctionAddresses);
181171 llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
182 LogReader::LoaderFunction Loader;
183 switch (ConvertInputFormat) {
184 case ConvertFormats::BINARY:
185 Loader = NaiveLogLoader;
186 break;
187 case ConvertFormats::YAML:
188 Loader = YAMLLogLoader;
189 break;
190 }
191
192 LogReader Reader(ConvertInput, Err, ConvertSortInput, Loader);
193 if (Err)
194 return joinErrors(
195 make_error(
196 Twine("Failed loading input file '") + ConvertInput + "'.",
197 std::make_error_code(std::errc::executable_format_error)),
198 std::move(Err));
199
200172 raw_fd_ostream OS(ConvertOutput, EC,
201173 ConvertOutputFormat == ConvertFormats::BINARY
202174 ? sys::fs::OpenFlags::F_None
205177 return make_error(
206178 Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
207179
208 switch (ConvertOutputFormat) {
209 case ConvertFormats::YAML:
210 TC.exportAsYAML(Reader, OS);
211 break;
212 case ConvertFormats::BINARY:
213 TC.exportAsRAWv1(Reader, OS);
214 break;
180 if (auto TraceOrErr = loadTraceFile(ConvertInput, ConvertSortInput)) {
181 auto &T = *TraceOrErr;
182 switch (ConvertOutputFormat) {
183 case ConvertFormats::YAML:
184 TC.exportAsYAML(T, OS);
185 break;
186 case ConvertFormats::BINARY:
187 TC.exportAsRAWv1(T, OS);
188 break;
189 }
190 } else {
191 return joinErrors(
192 make_error(
193 Twine("Failed loading input file '") + ConvertInput + "'.",
194 std::make_error_code(std::errc::protocol_error)),
195 TraceOrErr.takeError());
215196 }
216197 return Error::success();
217198 });
1414 #define LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
1515
1616 #include "func-id-helper.h"
17 #include "xray-log-reader.h"
18 #include "xray-record.h"
17 #include "llvm/XRay/XRayRecord.h"
18 #include "llvm/XRay/Trace.h"
1919
2020 namespace llvm {
2121 namespace xray {
2828 TraceConverter(FuncIdConversionHelper &FuncIdHelper, bool Symbolize = false)
2929 : FuncIdHelper(FuncIdHelper), Symbolize(Symbolize) {}
3030
31 void exportAsYAML(const LogReader &Records, raw_ostream &OS);
32 void exportAsRAWv1(const LogReader &Records, raw_ostream &OS);
31 void exportAsYAML(const Trace &Records, raw_ostream &OS);
32 void exportAsRAWv1(const Trace &Records, raw_ostream &OS);
3333 };
3434
3535 } // namespace xray
+0
-163
tools/llvm-xray/xray-log-reader.cc less more
None //===- 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 "xray-log-reader.h"
13 #include "xray-record-yaml.h"
14 #include "llvm/Support/DataExtractor.h"
15 #include "llvm/Support/FileSystem.h"
16
17 using namespace llvm;
18 using namespace llvm::xray;
19 using llvm::yaml::Input;
20
21 LogReader::LogReader(
22 StringRef Filename, Error &Err, bool Sort,
23 std::function &)>
24 Loader) {
25 ErrorAsOutParameter Guard(&Err);
26 int Fd;
27 if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
28 Err = make_error(
29 Twine("Cannot read log from '") + Filename + "'", EC);
30 return;
31 }
32 uint64_t FileSize;
33 if (auto EC = sys::fs::file_size(Filename, FileSize)) {
34 Err = make_error(
35 Twine("Cannot read log from '") + Filename + "'", EC);
36 return;
37 }
38
39 std::error_code EC;
40 sys::fs::mapped_file_region MappedFile(
41 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
42 if (EC) {
43 Err = make_error(
44 Twine("Cannot read log from '") + Filename + "'", EC);
45 return;
46 }
47
48 if (auto E = Loader(StringRef(MappedFile.data(), MappedFile.size()),
49 FileHeader, Records)) {
50 Err = std::move(E);
51 return;
52 }
53
54 if (Sort)
55 std::sort(
56 Records.begin(), Records.end(),
57 [](const XRayRecord &L, const XRayRecord &R) { return L.TSC < R.TSC; });
58 }
59
60 Error llvm::xray::NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
61 std::vector &Records) {
62 // FIXME: Maybe deduce whether the data is little or big-endian using some
63 // magic bytes in the beginning of the file?
64
65 // First 32 bytes of the file will always be the header. We assume a certain
66 // format here:
67 //
68 // (2) uint16 : version
69 // (2) uint16 : type
70 // (4) uint32 : bitfield
71 // (8) uint64 : cycle frequency
72 // (16) - : padding
73 //
74 if (Data.size() < 32)
75 return make_error(
76 "Not enough bytes for an XRay log.",
77 std::make_error_code(std::errc::invalid_argument));
78
79 if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
80 return make_error(
81 "Invalid-sized XRay data.",
82 std::make_error_code(std::errc::invalid_argument));
83
84 DataExtractor HeaderExtractor(Data, true, 8);
85 uint32_t OffsetPtr = 0;
86 FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
87 FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
88 uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
89 FileHeader.ConstantTSC = Bitfield & 1uL;
90 FileHeader.NonstopTSC = Bitfield & 1uL << 1;
91 FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
92
93 if (FileHeader.Version != 1)
94 return make_error(
95 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
96 std::make_error_code(std::errc::invalid_argument));
97
98 // Each record after the header will be 32 bytes, in the following format:
99 //
100 // (2) uint16 : record type
101 // (1) uint8 : cpu id
102 // (1) uint8 : type
103 // (4) sint32 : function id
104 // (8) uint64 : tsc
105 // (4) uint32 : thread id
106 // (12) - : padding
107 for (auto S = Data.drop_front(32); !S.empty(); S = S.drop_front(32)) {
108 DataExtractor RecordExtractor(S, true, 8);
109 uint32_t OffsetPtr = 0;
110 Records.emplace_back();
111 auto &Record = Records.back();
112 Record.RecordType = RecordExtractor.getU16(&OffsetPtr);
113 Record.CPU = RecordExtractor.getU8(&OffsetPtr);
114 auto Type = RecordExtractor.getU8(&OffsetPtr);
115 switch (Type) {
116 case 0:
117 Record.Type = RecordTypes::ENTER;
118 break;
119 case 1:
120 Record.Type = RecordTypes::EXIT;
121 break;
122 default:
123 return make_error(
124 Twine("Unknown record type '") + Twine(int{Type}) + "'",
125 std::make_error_code(std::errc::executable_format_error));
126 }
127 Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t));
128 Record.TSC = RecordExtractor.getU64(&OffsetPtr);
129 Record.TId = RecordExtractor.getU32(&OffsetPtr);
130 }
131 return Error::success();
132 }
133
134 Error llvm::xray::YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
135 std::vector &Records) {
136
137 // Load the documents from the MappedFile.
138 YAMLXRayTrace Trace;
139 Input In(Data);
140 In >> Trace;
141 if (In.error())
142 return make_error("Failed loading YAML Data.", In.error());
143
144 FileHeader.Version = Trace.Header.Version;
145 FileHeader.Type = Trace.Header.Type;
146 FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
147 FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
148 FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
149
150 if (FileHeader.Version != 1)
151 return make_error(
152 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
153 std::make_error_code(std::errc::invalid_argument));
154
155 Records.clear();
156 std::transform(Trace.Records.begin(), Trace.Records.end(),
157 std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
158 return XRayRecord{R.RecordType, R.CPU, R.Type,
159 R.FuncId, R.TSC, R.TId};
160 });
161 return Error::success();
162 }
+0
-57
tools/llvm-xray/xray-log-reader.h less more
None //===- 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
-102
tools/llvm-xray/xray-record-yaml.h less more
None //===- 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
-55
tools/llvm-xray/xray-record.h less more
None //===- 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