Index: test/tools/llvm-xray/X86/convert-roundtrip.yaml
===================================================================
--- /dev/null
+++ test/tools/llvm-xray/X86/convert-roundtrip.yaml
@@ -0,0 +1,28 @@
+#RUN: llvm-xray convert %s -i=yaml -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
+---
+header:
+  version: 1
+  type: 0
+  constant-tsc: true
+  nonstop-tsc: true
+  cycle-frequency: 2601000000
+records:
+  - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-enter,
+    tsc: 10001 }
+  - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-exit,
+    tsc: 10100 }
+...
+
+#CHECK:       ---
+#CHECK-NEXT:  header:
+#CHECK-NEXT:    version: 1
+#CHECK-NEXT:    type: 0
+#CHECK-NEXT:    constant-tsc: true
+#CHECK-NEXT:    nonstop-tsc: true
+#CHECK-NEXT:    cycle-frequency: 2601000000
+#CHECK-NEXT:  records:
+#CHECK-NEXT:    - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-enter,
+#CHECK-NEXT:      tsc: 10001 }
+#CHECK-NEXT:    - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-exit,
+#CHECK-NEXT:      tsc: 10100 }
+#CHECK-NEXT:  ...
Index: tools/llvm-xray/CMakeLists.txt
===================================================================
--- tools/llvm-xray/CMakeLists.txt
+++ tools/llvm-xray/CMakeLists.txt
@@ -1,10 +1,16 @@
 set(LLVM_LINK_COMPONENTS
   ${LLVM_TARGETS_TO_BUILD}
+  DebugInfoDWARF
+  Object
   Support
-  Object)
+  Symbolize)
 
 set(LLVM_XRAY_TOOLS
+  func-id-helper.cc
+  xray-converter.cc
   xray-extract.cc
+  xray-extract.cc
+  xray-log-reader.cc
   xray-registry.cc)
 
 add_llvm_tool(llvm-xray llvm-xray.cc ${LLVM_XRAY_TOOLS})
Index: tools/llvm-xray/func-id-helper.h
===================================================================
--- /dev/null
+++ tools/llvm-xray/func-id-helper.h
@@ -0,0 +1,51 @@
+//===- func-id-helper.h - XRay Function ID Conversion Helpers -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines helper tools dealing with XRay-generated function ids.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
+#define LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
+
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include <unordered_map>
+
+namespace llvm {
+namespace xray {
+
+// This class consolidates common operations related to Function IDs.
+class FuncIdConversionHelper {
+public:
+  using FunctionAddressMap = std::unordered_map<int32_t, uint64_t>;
+
+private:
+  std::string BinaryInstrMap;
+  symbolize::LLVMSymbolizer &Symbolizer;
+  const FunctionAddressMap &FunctionAddresses;
+
+public:
+  FuncIdConversionHelper(std::string BinaryInstrMap,
+                         symbolize::LLVMSymbolizer &Symbolizer,
+                         const FunctionAddressMap &FunctionAddresses)
+      : BinaryInstrMap(std::move(BinaryInstrMap)), Symbolizer(Symbolizer),
+        FunctionAddresses(FunctionAddresses) {}
+
+  FuncIdConversionHelper(const FuncIdConversionHelper &) = default;
+
+  // Returns the symbol or a string representation of the function id.
+  std::string SymbolOrNumber(int32_t FuncId) const;
+
+  // Returns the file and column from debug info for the given function id.
+  std::string FileLineAndColumn(int32_t FuncId) const;
+};
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H
Index: tools/llvm-xray/func-id-helper.cc
===================================================================
--- /dev/null
+++ tools/llvm-xray/func-id-helper.cc
@@ -0,0 +1,56 @@
+//===- xray-fc-account.cc - XRay Function Call Accounting Tool ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the helper tools dealing with XRay-generated function ids.
+//
+//===----------------------------------------------------------------------===//
+
+#include <sstream>
+#include "func-id-helper.h"
+
+using namespace llvm;
+using namespace xray;
+
+std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const {
+  std::ostringstream F;
+  auto It = FunctionAddresses.find(FuncId);
+  if (It == FunctionAddresses.end()) {
+    F << "#" << FuncId;
+    return F.str();
+  }
+
+  auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second);
+  if (!ResOrErr || ResOrErr.get().FunctionName == "<invalid>") {
+    F << "@(" << std::hex << It->second << ")";
+  } else {
+    auto &DI = ResOrErr.get();
+    F << DI.FunctionName;
+  }
+  return F.str();
+}
+
+std::string FuncIdConversionHelper::FileLineAndColumn(int32_t FuncId) const {
+  auto It = FunctionAddresses.find(FuncId);
+  if (It == FunctionAddresses.end()) {
+    return "(unknown)";
+  }
+  std::ostringstream F;
+  auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second);
+  if (!ResOrErr || ResOrErr.get().FileName == "<invalid>")
+    return "(unknown)";
+  auto &DI = ResOrErr.get();
+  auto LastSlash = DI.FileName.find_last_of('/');
+  if (LastSlash != std::string::npos) {
+    F << DI.FileName.substr(LastSlash + 1);
+  } else {
+    F << DI.FileName;
+  }
+  F << ":" << DI.Line << ":" << DI.Column;
+  return F.str();
+}
Index: tools/llvm-xray/llvm-xray.cc
===================================================================
--- tools/llvm-xray/llvm-xray.cc
+++ tools/llvm-xray/llvm-xray.cc
@@ -18,8 +18,6 @@
 //
 #include "xray-registry.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/raw_ostream.h"
 #include <unistd.h>
 
 using namespace llvm;
