FileHeaderReader.cpp revision 343171
1238106Sdes//===- FileHeaderReader.cpp - XRay File Header Reader  --------------------===//
2238106Sdes//
3238106Sdes//                     The LLVM Compiler Infrastructure
4238106Sdes//
5238106Sdes// This file is distributed under the University of Illinois Open Source
6238106Sdes// License. See LICENSE.TXT for details.
7238106Sdes//
8238106Sdes//===----------------------------------------------------------------------===//
9238106Sdes#include "llvm/XRay/FileHeaderReader.h"
10238106Sdes
11238106Sdesnamespace llvm {
12238106Sdesnamespace xray {
13238106Sdes
14238106Sdes// Populates the FileHeader reference by reading the first 32 bytes of the file.
15238106SdesExpected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor,
16238106Sdes                                                uint32_t &OffsetPtr) {
17238106Sdes  // FIXME: Maybe deduce whether the data is little or big-endian using some
18238106Sdes  // magic bytes in the beginning of the file?
19238106Sdes
20238106Sdes  // First 32 bytes of the file will always be the header. We assume a certain
21238106Sdes  // format here:
22238106Sdes  //
23238106Sdes  //   (2)   uint16 : version
24266114Sdes  //   (2)   uint16 : type
25266114Sdes  //   (4)   uint32 : bitfield
26266114Sdes  //   (8)   uint64 : cycle frequency
27266114Sdes  //   (16)  -      : padding
28266114Sdes  XRayFileHeader FileHeader;
29266114Sdes  auto PreReadOffset = OffsetPtr;
30266114Sdes  FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
31266114Sdes  if (OffsetPtr == PreReadOffset)
32266114Sdes    return createStringError(
33266114Sdes        std::make_error_code(std::errc::invalid_argument),
34238106Sdes        "Failed reading version from file header at offset %d.", OffsetPtr);
35238106Sdes
36238106Sdes  PreReadOffset = OffsetPtr;
37238106Sdes  FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
38238106Sdes  if (OffsetPtr == PreReadOffset)
39238106Sdes    return createStringError(
40238106Sdes        std::make_error_code(std::errc::invalid_argument),
41238106Sdes        "Failed reading file type from file header at offset %d.", OffsetPtr);
42238106Sdes
43238106Sdes  PreReadOffset = OffsetPtr;
44238106Sdes  uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
45238106Sdes  if (OffsetPtr == PreReadOffset)
46368129Scy    return createStringError(
47368129Scy        std::make_error_code(std::errc::invalid_argument),
48368129Scy        "Failed reading flag bits from file header at offset %d.", OffsetPtr);
49238106Sdes
50238106Sdes  FileHeader.ConstantTSC = Bitfield & 1uL;
51238106Sdes  FileHeader.NonstopTSC = Bitfield & 1uL << 1;
52266114Sdes  PreReadOffset = OffsetPtr;
53356345Scy  FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
54238106Sdes  if (OffsetPtr == PreReadOffset)
55238106Sdes    return createStringError(
56238106Sdes        std::make_error_code(std::errc::invalid_argument),
57238106Sdes        "Failed reading cycle frequency from file header at offset %d.",
58238106Sdes        OffsetPtr);
59238106Sdes
60238106Sdes  std::memcpy(&FileHeader.FreeFormData,
61238106Sdes              HeaderExtractor.getData().bytes_begin() + OffsetPtr, 16);
62238106Sdes
63238106Sdes  // Manually advance the offset pointer 16 bytes, after getting a raw memcpy
64238106Sdes  // from the underlying data.
65266114Sdes  OffsetPtr += 16;
66356345Scy  return std::move(FileHeader);
67356345Scy}
68356345Scy
69238106Sdes} // namespace xray
70238106Sdes} // namespace llvm
71238106Sdes