32
32
#include <stdio.h>
33
33
#include <stdlib.h>
34
34
#include <string.h>
35
- #include <sys/time.h>
36
35
#include <stdbool.h>
37
36
38
37
#include "backend.h"
41
40
#include "fetch.h"
42
41
#include "library.h"
43
42
#include "proc.h"
44
- #include "value_dict.h"
45
43
#include "prototype.h"
44
+ #include "summary.h"
45
+ #include "value_dict.h"
46
46
47
47
static void handle_signal (Event * event );
48
48
static void handle_exit (Event * event );
@@ -419,32 +419,11 @@ handle_signal(Event *event) {
419
419
continue_after_signal (event -> proc -> pid , event -> e_un .signum );
420
420
}
421
421
422
- static void
423
- handle_exit (Event * event ) {
424
- debug (DEBUG_FUNCTION , "handle_exit(pid=%d, status=%d)" , event -> proc -> pid , event -> e_un .ret_val );
425
- if (event -> proc -> state != STATE_IGNORED ) {
426
- output_line (event -> proc , "+++ exited (status %d) +++" ,
427
- event -> e_un .ret_val );
428
- }
429
- remove_process (event -> proc );
430
- }
431
-
432
- static void
433
- handle_exit_signal (Event * event ) {
434
- debug (DEBUG_FUNCTION , "handle_exit_signal(pid=%d, signum=%d)" , event -> proc -> pid , event -> e_un .signum );
435
- if (event -> proc -> state != STATE_IGNORED ) {
436
- output_line (event -> proc , "+++ killed by %s +++" ,
437
- shortsignal (event -> proc , event -> e_un .signum ));
438
- }
439
- remove_process (event -> proc );
440
- }
441
-
442
- static void
443
- output_syscall (struct process * proc , const char * name , enum tof tof ,
444
- void (* output )(enum tof , struct process * ,
445
- struct library_symbol * ))
422
+ static int
423
+ init_syscall_symbol (struct library_symbol * libsym , const char * name )
446
424
{
447
425
static struct library syscall_lib ;
426
+
448
427
if (syscall_lib .protolib == NULL ) {
449
428
struct protolib * protolib
450
429
= protolib_cache_load (& g_protocache , "syscalls" , 0 , 1 );
@@ -475,28 +454,111 @@ output_syscall(struct process *proc, const char *name, enum tof tof,
475
454
syscall_lib .protolib = protolib ;
476
455
}
477
456
457
+ if (library_symbol_init (libsym , 0 , name , 0 , LS_TOPLT_NONE ) < 0 )
458
+ return -1 ;
459
+
460
+ libsym -> lib = & syscall_lib ;
461
+ return 0 ;
462
+ }
463
+
464
+ /* Account the unfinished functions on the call stack. */
465
+ static void
466
+ account_current_callstack (struct process * proc )
467
+ {
468
+ if (! options .summary )
469
+ return ;
470
+
471
+ struct timedelta spent [proc -> callstack_depth ];
472
+
473
+ size_t i ;
474
+ for (i = 0 ; i < proc -> callstack_depth ; ++ i ) {
475
+ struct callstack_element * elem = & proc -> callstack [i ];
476
+ spent [i ] = calc_time_spent (elem -> enter_time );
477
+ }
478
+
479
+ for (i = 0 ; i < proc -> callstack_depth ; ++ i ) {
480
+ struct callstack_element * elem = & proc -> callstack [i ];
481
+ struct library_symbol syscall , * libsym = NULL ;
482
+ if (elem -> is_syscall ) {
483
+ const char * name = sysname (proc , elem -> c_un .syscall );
484
+ if (init_syscall_symbol (& syscall , name ) >= 0 )
485
+ libsym = & syscall ;
486
+
487
+ } else {
488
+ libsym = elem -> c_un .libfunc ;
489
+ }
490
+
491
+ if (libsym != NULL ) {
492
+ summary_account_call (libsym , spent [i ]);
493
+
494
+ if (elem -> is_syscall )
495
+ library_symbol_destroy (& syscall );
496
+ }
497
+ }
498
+ }
499
+
500
+ static void
501
+ handle_exit (Event * event ) {
502
+ debug (DEBUG_FUNCTION , "handle_exit(pid=%d, status=%d)" , event -> proc -> pid , event -> e_un .ret_val );
503
+ if (event -> proc -> state != STATE_IGNORED ) {
504
+ output_line (event -> proc , "+++ exited (status %d) +++" ,
505
+ event -> e_un .ret_val );
506
+ }
507
+
508
+ account_current_callstack (event -> proc );
509
+ remove_process (event -> proc );
510
+ }
511
+
512
+ static void
513
+ handle_exit_signal (Event * event ) {
514
+ debug (DEBUG_FUNCTION , "handle_exit_signal(pid=%d, signum=%d)" , event -> proc -> pid , event -> e_un .signum );
515
+ if (event -> proc -> state != STATE_IGNORED ) {
516
+ output_line (event -> proc , "+++ killed by %s +++" ,
517
+ shortsignal (event -> proc , event -> e_un .signum ));
518
+ }
519
+
520
+ account_current_callstack (event -> proc );
521
+ remove_process (event -> proc );
522
+ }
523
+
524
+ static void
525
+ output_syscall (struct process * proc , const char * name , enum tof tof ,
526
+ bool left , struct timedelta * spent )
527
+ {
528
+ if (left )
529
+ assert (spent == NULL );
530
+
478
531
struct library_symbol syscall ;
479
- if (library_symbol_init (& syscall , 0 , name , 0 , LS_TOPLT_NONE ) >= 0 ) {
480
- syscall .lib = & syscall_lib ;
481
- (* output )(tof , proc , & syscall );
532
+ if (init_syscall_symbol (& syscall , name ) >= 0 ) {
533
+ if (left ) {
534
+ if (! options .summary )
535
+ output_left (tof , proc , & syscall );
536
+ } else if (options .summary ) {
537
+ summary_account_call (& syscall , * spent );
538
+ } else {
539
+ output_right (tof , proc , & syscall , spent );
540
+ }
541
+
482
542
library_symbol_destroy (& syscall );
483
543
}
484
544
}
485
545
486
546
static void
487
547
output_syscall_left (struct process * proc , const char * name )
488
548
{
489
- output_syscall (proc , name , LT_TOF_SYSCALL , & output_left );
549
+ output_syscall (proc , name , LT_TOF_SYSCALL , true, NULL );
490
550
}
491
551
492
552
static void
493
- output_syscall_right (struct process * proc , const char * name )
553
+ output_syscall_right (struct process * proc , const char * name ,
554
+ struct timedelta * spent )
494
555
{
495
- output_syscall (proc , name , LT_TOF_SYSCALLR , & output_right );
556
+ output_syscall (proc , name , LT_TOF_SYSCALLR , false, spent );
496
557
}
497
558
498
559
static void
499
- handle_syscall (Event * event ) {
560
+ handle_syscall (Event * event )
561
+ {
500
562
debug (DEBUG_FUNCTION , "handle_syscall(pid=%d, sysnum=%d)" , event -> proc -> pid , event -> e_un .sysnum );
501
563
if (event -> proc -> state != STATE_IGNORED ) {
502
564
callstack_push_syscall (event -> proc , event -> e_un .sysnum );
@@ -526,6 +588,8 @@ handle_exec(Event *event)
526
588
}
527
589
output_line (proc , "--- Called exec() ---" );
528
590
591
+ account_current_callstack (proc );
592
+
529
593
if (process_exec (proc ) < 0 ) {
530
594
fprintf (stderr ,
531
595
"couldn't reinitialize process %d after exec\n" , pid );
@@ -549,74 +613,58 @@ handle_arch_syscall(Event *event) {
549
613
continue_process (event -> proc -> pid );
550
614
}
551
615
552
- struct timeval current_time_spent ;
553
-
554
616
static void
555
- calc_time_spent ( struct process * proc )
617
+ handle_x_sysret ( Event * event , char * ( * name_cb )( struct process * , int ) )
556
618
{
557
- struct timeval tv ;
558
- struct timezone tz ;
559
- struct timeval diff ;
560
- struct callstack_element * elem ;
561
-
562
- debug (DEBUG_FUNCTION , "calc_time_spent(pid=%d)" , proc -> pid );
563
- elem = & proc -> callstack [proc -> callstack_depth - 1 ];
564
-
565
- gettimeofday (& tv , & tz );
619
+ debug (DEBUG_FUNCTION , "handle_x_sysret(pid=%d, sysnum=%d)" ,
620
+ event -> proc -> pid , event -> e_un .sysnum );
566
621
567
- diff .tv_sec = tv .tv_sec - elem -> time_spent .tv_sec ;
568
- if (tv .tv_usec >= elem -> time_spent .tv_usec ) {
569
- diff .tv_usec = tv .tv_usec - elem -> time_spent .tv_usec ;
570
- } else {
571
- diff .tv_sec -- ;
572
- diff .tv_usec = 1000000 + tv .tv_usec - elem -> time_spent .tv_usec ;
573
- }
574
- current_time_spent = diff ;
575
- }
622
+ unsigned d = event -> proc -> callstack_depth ;
623
+ assert (d > 0 );
624
+ struct callstack_element * elem = & event -> proc -> callstack [d - 1 ];
625
+ assert (elem -> is_syscall );
576
626
577
- static void
578
- handle_sysret (Event * event ) {
579
- debug (DEBUG_FUNCTION , "handle_sysret(pid=%d, sysnum=%d)" , event -> proc -> pid , event -> e_un .sysnum );
580
627
if (event -> proc -> state != STATE_IGNORED ) {
581
- if (opt_T || options .summary ) {
582
- calc_time_spent (event -> proc );
583
- }
628
+ struct timedelta spent = calc_time_spent (elem -> enter_time );
584
629
if (options .syscalls )
585
630
output_syscall_right (event -> proc ,
586
- sysname (event -> proc ,
587
- event -> e_un .sysnum ));
631
+ name_cb (event -> proc ,
632
+ event -> e_un .sysnum ),
633
+ & spent );
588
634
589
- assert (event -> proc -> callstack_depth > 0 );
590
- unsigned d = event -> proc -> callstack_depth - 1 ;
591
- assert (event -> proc -> callstack [d ].is_syscall );
592
635
callstack_pop (event -> proc );
593
636
}
594
637
continue_after_syscall (event -> proc , event -> e_un .sysnum , 1 );
595
638
}
596
639
597
640
static void
598
- handle_arch_sysret (Event * event ) {
599
- debug (DEBUG_FUNCTION , "handle_arch_sysret(pid=%d, sysnum=%d)" , event -> proc -> pid , event -> e_un .sysnum );
600
- if (event -> proc -> state != STATE_IGNORED ) {
601
- if (opt_T || options .summary ) {
602
- calc_time_spent (event -> proc );
603
- }
604
- if (options .syscalls )
605
- output_syscall_right (event -> proc ,
606
- arch_sysname (event -> proc ,
607
- event -> e_un .sysnum ));
608
- callstack_pop (event -> proc );
609
- }
610
- continue_process (event -> proc -> pid );
641
+ handle_sysret (Event * event )
642
+ {
643
+ handle_x_sysret (event , & sysname );
644
+ }
645
+
646
+ static void
647
+ handle_arch_sysret (Event * event )
648
+ {
649
+ handle_x_sysret (event , & arch_sysname );
611
650
}
612
651
613
652
static void
614
653
output_right_tos (struct process * proc )
615
654
{
616
655
size_t d = proc -> callstack_depth ;
656
+ assert (d > 0 );
617
657
struct callstack_element * elem = & proc -> callstack [d - 1 ];
618
- if (proc -> state != STATE_IGNORED )
619
- output_right (LT_TOF_FUNCTIONR , proc , elem -> c_un .libfunc );
658
+ assert (! elem -> is_syscall );
659
+
660
+ if (proc -> state != STATE_IGNORED ) {
661
+ struct timedelta spent = calc_time_spent (elem -> enter_time );
662
+ if (options .summary )
663
+ summary_account_call (elem -> c_un .libfunc , spent );
664
+ else
665
+ output_right (LT_TOF_FUNCTIONR , proc , elem -> c_un .libfunc ,
666
+ & spent );
667
+ }
620
668
}
621
669
622
670
#ifndef ARCH_HAVE_SYMBOL_RET
@@ -645,14 +693,8 @@ handle_breakpoint(Event *event)
645
693
646
694
for (i = event -> proc -> callstack_depth - 1 ; i >= 0 ; i -- ) {
647
695
if (brk_addr == event -> proc -> callstack [i ].return_addr ) {
648
- for (j = event -> proc -> callstack_depth - 1 ; j > i ; j -- ) {
696
+ for (j = event -> proc -> callstack_depth - 1 ; j > i ; j -- )
649
697
callstack_pop (event -> proc );
650
- }
651
- if (event -> proc -> state != STATE_IGNORED ) {
652
- if (opt_T || options .summary ) {
653
- calc_time_spent (event -> proc );
654
- }
655
- }
656
698
657
699
struct library_symbol * libsym =
658
700
event -> proc -> callstack [i ].c_un .libfunc ;
@@ -705,11 +747,14 @@ handle_breakpoint(Event *event)
705
747
/* breakpoint_on_hit may delete its own breakpoint, so we have
706
748
* to look it up again. */
707
749
if ((sbp = address2bpstruct (leader , brk_addr )) != NULL ) {
750
+
708
751
if (event -> proc -> state != STATE_IGNORED
709
752
&& sbp -> libsym != NULL ) {
710
753
event -> proc -> stack_pointer = get_stack_pointer (event -> proc );
711
754
callstack_push_symfunc (event -> proc , sbp );
712
- output_left (LT_TOF_FUNCTION , event -> proc , sbp -> libsym );
755
+ if (! options .summary )
756
+ output_left (LT_TOF_FUNCTION , event -> proc ,
757
+ sbp -> libsym );
713
758
}
714
759
715
760
breakpoint_on_continue (sbp , event -> proc );
@@ -743,7 +788,7 @@ callstack_push_syscall(struct process *proc, int sysnum)
743
788
proc -> callstack_depth ++ ;
744
789
if (opt_T || options .summary ) {
745
790
struct timezone tz ;
746
- gettimeofday (& elem -> time_spent , & tz );
791
+ gettimeofday (& elem -> enter_time , & tz );
747
792
}
748
793
}
749
794
@@ -781,7 +826,7 @@ callstack_push_symfunc(struct process *proc, struct breakpoint *bp)
781
826
782
827
if (opt_T || options .summary ) {
783
828
struct timezone tz ;
784
- gettimeofday (& elem -> time_spent , & tz );
829
+ gettimeofday (& elem -> enter_time , & tz );
785
830
}
786
831
}
787
832
0 commit comments