Index: tools/llvm-xray/xray-converter.h
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-converter.h
@@ -0,0 +1,39 @@
+//===- xray-converter.h - XRay Trace Conversion ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the TraceConverter class for turning binary traces into
+// human-readable text and vice versa.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
+#define LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
+
+#include "func-id-helper.h"
+#include "xray-log-reader.h"
+#include "xray-record.h"
+
+namespace llvm {
+namespace xray {
+
+class TraceConverter {
+  FuncIdConversionHelper &FuncIdHelper;
+  bool Symbolize;
+
+public:
+  TraceConverter(FuncIdConversionHelper &FuncIdHelper, bool Symbolize = false)
+      : FuncIdHelper(FuncIdHelper), Symbolize(Symbolize) {}
+
+  void exportAsYAML(const NaiveLogReader &Records, raw_ostream &OS);
+  void exportAsRAW(const YAMLLogReader &Records, int Fd);
+};
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
Index: tools/llvm-xray/xray-converter.cc
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-converter.cc
@@ -0,0 +1,251 @@
+//===- xray-converter.cc - XRay Trace Conversion --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the trace conversion functions.
+//
+//===----------------------------------------------------------------------===//
+#include "xray-converter.h"
+
+#include "xray-extract.h"
+#include "xray-record-yaml.h"
+#include "xray-registry.h"
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <unistd.h>
+
+using namespace llvm;
+using namespace xray;
+
+// llvm-xray convert
+// ----------------------------------------------------------------------------
+static cl::SubCommand Convert("convert", "Trace Format Conversion");
+static cl::opt<std::string> ConvertInput(cl::Positional,
+                                         cl::desc("<xray log file>"),
+                                         cl::Required, cl::sub(Convert));
+enum class ConvertFormats { BINARY, YAML };
+static cl::opt<ConvertFormats> ConvertInputFormat(
+    "input-format", cl::desc("input format"),
+    cl::values(clEnumValN(ConvertFormats::BINARY, "raw",
+                          "input is in raw binary"),
+               clEnumValN(ConvertFormats::YAML, "yaml", "input is in yaml")),
+    cl::sub(Convert));
+static cl::alias ConvertInputFormat2("i", cl::aliasopt(ConvertInputFormat),
+                                     cl::desc("Alias for -input-format"),
+                                     cl::sub(Convert));
+static cl::opt<ConvertFormats> ConvertOutputFormat(
+    "output-format", cl::desc("output format"),
+    cl::values(clEnumValN(ConvertFormats::BINARY, "raw", "output in binary"),
+               clEnumValN(ConvertFormats::YAML, "yaml", "output in yaml")),
+    cl::sub(Convert));
+static cl::alias ConvertOutputFormat2("f", cl::aliasopt(ConvertOutputFormat),
+                                      cl::desc("Alias for -output-format"),
+                                      cl::sub(Convert));
+static cl::opt<std::string>
+    ConvertOutput("output", cl::value_desc("output file"), cl::init("-"),
+                  cl::desc("output file; use '-' for stdout"),
+                  cl::sub(Convert));
+static cl::alias ConvertOutput2("o", cl::aliasopt(ConvertOutput),
+                                cl::desc("Alias for -output"),
+                                cl::sub(Convert));
+
+static cl::opt<bool>
+    ConvertSymbolize("symbolize",
+                     cl::desc("symbolize function ids from the input log"),
+                     cl::init(false), cl::sub(Convert));
+
+static cl::opt<std::string>
+    ConvertInstrMap("instr_map",
+                    cl::desc("binary with the instrumentation map, or "
+                             "a separate instrumentation map"),
+                    cl::value_desc("binary with xray_instr_map"),
+                    cl::sub(Convert), cl::init(""));
+static cl::alias ConvertInstrMap2("m", cl::aliasopt(ConvertInstrMap),
+                                  cl::desc("Alias for -instr_map"),
+                                  cl::sub(Convert));
+static cl::opt<bool> ConvertSortInput(
+    "sort",
+    cl::desc("determines whether to sort input log records by timestamp"),
+    cl::sub(Convert), cl::init(true));
+static cl::alias ConvertSortInput2("s", cl::aliasopt(ConvertSortInput),
+                                   cl::desc("Alias for -sort"),
+                                   cl::sub(Convert));
+static cl::opt<InstrumentationMapExtractor::InputFormats> InstrMapFormat(
+    "instr-map-format", cl::desc("format of instrumentation map"),
+    cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf",
+                          "instrumentation map in an ELF header"),
+               clEnumValN(InstrumentationMapExtractor::InputFormats::YAML,
+                          "yaml", "instrumentation map in YAML")),
+    cl::sub(Convert), cl::init(InstrumentationMapExtractor::InputFormats::ELF));
+static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat),
+                                 cl::desc("Alias for -instr-map-format"),
+                                 cl::sub(Convert));
+
+using llvm::yaml::MappingTraits;
+using llvm::yaml::ScalarEnumerationTraits;
+using llvm::yaml::IO;
+using llvm::yaml::Output;
+
+void TraceConverter::exportAsYAML(const NaiveLogReader &Records,
+                                  raw_ostream &OS) {
+  YAMLXRayTrace Trace;
+  const auto &FH = Records.getFileHeader();
+  Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC,
+                  FH.CycleFrequency};
+  Trace.Records.reserve(Records.size());
+  for (const auto &R : Records) {
+    Trace.Records.push_back(
+        {R.RecordType, R.CPU,
+         R.Type == 0 ? RecordTypes::ENTER : RecordTypes::EXIT, R.FuncId,
+         Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
+                   : std::to_string(R.FuncId),
+         R.TSC, R.TId});
+  }
+  Output Out(OS);
+  Out << Trace;
+}
+
+namespace {
+
+void retryingWriteAll(int Fd, const char *Begin, const char *End) {
+  if (Begin == End)
+    return;
+  auto TotalBytes = std::distance(Begin, End);
+  while (auto Written = write(Fd, Begin, TotalBytes)) {
+    if (Written < 0) {
+      if (errno == EINTR)
+        continue;
+      return;
+    }
+    TotalBytes -= Written;
+    if (TotalBytes == 0)
+      break;
+    Begin += Written;
+  }
+  return;
+}
+
+} // namespace
+
+void TraceConverter::exportAsRAW(const YAMLLogReader &Records, int Fd) {
+  retryingWriteAll(Fd, reinterpret_cast<const char *>(&Records.getFileHeader()),
+                   reinterpret_cast<const char *>(&Records.getFileHeader()) +
+                       sizeof(XRayFileHeader));
+
+  // Now we write each record as binary.
+  std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type Buffer;
+  for (const auto &Y : Records) {
+    std::ignore = toXRayRecord(Y, Buffer);
+    retryingWriteAll(Fd, reinterpret_cast<const char *>(&Buffer),
+                     reinterpret_cast<const char *>(&Buffer) +
+                         sizeof(XRayRecord));
+  }
+}
+
+namespace llvm {
+namespace xray {
+
+static CommandRegistration Unused(&Convert, [] {
+  if (ConvertInputFormat == ConvertOutputFormat)
+    return make_error<StringError>(
+        "-input-format and -output-format are the same, bailing out.",
+        std::make_error_code(std::errc::invalid_argument));
+
+  int Fd;
+  auto EC = sys::fs::openFileForRead(ConvertInput, Fd);
+  if (EC)
+    return make_error<StringError>(
+        Twine("Cannot open file '") + ConvertInput + "'", EC);
+
+  Error Err;
+  xray::InstrumentationMapExtractor Extractor(ConvertInstrMap, InstrMapFormat,
+                                              Err);
+  if (auto E =
+          handleErrors(std::move(Err), [&](std::unique_ptr<StringError> E) {
+            if (E->convertToErrorCode() == std::errc::no_such_file_or_directory)
+              return Error::success();
+            return Error(std::move(E));
+          }))
+    return E;
+
+  const auto &FunctionAddresses = Extractor.getFunctionAddresses();
+  symbolize::LLVMSymbolizer::Options Opts(
+      symbolize::FunctionNameKind::LinkageName, true, true, false, "");
+  symbolize::LLVMSymbolizer Symbolizer(Opts);
+  llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
+                                                  FunctionAddresses);
+  llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
+  switch (ConvertInputFormat) {
+  case ConvertFormats::BINARY: {
+    xray::NaiveLogReader LogReader(Fd, EC, ConvertSortInput);
+    if (EC)
+      return make_error<StringError>(
+          Twine("Failed loading input file '") + ConvertInput + "'", EC);
+
+    if (LogReader.getFileHeader().Version != 1)
+      return make_error<StringError>(
+          Twine("Unsupported XRay file version: ") +
+              Twine(LogReader.getFileHeader().Version),
+          std::make_error_code(std::errc::invalid_argument));
+
+    raw_fd_ostream OS(ConvertOutput, EC,
+                      ConvertOutputFormat == ConvertFormats::BINARY
+                          ? sys::fs::OpenFlags::F_None
+                          : sys::fs::OpenFlags::F_Text);
+    if (EC)
+      return make_error<StringError>(
+          Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
+
+    switch (ConvertOutputFormat) {
+    case ConvertFormats::YAML:
+      TC.exportAsYAML(LogReader, OS);
+      return Error::success();
+    default:
+      return make_error<StringError>(
+          "input-output conversion for provided formats not supported yet.",
+          std::make_error_code(std::errc::invalid_argument));
+    }
+    break;
+  }
+  case ConvertFormats::YAML: {
+    xray::YAMLLogReader LogReader(Fd, EC, ConvertSortInput);
+    if (EC)
+      return make_error<StringError>(
+          Twine("Failed loading input file '") + ConvertInput + "'", EC);
+    if (LogReader.getFileHeader().Version != 1)
+      return make_error<StringError>(
+          Twine("Unsupported XRay file version: ") +
+              Twine(LogReader.getFileHeader().Version),
+          std::make_error_code(std::errc::invalid_argument));
+
+    int Fd;
+    sys::fs::openFileForWrite(ConvertOutput, Fd, sys::fs::OpenFlags::F_None);
+    if (EC)
+      return make_error<StringError>(
+          Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
+    switch (ConvertOutputFormat) {
+    case ConvertFormats::BINARY:
+      TC.exportAsRAW(LogReader, Fd);
+      close(Fd);
+      return Error::success();
+    default:
+      close(Fd);
+      return make_error<StringError>(
+          "input-output conversion for provided formats not supported yet.",
+          std::make_error_code(std::errc::invalid_argument));
+    }
+    break;
+  }
+  }
+  return Error::success();
+});
+
+} // namespace xray
+} // namespace llvm
Index: tools/llvm-xray/xray-log-reader.h
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-log-reader.h
@@ -0,0 +1,79 @@
+//===- xray-log-reader.h - XRay Log Reader Interface ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Define the interface for an XRay log reader. Currently we only support one
+// version of the log (naive log) with fixed-sized records.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
+#define LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
+
+#include <cstdint>
+#include <deque>
+#include <vector>
+
+#include "xray-record-yaml.h"
+#include "xray-record.h"
+
+namespace llvm {
+namespace xray {
+
+class NaiveLogReader {
+  XRayFileHeader FileHeader;
+  typedef std::deque<XRayRecord> RecordsDeque;
+  RecordsDeque Records;
+  using iterator = RecordsDeque::iterator;
+  using citerator = RecordsDeque::const_iterator;
+
+public:
+  // Loads the contents of the file into memory, then sorts the events by TSC if
+  // |Sort| is true.
+  explicit NaiveLogReader(int Fd, std::error_code &EC, bool Sort = true);
+
+  const XRayFileHeader &getFileHeader() const { return FileHeader; }
+
+  iterator begin() { return Records.begin(); }
+  iterator end() { return Records.end(); }
+  citerator cbegin() { return Records.cbegin(); }
+  citerator cend() { return Records.cend(); }
+  citerator begin() const { return Records.begin(); }
+  citerator end() const { return Records.end(); }
+  citerator cbegin() const { return Records.begin(); }
+  citerator cend() const { return Records.end(); }
+  size_t size() const { return Records.size(); }
+};
+
+class YAMLLogReader {
+  XRayFileHeader FileHeader;
+  typedef std::vector<YAMLXRayRecord> RecordsVector;
+  RecordsVector Records;
+  using iterator = RecordsVector::iterator;
+  using citerator = RecordsVector::const_iterator;
+
+public:
+  // Loads the contents of the file from |Fd|, parses the YAML and turns those
+  // into XRayRecord entries. Sorts the events by TSC if |Sort| is true.
+  explicit YAMLLogReader(int Fd, std::error_code &EC, bool Sort = true);
+
+  const XRayFileHeader &getFileHeader() const { return FileHeader; };
+  iterator begin() { return Records.begin(); }
+  iterator end() { return Records.end(); }
+  citerator cbegin() { return Records.cbegin(); }
+  citerator cend() { return Records.cend(); }
+  citerator begin() const { return Records.begin(); }
+  citerator end() const { return Records.end(); }
+  citerator cbegin() const { return Records.begin(); }
+  citerator cend() const { return Records.end(); }
+  size_t size() const { return Records.size(); }
+};
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
Index: tools/llvm-xray/xray-log-reader.cc
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-log-reader.cc
@@ -0,0 +1,86 @@
+//===- xray-log-reader.cc - XRay Log Reader Implementation ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// XRay log reader implementation.
+//
+//===----------------------------------------------------------------------===//
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "xray-log-reader.h"
+#include "xray-record-yaml.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace llvm;
+using namespace llvm::xray;
+using llvm::yaml::Input;
+
+NaiveLogReader::NaiveLogReader(int Fd, std::error_code &EC, bool Sort) {
+  off_t FileSize;
+  while ((FileSize = lseek(Fd, 0, SEEK_END)) == -1) {
+    if (errno == EINTR)
+      continue;
+  }
+  assert(FileSize != -1 && "Error seeking to the end of file");
+  sys::fs::mapped_file_region MappedFile(
+      Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
+  if (EC)
+    return;
+
+  // Set up the FileHeader.
+  memcpy(&FileHeader, MappedFile.data(), sizeof(XRayFileHeader));
+
+  // Start copying the data from the MappedFile into the Records data structure.
+  auto I = MappedFile.data() + sizeof(XRayFileHeader);
+  auto E = MappedFile.data() + MappedFile.size();
+  while (I + sizeof(XRayRecord) <= E) {
+    Records.push_back({});
+    memcpy(&Records.back(), I, sizeof(XRayRecord));
+    I += sizeof(XRayRecord);
+  }
+
+  if (Sort)
+    std::sort(
+        Records.begin(), Records.end(),
+        [](const XRayRecord &L, const XRayRecord &R) { return L.TSC < R.TSC; });
+}
+
+YAMLLogReader::YAMLLogReader(int Fd, std::error_code &EC, bool Sort) {
+  off_t FileSize;
+  while ((FileSize = lseek(Fd, 0, SEEK_END)) == -1) {
+    if (errno == EINTR)
+      continue;
+  }
+  assert(FileSize != -1 && "Error seeking to the end of the file");
+  sys::fs::mapped_file_region MappedFile(
+      Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
+  if (EC)
+    return;
+
+  // Load the documents from the MappedFile.
+  YAMLXRayTrace Trace;
+  Input In(StringRef(MappedFile.data(), FileSize));
+  In >> Trace;
+  if (In.error()) {
+    EC = std::make_error_code(std::errc::io_error);
+    return;
+  }
+  // Only read the first trace in the document.
+  FileHeader.Version = Trace.Header.Version;
+  FileHeader.Type = Trace.Header.Type;
+  FileHeader.ConstantTSC = Trace.Header.ConstantTSC;
+  FileHeader.NonstopTSC = Trace.Header.NonstopTSC;
+  FileHeader.CycleFrequency = Trace.Header.CycleFrequency;
+  Records.swap(Trace.Records);
+  if (Sort)
+    std::sort(Records.begin(), Records.end(),
+              [](const YAMLXRayRecord &L, const YAMLXRayRecord &R) {
+                return L.TSC < R.TSC;
+              });
+}
Index: tools/llvm-xray/xray-record-yaml.h
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-record-yaml.h
@@ -0,0 +1,126 @@
+//===- xray-record-yaml.h - XRay Record YAML Support Definitions ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Types and traits specialisations for YAML I/O of XRay log entries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
+#define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
+
+#include <type_traits>
+
+#include "xray-record.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace xray {
+
+struct YAMLXRayFileHeader {
+  uint16_t Version;
+  uint16_t Type;
+  bool ConstantTSC;
+  bool NonstopTSC;
+  uint64_t CycleFrequency;
+};
+
+enum class RecordTypes { ENTER, EXIT };
+
+struct YAMLXRayRecord {
+  uint16_t RecordType;
+  uint8_t CPU;
+  RecordTypes Type;
+  int32_t FuncId;
+  std::string Function;
+  uint64_t TSC;
+  uint32_t TId;
+};
+
+struct YAMLXRayTrace {
+  YAMLXRayFileHeader Header;
+  std::vector<YAMLXRayRecord> Records;
+};
+
+using XRayRecordStorage =
+    std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
+
+/// Converts a YAMLXRayRecord into an XRayRecord stored in an aligned storage
+/// buffer |Buf| then returns a reference to that object.
+inline XRayRecord &toXRayRecord(const YAMLXRayRecord &Y,
+                                XRayRecordStorage &Buf) {
+  XRayRecord &R = *reinterpret_cast<XRayRecord *>(&Buf);
+  R.RecordType = Y.RecordType;
+  R.CPU = Y.CPU;
+  switch (Y.Type) {
+  case RecordTypes::ENTER:
+    R.Type = 0;
+    break;
+  case RecordTypes::EXIT:
+    R.Type = 1;
+    break;
+  }
+  R.FuncId = Y.FuncId;
+  R.TSC = Y.TSC;
+  R.TId = Y.TId;
+  memset(R.Buffer, 0, sizeof(R.Buffer));
+  return R;
+}
+
+} // namespace xray
+
+namespace yaml {
+
+// YAML Traits
+// -----------
+template <> struct ScalarEnumerationTraits<xray::RecordTypes> {
+  static void enumeration(IO &IO, xray::RecordTypes &Type) {
+    IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
+    IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
+  }
+};
+
+template <> struct MappingTraits<xray::YAMLXRayFileHeader> {
+  static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) {
+    IO.mapRequired("version", Header.Version);
+    IO.mapRequired("type", Header.Type);
+    IO.mapRequired("constant-tsc", Header.ConstantTSC);
+    IO.mapRequired("nonstop-tsc", Header.NonstopTSC);
+    IO.mapRequired("cycle-frequency", Header.CycleFrequency);
+  }
+};
+
+template <> struct MappingTraits<xray::YAMLXRayRecord> {
+  static void mapping(IO &IO, xray::YAMLXRayRecord &Record) {
+    // FIXME: Make this type actually be descriptive
+    IO.mapRequired("type", Record.RecordType);
+    IO.mapRequired("func-id", Record.FuncId);
+    IO.mapOptional("function", Record.Function);
+    IO.mapRequired("cpu", Record.CPU);
+    IO.mapRequired("thread", Record.TId);
+    IO.mapRequired("kind", Record.Type);
+    IO.mapRequired("tsc", Record.TSC);
+  }
+
+  static constexpr bool flow = true;
+};
+
+template <> struct MappingTraits<xray::YAMLXRayTrace> {
+  static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) {
+    // A trace file contains two parts, the header and the list of all the
+    // trace records.
+    IO.mapRequired("header", Trace.Header);
+    IO.mapRequired("records", Trace.Records);
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord);
+
+#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
Index: tools/llvm-xray/xray-record.h
===================================================================
--- /dev/null
+++ tools/llvm-xray/xray-record.h
@@ -0,0 +1,60 @@
+//===- xray-record.h - XRay Trace Record ----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file replicates the record definition for XRay log entries. This should
+// follow the evolution of the log record versions supported in the compiler-rt
+// xray project.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H
+#define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H
+
+#include <cstdint>
+
+namespace llvm {
+namespace xray {
+
+struct alignas(32) XRayFileHeader {
+  uint16_t Version = 0;
+  uint16_t Type = 0;
+  bool ConstantTSC : 1;
+  bool NonstopTSC : 1;
+  alignas(8) uint64_t CycleFrequency = 0;
+} __attribute__((packed));
+
+static_assert(sizeof(XRayFileHeader) == 32, "XRayFileHeader != 32 bytes");
+
+struct alignas(32) XRayRecord {
+  uint16_t RecordType = 0;
+
+  // The CPU where the thread is running. We assume number of CPUs <= 256.
+  uint8_t CPU = 0;
+
+  // The type of the event. Usually either ENTER = 0 or EXIT = 1.
+  uint8_t Type = 0;
+
+  // The function ID for the record.
+  int32_t FuncId = 0;
+
+  // Get the full 8 bytes of the TSC when we get the log record.
+  uint64_t TSC = 0;
+
+  // The thread ID for the currently running thread.
+  uint32_t TId = 0;
+
+  // Use some bytes in the end of the record for buffers.
+  char Buffer[4] = {};
+} __attribute__((packed));
+
+static_assert(sizeof(XRayRecord) == 32, "XRayRecord != 32 bytes");
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H