1 //===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "llvm/XRay/FDRRecords.h" 10 11 namespace llvm { 12 namespace xray { 13 14 Error RecordInitializer::visit(BufferExtents &R) { 15 if (!E.isValidOffsetForDataOfSize(OffsetPtr, sizeof(uint64_t))) 16 return createStringError(std::make_error_code(std::errc::bad_address), 17 "Invalid offset for a buffer extent (%d).", 18 OffsetPtr); 19 20 auto PreReadOffset = OffsetPtr; 21 R.Size = E.getU64(&OffsetPtr); 22 if (PreReadOffset == OffsetPtr) 23 return createStringError(std::make_error_code(std::errc::bad_message), 24 "Cannot read buffer extent at offset %d.", 25 OffsetPtr); 26 27 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 28 return Error::success(); 29 } 30 31 Error RecordInitializer::visit(WallclockRecord &R) { 32 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 33 MetadataRecord::kMetadataBodySize)) 34 return createStringError(std::make_error_code(std::errc::bad_address), 35 "Invalid offset for a wallclock record (%d).", 36 OffsetPtr); 37 auto BeginOffset = OffsetPtr; 38 auto PreReadOffset = OffsetPtr; 39 R.Seconds = E.getU64(&OffsetPtr); 40 if (OffsetPtr == PreReadOffset) 41 return createStringError( 42 std::make_error_code(std::errc::bad_message), 43 "Cannot read wall clock 'seconds' field at offset %d.", OffsetPtr); 44 45 PreReadOffset = OffsetPtr; 46 R.Nanos = E.getU32(&OffsetPtr); 47 if (OffsetPtr == PreReadOffset) 48 return createStringError( 49 std::make_error_code(std::errc::bad_message), 50 "Cannot read wall clock 'nanos' field at offset %d.", OffsetPtr); 51 52 // Align to metadata record size boundary. 53 assert(OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); 54 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); 55 return Error::success(); 56 } 57 58 Error RecordInitializer::visit(NewCPUIDRecord &R) { 59 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 60 MetadataRecord::kMetadataBodySize)) 61 return createStringError(std::make_error_code(std::errc::bad_address), 62 "Invalid offset for a new cpu id record (%d).", 63 OffsetPtr); 64 auto PreReadOffset = OffsetPtr; 65 R.CPUId = E.getU16(&OffsetPtr); 66 if (OffsetPtr == PreReadOffset) 67 return createStringError(std::make_error_code(std::errc::bad_message), 68 "Cannot read CPU id at offset %d.", OffsetPtr); 69 70 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 71 return Error::success(); 72 } 73 74 Error RecordInitializer::visit(TSCWrapRecord &R) { 75 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 76 MetadataRecord::kMetadataBodySize)) 77 return createStringError(std::make_error_code(std::errc::bad_address), 78 "Invalid offset for a new TSC wrap record (%d).", 79 OffsetPtr); 80 81 auto PreReadOffset = OffsetPtr; 82 R.BaseTSC = E.getU64(&OffsetPtr); 83 if (PreReadOffset == OffsetPtr) 84 return createStringError(std::make_error_code(std::errc::bad_message), 85 "Cannot read TSC wrap record at offset %d.", 86 OffsetPtr); 87 88 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 89 return Error::success(); 90 } 91 92 Error RecordInitializer::visit(CustomEventRecord &R) { 93 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 94 MetadataRecord::kMetadataBodySize)) 95 return createStringError(std::make_error_code(std::errc::bad_address), 96 "Invalid offset for a custom event record (%d).", 97 OffsetPtr); 98 99 auto BeginOffset = OffsetPtr; 100 auto PreReadOffset = OffsetPtr; 101 R.Size = E.getSigned(&OffsetPtr, sizeof(int32_t)); 102 if (PreReadOffset == OffsetPtr) 103 return createStringError( 104 std::make_error_code(std::errc::bad_message), 105 "Cannot read a custom event record size field offset %d.", OffsetPtr); 106 107 PreReadOffset = OffsetPtr; 108 R.TSC = E.getU64(&OffsetPtr); 109 if (PreReadOffset == OffsetPtr) 110 return createStringError( 111 std::make_error_code(std::errc::bad_message), 112 "Cannot read a custom event TSC field at offset %d.", OffsetPtr); 113 114 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); 115 116 // Next we read in a fixed chunk of data from the given offset. 117 if (!E.isValidOffsetForDataOfSize(OffsetPtr, R.Size)) 118 return createStringError( 119 std::make_error_code(std::errc::bad_address), 120 "Cannot read %d bytes of custom event data from offset %d.", R.Size, 121 OffsetPtr); 122 123 std::vector<uint8_t> Buffer; 124 Buffer.resize(R.Size); 125 if (E.getU8(&OffsetPtr, Buffer.data(), R.Size) != Buffer.data()) 126 return createStringError( 127 std::make_error_code(std::errc::bad_message), 128 "Failed reading data into buffer of size %d at offset %d.", R.Size, 129 OffsetPtr); 130 R.Data.assign(Buffer.begin(), Buffer.end()); 131 return Error::success(); 132 } 133 134 Error RecordInitializer::visit(CallArgRecord &R) { 135 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 136 MetadataRecord::kMetadataBodySize)) 137 return createStringError(std::make_error_code(std::errc::bad_address), 138 "Invalid offset for a call argument record (%d).", 139 OffsetPtr); 140 141 auto PreReadOffset = OffsetPtr; 142 R.Arg = E.getU64(&OffsetPtr); 143 if (PreReadOffset == OffsetPtr) 144 return createStringError(std::make_error_code(std::errc::bad_message), 145 "Cannot read a call arg record at offset %d.", 146 OffsetPtr); 147 148 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 149 return Error::success(); 150 } 151 152 Error RecordInitializer::visit(PIDRecord &R) { 153 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 154 MetadataRecord::kMetadataBodySize)) 155 return createStringError(std::make_error_code(std::errc::bad_address), 156 "Invalid offset for a process ID record (%d).", 157 OffsetPtr); 158 159 auto PreReadOffset = OffsetPtr; 160 R.PID = E.getSigned(&OffsetPtr, 4); 161 if (PreReadOffset == OffsetPtr) 162 return createStringError(std::make_error_code(std::errc::bad_message), 163 "Cannot read a process ID record at offset %d.", 164 OffsetPtr); 165 166 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 167 return Error::success(); 168 } 169 170 Error RecordInitializer::visit(NewBufferRecord &R) { 171 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 172 MetadataRecord::kMetadataBodySize)) 173 return createStringError(std::make_error_code(std::errc::bad_address), 174 "Invalid offset for a new buffer record (%d).", 175 OffsetPtr); 176 177 auto PreReadOffset = OffsetPtr; 178 R.TID = E.getSigned(&OffsetPtr, sizeof(int32_t)); 179 if (PreReadOffset == OffsetPtr) 180 return createStringError(std::make_error_code(std::errc::bad_message), 181 "Cannot read a new buffer record at offset %d.", 182 OffsetPtr); 183 184 OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - PreReadOffset); 185 return Error::success(); 186 } 187 188 Error RecordInitializer::visit(EndBufferRecord &R) { 189 if (!E.isValidOffsetForDataOfSize(OffsetPtr, 190 MetadataRecord::kMetadataBodySize)) 191 return createStringError(std::make_error_code(std::errc::bad_address), 192 "Invalid offset for an end-of-buffer record (%d).", 193 OffsetPtr); 194 195 OffsetPtr += MetadataRecord::kMetadataBodySize; 196 return Error::success(); 197 } 198 199 Error RecordInitializer::visit(FunctionRecord &R) { 200 // For function records, we need to retreat one byte back to read a full 201 // unsigned 32-bit value. The first four bytes will have the following 202 // layout: 203 // 204 // bit 0 : function record indicator (must be 0) 205 // bits 1..3 : function record type 206 // bits 4..32 : function id 207 // 208 if (OffsetPtr == 0 || !E.isValidOffsetForDataOfSize( 209 --OffsetPtr, FunctionRecord::kFunctionRecordSize)) 210 return createStringError(std::make_error_code(std::errc::bad_address), 211 "Invalid offset for a function record (%d).", 212 OffsetPtr); 213 214 auto BeginOffset = OffsetPtr; 215 auto PreReadOffset = BeginOffset; 216 uint32_t Buffer = E.getU32(&OffsetPtr); 217 if (PreReadOffset == OffsetPtr) 218 return createStringError(std::make_error_code(std::errc::bad_address), 219 "Cannot read function id field from offset %d.", 220 OffsetPtr); 221 unsigned FunctionType = (Buffer >> 1) & 0x07; 222 switch (FunctionType) { 223 case static_cast<unsigned>(RecordTypes::ENTER): 224 case static_cast<unsigned>(RecordTypes::ENTER_ARG): 225 case static_cast<unsigned>(RecordTypes::EXIT): 226 case static_cast<unsigned>(RecordTypes::TAIL_EXIT): 227 R.Kind = static_cast<RecordTypes>(FunctionType); 228 break; 229 default: 230 return createStringError(std::make_error_code(std::errc::bad_message), 231 "Unknown function record type '%d' at offset %d.", 232 FunctionType, BeginOffset); 233 } 234 235 R.FuncId = Buffer >> 4; 236 PreReadOffset = OffsetPtr; 237 R.Delta = E.getU32(&OffsetPtr); 238 if (OffsetPtr == PreReadOffset) 239 return createStringError(std::make_error_code(std::errc::bad_message), 240 "Failed reading TSC delta from offset %d.", 241 OffsetPtr); 242 assert(FunctionRecord::kFunctionRecordSize == (OffsetPtr - BeginOffset)); 243 return Error::success(); 244 } 245 246 } // namespace xray 247 } // namespace llvm 248