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