Home | History | Annotate | Download | only in ftrace
      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 #ifndef SRC_TRACED_PROBES_FTRACE_PROTO_TRANSLATION_TABLE_H_
     18 #define SRC_TRACED_PROBES_FTRACE_PROTO_TRANSLATION_TABLE_H_
     19 
     20 #include <stdint.h>
     21 
     22 #include <map>
     23 #include <memory>
     24 #include <set>
     25 #include <string>
     26 #include <vector>
     27 
     28 #include "perfetto/base/scoped_file.h"
     29 #include "src/traced/probes/ftrace/event_info.h"
     30 #include "src/traced/probes/ftrace/format_parser.h"
     31 
     32 namespace perfetto {
     33 
     34 class FtraceProcfs;
     35 
     36 namespace protos {
     37 namespace pbzero {
     38 class FtraceEventBundle;
     39 }  // namespace pbzero
     40 }  // namespace protos
     41 
     42 // Used when reading the config to store the group and name info for the
     43 // ftrace event.
     44 class GroupAndName {
     45  public:
     46   GroupAndName(const std::string& group, const std::string& name)
     47       : group_(group), name_(name) {}
     48 
     49   bool operator==(const GroupAndName& other) const {
     50     return std::tie(group_, name_) == std::tie(other.group(), other.name());
     51   }
     52 
     53   bool operator<(const GroupAndName& other) const {
     54     return std::tie(group_, name_) < std::tie(other.group(), other.name());
     55   }
     56 
     57   const std::string& name() const { return name_; }
     58   const std::string& group() const { return group_; }
     59 
     60   std::string ToString() const { return group_ + "/" + name_; }
     61 
     62  private:
     63   std::string group_;
     64   std::string name_;
     65 };
     66 
     67 bool InferFtraceType(const std::string& type_and_name,
     68                      size_t size,
     69                      bool is_signed,
     70                      FtraceFieldType* out);
     71 
     72 class ProtoTranslationTable {
     73  public:
     74   struct FtracePageHeaderSpec {
     75     FtraceEvent::Field timestamp{};
     76     FtraceEvent::Field overwrite{};
     77     FtraceEvent::Field size{};
     78   };
     79 
     80   static FtracePageHeaderSpec DefaultPageHeaderSpecForTesting();
     81 
     82   // This method mutates the |events| and |common_fields| vectors to
     83   // fill some of the fields and to delete unused events/fields
     84   // before std:move'ing them into the ProtoTranslationTable.
     85   static std::unique_ptr<ProtoTranslationTable> Create(
     86       const FtraceProcfs* ftrace_procfs,
     87       std::vector<Event> events,
     88       std::vector<Field> common_fields);
     89   virtual ~ProtoTranslationTable();
     90 
     91   ProtoTranslationTable(const FtraceProcfs* ftrace_procfs,
     92                         const std::vector<Event>& events,
     93                         std::vector<Field> common_fields,
     94                         FtracePageHeaderSpec ftrace_page_header_spec);
     95 
     96   size_t largest_id() const { return largest_id_; }
     97 
     98   const std::vector<Field>& common_fields() const { return common_fields_; }
     99 
    100   // Virtual for testing.
    101   virtual const Event* GetEvent(const GroupAndName& group_and_name) const {
    102     if (!group_and_name_to_event_.count(group_and_name))
    103       return nullptr;
    104     return group_and_name_to_event_.at(group_and_name);
    105   }
    106 
    107   const std::vector<const Event*>* GetEventsByGroup(
    108       const std::string& group) const {
    109     if (!group_to_events_.count(group))
    110       return nullptr;
    111     return &group_to_events_.at(group);
    112   }
    113 
    114   const Event* GetEventById(size_t id) const {
    115     if (id == 0 || id > largest_id_)
    116       return nullptr;
    117     if (!events_.at(id).ftrace_event_id)
    118       return nullptr;
    119     return &events_.at(id);
    120   }
    121 
    122   size_t EventToFtraceId(const GroupAndName& group_and_name) const {
    123     if (!group_and_name_to_event_.count(group_and_name))
    124       return 0;
    125     return group_and_name_to_event_.at(group_and_name)->ftrace_event_id;
    126   }
    127 
    128   const std::vector<Event>& events() { return events_; }
    129   const FtracePageHeaderSpec& ftrace_page_header_spec() const {
    130     return ftrace_page_header_spec_;
    131   }
    132 
    133   // Returns the size in bytes of the "size" field in the ftrace header. This
    134   // usually matches sizeof(void*) in the kernel (which can be != sizeof(void*)
    135   // of user space on 32bit-user + 64-bit-kernel configurations).
    136   inline uint16_t page_header_size_len() const {
    137     // TODO(fmayer): Do kernel deepdive to double check this.
    138     return ftrace_page_header_spec_.size.size;
    139   }
    140 
    141   // Retrieves the ftrace event from the proto translation
    142   // table. If it does not exist, reads the format file and creates a
    143   // new event with the proto id set to generic. Virtual for testing.
    144   virtual const Event* GetOrCreateEvent(const GroupAndName&);
    145 
    146   // This is for backwards compatibility. If a group is not specified in the
    147   // config then the first event with that name will be returned.
    148   const Event* GetEventByName(const std::string& name) const {
    149     if (!name_to_events_.count(name))
    150       return nullptr;
    151     return name_to_events_.at(name)[0];
    152   }
    153 
    154  private:
    155   ProtoTranslationTable(const ProtoTranslationTable&) = delete;
    156   ProtoTranslationTable& operator=(const ProtoTranslationTable&) = delete;
    157 
    158   // Store strings so they can be read when writing the trace output.
    159   const char* InternString(const std::string& str);
    160 
    161   uint16_t CreateGenericEventField(const FtraceEvent::Field& ftrace_field,
    162                                    Event& event);
    163 
    164   const FtraceProcfs* ftrace_procfs_;
    165   std::vector<Event> events_;
    166   size_t largest_id_;
    167   std::map<GroupAndName, const Event*> group_and_name_to_event_;
    168   std::map<std::string, std::vector<const Event*>> name_to_events_;
    169   std::map<std::string, std::vector<const Event*>> group_to_events_;
    170   std::vector<Field> common_fields_;
    171   FtracePageHeaderSpec ftrace_page_header_spec_{};
    172   std::set<std::string> interned_strings_;
    173 };
    174 
    175 // Class for efficient 'is event with id x enabled?' checks.
    176 // Mirrors the data in a FtraceConfig but in a format better suited
    177 // to be consumed by CpuReader.
    178 class EventFilter {
    179  public:
    180   EventFilter();
    181   ~EventFilter();
    182   EventFilter(EventFilter&&) = default;
    183   EventFilter& operator=(EventFilter&&) = default;
    184 
    185   void AddEnabledEvent(size_t ftrace_event_id);
    186   void DisableEvent(size_t ftrace_event_id);
    187   bool IsEventEnabled(size_t ftrace_event_id) const;
    188   std::set<size_t> GetEnabledEvents() const;
    189   void EnableEventsFrom(const EventFilter&);
    190 
    191  private:
    192   EventFilter(const EventFilter&) = delete;
    193   EventFilter& operator=(const EventFilter&) = delete;
    194 
    195   std::vector<bool> enabled_ids_;
    196 };
    197 
    198 }  // namespace perfetto
    199 
    200 #endif  // SRC_TRACED_PROBES_FTRACE_PROTO_TRANSLATION_TABLE_H_
    201