LLVM  4.0.0
XRay/Trace.cpp
Go to the documentation of this file.
1 //===- Trace.cpp - XRay Trace Loading implementation. ---------------------===//
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 // XRay log reader implementation.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "llvm/XRay/Trace.h"
14 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Support/Error.h"
19 
20 using namespace llvm;
21 using namespace llvm::xray;
22 using llvm::yaml::Input;
23 
24 using XRayRecordStorage =
25  std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
26 
28  std::vector<XRayRecord> &Records) {
29  // FIXME: Maybe deduce whether the data is little or big-endian using some
30  // magic bytes in the beginning of the file?
31 
32  // First 32 bytes of the file will always be the header. We assume a certain
33  // format here:
34  //
35  // (2) uint16 : version
36  // (2) uint16 : type
37  // (4) uint32 : bitfield
38  // (8) uint64 : cycle frequency
39  // (16) - : padding
40  //
41  if (Data.size() < 32)
42  return make_error<StringError>(
43  "Not enough bytes for an XRay log.",
44  std::make_error_code(std::errc::invalid_argument));
45 
46  if (Data.size() - 32 == 0 || Data.size() % 32 != 0)
47  return make_error<StringError>(
48  "Invalid-sized XRay data.",
49  std::make_error_code(std::errc::invalid_argument));
50 
51  DataExtractor HeaderExtractor(Data, true, 8);
52  uint32_t OffsetPtr = 0;
53  FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
54  FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
55  uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
56  FileHeader.ConstantTSC = Bitfield & 1uL;
57  FileHeader.NonstopTSC = Bitfield & 1uL << 1;
58  FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
59 
60  if (FileHeader.Version != 1)
61  return make_error<StringError>(
62  Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
63  std::make_error_code(std::errc::invalid_argument));
64 
65  // Each record after the header will be 32 bytes, in the following format:
66  //
67  // (2) uint16 : record type
68  // (1) uint8 : cpu id
69  // (1) uint8 : type
70  // (4) sint32 : function id
71  // (8) uint64 : tsc
72  // (4) uint32 : thread id
73  // (12) - : padding
74  for (auto S = Data.drop_front(32); !S.empty(); S = S.drop_front(32)) {
75  DataExtractor RecordExtractor(S, true, 8);
76  uint32_t OffsetPtr = 0;
77  Records.emplace_back();
78  auto &Record = Records.back();
79  Record.RecordType = RecordExtractor.getU16(&OffsetPtr);
80  Record.CPU = RecordExtractor.getU8(&OffsetPtr);
81  auto Type = RecordExtractor.getU8(&OffsetPtr);
82  switch (Type) {
83  case 0:
85  break;
86  case 1:
88  break;
89  default:
90  return make_error<StringError>(
91  Twine("Unknown record type '") + Twine(int{Type}) + "'",
92  std::make_error_code(std::errc::executable_format_error));
93  }
94  Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t));
95  Record.TSC = RecordExtractor.getU64(&OffsetPtr);
96  Record.TId = RecordExtractor.getU32(&OffsetPtr);
97  }
98  return Error::success();
99 }
100 
102  std::vector<XRayRecord> &Records) {
103 
104  // Load the documents from the MappedFile.
106  Input In(Data);
107  In >> Trace;
108  if (In.error())
109  return make_error<StringError>("Failed loading YAML Data.", In.error());
110 
111  FileHeader.Version = Trace.Header.Version;
112  FileHeader.Type = Trace.Header.Type;
113  FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
114  FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
115  FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
116 
117  if (FileHeader.Version != 1)
118  return make_error<StringError>(
119  Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),
120  std::make_error_code(std::errc::invalid_argument));
121 
122  Records.clear();
123  std::transform(Trace.Records.begin(), Trace.Records.end(),
124  std::back_inserter(Records), [&](const YAMLXRayRecord &R) {
125  return XRayRecord{R.RecordType, R.CPU, R.Type,
126  R.FuncId, R.TSC, R.TId};
127  });
128  return Error::success();
129 }
130 
132  int Fd;
133  if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
134  return make_error<StringError>(
135  Twine("Cannot read log from '") + Filename + "'", EC);
136  }
137 
138  // Attempt to get the filesize.
139  uint64_t FileSize;
140  if (auto EC = sys::fs::file_size(Filename, FileSize)) {
141  return make_error<StringError>(
142  Twine("Cannot read log from '") + Filename + "'", EC);
143  }
144  if (FileSize < 4) {
145  return make_error<StringError>(
146  Twine("File '") + Filename + "' too small for XRay.",
147  std::make_error_code(std::errc::executable_format_error));
148  }
149 
150  // Attempt to mmap the file.
151  std::error_code EC;
152  sys::fs::mapped_file_region MappedFile(
153  Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
154  if (EC) {
155  return make_error<StringError>(
156  Twine("Cannot read log from '") + Filename + "'", EC);
157  }
158 
159  // Attempt to detect the file type using file magic. We have a slight bias
160  // towards the binary format, and we do this by making sure that the first 4
161  // bytes of the binary file is some combination of the following byte
162  // patterns:
163  //
164  // 0x0001 0x0000 - version 1, "naive" format
165  // 0x0001 0x0001 - version 1, "flight data recorder" format
166  //
167  // YAML files dont' typically have those first four bytes as valid text so we
168  // try loading assuming YAML if we don't find these bytes.
169  //
170  // Only if we can't load either the binary or the YAML format will we yield an
171  // error.
172  StringRef Magic(MappedFile.data(), 4);
173  DataExtractor HeaderExtractor(Magic, true, 8);
174  uint32_t OffsetPtr = 0;
175  uint16_t Version = HeaderExtractor.getU16(&OffsetPtr);
176  uint16_t Type = HeaderExtractor.getU16(&OffsetPtr);
177 
178  Trace T;
179  if (Version == 1 && (Type == 0 || Type == 1)) {
180  if (auto E = NaiveLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
181  T.FileHeader, T.Records))
182  return std::move(E);
183  } else {
184  if (auto E = YAMLLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
185  T.FileHeader, T.Records))
186  return std::move(E);
187  }
188 
189  if (Sort)
190  std::sort(T.Records.begin(), T.Records.end(),
191  [&](const XRayRecord &L, const XRayRecord &R) {
192  return L.TSC < R.TSC;
193  });
194 
195  return std::move(T);
196 }
MachineLoop * L
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:634
std::error_code error()
Definition: YAMLTraits.cpp:59
uint16_t RecordType
The type of record.
Definition: XRayRecord.h:55
std::error_code openFileForRead(const Twine &Name, int &ResultFD, SmallVectorImpl< char > *RealPath=nullptr)
This class represents a memory mapped file.
Definition: FileSystem.h:685
Expected< Trace > loadTraceFile(StringRef Filename, bool Sort=false)
This function will attempt to load XRay trace records from the provided |Filename|.
Definition: XRay/Trace.cpp:131
int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const
Extract an signed integer of size byte_size from *offset_ptr.
Error YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)
Definition: XRay/Trace.cpp:101
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
std::error_code make_error_code(BitcodeError E)
std::error_code file_size(const Twine &Path, uint64_t &Result)
Get file size.
Definition: FileSystem.h:540
Tagged union holding either a T or a Error.
The Input class is used to parse a yaml document into in-memory structs and vectors.
Definition: YAMLTraits.h:1099
uint64_t CycleFrequency
The number of cycles per second for the CPU that produced the timestamp counter (TSC) values...
Definition: XRayRecord.h:44
#define T
uint16_t Type
A numeric identifier for the type of file this is.
Definition: XRayRecord.h:32
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
A Trace object represents the records that have been loaded from XRay log files generated by instrume...
Definition: XRay/Trace.h:47
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
bool NonstopTSC
Whether the CPU that produced the timestamp counters (TSC) do not stop.
Definition: XRayRecord.h:39
uint64_t getU64(uint32_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
static const char *const Magic
Definition: Archive.cpp:25
static ErrorSuccess success()
Create a success value.
Error NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)
Definition: XRay/Trace.cpp:27
uint64_t TSC
Get the full 8 bytes of the TSC when we get the log record.
Definition: XRayRecord.h:67
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:130
bool ConstantTSC
Whether the CPU that produced the timestamp counters (TSC) move at a constant rate.
Definition: XRayRecord.h:36
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere...
Definition: STLExtras.h:807
Lightweight error class with error context and mandatory checking.
XRay traces all have a header providing some top-matter information useful to help tools determine ho...
Definition: XRayRecord.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
const uint64_t Version
Definition: InstrProf.h:799
std::aligned_storage< sizeof(XRayRecord), alignof(XRayRecord)>::type XRayRecordStorage
Definition: XRay/Trace.cpp:25
uint16_t Version
Version of the XRay implementation that produced this file.
Definition: XRayRecord.h:28