1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/traced/probes/ftrace/cpu_reader.h"
18
19 #include <signal.h>
20
21 #include <dirent.h>
22 #include <map>
23 #include <queue>
24 #include <string>
25 #include <utility>
26
27 #include "perfetto/base/build_config.h"
28 #include "perfetto/base/logging.h"
29 #include "perfetto/base/metatrace.h"
30 #include "perfetto/base/optional.h"
31 #include "perfetto/base/utils.h"
32 #include "src/traced/probes/ftrace/ftrace_controller.h"
33 #include "src/traced/probes/ftrace/ftrace_data_source.h"
34 #include "src/traced/probes/ftrace/ftrace_thread_sync.h"
35 #include "src/traced/probes/ftrace/proto_translation_table.h"
36
37 #include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
38 #include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
39 #include "perfetto/trace/ftrace/generic.pbzero.h"
40 #include "perfetto/trace/trace_packet.pbzero.h"
41
42 namespace perfetto {
43
44 namespace {
45
46 // For further documentation of these constants see the kernel source:
47 // linux/include/linux/ring_buffer.h
48 // Some information about the values of these constants are exposed to user
49 // space at: /sys/kernel/debug/tracing/events/header_event
50 constexpr uint32_t kTypeDataTypeLengthMax = 28;
51 constexpr uint32_t kTypePadding = 29;
52 constexpr uint32_t kTypeTimeExtend = 30;
53 constexpr uint32_t kTypeTimeStamp = 31;
54
55 struct PageHeader {
56 uint64_t timestamp;
57 uint64_t size;
58 uint64_t overwrite;
59 };
60
61 struct EventHeader {
62 uint32_t type_or_length : 5;
63 uint32_t time_delta : 27;
64 };
65
66 struct TimeStamp {
67 uint64_t tv_nsec;
68 uint64_t tv_sec;
69 };
70
ReadIntoString(const uint8_t * start,const uint8_t * end,uint32_t field_id,protozero::Message * out)71 bool ReadIntoString(const uint8_t* start,
72 const uint8_t* end,
73 uint32_t field_id,
74 protozero::Message* out) {
75 for (const uint8_t* c = start; c < end; c++) {
76 if (*c != '\0')
77 continue;
78 out->AppendBytes(field_id, reinterpret_cast<const char*>(start),
79 static_cast<uintptr_t>(c - start));
80 return true;
81 }
82 return false;
83 }
84
ReadDataLoc(const uint8_t * start,const uint8_t * field_start,const uint8_t * end,const Field & field,protozero::Message * message)85 bool ReadDataLoc(const uint8_t* start,
86 const uint8_t* field_start,
87 const uint8_t* end,
88 const Field& field,
89 protozero::Message* message) {
90 PERFETTO_DCHECK(field.ftrace_size == 4);
91 // See
92 // https://github.com/torvalds/linux/blob/master/include/trace/trace_events.h
93 uint32_t data = 0;
94 const uint8_t* ptr = field_start;
95 if (!CpuReader::ReadAndAdvance(&ptr, end, &data)) {
96 PERFETTO_DFATAL("Buffer overflowed.");
97 return false;
98 }
99
100 const uint16_t offset = data & 0xffff;
101 const uint16_t len = (data >> 16) & 0xffff;
102 const uint8_t* const string_start = start + offset;
103 const uint8_t* const string_end = string_start + len;
104 if (string_start <= start || string_end > end) {
105 PERFETTO_DFATAL("Buffer overflowed.");
106 return false;
107 }
108 ReadIntoString(string_start, string_end, field.proto_field_id, message);
109 return true;
110 }
111
SetBlocking(int fd,bool is_blocking)112 bool SetBlocking(int fd, bool is_blocking) {
113 int flags = fcntl(fd, F_GETFL, 0);
114 flags = (is_blocking) ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
115 return fcntl(fd, F_SETFL, flags) == 0;
116 }
117
ParsePageHeader(const uint8_t ** ptr,uint16_t page_header_size_len)118 base::Optional<PageHeader> ParsePageHeader(const uint8_t** ptr,
119 uint16_t page_header_size_len) {
120 const uint8_t* end_of_page = *ptr + base::kPageSize;
121 PageHeader page_header;
122 if (!CpuReader::ReadAndAdvance<uint64_t>(ptr, end_of_page,
123 &page_header.timestamp))
124 return base::nullopt;
125
126 uint32_t overwrite_and_size;
127
128 // On little endian, we can just read a uint32_t and reject the rest of the
129 // number later.
130 if (!CpuReader::ReadAndAdvance<uint32_t>(
131 ptr, end_of_page, base::AssumeLittleEndian(&overwrite_and_size)))
132 return base::nullopt;
133
134 page_header.size = (overwrite_and_size & 0x000000000000ffffull) >> 0;
135 page_header.overwrite = (overwrite_and_size & 0x00000000ff000000ull) >> 24;
136 PERFETTO_DCHECK(page_header.size <= base::kPageSize);
137
138 // Reject rest of the number, if applicable. On 32-bit, size_bytes - 4 will
139 // evaluate to 0 and this will be a no-op. On 64-bit, this will advance by 4
140 // bytes.
141 PERFETTO_DCHECK(page_header_size_len >= 4);
142 *ptr += page_header_size_len - 4;
143
144 return base::make_optional(page_header);
145 }
146
147 } // namespace
148
149 using protos::pbzero::GenericFtraceEvent;
150
CpuReader(const ProtoTranslationTable * table,FtraceThreadSync * thread_sync,size_t cpu,int generation,base::ScopedFile fd)151 CpuReader::CpuReader(const ProtoTranslationTable* table,
152 FtraceThreadSync* thread_sync,
153 size_t cpu,
154 int generation,
155 base::ScopedFile fd)
156 : table_(table),
157 thread_sync_(thread_sync),
158 cpu_(cpu),
159 trace_fd_(std::move(fd)) {
160 // Make reads from the raw pipe blocking so that splice() can sleep.
161 PERFETTO_CHECK(trace_fd_);
162 PERFETTO_CHECK(SetBlocking(*trace_fd_, true));
163
164 // We need a non-default SIGPIPE handler to make it so that the blocking
165 // splice() is woken up when the ~CpuReader() dtor destroys the pipes.
166 // Just masking out the signal would cause an implicit syscall restart and
167 // hence make the join() in the dtor unreliable.
168 struct sigaction current_act = {};
169 PERFETTO_CHECK(sigaction(SIGPIPE, nullptr, ¤t_act) == 0);
170 #pragma GCC diagnostic push
171 #if defined(__clang__)
172 #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
173 #endif
174 if (current_act.sa_handler == SIG_DFL || current_act.sa_handler == SIG_IGN) {
175 struct sigaction act = {};
176 act.sa_sigaction = [](int, siginfo_t*, void*) {};
177 PERFETTO_CHECK(sigaction(SIGPIPE, &act, nullptr) == 0);
178 }
179 #pragma GCC diagnostic pop
180
181 worker_thread_ = std::thread(std::bind(&RunWorkerThread, cpu_, generation,
182 *trace_fd_, &pool_, thread_sync_,
183 table->page_header_size_len()));
184 }
185
~CpuReader()186 CpuReader::~CpuReader() {
187 // FtraceController (who owns this) is supposed to issue a kStop notification
188 // to the thread sync object before destroying the CpuReader.
189 #if PERFETTO_DCHECK_IS_ON()
190 {
191 std::lock_guard<std::mutex> lock(thread_sync_->mutex);
192 PERFETTO_DCHECK(thread_sync_->cmd == FtraceThreadSync::kQuit);
193 }
194 #endif
195
196 // The kernel's splice implementation for the trace pipe doesn't generate a
197 // SIGPIPE if the output pipe is closed (b/73807072). Instead, the call to
198 // close() on the pipe hangs forever. To work around this, we first close the
199 // trace fd (which prevents another splice from starting), raise SIGPIPE and
200 // wait for the worker to exit (i.e., to guarantee no splice is in progress)
201 // and only then close the staging pipe.
202 trace_fd_.reset();
203 InterruptWorkerThreadWithSignal();
204 worker_thread_.join();
205 }
206
InterruptWorkerThreadWithSignal()207 void CpuReader::InterruptWorkerThreadWithSignal() {
208 pthread_kill(worker_thread_.native_handle(), SIGPIPE);
209 }
210
211 // The worker thread reads data from the ftrace trace_pipe_raw and moves it to
212 // the page |pool| allowing the main thread to read and decode that.
213 // See //docs/ftrace.md for the design of the ftrace worker scheduler.
214 // static
RunWorkerThread(size_t cpu,int generation,int trace_fd,PagePool * pool,FtraceThreadSync * thread_sync,uint16_t header_size_len)215 void CpuReader::RunWorkerThread(size_t cpu,
216 int generation,
217 int trace_fd,
218 PagePool* pool,
219 FtraceThreadSync* thread_sync,
220 uint16_t header_size_len) {
221 // Before attempting any changes to this function, think twice. The kernel
222 // ftrace pipe code is full of caveats and bugs. This code carefully works
223 // around those bugs. See b/120188810 and b/119805587 for the full narrative.
224 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
225 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
226 char thread_name[16];
227 snprintf(thread_name, sizeof(thread_name), "traced_probes%zu", cpu);
228 pthread_setname_np(pthread_self(), thread_name);
229
230 // When using splice() the target fd needs to be an actual pipe. This pipe is
231 // used only within this thread and is mainly for synchronization purposes.
232 // A blocking splice() is the only way to block and wait for a new page of
233 // ftrace data.
234 base::Pipe sync_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
235
236 enum ReadMode { kRead, kSplice };
237 enum Block { kBlock, kNonBlock };
238 constexpr auto kPageSize = base::kPageSize;
239
240 // This lambda function reads the ftrace raw pipe using either read() or
241 // splice(), either in blocking or non-blocking mode.
242 // Returns the number of ftrace bytes read, or -1 in case of failure.
243 auto read_ftrace_pipe = [&sync_pipe, trace_fd, pool, cpu, header_size_len](
244 ReadMode mode, Block block) -> int {
245 static const char* const kModesStr[] = {"read-nonblock", "read-block",
246 "splice-nonblock", "splice-block"};
247 const char* mode_str = kModesStr[(mode == kSplice) * 2 + (block == kBlock)];
248 PERFETTO_METATRACE(mode_str, cpu);
249 uint8_t* pool_page = pool->BeginWrite();
250 PERFETTO_DCHECK(pool_page);
251
252 ssize_t res;
253 int err = 0;
254 if (mode == kSplice) {
255 uint32_t flg = SPLICE_F_MOVE | ((block == kNonBlock) * SPLICE_F_NONBLOCK);
256 res = splice(trace_fd, nullptr, *sync_pipe.wr, nullptr, kPageSize, flg);
257 err = errno;
258 if (res > 0) {
259 // If the splice() succeeded, read back from the other end of our own
260 // pipe and copy the data into the pool.
261 ssize_t rdres = read(*sync_pipe.rd, pool_page, kPageSize);
262 PERFETTO_DCHECK(rdres == res);
263 }
264 } else {
265 if (block == kNonBlock)
266 SetBlocking(trace_fd, false);
267 res = read(trace_fd, pool_page, kPageSize);
268 err = errno;
269 if (res > 0) {
270 // Need to copy the ptr, ParsePageHeader() advances the passed ptr arg.
271 const uint8_t* ptr = pool_page;
272
273 // The caller of this function wants to have a sufficient approximation
274 // of how many bytes of ftrace data have been read. Unfortunately the
275 // return value of read() is a lie. The problem is that the ftrace
276 // read() implementation, for good reasons, always reconstructs a whole
277 // ftrace page, copying the events over and zero-filling at the end.
278 // This is nice, because we always get a valid ftrace header, but also
279 // causes read to always returns 4096. The only way to have a good
280 // indication of how many bytes of ftrace data have been read is to
281 // parse the ftrace header.
282 // Note: |header_size_len| is *not* an indication on how many bytes are
283 // available form |ptr|. It's just an independent piece of information
284 // that needs to be passed to ParsePageHeader() (a static function) in
285 // order to work.
286 base::Optional<PageHeader> hdr = ParsePageHeader(&ptr, header_size_len);
287 PERFETTO_DCHECK(hdr && hdr->size > 0 && hdr->size <= base::kPageSize);
288 res = hdr.has_value() ? static_cast<int>(hdr->size) : -1;
289 }
290 if (block == kNonBlock)
291 SetBlocking(trace_fd, true);
292 }
293
294 if (res > 0) {
295 // splice() should return full pages, read can return < a page.
296 PERFETTO_DCHECK(res == base::kPageSize || mode == kRead);
297 pool->EndWrite();
298 return static_cast<int>(res);
299 }
300
301 // It is fine to leave the BeginWrite() unpaired in the error case.
302
303 if (res && err != EAGAIN && err != ENOMEM && err != EBUSY && err != EINTR &&
304 err != EBADF) {
305 // EAGAIN: no data when in non-blocking mode.
306 // ENONMEM, EBUSY: temporary ftrace failures (they happen).
307 // EINTR: signal interruption, likely from main thread to issue a new cmd.
308 // EBADF: the main thread has closed the fd (happens during dtor).
309 PERFETTO_PLOG("Unexpected %s() err", mode == kRead ? "read" : "splice");
310 }
311 return -1;
312 };
313
314 uint64_t last_cmd_id = 0;
315 ReadMode cur_mode = kSplice;
316 for (bool run_loop = true; run_loop;) {
317 FtraceThreadSync::Cmd cmd;
318 // Wait for a new command from the main thread issued by FtraceController.
319 // The FtraceController issues also a signal() after every new command. This
320 // is not necessary for the condition variable itself, but it's necessary to
321 // unblock us if we are in a blocking read() or splice().
322 // Commands are tagged with an ID, every new command has a new |cmd_id|, so
323 // we can distinguish spurious wakeups from actual cmd requests.
324 {
325 PERFETTO_METATRACE("wait cmd", cpu);
326 std::unique_lock<std::mutex> lock(thread_sync->mutex);
327 while (thread_sync->cmd_id == last_cmd_id)
328 thread_sync->cond.wait(lock);
329 cmd = thread_sync->cmd;
330 last_cmd_id = thread_sync->cmd_id;
331 }
332
333 // An empirical threshold (bytes read/spliced from the raw pipe) to make an
334 // educated guess on whether we should read/splice more. If we read fewer
335 // bytes it means that we caught up with the write pointer and we started
336 // consuming ftrace events in real-time. This cannot be just 4096 because
337 // it needs to account for fragmentation, i.e. for the fact that the last
338 // trace event didn't fit in the current page and hence the current page
339 // was terminated prematurely.
340 constexpr int kRoughlyAPage = 4096 - 512;
341
342 switch (cmd) {
343 case FtraceThreadSync::kQuit:
344 run_loop = false;
345 break;
346
347 case FtraceThreadSync::kRun: {
348 PERFETTO_METATRACE(cur_mode == kRead ? "read" : "splice", cpu);
349
350 // Do a blocking read/splice. This can fail for a variety of reasons:
351 // - FtraceController interrupts us with a signal for a new cmd
352 // (e.g. it wants us to quit or do a flush).
353 // - A temporary read/splice() failure occurred (it has been observed
354 // to happen if the system is under high load).
355 // In all these cases the most useful thing we can do is skip the
356 // current cycle and try again later.
357 if (read_ftrace_pipe(cur_mode, kBlock) <= 0)
358 break; // Wait for next command.
359
360 // If we are in read mode (because of a previous flush) check if the
361 // in-kernel read cursor is page-aligned again. If a non-blocking splice
362 // succeeds, it means that we can safely switch back to splice mode
363 // (See b/120188810).
364 if (cur_mode == kRead && read_ftrace_pipe(kSplice, kNonBlock) > 0)
365 cur_mode = kSplice;
366
367 // Do as many non-blocking read/splice as we can.
368 while (read_ftrace_pipe(cur_mode, kNonBlock) > kRoughlyAPage) {
369 }
370 pool->CommitWrittenPages();
371 FtraceController::OnCpuReaderRead(cpu, generation, thread_sync);
372 break;
373 }
374
375 case FtraceThreadSync::kFlush: {
376 PERFETTO_METATRACE("flush", cpu);
377 cur_mode = kRead;
378 while (read_ftrace_pipe(cur_mode, kNonBlock) > kRoughlyAPage) {
379 }
380 pool->CommitWrittenPages();
381 FtraceController::OnCpuReaderFlush(cpu, generation, thread_sync);
382 break;
383 }
384 } // switch(cmd)
385 } // for(run_loop)
386 PERFETTO_DPLOG("Terminating CPUReader thread for CPU %zd.", cpu);
387 #else
388 base::ignore_result(cpu);
389 base::ignore_result(generation);
390 base::ignore_result(trace_fd);
391 base::ignore_result(pool);
392 base::ignore_result(thread_sync);
393 base::ignore_result(header_size_len);
394 PERFETTO_ELOG("Supported only on Linux/Android");
395 #endif
396 }
397
398 // Invoked on the main thread by FtraceController, |drain_rate_ms| after the
399 // first CPU wakes up from the blocking read()/splice().
Drain(const std::set<FtraceDataSource * > & data_sources)400 void CpuReader::Drain(const std::set<FtraceDataSource*>& data_sources) {
401 PERFETTO_DCHECK_THREAD(thread_checker_);
402 PERFETTO_METATRACE("Drain(" + std::to_string(cpu_) + ")",
403 base::MetaTrace::kMainThreadCpu);
404
405 auto page_blocks = pool_.BeginRead();
406 for (const auto& page_block : page_blocks) {
407 for (size_t i = 0; i < page_block.size(); i++) {
408 const uint8_t* page = page_block.At(i);
409
410 for (FtraceDataSource* data_source : data_sources) {
411 auto packet = data_source->trace_writer()->NewTracePacket();
412 auto* bundle = packet->set_ftrace_events();
413 auto* metadata = data_source->mutable_metadata();
414 auto* filter = data_source->event_filter();
415
416 // Note: The fastpath in proto_trace_parser.cc speculates on the fact
417 // that the cpu field is the first field of the proto message. If this
418 // changes, change proto_trace_parser.cc accordingly.
419 bundle->set_cpu(static_cast<uint32_t>(cpu_));
420
421 size_t evt_size = ParsePage(page, filter, bundle, table_, metadata);
422 PERFETTO_DCHECK(evt_size);
423 bundle->set_overwrite_count(metadata->overwrite_count);
424 }
425 }
426 }
427 pool_.EndRead(std::move(page_blocks));
428 }
429
430 // The structure of a raw trace buffer page is as follows:
431 // First a page header:
432 // 8 bytes of timestamp
433 // 8 bytes of page length TODO(hjd): other fields also defined here?
434 // // TODO(hjd): Document rest of format.
435 // Some information about the layout of the page header is available in user
436 // space at: /sys/kernel/debug/tracing/events/header_event
437 // This method is deliberately static so it can be tested independently.
ParsePage(const uint8_t * ptr,const EventFilter * filter,FtraceEventBundle * bundle,const ProtoTranslationTable * table,FtraceMetadata * metadata)438 size_t CpuReader::ParsePage(const uint8_t* ptr,
439 const EventFilter* filter,
440 FtraceEventBundle* bundle,
441 const ProtoTranslationTable* table,
442 FtraceMetadata* metadata) {
443 const uint8_t* const start_of_page = ptr;
444 const uint8_t* const end_of_page = ptr + base::kPageSize;
445
446 auto page_header = ParsePageHeader(&ptr, table->page_header_size_len());
447 if (!page_header.has_value())
448 return 0;
449
450 // ParsePageHeader advances |ptr| to point past the end of the header.
451
452 metadata->overwrite_count = static_cast<uint32_t>(page_header->overwrite);
453 const uint8_t* const end = ptr + page_header->size;
454 if (end > end_of_page)
455 return 0;
456
457 uint64_t timestamp = page_header->timestamp;
458
459 while (ptr < end) {
460 EventHeader event_header;
461 if (!ReadAndAdvance(&ptr, end, &event_header))
462 return 0;
463
464 timestamp += event_header.time_delta;
465
466 switch (event_header.type_or_length) {
467 case kTypePadding: {
468 // Left over page padding or discarded event.
469 if (event_header.time_delta == 0) {
470 // Not clear what the correct behaviour is in this case.
471 PERFETTO_DFATAL("Empty padding event.");
472 return 0;
473 }
474 uint32_t length;
475 if (!ReadAndAdvance<uint32_t>(&ptr, end, &length))
476 return 0;
477 ptr += length;
478 break;
479 }
480 case kTypeTimeExtend: {
481 // Extend the time delta.
482 uint32_t time_delta_ext;
483 if (!ReadAndAdvance<uint32_t>(&ptr, end, &time_delta_ext))
484 return 0;
485 // See https://goo.gl/CFBu5x
486 timestamp += (static_cast<uint64_t>(time_delta_ext)) << 27;
487 break;
488 }
489 case kTypeTimeStamp: {
490 // Sync time stamp with external clock.
491 TimeStamp time_stamp;
492 if (!ReadAndAdvance<TimeStamp>(&ptr, end, &time_stamp))
493 return 0;
494 // Not implemented in the kernel, nothing should generate this.
495 PERFETTO_DFATAL("Unimplemented in kernel. Should be unreachable.");
496 break;
497 }
498 // Data record:
499 default: {
500 PERFETTO_CHECK(event_header.type_or_length <= kTypeDataTypeLengthMax);
501 // type_or_length is <=28 so it represents the length of a data
502 // record. if == 0, this is an extended record and the size of the
503 // record is stored in the first uint32_t word in the payload. See
504 // Kernel's include/linux/ring_buffer.h
505 uint32_t event_size;
506 if (event_header.type_or_length == 0) {
507 if (!ReadAndAdvance<uint32_t>(&ptr, end, &event_size))
508 return 0;
509 // Size includes the size field itself.
510 if (event_size < 4)
511 return 0;
512 event_size -= 4;
513 } else {
514 event_size = 4 * event_header.type_or_length;
515 }
516 const uint8_t* start = ptr;
517 const uint8_t* next = ptr + event_size;
518
519 if (next > end)
520 return 0;
521
522 uint16_t ftrace_event_id;
523 if (!ReadAndAdvance<uint16_t>(&ptr, end, &ftrace_event_id))
524 return 0;
525 if (filter->IsEventEnabled(ftrace_event_id)) {
526 protos::pbzero::FtraceEvent* event = bundle->add_event();
527 event->set_timestamp(timestamp);
528 if (!ParseEvent(ftrace_event_id, start, next, table, event, metadata))
529 return 0;
530 }
531
532 // Jump to next event.
533 ptr = next;
534 }
535 }
536 }
537 return static_cast<size_t>(ptr - start_of_page);
538 }
539
540 // |start| is the start of the current event.
541 // |end| is the end of the buffer.
ParseEvent(uint16_t ftrace_event_id,const uint8_t * start,const uint8_t * end,const ProtoTranslationTable * table,protozero::Message * message,FtraceMetadata * metadata)542 bool CpuReader::ParseEvent(uint16_t ftrace_event_id,
543 const uint8_t* start,
544 const uint8_t* end,
545 const ProtoTranslationTable* table,
546 protozero::Message* message,
547 FtraceMetadata* metadata) {
548 PERFETTO_DCHECK(start < end);
549 const size_t length = static_cast<size_t>(end - start);
550
551 // TODO(hjd): Rework to work even if the event is unknown.
552 const Event& info = *table->GetEventById(ftrace_event_id);
553
554 // TODO(hjd): Test truncated events.
555 // If the end of the buffer is before the end of the event give up.
556 if (info.size > length) {
557 PERFETTO_DFATAL("Buffer overflowed.");
558 return false;
559 }
560
561 bool success = true;
562 for (const Field& field : table->common_fields())
563 success &= ParseField(field, start, end, message, metadata);
564
565 protozero::Message* nested =
566 message->BeginNestedMessage<protozero::Message>(info.proto_field_id);
567
568 // Parse generic event.
569 if (info.proto_field_id == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
570 nested->AppendString(GenericFtraceEvent::kEventNameFieldNumber, info.name);
571 for (const Field& field : info.fields) {
572 auto generic_field = nested->BeginNestedMessage<protozero::Message>(
573 GenericFtraceEvent::kFieldFieldNumber);
574 // TODO(taylori): Avoid outputting field names every time.
575 generic_field->AppendString(GenericFtraceEvent::Field::kNameFieldNumber,
576 field.ftrace_name);
577 success &= ParseField(field, start, end, generic_field, metadata);
578 }
579 } else { // Parse all other events.
580 for (const Field& field : info.fields) {
581 success &= ParseField(field, start, end, nested, metadata);
582 }
583 }
584
585 if (PERFETTO_UNLIKELY(info.proto_field_id ==
586 protos::pbzero::FtraceEvent::kTaskRenameFieldNumber)) {
587 // For task renames, we want to store that the pid was renamed. We use the
588 // common pid to reduce code complexity as in all the cases we care about,
589 // the common pid is the same as the renamed pid (the pid inside the event).
590 PERFETTO_DCHECK(metadata->last_seen_common_pid);
591 metadata->AddRenamePid(metadata->last_seen_common_pid);
592 }
593
594 // This finalizes |nested| and |proto_field| automatically.
595 message->Finalize();
596 metadata->FinishEvent();
597 return success;
598 }
599
600 // Caller must guarantee that the field fits in the range,
601 // explicitly: start + field.ftrace_offset + field.ftrace_size <= end
602 // The only exception is fields with strategy = kCStringToString
603 // where the total size isn't known up front. In this case ParseField
604 // will check the string terminates in the bounds and won't read past |end|.
ParseField(const Field & field,const uint8_t * start,const uint8_t * end,protozero::Message * message,FtraceMetadata * metadata)605 bool CpuReader::ParseField(const Field& field,
606 const uint8_t* start,
607 const uint8_t* end,
608 protozero::Message* message,
609 FtraceMetadata* metadata) {
610 PERFETTO_DCHECK(start + field.ftrace_offset + field.ftrace_size <= end);
611 const uint8_t* field_start = start + field.ftrace_offset;
612 uint32_t field_id = field.proto_field_id;
613
614 switch (field.strategy) {
615 case kUint8ToUint32:
616 case kUint8ToUint64:
617 ReadIntoVarInt<uint8_t>(field_start, field_id, message);
618 return true;
619 case kUint16ToUint32:
620 case kUint16ToUint64:
621 ReadIntoVarInt<uint16_t>(field_start, field_id, message);
622 return true;
623 case kUint32ToUint32:
624 case kUint32ToUint64:
625 ReadIntoVarInt<uint32_t>(field_start, field_id, message);
626 return true;
627 case kUint64ToUint64:
628 ReadIntoVarInt<uint64_t>(field_start, field_id, message);
629 return true;
630 case kInt8ToInt32:
631 case kInt8ToInt64:
632 ReadIntoVarInt<int8_t>(field_start, field_id, message);
633 return true;
634 case kInt16ToInt32:
635 case kInt16ToInt64:
636 ReadIntoVarInt<int16_t>(field_start, field_id, message);
637 return true;
638 case kInt32ToInt32:
639 case kInt32ToInt64:
640 ReadIntoVarInt<int32_t>(field_start, field_id, message);
641 return true;
642 case kInt64ToInt64:
643 ReadIntoVarInt<int64_t>(field_start, field_id, message);
644 return true;
645 case kFixedCStringToString:
646 // TODO(hjd): Add AppendMaxLength string to protozero.
647 return ReadIntoString(field_start, field_start + field.ftrace_size,
648 field_id, message);
649 case kCStringToString:
650 // TODO(hjd): Kernel-dive to check this how size:0 char fields work.
651 return ReadIntoString(field_start, end, field.proto_field_id, message);
652 case kStringPtrToString:
653 // TODO(hjd): Figure out how to read these.
654 return true;
655 case kDataLocToString:
656 return ReadDataLoc(start, field_start, end, field, message);
657 case kBoolToUint32:
658 case kBoolToUint64:
659 ReadIntoVarInt<uint8_t>(field_start, field_id, message);
660 return true;
661 case kInode32ToUint64:
662 ReadInode<uint32_t>(field_start, field_id, message, metadata);
663 return true;
664 case kInode64ToUint64:
665 ReadInode<uint64_t>(field_start, field_id, message, metadata);
666 return true;
667 case kPid32ToInt32:
668 case kPid32ToInt64:
669 ReadPid(field_start, field_id, message, metadata);
670 return true;
671 case kCommonPid32ToInt32:
672 case kCommonPid32ToInt64:
673 ReadCommonPid(field_start, field_id, message, metadata);
674 return true;
675 case kDevId32ToUint64:
676 ReadDevId<uint32_t>(field_start, field_id, message, metadata);
677 return true;
678 case kDevId64ToUint64:
679 ReadDevId<uint64_t>(field_start, field_id, message, metadata);
680 return true;
681 }
682 PERFETTO_FATAL("Not reached"); // For gcc
683 }
684
685 } // namespace perfetto
686