--- /dev/null
+//===- Trace.h - XRay Trace Abstraction -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the XRay Trace class representing records in an XRay trace file.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_XRAY_TRACE_H
+#define LLVM_XRAY_TRACE_H
+
+#include <cstdint>
+#include <vector>
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/XRay/XRayRecord.h"
+
+namespace llvm {
+namespace xray {
+
+/// A Trace object represents the records that have been loaded from XRay
+/// log files generated by instrumented binaries. We encapsulate the logic of
+/// reading the traces in factory functions that populate the Trace object
+/// appropriately.
+///
+/// Trace objects provide an accessor to an XRayFileHeader which says more about
+/// details of the file from which the XRay trace was loaded from.
+///
+/// Usage:
+///
+/// if (auto TraceOrErr = loadTraceFile("xray-log.something.xray")) {
+/// auto& T = *TraceOrErr;
+/// // T.getFileHeader() will provide information from the trace header.
+/// for (const XRayRecord &R : T) {
+/// // ... do something with R here.
+/// }
+/// } else {
+/// // Handle the error here.
+/// }
+///
+class Trace {
+ XRayFileHeader FileHeader;
+ std::vector<XRayRecord> Records;
+
+ typedef std::vector<XRayRecord>::const_iterator citerator;
+
+ friend Expected<Trace> loadTraceFile(StringRef, bool);
+
+public:
+ /// Provides access to the loaded XRay trace file header.
+ const XRayFileHeader &getFileHeader() const { return FileHeader; }
+
+ citerator begin() const { return Records.begin(); }
+ citerator end() const { return Records.end(); }
+ size_t size() const { return Records.size(); }
+};
+
+/// This function will attempt to load XRay trace records from the provided
+/// |Filename|.
+Expected<Trace> loadTraceFile(StringRef Filename, bool Sort = false);
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_XRAY_TRACE_H
--- /dev/null
+//===- XRayRecord.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_XRAY_XRAY_RECORD_H
+#define LLVM_XRAY_XRAY_RECORD_H
+
+#include <cstdint>
+
+namespace llvm {
+namespace xray {
+
+/// XRay traces all have a header providing some top-matter information useful
+/// to help tools determine how to interpret the information available in the
+/// trace.
+struct XRayFileHeader {
+ /// Version of the XRay implementation that produced this file.
+ uint16_t Version = 0;
+
+ /// A numeric identifier for the type of file this is. Best used in
+ /// combination with Version.
+ uint16_t Type = 0;
+
+ /// Whether the CPU that produced the timestamp counters (TSC) move at a
+ /// constant rate.
+ bool ConstantTSC;
+
+ /// Whether the CPU that produced the timestamp counters (TSC) do not stop.
+ bool NonstopTSC;
+
+ /// The number of cycles per second for the CPU that produced the timestamp
+ /// counter (TSC) values. Useful for estimating the amount of time that
+ /// elapsed between two TSCs on some platforms.
+ uint64_t CycleFrequency = 0;
+};
+
+/// Determines the supported types of records that could be seen in XRay traces.
+/// This may or may not correspond to actual record types in the raw trace (as
+/// the loader implementation may synthesize this information in the process of
+/// of loading).
+enum class RecordTypes { ENTER, EXIT };
+
+struct XRayRecord {
+ /// The type of record.
+ uint16_t RecordType;
+
+ /// The CPU where the thread is running. We assume number of CPUs <= 256.
+ uint8_t CPU;
+
+ /// Identifies the type of record.
+ RecordTypes Type;
+
+ /// The function ID for the record.
+ int32_t FuncId;
+
+ /// Get the full 8 bytes of the TSC when we get the log record.
+ uint64_t TSC;
+
+ /// The thread ID for the currently running thread.
+ uint32_t TId;
+};
+
+} // namespace xray
+} // namespace llvm
+
+#endif // LLVM_XRAY_XRAY_RECORD_H
-//===- xray-record-yaml.h - XRay Record YAML Support Definitions ----------===//
+//===- YAMLXRayRecord.h - XRay Record YAML Support Definitions ------------===//
//
// The LLVM Compiler Infrastructure
//
// 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
+#ifndef LLVM_XRAY_YAML_XRAY_RECORD_H
+#define LLVM_XRAY_YAML_XRAY_RECORD_H
#include <type_traits>
-#include "xray-record.h"
#include "llvm/Support/YAMLTraits.h"
+#include "llvm/XRay/XRayRecord.h"
namespace llvm {
namespace xray {
std::vector<YAMLXRayRecord> Records;
};
-using XRayRecordStorage =
- std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
-
} // namespace xray
namespace yaml {
} // namespace yaml
} // namespace llvm
-LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord)
+LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord)
-#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H
+#endif // LLVM_XRAY_YAML_XRAY_RECORD_H
add_subdirectory(Fuzzer)
add_subdirectory(Passes)
add_subdirectory(LibDriver)
+add_subdirectory(XRay)
--- /dev/null
+add_llvm_library(LLVMXRay
+ Trace.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/ADT
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/XRay
+
+ DEPENDS
+ LLVMSupport
+
+ LINK_LIBS
+ LLVMSupport
+ )
-//===- xray-log-reader.cc - XRay Log Reader Implementation ----------------===//
+//===- Trace.cpp - XRay Trace Loading implementation. ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// XRay log reader implementation.
//
//===----------------------------------------------------------------------===//
-#include "xray-log-reader.h"
-#include "xray-record-yaml.h"
+#include "llvm/XRay/Trace.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/XRay/YAMLXRayRecord.h"
using namespace llvm;
using namespace llvm::xray;
using llvm::yaml::Input;
-LogReader::LogReader(
- StringRef Filename, Error &Err, bool Sort,
- std::function<Error(StringRef, XRayFileHeader &, std::vector<XRayRecord> &)>
- Loader) {
- ErrorAsOutParameter Guard(&Err);
- int Fd;
- if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
- Err = make_error<StringError>(
- Twine("Cannot read log from '") + Filename + "'", EC);
- return;
- }
- uint64_t FileSize;
- if (auto EC = sys::fs::file_size(Filename, FileSize)) {
- Err = make_error<StringError>(
- Twine("Cannot read log from '") + Filename + "'", EC);
- return;
- }
-
- std::error_code EC;
- sys::fs::mapped_file_region MappedFile(
- Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
- if (EC) {
- Err = make_error<StringError>(
- Twine("Cannot read log from '") + Filename + "'", EC);
- return;
- }
-
- if (auto E = Loader(StringRef(MappedFile.data(), MappedFile.size()),
- FileHeader, Records)) {
- Err = std::move(E);
- return;
- }
-
- if (Sort)
- std::sort(
- Records.begin(), Records.end(),
- [](const XRayRecord &L, const XRayRecord &R) { return L.TSC < R.TSC; });
-}
+using XRayRecordStorage =
+ std::aligned_storage<sizeof(XRayRecord), alignof(XRayRecord)>::type;
-Error llvm::xray::NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
- std::vector<XRayRecord> &Records) {
+Error NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
+ std::vector<XRayRecord> &Records) {
// FIXME: Maybe deduce whether the data is little or big-endian using some
// magic bytes in the beginning of the file?
return Error::success();
}
-Error llvm::xray::YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
- std::vector<XRayRecord> &Records) {
+Error YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
+ std::vector<XRayRecord> &Records) {
// Load the documents from the MappedFile.
YAMLXRayTrace Trace;
});
return Error::success();
}
+
+Expected<Trace> llvm::xray::loadTraceFile(StringRef Filename, bool Sort) {
+ int Fd;
+ if (auto EC = sys::fs::openFileForRead(Filename, Fd)) {
+ return make_error<StringError>(
+ Twine("Cannot read log from '") + Filename + "'", EC);
+ }
+
+ // Attempt to get the filesize.
+ uint64_t FileSize;
+ if (auto EC = sys::fs::file_size(Filename, FileSize)) {
+ return make_error<StringError>(
+ Twine("Cannot read log from '") + Filename + "'", EC);
+ }
+ if (FileSize < 4) {
+ return make_error<StringError>(
+ Twine("File '") + Filename + "' too small for XRay.",
+ std::make_error_code(std::errc::protocol_error));
+ }
+
+ // Attempt to mmap the file.
+ std::error_code EC;
+ sys::fs::mapped_file_region MappedFile(
+ Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
+ if (EC) {
+ return make_error<StringError>(
+ Twine("Cannot read log from '") + Filename + "'", EC);
+ }
+
+ // Attempt to detect the file type using file magic. We have a slight bias
+ // towards the binary format, and we do this by making sure that the first 4
+ // bytes of the binary file is some combination of the following byte
+ // patterns:
+ //
+ // 0x0001 0x0000 - version 1, "naive" format
+ // 0x0001 0x0001 - version 1, "flight data recorder" format
+ //
+ // YAML files dont' typically have those first four bytes as valid text so we
+ // try loading assuming YAML if we don't find these bytes.
+ //
+ // Only if we can't load either the binary or the YAML format will we yield an
+ // error.
+ StringRef Magic(MappedFile.data(), 4);
+ DataExtractor HeaderExtractor(Magic, true, 8);
+ uint32_t OffsetPtr = 0;
+ uint16_t Version = HeaderExtractor.getU16(&OffsetPtr);
+ uint16_t Type = HeaderExtractor.getU16(&OffsetPtr);
+
+ Trace T;
+ if (Version == 1 && (Type == 0 || Type == 1)) {
+ if (auto E = NaiveLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
+ T.FileHeader, T.Records))
+ return std::move(E);
+ } else {
+ if (auto E = YAMLLogLoader(StringRef(MappedFile.data(), MappedFile.size()),
+ T.FileHeader, T.Records))
+ return std::move(E);
+ }
+
+ if (Sort)
+ std::sort(T.Records.begin(), T.Records.end(),
+ [&](const XRayRecord &L, const XRayRecord &R) {
+ return L.TSC < R.TSC;
+ });
+
+ return std::move(T);
+}
-#RUN: llvm-xray convert %s -i=yaml -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
+#RUN: llvm-xray convert %s -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s
---
header:
version: 1
DebugInfoDWARF
Object
Support
- Symbolize)
+ Symbolize
+ XRay)
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})
#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/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/XRay/Trace.h"
+#include "llvm/XRay/YAMLXRayRecord.h"
using namespace llvm;
using namespace xray;
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"),
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 LogReader &Records, raw_ostream &OS) {
+void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) {
YAMLXRayTrace Trace;
const auto &FH = Records.getFileHeader();
Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC,
Out << Trace;
}
-void TraceConverter::exportAsRAWv1(const LogReader &Records, raw_ostream &OS) {
+void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
// First write out the file header, in the correct endian-appropriate format
// (XRay assumes currently little endian).
support::endian::Writer<support::endianness::little> Writer(OS);
llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer,
FunctionAddresses);
llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize);
- LogReader::LoaderFunction Loader;
- switch (ConvertInputFormat) {
- case ConvertFormats::BINARY:
- Loader = NaiveLogLoader;
- break;
- case ConvertFormats::YAML:
- Loader = YAMLLogLoader;
- break;
- }
-
- LogReader Reader(ConvertInput, Err, ConvertSortInput, Loader);
- if (Err)
- return joinErrors(
- make_error<StringError>(
- Twine("Failed loading input file '") + ConvertInput + "'.",
- std::make_error_code(std::errc::executable_format_error)),
- std::move(Err));
-
raw_fd_ostream OS(ConvertOutput, EC,
ConvertOutputFormat == ConvertFormats::BINARY
? sys::fs::OpenFlags::F_None
return make_error<StringError>(
Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
- switch (ConvertOutputFormat) {
- case ConvertFormats::YAML:
- TC.exportAsYAML(Reader, OS);
- break;
- case ConvertFormats::BINARY:
- TC.exportAsRAWv1(Reader, OS);
- break;
+ if (auto TraceOrErr = loadTraceFile(ConvertInput, ConvertSortInput)) {
+ auto &T = *TraceOrErr;
+ switch (ConvertOutputFormat) {
+ case ConvertFormats::YAML:
+ TC.exportAsYAML(T, OS);
+ break;
+ case ConvertFormats::BINARY:
+ TC.exportAsRAWv1(T, OS);
+ break;
+ }
+ } else {
+ return joinErrors(
+ make_error<StringError>(
+ Twine("Failed loading input file '") + ConvertInput + "'.",
+ std::make_error_code(std::errc::protocol_error)),
+ TraceOrErr.takeError());
}
return Error::success();
});
#define LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H
#include "func-id-helper.h"
-#include "xray-log-reader.h"
-#include "xray-record.h"
+#include "llvm/XRay/XRayRecord.h"
+#include "llvm/XRay/Trace.h"
namespace llvm {
namespace xray {
TraceConverter(FuncIdConversionHelper &FuncIdHelper, bool Symbolize = false)
: FuncIdHelper(FuncIdHelper), Symbolize(Symbolize) {}
- void exportAsYAML(const LogReader &Records, raw_ostream &OS);
- void exportAsRAWv1(const LogReader &Records, raw_ostream &OS);
+ void exportAsYAML(const Trace &Records, raw_ostream &OS);
+ void exportAsRAWv1(const Trace &Records, raw_ostream &OS);
};
} // namespace xray
+++ /dev/null
-//===- 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"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-
-namespace llvm {
-namespace xray {
-
-class LogReader {
- XRayFileHeader FileHeader;
- std::vector<XRayRecord> Records;
-
- typedef std::vector<XRayRecord>::const_iterator citerator;
-
-public:
- typedef std::function<Error(StringRef, XRayFileHeader &,
- std::vector<XRayRecord> &)>
- LoaderFunction;
-
- LogReader(StringRef Filename, Error &Err, bool Sort, LoaderFunction Loader);
-
- const XRayFileHeader &getFileHeader() const { return FileHeader; }
-
- citerator begin() const { return Records.begin(); }
- citerator end() const { return Records.end(); }
- size_t size() const { return Records.size(); }
-};
-
-Error NaiveLogLoader(StringRef Data, XRayFileHeader &FileHeader,
- std::vector<XRayRecord> &Records);
-Error YAMLLogLoader(StringRef Data, XRayFileHeader &FileHeader,
- std::vector<XRayRecord> &Records);
-
-} // namespace xray
-} // namespace llvm
-
-#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H
+++ /dev/null
-//===- 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 XRayFileHeader {
- uint16_t Version = 0;
- uint16_t Type = 0;
- bool ConstantTSC;
- bool NonstopTSC;
- uint64_t CycleFrequency = 0;
-};
-
-enum class RecordTypes { ENTER, EXIT };
-
-struct XRayRecord {
- uint16_t RecordType;
-
- // The CPU where the thread is running. We assume number of CPUs <= 256.
- uint8_t CPU;
-
- // Identifies the type of record.
- RecordTypes Type;
-
- // The function ID for the record.
- int32_t FuncId;
-
- // Get the full 8 bytes of the TSC when we get the log record.
- uint64_t TSC;
-
- // The thread ID for the currently running thread.
- uint32_t TId;
-};
-
-} // namespace xray
-} // namespace llvm
-
-#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H