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