summaryrefslogtreecommitdiffstats
path: root/llvm/lib/XRay/FDRRecordProducer.cpp
blob: 4b010f1fa624b7fbc619f29eca6feadea8c2bef3 (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
//===- 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 {

Expected<std::unique_ptr<Record>>
metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
  // Keep this in sync with the values written in the XRay FDR mode runtime in
  // compiler-rt.
  enum MetadataRecordKinds : uint8_t {
    NewBufferKind,
    EndOfBufferKind,
    NewCPUIdKind,
    TSCWrapKind,
    WalltimeMarkerKind,
    CustomEventMarkerKind,
    CallArgumentKind,
    BufferExtentsKind,
    TypedEventMarkerKind,
    PidKind,
    // This is an end marker, used to identify the upper bound for this enum.
    EnumEndMarker,
  };

  if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker))
    return createStringError(std::make_error_code(std::errc::invalid_argument),
                             "Invalid metadata record type: %d", T);
  switch (T) {
  case MetadataRecordKinds::NewBufferKind:
    return make_unique<NewBufferRecord>();
  case MetadataRecordKinds::EndOfBufferKind:
    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::NewCPUIdKind:
    return make_unique<NewCPUIDRecord>();
  case MetadataRecordKinds::TSCWrapKind:
    return make_unique<TSCWrapRecord>();
  case MetadataRecordKinds::WalltimeMarkerKind:
    return make_unique<WallclockRecord>();
  case MetadataRecordKinds::CustomEventMarkerKind:
    return make_unique<CustomEventRecord>();
  case MetadataRecordKinds::CallArgumentKind:
    return make_unique<CallArgRecord>();
  case MetadataRecordKinds::BufferExtentsKind:
    return make_unique<BufferExtents>();
  case MetadataRecordKinds::TypedEventMarkerKind:
    return createStringError(std::make_error_code(std::errc::invalid_argument),
                             "Encountered an unsupported TypedEventMarker.");
  case MetadataRecordKinds::PidKind:
    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