• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &current_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