Index: llvm/trunk/lib/XRay/Trace.cpp =================================================================== --- llvm/trunk/lib/XRay/Trace.cpp +++ llvm/trunk/lib/XRay/Trace.cpp @@ -82,29 +82,59 @@ for (auto S = Data.drop_front(32); !S.empty(); S = S.drop_front(32)) { DataExtractor RecordExtractor(S, true, 8); uint32_t OffsetPtr = 0; - Records.emplace_back(); - auto &Record = Records.back(); - Record.RecordType = RecordExtractor.getU16(&OffsetPtr); - Record.CPU = RecordExtractor.getU8(&OffsetPtr); - auto Type = RecordExtractor.getU8(&OffsetPtr); - switch (Type) { - case 0: - Record.Type = RecordTypes::ENTER; - break; - case 1: - Record.Type = RecordTypes::EXIT; + switch (auto RecordType = RecordExtractor.getU16(&OffsetPtr)) { + case 0: { // Normal records. + Records.emplace_back(); + auto &Record = Records.back(); + Record.RecordType = RecordType; + Record.CPU = RecordExtractor.getU8(&OffsetPtr); + auto Type = RecordExtractor.getU8(&OffsetPtr); + switch (Type) { + case 0: + Record.Type = RecordTypes::ENTER; + break; + case 1: + Record.Type = RecordTypes::EXIT; + break; + case 2: + Record.Type = RecordTypes::TAIL_EXIT; + break; + case 3: + Record.Type = RecordTypes::ENTER_ARG; + break; + default: + return make_error( + Twine("Unknown record type '") + Twine(int{Type}) + "'", + std::make_error_code(std::errc::executable_format_error)); + } + Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t)); + Record.TSC = RecordExtractor.getU64(&OffsetPtr); + Record.TId = RecordExtractor.getU32(&OffsetPtr); break; - case 2: - Record.Type = RecordTypes::TAIL_EXIT; + } + case 1: { // Arg payload record. + auto &Record = Records.back(); + // Advance two bytes to avoid padding. + OffsetPtr += 2; + int32_t FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t)); + auto TId = RecordExtractor.getU32(&OffsetPtr); + if (Record.FuncId != FuncId || Record.TId != TId) + return make_error( + Twine("Corrupted log, found payload following non-matching " + "function + thread record. Record for ") + + Twine(Record.FuncId) + " != " + Twine(FuncId), + std::make_error_code(std::errc::executable_format_error)); + // Advance another four bytes to avoid padding. + OffsetPtr += 4; + auto Arg = RecordExtractor.getU64(&OffsetPtr); + Record.CallArgs.push_back(Arg); break; + } default: return make_error( - Twine("Unknown record type '") + Twine(int{Type}) + "'", + Twine("Unknown record type == ") + Twine(RecordType), std::make_error_code(std::errc::executable_format_error)); } - Record.FuncId = RecordExtractor.getSigned(&OffsetPtr, sizeof(int32_t)); - Record.TSC = RecordExtractor.getU64(&OffsetPtr); - Record.TId = RecordExtractor.getU32(&OffsetPtr); } return Error::success(); } @@ -234,8 +264,8 @@ uint32_t DataSize = RecordExtractor.getU32(&OffsetPtr); uint64_t TSC = RecordExtractor.getU64(&OffsetPtr); - // FIXME: Actually represent the record through the API. For now we only skip - // through the data. + // FIXME: Actually represent the record through the API. For now we only + // skip through the data. (void)TSC; RecordSize = 16 + DataSize; return Error::success(); @@ -507,8 +537,8 @@ Records.clear(); std::transform(Trace.Records.begin(), Trace.Records.end(), std::back_inserter(Records), [&](const YAMLXRayRecord &R) { - return XRayRecord{R.RecordType, R.CPU, R.Type, - R.FuncId, R.TSC, R.TId, R.CallArgs}; + return XRayRecord{R.RecordType, R.CPU, R.Type, R.FuncId, + R.TSC, R.TId, R.CallArgs}; }); return Error::success(); } Index: llvm/trunk/test/tools/llvm-xray/X86/convert-basic-arg1-to-yaml.txt =================================================================== --- llvm/trunk/test/tools/llvm-xray/X86/convert-basic-arg1-to-yaml.txt +++ llvm/trunk/test/tools/llvm-xray/X86/convert-basic-arg1-to-yaml.txt @@ -0,0 +1,15 @@ +; RUN: llvm-xray convert %S/Inputs/naive-with-arg1-entries.xray -f=yaml -o - | FileCheck %s + +; CHECK: --- +; CHECK-NEXT: header: +; CHECK-NEXT: version: 2 +; CHECK-NEXT: type: 0 +; CHECK-NEXT: constant-tsc: true +; CHECK-NEXT: nonstop-tsc: true +; CHECK-NEXT: cycle-frequency: 3500000000 +; CHECK-NEXT: records: +; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 17, thread: 8715, kind: function-enter, tsc: 22555670288232728 } +; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 17, thread: 8715, kind: function-exit, tsc: 22555670288334784 } +; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', args: [ 1 ], cpu: 17, thread: 8715, kind: function-enter-arg, tsc: 22555670288335768 } +; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 17, thread: 8715, kind: function-exit, tsc: 22555670288365224 } +; CHECK-NEXT: ...