diff options
| author | vvvv <[email protected]> | 2024-02-06 20:01:22 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2024-02-06 20:22:16 +0300 |
| commit | 0203b7a9a40828bb2bd4c32029b79ff0ea3d1f8f (patch) | |
| tree | e630d0d5bd0bd29fc8c2d2842ed2cfde781b993a /contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp | |
| parent | ba27db76d99d12a4f1c06960b5449423218614c4 (diff) | |
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp')
| -rw-r--r-- | contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp b/contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp new file mode 100644 index 00000000000..68ab3db0620 --- /dev/null +++ b/contrib/libs/llvm16/lib/XRay/RecordInitializer.cpp @@ -0,0 +1,431 @@ +//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===// +// +// 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/XRay/FDRRecords.h" + +namespace llvm { +namespace xray { + +Error RecordInitializer::visit(BufferExtents &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t))) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a buffer extent (%" PRId64 ").", OffsetPtr); + + auto PreReadOffset = OffsetPtr; + R.Size = E.getU64(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Cannot read buffer extent at offset %" PRId64 ".", + OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); + return Error::success(); +} + +Error RecordInitializer::visit(WallclockRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a wallclock record (%" PRId64 ").", OffsetPtr); + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + R.Seconds = E.getU64(&OffsetPtr); + if (OffsetPtr == PreReadOffset) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read wall clock 'seconds' field at offset %" PRId64 ".", + OffsetPtr); + + PreReadOffset = OffsetPtr; + R.Nanos = E.getU32(&OffsetPtr); + if (OffsetPtr == PreReadOffset) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read wall clock 'nanos' field at offset %" PRId64 ".", + OffsetPtr); + + // Align to metadata record size boundary. + assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + return Error::success(); +} + +Error RecordInitializer::visit(NewCPUIDRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a new cpu id record (%" PRId64 ").", OffsetPtr); + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + R.CPUId = E.getU16(&OffsetPtr); + if (OffsetPtr == PreReadOffset) + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Cannot read CPU id at offset %" PRId64 ".", + OffsetPtr); + + PreReadOffset = OffsetPtr; + R.TSC = E.getU64(&OffsetPtr); + if (OffsetPtr == PreReadOffset) + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Cannot read CPU TSC at offset %" PRId64 ".", + OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + return Error::success(); +} + +Error RecordInitializer::visit(TSCWrapRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a new TSC wrap record (%" PRId64 ").", OffsetPtr); + + auto PreReadOffset = OffsetPtr; + R.BaseTSC = E.getU64(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read TSC wrap record at offset %" PRId64 ".", OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); + return Error::success(); +} + +Error RecordInitializer::visit(CustomEventRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event record size field offset %" PRId64 ".", + OffsetPtr); + + if (R.Size <= 0) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid size for custom event (size = %d) at offset %" PRId64 ".", + R.Size, OffsetPtr); + + PreReadOffset = OffsetPtr; + R.TSC = E.getU64(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event TSC field at offset %" PRId64 ".", + OffsetPtr); + + // For version 4 onwards, of the FDR log, we want to also capture the CPU ID + // of the custom event. + if (Version >= 4) { + PreReadOffset = OffsetPtr; + R.CPU = E.getU16(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Missing CPU field at offset %" PRId64 ".", OffsetPtr); + } + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + + // Next we read in a fixed chunk of data from the given offset. + if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read %d bytes of custom event data from offset %" PRId64 ".", + R.Size, OffsetPtr); + + std::vector<uint8_t> Buffer; + Buffer.resize(R.Size); + PreReadOffset = OffsetPtr; + if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading data into buffer of size %d at offset %" PRId64 ".", + R.Size, OffsetPtr); + + assert(OffsetPtr >= PreReadOffset); + if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size)) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading enough bytes for the custom event payload -- read " + "%" PRId64 " expecting %d bytes at offset %" PRId64 ".", + OffsetPtr - PreReadOffset, R.Size, PreReadOffset); + + R.Data.assign(Buffer.begin(), Buffer.end()); + return Error::success(); +} + +Error RecordInitializer::visit(CustomEventRecordV5 &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a custom event record (%" PRId64 ").", OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + + R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event record size field offset %" PRId64 ".", + OffsetPtr); + + if (R.Size <= 0) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid size for custom event (size = %d) at offset %" PRId64 ".", + R.Size, OffsetPtr); + + PreReadOffset = OffsetPtr; + R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a custom event record TSC delta field at offset " + "%" PRId64 ".", + OffsetPtr); + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + + // Next we read in a fixed chunk of data from the given offset. + if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read %d bytes of custom event data from offset %" PRId64 ".", + R.Size, OffsetPtr); + + std::vector<uint8_t> Buffer; + Buffer.resize(R.Size); + PreReadOffset = OffsetPtr; + if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading data into buffer of size %d at offset %" PRId64 ".", + R.Size, OffsetPtr); + + assert(OffsetPtr >= PreReadOffset); + if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size)) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading enough bytes for the custom event payload -- read " + "%" PRId64 " expecting %d bytes at offset %" PRId64 ".", + OffsetPtr - PreReadOffset, R.Size, PreReadOffset); + + R.Data.assign(Buffer.begin(), Buffer.end()); + return Error::success(); +} + +Error RecordInitializer::visit(TypedEventRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a typed event record (%" PRId64 ").", OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = OffsetPtr; + + R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record size field offset %" PRId64 ".", + OffsetPtr); + + if (R.Size <= 0) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid size for typed event (size = %d) at offset %" PRId64 ".", + R.Size, OffsetPtr); + + PreReadOffset = OffsetPtr; + R.Delta = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record TSC delta field at offset " + "%" PRId64 ".", + OffsetPtr); + + PreReadOffset = OffsetPtr; + R.EventType = E.getU16(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a typed event record type field at offset %" PRId64 ".", + OffsetPtr); + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); + + // Next we read in a fixed chunk of data from the given offset. + if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read %d bytes of custom event data from offset %" PRId64 ".", + R.Size, OffsetPtr); + + std::vector<uint8_t> Buffer; + Buffer.resize(R.Size); + PreReadOffset = OffsetPtr; + if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading data into buffer of size %d at offset %" PRId64 ".", + R.Size, OffsetPtr); + + assert(OffsetPtr >= PreReadOffset); + if (OffsetPtr - PreReadOffset != static_cast<uint32_t>(R.Size)) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading enough bytes for the typed event payload -- read " + "%" PRId64 " expecting %d bytes at offset %" PRId64 ".", + OffsetPtr - PreReadOffset, R.Size, PreReadOffset); + + R.Data.assign(Buffer.begin(), Buffer.end()); + return Error::success(); +} + +Error RecordInitializer::visit(CallArgRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a call argument record (%" PRId64 ").", + OffsetPtr); + + auto PreReadOffset = OffsetPtr; + R.Arg = E.getU64(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a call arg record at offset %" PRId64 ".", OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); + return Error::success(); +} + +Error RecordInitializer::visit(PIDRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a process ID record (%" PRId64 ").", OffsetPtr); + + auto PreReadOffset = OffsetPtr; + R.PID = E.getSigned(&OffsetPtr, 4); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a process ID record at offset %" PRId64 ".", OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); + return Error::success(); +} + +Error RecordInitializer::visit(NewBufferRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a new buffer record (%" PRId64 ").", OffsetPtr); + + auto PreReadOffset = OffsetPtr; + R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t)); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Cannot read a new buffer record at offset %" PRId64 ".", OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); + return Error::success(); +} + +Error RecordInitializer::visit(EndBufferRecord &R) { + if (!E.isValidOffsetForDataOfSize(OffsetPtr, + MetadataRecord::kMetadataBodySize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for an end-of-buffer record (%" PRId64 ").", + OffsetPtr); + + OffsetPtr += MetadataRecord::kMetadataBodySize; + return Error::success(); +} + +Error RecordInitializer::visit(FunctionRecord &R) { + // For function records, we need to retreat one byte back to read a full + // unsigned 32-bit value. The first four bytes will have the following + // layout: + // + // bit 0 : function record indicator (must be 0) + // bits 1..3 : function record type + // bits 4..32 : function id + // + if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize( + --OffsetPtr, FunctionRecord::kFunctionRecordSize)) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Invalid offset for a function record (%" PRId64 ").", OffsetPtr); + + auto BeginOffset = OffsetPtr; + auto PreReadOffset = BeginOffset; + uint32_t Buffer = E.getU32(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::bad_address), + "Cannot read function id field from offset %" PRId64 ".", OffsetPtr); + + // To get the function record type, we shift the buffer one to the right + // (truncating the function record indicator) then take the three bits + // (0b0111) to get the record type as an unsigned value. + unsigned FunctionType = (Buffer >> 1) & 0x07u; + switch (FunctionType) { + case static_cast<unsigned>(RecordTypes::ENTER): + case static_cast<unsigned>(RecordTypes::ENTER_ARG): + case static_cast<unsigned>(RecordTypes::EXIT): + case static_cast<unsigned>(RecordTypes::TAIL_EXIT): + R.Kind = static_cast<RecordTypes>(FunctionType); + break; + default: + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Unknown function record type '%d' at offset %" PRId64 ".", + FunctionType, BeginOffset); + } + + R.FuncId = Buffer >> 4; + PreReadOffset = OffsetPtr; + R.Delta = E.getU32(&OffsetPtr); + if (OffsetPtr == PreReadOffset) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Failed reading TSC delta from offset %" PRId64 ".", OffsetPtr); + assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset)); + return Error::success(); +} + +} // namespace xray +} // namespace llvm |
