Path: blob/main/contrib/llvm-project/llvm/lib/XRay/BlockVerifier.cpp
35234 views
//===- BlockVerifier.cpp - FDR Block Verifier -----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "llvm/XRay/BlockVerifier.h"8#include "llvm/Support/Error.h"910#include <bitset>1112namespace llvm {13namespace xray {14namespace {1516constexpr unsigned long long mask(BlockVerifier::State S) {17return 1uLL << static_cast<std::size_t>(S);18}1920constexpr std::size_t number(BlockVerifier::State S) {21return static_cast<std::size_t>(S);22}2324StringRef recordToString(BlockVerifier::State R) {25switch (R) {26case BlockVerifier::State::BufferExtents:27return "BufferExtents";28case BlockVerifier::State::NewBuffer:29return "NewBuffer";30case BlockVerifier::State::WallClockTime:31return "WallClockTime";32case BlockVerifier::State::PIDEntry:33return "PIDEntry";34case BlockVerifier::State::NewCPUId:35return "NewCPUId";36case BlockVerifier::State::TSCWrap:37return "TSCWrap";38case BlockVerifier::State::CustomEvent:39return "CustomEvent";40case BlockVerifier::State::Function:41return "Function";42case BlockVerifier::State::CallArg:43return "CallArg";44case BlockVerifier::State::EndOfBuffer:45return "EndOfBuffer";46case BlockVerifier::State::TypedEvent:47return "TypedEvent";48case BlockVerifier::State::StateMax:49case BlockVerifier::State::Unknown:50return "Unknown";51}52llvm_unreachable("Unkown state!");53}5455struct Transition {56BlockVerifier::State From;57std::bitset<number(BlockVerifier::State::StateMax)> ToStates;58};5960} // namespace6162Error BlockVerifier::transition(State To) {63using ToSet = std::bitset<number(State::StateMax)>;64static constexpr std::array<const Transition, number(State::StateMax)>65TransitionTable{{{State::Unknown,66{mask(State::BufferExtents) | mask(State::NewBuffer)}},6768{State::BufferExtents, {mask(State::NewBuffer)}},6970{State::NewBuffer, {mask(State::WallClockTime)}},7172{State::WallClockTime,73{mask(State::PIDEntry) | mask(State::NewCPUId)}},7475{State::PIDEntry, {mask(State::NewCPUId)}},7677{State::NewCPUId,78{mask(State::NewCPUId) | mask(State::TSCWrap) |79mask(State::CustomEvent) | mask(State::Function) |80mask(State::EndOfBuffer) | mask(State::TypedEvent)}},8182{State::TSCWrap,83{mask(State::TSCWrap) | mask(State::NewCPUId) |84mask(State::CustomEvent) | mask(State::Function) |85mask(State::EndOfBuffer) | mask(State::TypedEvent)}},8687{State::CustomEvent,88{mask(State::CustomEvent) | mask(State::TSCWrap) |89mask(State::NewCPUId) | mask(State::Function) |90mask(State::EndOfBuffer) | mask(State::TypedEvent)}},9192{State::TypedEvent,93{mask(State::TypedEvent) | mask(State::TSCWrap) |94mask(State::NewCPUId) | mask(State::Function) |95mask(State::EndOfBuffer) | mask(State::CustomEvent)}},9697{State::Function,98{mask(State::Function) | mask(State::TSCWrap) |99mask(State::NewCPUId) | mask(State::CustomEvent) |100mask(State::CallArg) | mask(State::EndOfBuffer) |101mask(State::TypedEvent)}},102103{State::CallArg,104{mask(State::CallArg) | mask(State::Function) |105mask(State::TSCWrap) | mask(State::NewCPUId) |106mask(State::CustomEvent) | mask(State::EndOfBuffer) |107mask(State::TypedEvent)}},108109{State::EndOfBuffer, {}}}};110111if (CurrentRecord >= State::StateMax)112return createStringError(113std::make_error_code(std::errc::executable_format_error),114"BUG (BlockVerifier): Cannot find transition table entry for %s, "115"transitioning to %s.",116recordToString(CurrentRecord).data(), recordToString(To).data());117118// If we're at an EndOfBuffer record, we ignore anything that follows that119// isn't a NewBuffer record.120if (CurrentRecord == State::EndOfBuffer && To != State::NewBuffer)121return Error::success();122123auto &Mapping = TransitionTable[number(CurrentRecord)];124auto &Destinations = Mapping.ToStates;125assert(Mapping.From == CurrentRecord &&126"BUG: Wrong index for record mapping.");127if ((Destinations & ToSet(mask(To))) == 0)128return createStringError(129std::make_error_code(std::errc::executable_format_error),130"BlockVerifier: Invalid transition from %s to %s.",131recordToString(CurrentRecord).data(), recordToString(To).data());132133CurrentRecord = To;134return Error::success();135} // namespace xray136137Error BlockVerifier::visit(BufferExtents &) {138return transition(State::BufferExtents);139}140141Error BlockVerifier::visit(WallclockRecord &) {142return transition(State::WallClockTime);143}144145Error BlockVerifier::visit(NewCPUIDRecord &) {146return transition(State::NewCPUId);147}148149Error BlockVerifier::visit(TSCWrapRecord &) {150return transition(State::TSCWrap);151}152153Error BlockVerifier::visit(CustomEventRecord &) {154return transition(State::CustomEvent);155}156157Error BlockVerifier::visit(CustomEventRecordV5 &) {158return transition(State::CustomEvent);159}160161Error BlockVerifier::visit(TypedEventRecord &) {162return transition(State::TypedEvent);163}164165Error BlockVerifier::visit(CallArgRecord &) {166return transition(State::CallArg);167}168169Error BlockVerifier::visit(PIDRecord &) { return transition(State::PIDEntry); }170171Error BlockVerifier::visit(NewBufferRecord &) {172return transition(State::NewBuffer);173}174175Error BlockVerifier::visit(EndBufferRecord &) {176return transition(State::EndOfBuffer);177}178179Error BlockVerifier::visit(FunctionRecord &) {180return transition(State::Function);181}182183Error BlockVerifier::verify() {184// The known terminal conditions are the following:185switch (CurrentRecord) {186case State::EndOfBuffer:187case State::NewCPUId:188case State::CustomEvent:189case State::TypedEvent:190case State::Function:191case State::CallArg:192case State::TSCWrap:193return Error::success();194default:195return createStringError(196std::make_error_code(std::errc::executable_format_error),197"BlockVerifier: Invalid terminal condition %s, malformed block.",198recordToString(CurrentRecord).data());199}200}201202void BlockVerifier::reset() { CurrentRecord = State::Unknown; }203204} // namespace xray205} // namespace llvm206207208