llvm.org GIT mirror llvm / 62b2611
[XRay] convert FDR arg1 log entries Summary: A new FDR metadata record will support logging a function call argument; appending multiple metadata records will represent a sequence of arguments meaning that "holes" are not representable by the buffer format. Each call argument is currently a 64-bit value (useful for "this" pointers and synchronization objects). If present, we put this argument to the function call "entry" record it belongs to, and alter its type to notify the user of its presence. Reviewers: dberris Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D32840 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314269 91177308-0d34-0410-b5e6-96231b3b80d8 Martin Pelikan 2 years ago
8 changed file(s) with 63 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
5252 /// This may or may not correspond to actual record types in the raw trace (as
5353 /// the loader implementation may synthesize this information in the process of
5454 /// of loading).
55 enum class RecordTypes { ENTER, EXIT, TAIL_EXIT };
55 enum class RecordTypes { ENTER, EXIT, TAIL_EXIT, ENTER_ARG };
5656
5757 struct XRayRecord {
5858 /// The type of record.
7272
7373 /// The thread ID for the currently running thread.
7474 uint32_t TId;
75
76 /// The function call arguments.
77 std::vector CallArgs;
7578 };
7679
7780 } // namespace xray
3636 std::string Function;
3737 uint64_t TSC;
3838 uint32_t TId;
39 std::vector CallArgs;
3940 };
4041
4142 struct YAMLXRayTrace {
5455 IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER);
5556 IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT);
5657 IO.enumCase(Type, "function-tail-exit", xray::RecordTypes::TAIL_EXIT);
58 IO.enumCase(Type, "function-enter-arg", xray::RecordTypes::ENTER_ARG);
5759 }
5860 };
5961
7375 IO.mapRequired("type", Record.RecordType);
7476 IO.mapRequired("func-id", Record.FuncId);
7577 IO.mapOptional("function", Record.Function);
78 IO.mapOptional("args", Record.CallArgs);
7679 IO.mapRequired("cpu", Record.CPU);
7780 IO.mapRequired("thread", Record.TId);
7881 IO.mapRequired("kind", Record.Type);
8083 }
8184
8285 static constexpr bool flow = true;
86 };
87
88 template <> struct SequenceTraits> {
89 static constexpr bool flow = true;
90 static size_t size(IO &IO, std::vector &V) { return V.size(); }
91 static uint64_t &element(IO &IO, std::vector &V, size_t Index) {
92 if (Index >= V.size())
93 V.resize(Index + 1);
94 return V[Index];
95 }
8396 };
8497
8598 template <> struct MappingTraits {
127127 FUNCTION_SEQUENCE,
128128 SCAN_TO_END_OF_THREAD_BUF,
129129 CUSTOM_EVENT_DATA,
130 CALL_ARGUMENT,
130131 };
131132 Token Expects;
132133
150151 return "SCAN_TO_END_OF_THREAD_BUF";
151152 case FDRState::Token::CUSTOM_EVENT_DATA:
152153 return "CUSTOM_EVENT_DATA";
154 case FDRState::Token::CALL_ARGUMENT:
155 return "CALL_ARGUMENT";
153156 }
154157 return "UNKNOWN";
155158 }
237240 return Error::success();
238241 }
239242
243 /// State transition when a CallArgumentRecord is encountered.
244 Error processFDRCallArgumentRecord(FDRState &State, uint8_t RecordFirstByte,
245 DataExtractor &RecordExtractor,
246 std::vector &Records) {
247 uint32_t OffsetPtr = 1; // Read starting after the first byte.
248 auto &Enter = Records.back();
249
250 if (Enter.Type != RecordTypes::ENTER)
251 return make_error(
252 "CallArgument needs to be right after a function entry",
253 std::make_error_code(std::errc::executable_format_error));
254 Enter.Type = RecordTypes::ENTER_ARG;
255 Enter.CallArgs.emplace_back(RecordExtractor.getU64(&OffsetPtr));
256 return Error::success();
257 }
258
240259 /// Advances the state machine for reading the FDR record type by reading one
241260 /// Metadata Record and updating the State appropriately based on the kind of
242261 /// record encountered. The RecordKind is encoded in the first byte of the
244263 /// to determine that this is a metadata record as opposed to a function record.
245264 Error processFDRMetadataRecord(FDRState &State, uint8_t RecordFirstByte,
246265 DataExtractor &RecordExtractor,
247 size_t &RecordSize) {
266 size_t &RecordSize,
267 std::vector &Records) {
248268 // The remaining 7 bits are the RecordKind enum.
249269 uint8_t RecordKind = RecordFirstByte >> 1;
250270 switch (RecordKind) {
276296 case 5: // CustomEventMarker
277297 if (auto E = processCustomEventMarker(State, RecordFirstByte,
278298 RecordExtractor, RecordSize))
299 return E;
300 break;
301 case 6: // CallArgument
302 if (auto E = processFDRCallArgumentRecord(State, RecordFirstByte,
303 RecordExtractor, Records))
279304 return E;
280305 break;
281306 default:
433458 if (isMetadataRecord) {
434459 RecordSize = 16;
435460 if (auto E = processFDRMetadataRecord(State, BitField, RecordExtractor,
436 RecordSize))
461 RecordSize, Records))
437462 return E;
438463 } else { // Process Function Record
439464 RecordSize = 8;
0 ; RUN: llvm-xray convert %S/Inputs/fdr-log-arg1.xray -f=yaml -o - | FileCheck %s
1
2 ; CHECK: ---
3 ; CHECK-NEXT: header:
4 ; CHECK-NEXT: version: 1
5 ; CHECK-NEXT: type: 1
6 ; CHECK-NEXT: constant-tsc: true
7 ; CHECK-NEXT: nonstop-tsc: true
8 ; CHECK-NEXT: cycle-frequency: 3500000000
9 ; CHECK-NEXT: records:
10 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', args: [ 1 ], cpu: 49, thread: 14648, kind: function-enter-arg, tsc: 18828908666543318 }
11 ; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 49, thread: 14648, kind: function-exit, tsc: 18828908666595604 }
12 ; CHECK-NEXT: ...
145145
146146 auto &ThreadStack = PerThreadFunctionStack[Record.TId];
147147 switch (Record.Type) {
148 case RecordTypes::ENTER: {
148 case RecordTypes::ENTER:
149 case RecordTypes::ENTER_ARG: {
149150 ThreadStack.emplace_back(Record.FuncId, Record.TSC);
150151 break;
151152 }
8585 Trace.Records.push_back({R.RecordType, R.CPU, R.Type, R.FuncId,
8686 Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId)
8787 : llvm::to_string(R.FuncId),
88 R.TSC, R.TId});
88 R.TSC, R.TId, R.CallArgs});
8989 }
9090 Output Out(OS, nullptr, 0);
9191 Out << Trace;
122122 Writer.write(static_cast(R.CPU));
123123 switch (R.Type) {
124124 case RecordTypes::ENTER:
125 case RecordTypes::ENTER_ARG:
125126 Writer.write(uint8_t{0});
126127 break;
127128 case RecordTypes::EXIT:
207207
208208 auto &ThreadStack = PerThreadFunctionStack[Record.TId];
209209 switch (Record.Type) {
210 case RecordTypes::ENTER: {
210 case RecordTypes::ENTER:
211 case RecordTypes::ENTER_ARG: {
211212 if (Record.FuncId != 0 && G.count(Record.FuncId) == 0)
212213 G[Record.FuncId].SymbolName = FuncIdHelper.SymbolOrNumber(Record.FuncId);
213214 ThreadStack.push_back({Record.FuncId, Record.TSC});