summaryrefslogtreecommitdiffstats
path: root/llvm/lib/XRay/FDRRecordProducer.cpp
blob: ef2f6a47feea85ccfd76fe4e96effcdef35c205d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/XRay/FDRRecordProducer.h"
#include "llvm/Support/DataExtractor.h"

namespace llvm {
namespace xray {

namespace {

// Keep this in sync with the values written in the XRay FDR mode runtime in
// compiler-rt.
enum class MetadataRecordKinds : uint8_t {
  NewBuffer,
  EndOfBuffer,
  NewCPUId,
  TSCWrap,
  WalltimeMarker,
  CustomEventMarker,
  CallArgument,
  BufferExtents,
  TypedEventMarker,
  Pid,
  // This is an end marker, used to identify the upper bound for this enum.
  EnumEndMarker,
};

Expected<std::unique_ptr<Record>>
metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
  if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker))
    return createStringError(std::make_error_code(std::errc::invalid_argument),
                             "Invalid metadata record type: %d", T);
  static constexpr MetadataRecordKinds Mapping[] = {
      MetadataRecordKinds::NewBuffer,
      MetadataRecordKinds::EndOfBuffer,
      MetadataRecordKinds::NewCPUId,
      MetadataRecordKinds::TSCWrap,
      MetadataRecordKinds::WalltimeMarker,
      MetadataRecordKinds::CustomEventMarker,
      MetadataRecordKinds::CallArgument,
      MetadataRecordKinds::BufferExtents,
      MetadataRecordKinds::TypedEventMarker,
      MetadataRecordKinds::Pid,
  };
  switch (Mapping[T]) {
  case MetadataRecordKinds::NewBuffer:
    return make_unique<NewBufferRecord>();
  case MetadataRecordKinds::EndOfBuffer:
    if (Header.Version >= 2)
      return createStringError(
          std::make_error_code(std::errc::executable_format_error),
          "End of buffer records are no longer supported starting version "
          "2 of the log.");
    return make_unique<EndBufferRecord>();
  case MetadataRecordKinds::NewCPUId:
    return make_unique<NewCPUIDRecord>();
  case MetadataRecordKinds::TSCWrap:
    return make_unique<TSCWrapRecord>();
  case MetadataRecordKinds::WalltimeMarker:
    return make_unique<WallclockRecord>();
  case MetadataRecordKinds::CustomEventMarker:
    return make_unique<CustomEventRecord>();
  case MetadataRecordKinds::CallArgument:
    return make_unique<CallArgRecord>();
  case MetadataRecordKinds::BufferExtents:
    return make_unique<BufferExtents>();
  case MetadataRecordKinds::TypedEventMarker:
    return createStringError(std::make_error_code(std::errc::invalid_argument),
                             "Encountered an unsupported TypedEventMarker.");
  case MetadataRecordKinds::Pid:
    return make_unique<PIDRecord>();
  case MetadataRecordKinds::EnumEndMarker:
    llvm_unreachable("Invalid MetadataRecordKind");
  }
  llvm_unreachable("Unhandled MetadataRecordKinds enum value");
}

} // namespace

Expected<std::unique_ptr<Record>> FileBasedRecordProducer::produce() {
  // At the top level, we read one byte to determine the type of the record to
  // create. This byte will comprise of the following bits:
  //
  //   - offset 0: A '1' indicates a metadata record, a '0' indicates a function
  //     record.
  //   - offsets 1-7: For metadata records, this will indicate the kind of
  //     metadata record should be loaded.
  //
  // We read first byte, then create the appropriate type of record to consume
  // the rest of the bytes.
  auto PreReadOffset = OffsetPtr;
  uint8_t FirstByte = E.getU8(&OffsetPtr);
  std::unique_ptr<Record> R;

  // For metadata records, handle especially here.
  if (FirstByte & 0x01) {
    auto LoadedType = FirstByte >> 1;
    auto MetadataRecordOrErr = metadataRecordType(Header, LoadedType);
    if (!MetadataRecordOrErr)
      return joinErrors(
          MetadataRecordOrErr.takeError(),
          createStringError(
              std::make_error_code(std::errc::executable_format_error),
              "Encountered an unsupported metadata record (%d) at offset %d.",
              LoadedType, PreReadOffset));
    R = std::move(MetadataRecordOrErr.get());
  } else {
    R = llvm::make_unique<FunctionRecord>();
  }
  RecordInitializer RI(E, OffsetPtr);

  if (auto Err = R->apply(RI))
    return std::move(Err);

  assert(R != nullptr);
  return std::move(R);
}

} // namespace xray
} // namespace llvm
OpenPOWER on IntegriCloud