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. 14d764c1b6SDean Michael Berris Expected<XRayFileHeader> readBinaryFormatHeader(DataExtractor &HeaderExtractor, 15*f26a70a5SIgor 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), 33*f26a70a5SIgor Kudrin "Failed reading version from file header at offset %" PRId64 ".", 34*f26a70a5SIgor 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), 41*f26a70a5SIgor Kudrin "Failed reading file type from file header at offset %" PRId64 ".", 42*f26a70a5SIgor 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), 49*f26a70a5SIgor Kudrin "Failed reading flag bits from file header at offset %" PRId64 ".", 50*f26a70a5SIgor 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), 59*f26a70a5SIgor Kudrin "Failed reading cycle frequency from file header at offset %" PRId64 60*f26a70a5SIgor 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; 69d764c1b6SDean Michael Berris return std::move(FileHeader); 70d764c1b6SDean Michael Berris } 71d764c1b6SDean Michael Berris 72d764c1b6SDean Michael Berris } // namespace xray 73d764c1b6SDean Michael Berris } // namespace llvm 74