xref: /freebsd/contrib/llvm-project/llvm/lib/XRay/FileHeaderReader.cpp (revision 162ae9c834f6d9f9cb443bd62cceb23e0b5fef48)
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 
10 namespace llvm {
11 namespace xray {
12 
13 // Populates the FileHeader reference by reading the first 32 bytes of the file.
14 Expected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor,
15                                                 uint32_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 %d.", OffsetPtr);
34 
35   PreReadOffset = OffsetPtr;
36   FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
37   if (OffsetPtr == PreReadOffset)
38     return createStringError(
39         std::make_error_code(std::errc::invalid_argument),
40         "Failed reading file type from file header at offset %d.", OffsetPtr);
41 
42   PreReadOffset = OffsetPtr;
43   uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
44   if (OffsetPtr == PreReadOffset)
45     return createStringError(
46         std::make_error_code(std::errc::invalid_argument),
47         "Failed reading flag bits from file header at offset %d.", OffsetPtr);
48 
49   FileHeader.ConstantTSC = Bitfield & 1uL;
50   FileHeader.NonstopTSC = Bitfield & 1uL << 1;
51   PreReadOffset = OffsetPtr;
52   FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
53   if (OffsetPtr == PreReadOffset)
54     return createStringError(
55         std::make_error_code(std::errc::invalid_argument),
56         "Failed reading cycle frequency from file header at offset %d.",
57         OffsetPtr);
58 
59   std::memcpy(&FileHeader.FreeFormData,
60               HeaderExtractor.getData().bytes_begin() + OffsetPtr, 16);
61 
62   // Manually advance the offset pointer 16 bytes, after getting a raw memcpy
63   // from the underlying data.
64   OffsetPtr += 16;
65   return std::move(FileHeader);
66 }
67 
68 } // namespace xray
69 } // namespace llvm
70