1 /*
2 * Copyright (C) 2021 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 #pragma once
18
19 #include <sys/types.h>
20
21 #include <optional>
22 #include <regex>
23 #include <set>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27
28 #include "command.h"
29 #include "record.h"
30 #include "thread_tree.h"
31
32 namespace simpleperf {
33
34 #define RECORD_FILTER_OPTION_HELP_MSG \
35 "--exclude-pid pid1,pid2,... Exclude samples for selected processes.\n" \
36 "--exclude-tid tid1,tid2,... Exclude samples for selected threads.\n" \
37 "--exclude-process-name process_name_regex Exclude samples for processes with name\n" \
38 " containing the regular expression.\n" \
39 "--exclude-thread-name thread_name_regex Exclude samples for threads with name containing\n" \
40 " the regular expression.\n" \
41 "--exclude-uid uid1,uid2,... Exclude samples for processes belonging to selected uids.\n" \
42 "--include-pid pid1,pid2,... Include samples for selected processes.\n" \
43 "--include-tid tid1,tid2,... Include samples for selected threads.\n" \
44 "--include-process-name process_name_regex Include samples for processes with name\n" \
45 " containing the regular expression.\n" \
46 "--include-thread-name thread_name_regex Include samples for threads with name containing\n" \
47 " the regular expression.\n" \
48 "--include-uid uid1,uid2,... Include samples for processes belonging to selected uids.\n"
49
50 struct RecordFilterCondition {
51 bool used = false;
52 std::set<pid_t> pids;
53 std::set<pid_t> tids;
54 std::vector<std::regex> process_name_regs;
55 std::vector<std::regex> thread_name_regs;
56 std::set<uid_t> uids;
57 };
58
59 // Filter SampleRecords based on the rule below:
60 // out_sample_records = (in_sample_records & ~exclude_conditions) & include_conditions
61 // By default, exclude_conditions = 0, include_conditions = 1.
62 class RecordFilter {
63 public:
RecordFilter(const ThreadTree & thread_tree)64 RecordFilter(const ThreadTree& thread_tree) : thread_tree_(thread_tree) {}
65 bool ParseOptions(OptionValueMap& options);
66 void AddPids(const std::set<pid_t>& pids, bool exclude);
67 void AddTids(const std::set<pid_t>& tids, bool exclude);
68 void AddProcessNameRegex(const std::string& process_name, bool exclude);
69 void AddThreadNameRegex(const std::string& thread_name, bool exclude);
70 void AddUids(const std::set<uid_t>& uids, bool exclude);
71
72 // Return true if the record passes filter.
73 bool Check(const SampleRecord* r);
74
GetCondition(bool exclude)75 RecordFilterCondition& GetCondition(bool exclude) {
76 return exclude ? exclude_condition_ : include_condition_;
77 }
78 void Clear();
79
80 private:
81 bool CheckCondition(const SampleRecord* r, const RecordFilterCondition& condition);
82 bool SearchInRegs(const std::string& s, const std::vector<std::regex>& regs);
83 std::optional<uid_t> GetUidForProcess(pid_t pid);
84
85 const ThreadTree& thread_tree_;
86 RecordFilterCondition exclude_condition_;
87 RecordFilterCondition include_condition_;
88 std::unordered_map<pid_t, std::optional<uid_t>> pid_to_uid_map_;
89 };
90
GetRecordFilterOptionFormats()91 inline const OptionFormatMap& GetRecordFilterOptionFormats() {
92 static const OptionFormatMap option_formats = {
93 {"--exclude-pid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
94 {"--exclude-tid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
95 {"--exclude-process-name",
96 {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
97 {"--exclude-thread-name",
98 {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
99 {"--exclude-uid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
100 {"--include-pid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
101 {"--include-tid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
102 {"--include-process-name",
103 {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
104 {"--include-thread-name",
105 {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
106 {"--include-uid", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
107 };
108 return option_formats;
109 }
110
111 } // namespace simpleperf
112