summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2025-06-12 07:32:46 +0200
committerGravatar Nikias Bassen2025-06-12 07:32:46 +0200
commitd3aec6dd14f81b75f212632da66a510c75c6b9e8 (patch)
tree6b6cfab9c05923fa819ad295f39225aa41d78454 /tools
parenteeb320dc055716e0ebeeb8845c9ca8c4e2451124 (diff)
downloadlibimobiledevice-d3aec6dd14f81b75f212632da66a510c75c6b9e8.tar.gz
libimobiledevice-d3aec6dd14f81b75f212632da66a510c75c6b9e8.tar.bz2
idevicesyslog: Use new ostrace service implementation (iOS 9+)
Diffstat (limited to 'tools')
-rw-r--r--tools/idevicesyslog.c387
1 files changed, 301 insertions, 86 deletions
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index f185f3a..65a613b 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -33,6 +33,7 @@
33#include <stdlib.h> 33#include <stdlib.h>
34#include <unistd.h> 34#include <unistd.h>
35#include <getopt.h> 35#include <getopt.h>
36#include <time.h>
36 37
37#ifdef _WIN32 38#ifdef _WIN32
38#include <windows.h> 39#include <windows.h>
@@ -42,10 +43,12 @@
42#include <libimobiledevice/libimobiledevice.h> 43#include <libimobiledevice/libimobiledevice.h>
43#include <libimobiledevice/syslog_relay.h> 44#include <libimobiledevice/syslog_relay.h>
44#include <libimobiledevice-glue/termcolors.h> 45#include <libimobiledevice-glue/termcolors.h>
46#include <libimobiledevice/ostrace.h>
45 47
46static int quit_flag = 0; 48static int quit_flag = 0;
47static int exit_on_disconnect = 0; 49static int exit_on_disconnect = 0;
48static int show_device_name = 0; 50static int show_device_name = 0;
51static int force_syslog_relay = 0;
49 52
50static char* udid = NULL; 53static char* udid = NULL;
51static char** proc_filters = NULL; 54static char** proc_filters = NULL;
@@ -69,6 +72,7 @@ static int triggered = 0;
69 72
70static idevice_t device = NULL; 73static idevice_t device = NULL;
71static syslog_relay_client_t syslog = NULL; 74static syslog_relay_client_t syslog = NULL;
75static ostrace_client_t ostrace = NULL;
72 76
73static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd"; 77static const char QUIET_FILTER[] = "CircleJoinRequested|CommCenter|HeuristicInterpreter|MobileMail|PowerUIAgent|ProtectedCloudKeySyncing|SpringBoard|UserEventAgent|WirelessRadioManagerd|accessoryd|accountsd|aggregated|analyticsd|appstored|apsd|assetsd|assistant_service|backboardd|biometrickitd|bluetoothd|calaccessd|callservicesd|cloudd|com.apple.Safari.SafeBrowsing.Service|contextstored|corecaptured|coreduetd|corespeechd|cdpd|dasd|dataaccessd|distnoted|dprivacyd|duetexpertd|findmydeviced|fmfd|fmflocatord|gpsd|healthd|homed|identityservicesd|imagent|itunescloudd|itunesstored|kernel|locationd|maild|mDNSResponder|mediaremoted|mediaserverd|mobileassetd|nanoregistryd|nanotimekitcompaniond|navd|nsurlsessiond|passd|pasted|photoanalysisd|powerd|powerlogHelperd|ptpd|rapportd|remindd|routined|runningboardd|searchd|sharingd|suggestd|symptomsd|timed|thermalmonitord|useractivityd|vmd|wifid|wirelessproxd";
74 78
@@ -132,6 +136,70 @@ static int find_char(char c, char** p, const char* end)
132 136
133static void stop_logging(void); 137static void stop_logging(void);
134 138
139static int message_filter_matching(const char* message)
140{
141 if (num_msg_filters > 0) {
142 int found = 0;
143 int i;
144 for (i = 0; i < num_msg_filters; i++) {
145 if (strstr(message, msg_filters[i])) {
146 found = 1;
147 break;
148 }
149 }
150 if (!found) {
151 return 0;
152 }
153 }
154 if (num_msg_reverse_filters > 0) {
155 int found = 0;
156 int i;
157 for (i = 0; i < num_msg_reverse_filters; i++) {
158 if (strstr(message, msg_reverse_filters[i])) {
159 found = 1;
160 break;
161 }
162 }
163 if (found) {
164 return 0;
165 }
166 }
167 return 1;
168}
169
170static int process_filter_matching(int pid, const char* process_name, int process_name_length)
171{
172 int proc_matched = 0;
173 if (num_pid_filters > 0) {
174 int found = proc_filter_excluding;
175 int i = 0;
176 for (i = 0; i < num_pid_filters; i++) {
177 if (pid == pid_filters[i]) {
178 found = !proc_filter_excluding;
179 break;
180 }
181 }
182 if (found) {
183 proc_matched = 1;
184 }
185 }
186 if (num_proc_filters > 0 && !proc_matched) {
187 int found = proc_filter_excluding;
188 int i = 0;
189 for (i = 0; i < num_proc_filters; i++) {
190 if (!proc_filters[i]) continue;
191 if (strncmp(proc_filters[i], process_name, process_name_length) == 0) {
192 found = !proc_filter_excluding;
193 break;
194 }
195 }
196 if (found) {
197 proc_matched = 1;
198 }
199 }
200 return proc_matched;
201}
202
135static void syslog_callback(char c, void *user_data) 203static void syslog_callback(char c, void *user_data)
136{ 204{
137 if (lp >= line_buffer_size-1) { 205 if (lp >= line_buffer_size-1) {
@@ -205,35 +273,9 @@ static void syslog_callback(char c, void *user_data)
205 } 273 }
206 274
207 /* check message filters */ 275 /* check message filters */
208 if (num_msg_filters > 0) { 276 shall_print = message_filter_matching(device_name_end+1);
209 int found = 0; 277 if (!shall_print) {
210 int i; 278 break;
211 for (i = 0; i < num_msg_filters; i++) {
212 if (strstr(device_name_end+1, msg_filters[i])) {
213 found = 1;
214 break;
215 }
216 }
217 if (!found) {
218 shall_print = 0;
219 break;
220 }
221 shall_print = 1;
222 }
223 if (num_msg_reverse_filters > 0) {
224 int found = 0;
225 int i;
226 for (i = 0; i < num_msg_reverse_filters; i++) {
227 if (strstr(device_name_end+1, msg_reverse_filters[i])) {
228 found = 1;
229 break;
230 }
231 }
232 if (found) {
233 shall_print = 0;
234 break;
235 }
236 shall_print = 1;
237 } 279 }
238 280
239 /* process name */ 281 /* process name */
@@ -253,39 +295,10 @@ static void syslog_callback(char c, void *user_data)
253 proc_name_end = p; 295 proc_name_end = p;
254 p++; 296 p++;
255 297
256 int proc_matched = 0; 298 /* match pid / process name */
257 if (num_pid_filters > 0) { 299 char* endp = NULL;
258 char* endp = NULL; 300 int pid_value = (int)strtol(pid_start, &endp, 10);
259 int pid_value = (int)strtol(pid_start, &endp, 10); 301 if (process_filter_matching(pid_value, process_name_start, process_name_end-process_name_start)) {
260 if (endp && (*endp == ']')) {
261 int found = proc_filter_excluding;
262 int i = 0;
263 for (i = 0; i < num_pid_filters; i++) {
264 if (pid_value == pid_filters[i]) {
265 found = !proc_filter_excluding;
266 break;
267 }
268 }
269 if (found) {
270 proc_matched = 1;
271 }
272 }
273 }
274 if (num_proc_filters > 0 && !proc_matched) {
275 int found = proc_filter_excluding;
276 int i = 0;
277 for (i = 0; i < num_proc_filters; i++) {
278 if (!proc_filters[i]) continue;
279 if (strncmp(proc_filters[i], process_name_start, process_name_end-process_name_start) == 0) {
280 found = !proc_filter_excluding;
281 break;
282 }
283 }
284 if (found) {
285 proc_matched = 1;
286 }
287 }
288 if (proc_matched) {
289 shall_print = 1; 302 shall_print = 1;
290 } else { 303 } else {
291 if (num_pid_filters > 0 || num_proc_filters > 0) { 304 if (num_pid_filters > 0 || num_proc_filters > 0) {
@@ -363,6 +376,168 @@ static void syslog_callback(char c, void *user_data)
363 } 376 }
364} 377}
365 378
379static void ostrace_syslog_callback(const unsigned char* buf, unsigned int len, void* user_data)
380{
381 if (len < 0x81) {
382 fprintf(stderr, "Error: not enough data in callback function?!\n");
383 return;
384 }
385
386 struct ostrace_packet_header_t *trace_hdr = (struct ostrace_packet_header_t*)buf;
387
388 if (trace_hdr->marker != 2 || (trace_hdr->type != 8 && trace_hdr->type != 2)) {
389 fprintf(stderr, "unexpected packet data %02x %08x\n", trace_hdr->marker, trace_hdr->type);
390 }
391
392 const char* dataptr = (const char*)buf + trace_hdr->header_size;
393 const char* process_name = dataptr;
394 const char* image_name = (trace_hdr->imagepath_len > 0) ? dataptr + trace_hdr->procpath_len : NULL;
395 const char* message = (trace_hdr->message_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len : NULL;
396 //const char* subsystem = (trace_hdr->subsystem_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len : NULL;
397 //const char* category = (trace_hdr->category_len > 0) ? dataptr + trace_hdr->procpath_len + trace_hdr->imagepath_len + trace_hdr->message_len + trace_hdr->subsystem_len : NULL;
398
399 int shall_print = 1;
400 int trigger_off = 0;
401 const char* process_name_short = (process_name) ? strrchr(process_name, '/') : "";
402 process_name_short = (process_name_short) ? process_name_short+1 : process_name;
403 const char* image_name_short = (image_name) ? strrchr(image_name, '/') : NULL;
404 image_name_short = (image_name_short) ? image_name_short+1 : process_name;
405 if (image_name_short && !strcmp(image_name_short, process_name_short)) {
406 image_name_short = NULL;
407 }
408
409 do {
410 /* check if we have any triggers/untriggers */
411 if (num_untrigger_filters > 0 && triggered) {
412 int found = 0;
413 int i;
414 for (i = 0; i < num_untrigger_filters; i++) {
415 if (strstr(message, untrigger_filters[i])) {
416 found = 1;
417 break;
418 }
419 }
420 if (!found) {
421 shall_print = 1;
422 } else {
423 shall_print = 1;
424 trigger_off = 1;
425 }
426 } else if (num_trigger_filters > 0 && !triggered) {
427 int found = 0;
428 int i;
429 for (i = 0; i < num_trigger_filters; i++) {
430 if (strstr(message, trigger_filters[i])) {
431 found = 1;
432 break;
433 }
434 }
435 if (!found) {
436 shall_print = 0;
437 break;
438 }
439 triggered = 1;
440 shall_print = 1;
441 } else if (num_trigger_filters == 0 && num_untrigger_filters > 0 && !triggered) {
442 shall_print = 0;
443 quit_flag++;
444 break;
445 }
446
447 /* check message filters */
448 shall_print = message_filter_matching(message);
449 if (!shall_print) {
450 break;
451 }
452
453 /* check process filters */
454 if (process_filter_matching(trace_hdr->pid, process_name_short, strlen(process_name_short))) {
455 shall_print = 1;
456 } else {
457 if (num_pid_filters > 0 || num_proc_filters > 0) {
458 shall_print = 0;
459 }
460 }
461 if (!shall_print) {
462 break;
463 }
464 } while (0);
465
466 if (!shall_print) {
467 return;
468 }
469
470 const char* level_str = "Unknown";
471 const char* level_color = FG_YELLOW;
472 switch (trace_hdr->level) {
473 case 0:
474 level_str = "Notice";
475 level_color = FG_GREEN;
476 break;
477 case 0x01:
478 level_str = "Info";
479 level_color = FG_WHITE;
480 break;
481 case 0x02:
482 level_str = "Debug";
483 level_color = FG_MAGENTA;
484 break;
485 case 0x10:
486 level_str = "Error";
487 level_color = FG_RED;
488 break;
489 case 0x11:
490 level_str = "Fault";
491 level_color = FG_RED;
492 default:
493 break;
494 }
495
496 char datebuf[24];
497 struct tm *tp;
498 time_t time_sec = (time_t)trace_hdr->time_sec;
499#ifdef HAVE_LOCALTIME_R
500 struct tm tp_ = {0, };
501 tp = localtime_r(&time_sec, &tp_);
502#else
503 tp = localtime(&time_sec);
504#endif
505#ifdef _WIN32
506 strftime(datebuf, 16, "%b %#d %H:%M:%S", tp);
507#else
508 strftime(datebuf, 16, "%b %e %H:%M:%S", tp);
509#endif
510 snprintf(datebuf+15, 9, ".%06u", trace_hdr->time_usec);
511
512 /* write date and time */
513 cprintf(FG_LIGHT_GRAY "%s ", datebuf);
514
515 if (show_device_name) {
516 /* write device name TODO do we need this? */
517 //cprintf(FG_DARK_YELLOW "%s ", device_name);
518 }
519
520 /* write process name */
521 cprintf(FG_BRIGHT_CYAN "%s" FG_CYAN, process_name_short);
522 if (image_name_short) {
523 cprintf("(%s)", image_name_short);
524 }
525 cprintf("[%d]" COLOR_RESET " ", trace_hdr->pid);
526
527 /* write log level */
528 cprintf(level_color);
529 cprintf("<%s>:" COLOR_RESET " ", level_str);
530
531 /* write message */
532 cprintf(FG_WHITE);
533 cprintf("%s" COLOR_RESET "\n", message);
534 fflush(stdout);
535
536 if (trigger_off) {
537 triggered = 0;
538 }
539}
540
366static int start_logging(void) 541static int start_logging(void)
367{ 542{
368 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); 543 idevice_error_t ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
@@ -379,14 +554,21 @@ static int start_logging(void)
379 device = NULL; 554 device = NULL;
380 return -1; 555 return -1;
381 } 556 }
382
383 /* start syslog_relay service */
384 lockdownd_service_descriptor_t svc = NULL; 557 lockdownd_service_descriptor_t svc = NULL;
385 lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); 558
559 const char* service_name = OSTRACE_SERVICE_NAME;
560 int use_ostrace = 1;
561 if (idevice_get_device_version(device) < IDEVICE_DEVICE_VERSION(9,0,0) || force_syslog_relay) {
562 service_name = SYSLOG_RELAY_SERVICE_NAME;
563 use_ostrace = 0;
564 }
565
566 /* start syslog_relay/os_trace_relay service */
567 lerr = lockdownd_start_service(lockdown, service_name, &svc);
386 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { 568 if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) {
387 fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n"); 569 fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n");
388 while (!quit_flag) { 570 while (!quit_flag) {
389 lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); 571 lerr = lockdownd_start_service(lockdown, service_name, &svc);
390 if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) { 572 if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) {
391 break; 573 break;
392 } 574 }
@@ -394,33 +576,56 @@ static int start_logging(void)
394 } 576 }
395 } 577 }
396 if (lerr != LOCKDOWN_E_SUCCESS) { 578 if (lerr != LOCKDOWN_E_SUCCESS) {
397 fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr); 579 fprintf(stderr, "ERROR: Could not start %s service: %s (%d)\n", service_name, lockdownd_strerror(lerr), lerr);
398 idevice_free(device); 580 idevice_free(device);
399 device = NULL; 581 device = NULL;
400 return -1; 582 return -1;
401 } 583 }
402 lockdownd_client_free(lockdown); 584 lockdownd_client_free(lockdown);
403 585
404 /* connect to syslog_relay service */ 586 if (use_ostrace) {
405 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; 587 /* connect to os_trace_relay service */
406 serr = syslog_relay_client_new(device, svc, &syslog); 588 ostrace_error_t serr = OSTRACE_E_UNKNOWN_ERROR;
407 lockdownd_service_descriptor_free(svc); 589 serr = ostrace_client_new(device, svc, &ostrace);
408 if (serr != SYSLOG_RELAY_E_SUCCESS) { 590 lockdownd_service_descriptor_free(svc);
409 fprintf(stderr, "ERROR: Could not start service com.apple.syslog_relay.\n"); 591 if (serr != OSTRACE_E_SUCCESS) {
410 idevice_free(device); 592 fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
411 device = NULL; 593 idevice_free(device);
412 return -1; 594 device = NULL;
413 } 595 return -1;
596 }
414 597
415 /* start capturing syslog */ 598 serr = ostrace_start_activity(ostrace, NULL, ostrace_syslog_callback, NULL);
416 serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL); 599 if (serr != OSTRACE_E_SUCCESS) {
417 if (serr != SYSLOG_RELAY_E_SUCCESS) { 600 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
418 fprintf(stderr, "ERROR: Unable tot start capturing syslog.\n"); 601 ostrace_client_free(ostrace);
419 syslog_relay_client_free(syslog); 602 ostrace = NULL;
420 syslog = NULL; 603 idevice_free(device);
421 idevice_free(device); 604 device = NULL;
422 device = NULL; 605 return -1;
423 return -1; 606 }
607 } else {
608 /* connect to syslog_relay service */
609 syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR;
610 serr = syslog_relay_client_new(device, svc, &syslog);
611 lockdownd_service_descriptor_free(svc);
612 if (serr != SYSLOG_RELAY_E_SUCCESS) {
613 fprintf(stderr, "ERROR: Could not connect to %s service (%d)\n", service_name, serr);
614 idevice_free(device);
615 device = NULL;
616 return -1;
617 }
618
619 /* start capturing syslog */
620 serr = syslog_relay_start_capture_raw(syslog, syslog_callback, NULL);
621 if (serr != SYSLOG_RELAY_E_SUCCESS) {
622 fprintf(stderr, "ERROR: Unable to start capturing syslog.\n");
623 syslog_relay_client_free(syslog);
624 syslog = NULL;
625 idevice_free(device);
626 device = NULL;
627 return -1;
628 }
424 } 629 }
425 630
426 fprintf(stdout, "[connected:%s]\n", udid); 631 fprintf(stdout, "[connected:%s]\n", udid);
@@ -437,6 +642,11 @@ static void stop_logging(void)
437 syslog_relay_client_free(syslog); 642 syslog_relay_client_free(syslog);
438 syslog = NULL; 643 syslog = NULL;
439 } 644 }
645 if (ostrace) {
646 ostrace_stop_activity(ostrace);
647 ostrace_client_free(ostrace);
648 ostrace = NULL;
649 }
440 650
441 if (device) { 651 if (device) {
442 idevice_free(device); 652 idevice_free(device);
@@ -502,6 +712,7 @@ static void print_usage(int argc, char **argv, int is_error)
502 " -o, --output FILE write to FILE instead of stdout\n" 712 " -o, --output FILE write to FILE instead of stdout\n"
503 " (existing FILE will be overwritten)\n" 713 " (existing FILE will be overwritten)\n"
504 " --colors force writing colored output, e.g. for --output\n" 714 " --colors force writing colored output, e.g. for --output\n"
715 " --syslog_relay force use of syslog_relay service\n"
505 "\n" 716 "\n"
506 "FILTER OPTIONS:\n" 717 "FILTER OPTIONS:\n"
507 " -m, --match STRING only print messages that contain STRING\n" 718 " -m, --match STRING only print messages that contain STRING\n"
@@ -549,6 +760,7 @@ int main(int argc, char *argv[])
549 { "quiet-list", no_argument, NULL, 1 }, 760 { "quiet-list", no_argument, NULL, 1 },
550 { "no-colors", no_argument, NULL, 2 }, 761 { "no-colors", no_argument, NULL, 2 },
551 { "colors", no_argument, NULL, 3 }, 762 { "colors", no_argument, NULL, 3 },
763 { "syslog_relay", no_argument, NULL, 4 },
552 { "output", required_argument, NULL, 'o' }, 764 { "output", required_argument, NULL, 'o' },
553 { "version", no_argument, NULL, 'v' }, 765 { "version", no_argument, NULL, 'v' },
554 { NULL, 0, NULL, 0} 766 { NULL, 0, NULL, 0}
@@ -682,6 +894,9 @@ int main(int argc, char *argv[])
682 case 3: 894 case 3:
683 force_colors = 1; 895 force_colors = 1;
684 break; 896 break;
897 case 4:
898 force_syslog_relay = 1;
899 break;
685 case 'o': 900 case 'o':
686 if (!*optarg) { 901 if (!*optarg) {
687 fprintf(stderr, "ERROR: --output option requires an argument!\n"); 902 fprintf(stderr, "ERROR: --output option requires an argument!\n");