]> git.saurik.com Git - apple/system_cmds.git/blob - msa/main.cpp
system_cmds-670.1.2.tar.gz
[apple/system_cmds.git] / msa / main.cpp
1 //
2 // main.cpp
3 // msa
4 //
5 // Created by James McIlree on 1/30/14.
6 // Copyright (c) 2014 Apple. All rights reserved.
7 //
8
9 #include <CPPUtil/CPPUtil.h>
10
11 #include "global.h"
12
13 bool isVerbose = true;
14 bool shouldPrintVersion = true;
15 std::vector<std::string> procsOfInterest;
16 bool interestedInEverything = false;
17
18 __attribute__((noreturn)) void usage(const char *errorMsg) {
19 if (errorMsg) {
20 printf("%s\n", errorMsg);
21 exit(1);
22 }
23
24 // const char* BOLD = "\033[1m";
25 // const char* UNBOLD = "\033[0m";
26
27 // printf("01234567890123456789012345678901234567890123456789012345678901234567890123456789\n");
28 printf("msa [options]\n\n");
29 printf(" GLOBAL OPTIONS\n\n");
30 printf(" -h, --help Print this message\n");
31 printf(" --verbose Print additional information\n");
32 printf(" --version Print version info\n");
33 printf("\n");
34 printf(" TRACE COLLECTION OPTIONS\n\n");
35 printf(" -i, --initialize # Set the size of the kernel trace buffer\n");
36 printf(" --no-voucher-contents Disable collecting voucher contents\n");
37 printf(" -L path Capture and save trace output to path\n");
38 printf("\n");
39 printf(" OUTPUT OPTIONS\n\n");
40 printf(" --lifecycle all|user|none\n");
41 printf(" Set filter level for lifecycle events\n");
42 printf(" --mach-msg all|user|voucher|none\n");
43 printf(" Set filter level for mach msg events\n");
44 printf(" -o, --output path Print output to path\n");
45 printf(" --raw-timestamps Print timestamps as raw values, not deltas\n");
46 printf(" --mach-absolute-time Print timestamps in mach absolute time\n");
47 printf(" --event-index Print the index of each event\n");
48 printf("\n");
49 exit(1);
50 }
51
52 template <typename SIZE>
53 static bool check_interest_name(const MachineProcess<SIZE>& process) {
54 if (interestedInEverything)
55 return true;
56
57 const char* name = process.name();
58 for (auto& proc : procsOfInterest) {
59 if (strcmp(name, proc.c_str()) == 0)
60 return true;
61 }
62
63 return false;
64 }
65
66 static std::unique_ptr<Action> create_read_trace_file_action(const char* trace_file_path) {
67 if (Path::is_file(trace_file_path, true)) {
68 char resolved_path[PATH_MAX];
69 if (realpath(trace_file_path, resolved_path)) {
70 return std::make_unique<ReadTraceFileAction>(resolved_path);
71 }
72 }
73 char* errmsg = NULL;
74 asprintf(&errmsg, "%s does not exist or is not a file", trace_file_path);
75 usage(errmsg);
76 }
77
78 static std::vector<std::unique_ptr<Action>> parse_arguments(int argc, const char* argv[], Globals& globals) {
79 int i = 1;
80
81 std::vector<std::unique_ptr<Action>> actions;
82
83 while (i < argc) {
84 const char* arg = argv[i];
85 if ((strcmp(arg, "-h") == 0) || (strcasecmp(arg, "--help") == 0)) {
86 usage(NULL);
87 } else if ((strcmp(arg, "-v") == 0) || strcasecmp(arg, "--verbose") == 0) {
88 globals.set_is_verbose(true);
89 } else if (strcasecmp(arg, "--version") == 0) {
90 shouldPrintVersion = true;
91 } else if ((strcmp(arg, "-i") == 0) || strcasecmp(arg, "--initialize") == 0) {
92 if (++i >= argc)
93 usage("--initialize requires an argument");
94
95 arg = argv[i];
96 char* endptr;
97 uint32_t temp = (uint32_t)strtoul(arg, &endptr, 0);
98 if (*endptr == 0) {
99 globals.set_trace_buffer_size(temp);
100 } else {
101 usage("Unable to parse --initialize argument");
102 }
103 } else if (strcasecmp(arg, "--no-voucher-contents") == 0) {
104 globals.set_should_trace_voucher_contents(false);
105 } else if (strcasecmp(arg, "-L") == 0) {
106 if (++i >= argc)
107 usage("-L requires an argument");
108
109 arg = argv[i];
110 actions.push_back(std::make_unique<WriteTraceFileAction>(arg));
111 } else if (strcasecmp(arg, "--lifecycle") == 0) {
112 if (++i >= argc)
113 usage("--lifecycle requires an argument");
114
115 arg = argv[i];
116 if (strcasecmp(arg, "all") == 0) {
117 globals.set_lifecycle_filter(kLifecycleFilter::All);
118 } else if (strcasecmp(arg, "user") == 0) {
119 globals.set_lifecycle_filter(kLifecycleFilter::User);
120 } else if (strcasecmp(arg, "none") == 0) {
121 globals.set_lifecycle_filter(kLifecycleFilter::None);
122 } else {
123 usage("Unrecognized --lifecycle value");
124 }
125 } else if (strcasecmp(arg, "--mach-msg") == 0) {
126 if (++i >= argc)
127 usage("--mach-msg requires an argument");
128
129 arg = argv[i];
130 if (strcasecmp(arg, "all") == 0) {
131 globals.set_mach_msg_filter(kMachMsgFilter::All);
132 } else if (strcasecmp(arg, "user") == 0) {
133 globals.set_mach_msg_filter(kMachMsgFilter::User);
134 } else if (strcasecmp(arg, "voucher") == 0) {
135 globals.set_mach_msg_filter(kMachMsgFilter::Voucher);
136 } else if (strcasecmp(arg, "none") == 0) {
137 globals.set_mach_msg_filter(kMachMsgFilter::None);
138 } else {
139 usage("Unrecognized --mach-msg value");
140 }
141 } else if ((strcmp(arg, "-o") == 0) || strcasecmp(arg, "--output") == 0) {
142 if (++i >= argc)
143 usage("--output requires an argument");
144
145 FileDescriptor desc(argv[i], O_WRONLY | O_CREAT | O_TRUNC, 0644);
146 if (!desc.is_open()) {
147 char* errmsg = NULL;
148 asprintf(&errmsg, "Unable to create output file at %s", argv[i]);
149 usage(errmsg);
150 }
151 globals.set_output_fd(std::move(desc));
152 } else if (strcasecmp(arg, "--raw-timestamps") == 0) {
153 globals.set_should_zero_base_timestamps(false);
154 } else if (strcasecmp(arg, "--mach-absolute-time") == 0) {
155 globals.set_should_print_mach_absolute_timestamps(true);
156 } else if (strcasecmp(arg, "--event-index") == 0) {
157 globals.set_should_print_event_index(true);
158 } else {
159 //
160 // Last attempts to divine argument type/intent.
161 //
162 std::string temp(arg);
163
164 if (ends_with(temp, ".trace")) {
165 actions.push_back(create_read_trace_file_action(argv[i]));
166 goto no_error;
167 }
168
169 //
170 // ERROR!
171 //
172 char error_buffer[PATH_MAX];
173 snprintf(error_buffer, sizeof(error_buffer), "Unhandled argument: %s", arg);
174 usage(error_buffer);
175 }
176
177 no_error:
178
179 i++;
180 }
181
182 if (actions.empty()) {
183 actions.push_back(std::make_unique<LiveTraceAction>());
184 }
185
186 return actions;
187 }
188
189 int main(int argc, const char * argv[])
190 {
191 //
192 // Use host values as defaults.
193 // User overrides as needed via flags.
194 //
195 Globals globals;
196 auto actions = parse_arguments(argc, argv, globals);
197
198 interestedInEverything = procsOfInterest.empty();
199
200 // globals.set_should_print_mach_absolute_timestamps(true);
201
202 for (auto& action : actions) {
203 action->execute(globals);
204 }
205
206 return 0;
207 }
208