LLVM: lib/XRay/Trace.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

25#include

26#include

27

28using namespace llvm;

31

34 std::vector &Records) {

35 if (Data.size() < 32)

37 "Not enough bytes for an XRay log.",

38 std::make_error_code(std::errc::invalid_argument));

39

40 if (Data.size() - 32 == 0 || Data.size() % 32 != 0)

42 "Invalid-sized XRay data.",

43 std::make_error_code(std::errc::invalid_argument));

44

48 if (!FileHeaderOrError)

49 return FileHeaderOrError.takeError();

50 FileHeader = std::move(FileHeaderOrError.get());

51

53 Records.reserve(NumReservations);

54

55

56

57

58

59

60

61

62

63

64

68 std::make_error_code(std::errc::executable_format_error),

69 "Not enough bytes to read a full record at offset %" PRId64 ".",

70 OffsetPtr);

71 auto PreReadOffset = OffsetPtr;

73 if (OffsetPtr == PreReadOffset)

75 std::make_error_code(std::errc::executable_format_error),

76 "Failed reading record type at offset %" PRId64 ".", OffsetPtr);

77

79 case 0: {

83

84 PreReadOffset = OffsetPtr;

86 if (OffsetPtr == PreReadOffset)

88 std::make_error_code(std::errc::executable_format_error),

89 "Failed reading CPU field at offset %" PRId64 ".", OffsetPtr);

90

91 PreReadOffset = OffsetPtr;

92 auto Type = Reader.getU8(&OffsetPtr);

93 if (OffsetPtr == PreReadOffset)

95 std::make_error_code(std::errc::executable_format_error),

96 "Failed reading record type field at offset %" PRId64 ".",

97 OffsetPtr);

98

99 switch (Type) {

100 case 0:

102 break;

103 case 1:

105 break;

106 case 2:

108 break;

109 case 3:

111 break;

112 default:

114 std::make_error_code(std::errc::executable_format_error),

115 "Unknown record type '%d' at offset %" PRId64 ".", Type, OffsetPtr);

116 }

117

118 PreReadOffset = OffsetPtr;

119 Record.FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));

120 if (OffsetPtr == PreReadOffset)

122 std::make_error_code(std::errc::executable_format_error),

123 "Failed reading function id field at offset %" PRId64 ".",

124 OffsetPtr);

125

126 PreReadOffset = OffsetPtr;

128 if (OffsetPtr == PreReadOffset)

130 std::make_error_code(std::errc::executable_format_error),

131 "Failed reading TSC field at offset %" PRId64 ".", OffsetPtr);

132

133 PreReadOffset = OffsetPtr;

135 if (OffsetPtr == PreReadOffset)

137 std::make_error_code(std::errc::executable_format_error),

138 "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);

139

140 PreReadOffset = OffsetPtr;

142 if (OffsetPtr == PreReadOffset)

144 std::make_error_code(std::errc::executable_format_error),

145 "Failed reading process id at offset %" PRId64 ".", OffsetPtr);

146

147 break;

148 }

149 case 1: {

151

152

153

154 OffsetPtr += 2;

155 PreReadOffset = OffsetPtr;

156 int32_t FuncId = Reader.getSigned(&OffsetPtr, sizeof(int32_t));

157 if (OffsetPtr == PreReadOffset)

159 std::make_error_code(std::errc::executable_format_error),

160 "Failed reading function id field at offset %" PRId64 ".",

161 OffsetPtr);

162

163 PreReadOffset = OffsetPtr;

164 auto TId = Reader.getU32(&OffsetPtr);

165 if (OffsetPtr == PreReadOffset)

167 std::make_error_code(std::errc::executable_format_error),

168 "Failed reading thread id field at offset %" PRId64 ".", OffsetPtr);

169

170 PreReadOffset = OffsetPtr;

171 auto PId = Reader.getU32(&OffsetPtr);

172 if (OffsetPtr == PreReadOffset)

174 std::make_error_code(std::errc::executable_format_error),

175 "Failed reading process id field at offset %" PRId64 ".",

176 OffsetPtr);

177

178

179 if (Record.FuncId != FuncId || Record.TId != TId ||

180 (FileHeader.Version >= 3 ? Record.PId != PId : false))

182 std::make_error_code(std::errc::executable_format_error),

183 "Corrupted log, found arg payload following non-matching "

184 "function+thread record. Record for function %d != %d at offset "

185 "%" PRId64 ".",

186 Record.FuncId, FuncId, OffsetPtr);

187

188 PreReadOffset = OffsetPtr;

189 auto Arg = Reader.getU64(&OffsetPtr);

190 if (OffsetPtr == PreReadOffset)

192 std::make_error_code(std::errc::executable_format_error),

193 "Failed reading argument payload at offset %" PRId64 ".",

194 OffsetPtr);

195

196 Record.CallArgs.push_back(Arg);

197 break;

198 }

199 default:

201 std::make_error_code(std::errc::executable_format_error),

202 "Unknown record type '%d' at offset %" PRId64 ".", RecordType,

203 OffsetPtr);

204 }

205

206

207 OffsetPtr += 8;

208 }

210}

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

268 std::vector &Records) {

269

270 if (Data.size() < 32)

271 return createStringError(std::make_error_code(std::errc::invalid_argument),

272 "Not enough bytes for an XRay FDR log.");

274

277 if (!FileHeaderOrError)

278 return FileHeaderOrError.takeError();

279 FileHeader = std::move(FileHeaderOrError.get());

280

281

282 std::vector<std::unique_ptr> FDRRecords;

283

284 {

288 auto R = P.produce();

289 if (!R)

290 return R.takeError();

291 if (auto E = C.consume(std::move(R.get())))

292 return E;

293 }

294 }

