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