xref: /freebsd-src/contrib/llvm-project/llvm/lib/XRay/FileHeaderReader.cpp (revision 5b27928474e6a4103d65b347544705c40c9618fd)
10b57cec5SDimitry Andric //===- FileHeaderReader.cpp - XRay File Header Reader  --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "llvm/XRay/FileHeaderReader.h"
90b57cec5SDimitry Andric 
100b57cec5SDimitry Andric namespace llvm {
110b57cec5SDimitry Andric namespace xray {
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric // Populates the FileHeader reference by reading the first 32 bytes of the file.
readBinaryFormatHeader(DataExtractor & HeaderExtractor,uint64_t & OffsetPtr)140b57cec5SDimitry Andric Expected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor,
15*8bcb0991SDimitry Andric                                                 uint64_t &OffsetPtr) {
160b57cec5SDimitry Andric   // FIXME: Maybe deduce whether the data is little or big-endian using some
170b57cec5SDimitry Andric   // magic bytes in the beginning of the file?
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric   // First 32 bytes of the file will always be the header. We assume a certain
200b57cec5SDimitry Andric   // format here:
210b57cec5SDimitry Andric   //
220b57cec5SDimitry Andric   //   (2)   uint16 : version
230b57cec5SDimitry Andric   //   (2)   uint16 : type
240b57cec5SDimitry Andric   //   (4)   uint32 : bitfield
250b57cec5SDimitry Andric   //   (8)   uint64 : cycle frequency
260b57cec5SDimitry Andric   //   (16)  -      : padding
270b57cec5SDimitry Andric   XRayFileHeader FileHeader;
280b57cec5SDimitry Andric   auto PreReadOffset = OffsetPtr;
290b57cec5SDimitry Andric   FileHeader.Version = HeaderExtractor.getU16(&OffsetPtr);
300b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
310b57cec5SDimitry Andric     return createStringError(
320b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
33*8bcb0991SDimitry Andric         "Failed reading version from file header at offset %" PRId64 ".",
34*8bcb0991SDimitry Andric         OffsetPtr);
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
370b57cec5SDimitry Andric   FileHeader.Type = HeaderExtractor.getU16(&OffsetPtr);
380b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
390b57cec5SDimitry Andric     return createStringError(
400b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
41*8bcb0991SDimitry Andric         "Failed reading file type from file header at offset %" PRId64 ".",
42*8bcb0991SDimitry Andric         OffsetPtr);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
450b57cec5SDimitry Andric   uint32_t Bitfield = HeaderExtractor.getU32(&OffsetPtr);
460b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
470b57cec5SDimitry Andric     return createStringError(
480b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
49*8bcb0991SDimitry Andric         "Failed reading flag bits from file header at offset %" PRId64 ".",
50*8bcb0991SDimitry Andric         OffsetPtr);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   FileHeader.ConstantTSC = Bitfield & 1uL;
530b57cec5SDimitry Andric   FileHeader.NonstopTSC = Bitfield & 1uL << 1;
540b57cec5SDimitry Andric   PreReadOffset = OffsetPtr;
550b57cec5SDimitry Andric   FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr);
560b57cec5SDimitry Andric   if (OffsetPtr == PreReadOffset)
570b57cec5SDimitry Andric     return createStringError(
580b57cec5SDimitry Andric         std::make_error_code(std::errc::invalid_argument),
59*8bcb0991SDimitry Andric         "Failed reading cycle frequency from file header at offset %" PRId64
60*8bcb0991SDimitry Andric         ".",
610b57cec5SDimitry Andric         OffsetPtr);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   std::memcpy(&FileHeader.FreeFormData,
640b57cec5SDimitry Andric               HeaderExtractor.getData().bytes_begin() + OffsetPtr, 16);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   // Manually advance the offset pointer 16 bytes, after getting a raw memcpy
670b57cec5SDimitry Andric   // from the underlying data.
680b57cec5SDimitry Andric   OffsetPtr += 16;
690b57cec5SDimitry Andric   return std::move(FileHeader);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric } // namespace xray
730b57cec5SDimitry Andric } // namespace llvm
74