xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/syscalls/syscall_tracker.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_
19 
20 #include <limits>
21 #include <tuple>
22 
23 #include "perfetto/ext/base/string_view.h"
24 #include "src/kernel_utils/syscall_table.h"
25 #include "src/trace_processor/containers/bit_vector.h"
26 #include "src/trace_processor/importers/common/event_tracker.h"
27 #include "src/trace_processor/importers/common/slice_tracker.h"
28 #include "src/trace_processor/importers/common/track_tracker.h"
29 #include "src/trace_processor/storage/trace_storage.h"
30 #include "src/trace_processor/types/destructible.h"
31 #include "src/trace_processor/types/trace_processor_context.h"
32 
33 namespace perfetto::trace_processor {
34 
35 class SyscallTracker : public Destructible {
36  public:
37   SyscallTracker(const SyscallTracker&) = delete;
38   SyscallTracker& operator=(const SyscallTracker&) = delete;
39   ~SyscallTracker() override;
GetOrCreate(TraceProcessorContext * context)40   static SyscallTracker* GetOrCreate(TraceProcessorContext* context) {
41     if (!context->syscall_tracker) {
42       context->syscall_tracker.reset(new SyscallTracker(context));
43     }
44     return static_cast<SyscallTracker*>(context->syscall_tracker.get());
45   }
46 
47   void SetArchitecture(Architecture architecture);
48 
49   void Enter(int64_t ts,
50              UniqueTid utid,
51              uint32_t syscall_num,
52              EventTracker::SetArgsCallback args_callback =
53                  EventTracker::SetArgsCallback()) {
54     StringId name = SyscallNumberToStringId(syscall_num);
55     if (name.is_null())
56       return;
57 
58     TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
59 
60     // sys_rt_sigreturn does not return so should be inserted as an instant
61     // event. See https://github.com/google/perfetto/issues/733 for details.
62     if (name == sys_rt_sigreturn_string_id_) {
63       context_->slice_tracker->Scoped(ts, track_id, kNullStringId, name, 0,
64                                       args_callback);
65     } else {
66       context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */,
67                                      name, args_callback);
68     }
69 
70     if (name == sys_write_string_id_) {
71       if (utid >= in_sys_write_.size())
72         in_sys_write_.Resize(utid + 1);
73 
74       in_sys_write_.Set(utid);
75     }
76   }
77 
78   void Exit(int64_t ts,
79             UniqueTid utid,
80             uint32_t syscall_num,
81             EventTracker::SetArgsCallback args_callback =
82                 EventTracker::SetArgsCallback()) {
83     StringId name = SyscallNumberToStringId(syscall_num);
84     if (name.is_null())
85       return;
86 
87     if (name == sys_write_string_id_) {
88       if (utid >= in_sys_write_.size())
89         in_sys_write_.Resize(utid + 1);
90       // Either seeing an exit event without the corresponding entry at the
91       // start of the trace, or the slice was closed by
92       // MaybeTruncateOngoingWriteSlice.
93       if (!in_sys_write_.IsSet(utid))
94         return;
95       in_sys_write_.Clear(utid);
96     }
97 
98     TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
99     context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */, name,
100                                  args_callback);
101   }
102 
103   // Resolves slice nesting issues when the sys_write is for an atrace slice on
104   // android. See callsite for details.
MaybeTruncateOngoingWriteSlice(int64_t ts,UniqueTid utid)105   void MaybeTruncateOngoingWriteSlice(int64_t ts, UniqueTid utid) {
106     if (utid >= in_sys_write_.size())
107       in_sys_write_.Resize(utid + 1);
108 
109     if (!in_sys_write_.IsSet(utid))
110       return;
111     in_sys_write_.Clear(utid);
112     context_->storage->IncrementStats(stats::truncated_sys_write_duration);
113 
114     TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
115     context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */,
116                                  sys_write_string_id_);
117   }
118 
119  private:
120   explicit SyscallTracker(TraceProcessorContext*);
121 
122   TraceProcessorContext* const context_;
123 
SyscallNumberToStringId(uint32_t syscall_num)124   inline StringId SyscallNumberToStringId(uint32_t syscall_num) {
125     if (syscall_num > kMaxSyscalls)
126       return kNullStringId;
127     return arch_syscall_to_string_id_[syscall_num];
128   }
129 
130   // This is table from platform specific syscall number directly to
131   // the relevant StringId (this avoids having to always do two conversions).
132   std::array<StringId, kMaxSyscalls> arch_syscall_to_string_id_{};
133   StringId sys_write_string_id_ = std::numeric_limits<StringId>::max();
134   StringId sys_rt_sigreturn_string_id_ = std::numeric_limits<StringId>::max();
135   // UniqueTids currently in a sys_write syscall.
136   BitVector in_sys_write_;
137 };
138 
139 }  // namespace perfetto::trace_processor
140 
141 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_SYSCALLS_SYSCALL_TRACKER_H_
142