295

296

298 {

300 for (auto &R : FDRRecords)

301 if (auto E = R->apply(Indexer))

302 return E;

303 if (auto E = Indexer.flush())

304 return E;

305 }

306

307

308 {

309 for (auto &PTB : Index) {

310 auto &Blocks = PTB.second;

311 for (auto &B : Blocks) {

313 for (auto *R : B.Records)

314 if (auto E = R->apply(Verifier))

315 return E;

316 if (auto E = Verifier.verify())

317 return E;

318 }

319 }

320 }

321

322

323

324

325

326

327 {

328 for (auto &PTB : Index) {

329 auto &Blocks = PTB.second;

332 return (L.WallclockTime->seconds() < R.WallclockTime->seconds() &&

333 L.WallclockTime->nanos() < R.WallclockTime->nanos());

334 });

337 for (auto &B : Blocks) {

338 for (auto *R : B.Records)

339 if (auto E = R->apply(Expander))

340 return E;

341 }

342 if (auto E = Expander.flush())

343 return E;

344 }

345 }

346

348}

349

351 std::vector &Records) {

355 if (In.error())

357

359 FileHeader.Type = Trace.Header.Type;

363

364 if (FileHeader.Version != 1)

366 Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version),

367 std::make_error_code(std::errc::invalid_argument));

368

371 std::back_inserter(Records), [&](const YAMLXRayRecord &R) {

372 return XRayRecord{R.RecordType, R.CPU, R.Type,

373 R.FuncId, R.TSC, R.TId,

374 R.PId, R.CallArgs, R.Data};

375 });

377}

378

381 if (!FdOrErr)

383

387 Twine("Cannot read log from '") + Filename + "'", EC);

388 }

389 if (FileSize < 4) {

391 Twine("File '") + Filename + "' too small for XRay.",

392 std::make_error_code(std::errc::executable_format_error));

393 }

394

395

396 std::error_code EC;

399 EC);

401 if (EC) {

403 Twine("Cannot read log from '") + Filename + "'", EC);

404 }

406

407

409 auto TraceOrError = loadTrace(LittleEndianDE, Sort);

410 if (!TraceOrError) {

413 TraceOrError = loadTrace(BigEndianDE, Sort);

414 }

415 return TraceOrError;

416}

417

419

420

421

422

423

424

425

426

427

428

429

430

431

432

437

438 enum BinaryFormatType { NAIVE_FORMAT = 0, FLIGHT_DATA_RECORDER_FORMAT = 1 };

439

441 switch (Type) {

442 case NAIVE_FORMAT:

445 T.FileHeader, T.Records))

446 return std::move(E);

447 } else {

449 Twine("Unsupported version for Basic/Naive Mode logging: ") +

451 std::make_error_code(std::errc::executable_format_error));

452 }

453 break;

454 case FLIGHT_DATA_RECORDER_FORMAT:

457 T.Records))

458 return std::move(E);

459 } else {

461 Twine("Unsupported version for FDR Mode logging: ") + Twine(Version),

462 std::make_error_code(std::errc::executable_format_error));

463 }

464 break;

465 default:

467 return std::move(E);

468 }

469

470 if (Sort)

472 return L.TSC < R.TSC;

473 });

474

475 return std::move(T);

476}

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

FunctionLoweringInfo::StatepointRelocationRecord RecordType

static Error loadFDRLog(StringRef Data, bool IsLittleEndian, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)

Reads a log in FDR mode for version 1 of this binary format.

Definition Trace.cpp:266

static Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)

Definition Trace.cpp:32

static Error loadYAMLLog(StringRef Data, XRayFileHeader &FileHeader, std::vector< XRayRecord > &Records)

Definition Trace.cpp:350

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

void push_back(const T &Elt)

StringRef - Represent a constant reference to a string, i.e.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

This class represents a memory mapped file.

LLVM_ABI size_t size() const

@ readonly

May only access map via const_data as read only.

LLVM_ABI char * data() const

DenseMap< std::pair< uint64_t, int32_t >, std::vector< Block > > Index

Error flush()

The flush() function will clear out the current state of the visitor, to allow for explicitly flushin...

A Trace object represents the records that have been loaded from XRay log files generated by instrume...

The Input class is used to parse a yaml document into in-memory structs and vectors.

@ C

The default llvm calling convention, compatible with C.

LLVM_ABI std::error_code closeFile(file_t &F)

Close the file object.

LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)

Opens the file with the given name in a read-only mode, returning its open file descriptor.

std::error_code file_size(const Twine &Path, uint64_t &Result)

Get file size.

LLVM_ABI Expected< Trace > loadTrace(const DataExtractor &Extractor, bool Sort=false)

This function will attempt to load XRay trace records from the provided DataExtractor.

Definition Trace.cpp:418

LLVM_ABI Expected< XRayFileHeader > readBinaryFormatHeader(DataExtractor &HeaderExtractor, uint64_t &OffsetPtr)

Convenience function for loading the file header given a data extractor at a specified offset.

LLVM_ABI Expected< Trace > loadTraceFile(StringRef Filename, bool Sort=false)

This function will attempt to load XRay trace records from the provided |Filename|.

Definition Trace.cpp:379

This is an optimization pass for GlobalISel generic memory operations.

void stable_sort(R &&Range)

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

FunctionAddr VTableAddr uintptr_t uintptr_t Version

void sort(IteratorTy Start, IteratorTy End)

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

constexpr T divideCeil(U Numerator, V Denominator)

Returns the integer ceil(Numerator / Denominator).

FunctionAddr VTableAddr uintptr_t uintptr_t Data

void consumeError(Error Err)

Consume a Error without doing anything.

An XRayRecord is the denormalized view of data associated in a trace.