//===- SFrameParser.cpp ---------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/Object/SFrameParser.h" #include "llvm/BinaryFormat/SFrame.h" #include "llvm/Object/Error.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" using namespace llvm; using namespace llvm::object; static Expected> getDataSlice(ArrayRef Data, uint64_t Offset, uint64_t Size) { uint64_t End = SaturatingAdd(Offset, Size); // Data.size() cannot be UINT64_MAX, as it would occupy the whole address // space. if (End > Data.size()) { return createStringError( formatv("unexpected end of data at offset {0:x} while reading [{1:x}, " "{2:x})", Data.size(), Offset, End) .str(), object_error::unexpected_eof); } return Data.slice(Offset, Size); } template static Expected getDataSliceAs(ArrayRef Data, uint64_t Offset) { static_assert(std::is_trivial_v); Expected> Slice = getDataSlice(Data, Offset, sizeof(T)); if (!Slice) return Slice.takeError(); return *reinterpret_cast(Slice->data()); } template Expected> SFrameParser::create(ArrayRef Contents, uint64_t SectionAddress) { Expected &> Preamble = getDataSliceAs>(Contents, 0); if (!Preamble) return Preamble.takeError(); if (Preamble->Magic != sframe::Magic) return createError( formatv("invalid magic number ({0:x+4})", Preamble->Magic.value())); if (Preamble->Version != sframe::Version::V2) return createError( formatv("invalid/unsupported version number ({0})", static_cast(Preamble->Version.value()))); Expected &> Header = getDataSliceAs>(Contents, 0); if (!Header) return Header.takeError(); return SFrameParser(Contents, SectionAddress, *Header); } template Expected> SFrameParser::getAuxHeader() const { return getDataSlice(Data, sizeof(Header), Header.AuxHdrLen); } template Expected>> SFrameParser::fdes() const { Expected> Slice = getDataSlice( Data, getFDEBase(), Header.NumFDEs * sizeof(sframe::FuncDescEntry)); if (!Slice) return Slice.takeError(); return ArrayRef( reinterpret_cast *>(Slice->data()), Header.NumFDEs); } template uint64_t SFrameParser::getAbsoluteStartAddress( typename FDERange::iterator FDE) const { uint64_t Result = SectionAddress + FDE->StartAddress; if ((getPreamble().Flags.value() & sframe::Flags::FDEFuncStartPCRel) == sframe::Flags::FDEFuncStartPCRel) { uintptr_t DataPtr = reinterpret_cast(Data.data()); uintptr_t FDEPtr = reinterpret_cast(&*FDE); assert(DataPtr <= FDEPtr && FDEPtr < DataPtr + Data.size() && "Iterator does not belong to this object!"); Result += FDEPtr - DataPtr; } return Result; } template class LLVM_EXPORT_TEMPLATE llvm::object::SFrameParser; template class LLVM_EXPORT_TEMPLATE llvm::object::SFrameParser;