FileHeaderReader.cpp revision 360784
1//===- FileHeaderReader.cpp - XRay File Header Reader  --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#include "llvm/XRay/FileHeaderReader.h"
9
10namespace llvm {
11namespace xray {
12
13// Populates the FileHeader reference by reading the first 32 bytes of the file.
14Expected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor,
15                                                uint64_t &OffsetPtr) {
16  // FIXME: Maybe deduce whether the data is little or big-endian using some
17  // magic bytes in the beginning of the file?
18
19  // First 32 bytes of the file will always be the header. We assume a certain
20  // format here:
21  //
22  //   (2)   uint16 : version
23  //   (2)   uint16 : type
24  //   (4)   uint32 : bitfield
25  //   (8)   uint64 : cycle frequency
26  //   (16)  -      : padding
27  XRayFileHeader FileHeader;
28  auto PreReadOffset = OffsetPtr;
29  FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
30  if (OffsetPtr == PreReadOffset)
31    return createStringError(
32        std::make_error_code(std::errc::invalid_argument),
33        "Failed reading version from file header at offset %" PRId64 ".",
34        OffsetPtr);
35
36  PreReadOffset = OffsetPtr;
37  FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
38  if (OffsetPtr == PreReadOffset)
39    return createStringError(
40        std::make_error_code(std::errc::invalid_argument),
41        "Failed reading file type from file header at offset %" PRId64 ".",
42        OffsetPtr);
43
44  PreReadOffset = OffsetPtr;
45  uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
46  if (OffsetPtr == PreReadOffset)
47    return createStringError(
48        std::make_error_code(std::errc::invalid_argument),
49        "Failed reading flag bits from file header at offset %" PRId64 ".",
50        OffsetPtr);
51
52  FileHeader.ConstantTSC = Bitfield & 1uL;
53  FileHeader.NonstopTSC = Bitfield & 1uL << 1;
54  PreReadOffset = OffsetPtr;
55  FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
56  if (OffsetPtr == PreReadOffset)
57    return createStringError(
58        std::make_error_code(std::errc::invalid_argument),
59        "Failed reading cycle frequency from file header at offset %" PRId64
60        ".",
61        OffsetPtr);
62
63  std::memcpy(&FileHeader.FreeFormData,
64              HeaderExtractor.getData().bytes_begin() + OffsetPtr, 16);
65
66  // Manually advance the offset pointer 16 bytes, after getting a raw memcpy
67  // from the underlying data.
68  OffsetPtr += 16;
69  return std::move(FileHeader);
70}
71
72} // namespace xray
73} // namespace llvm
74