1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <ctype.h>
30 #include <string.h>
31 #include <sys/param.h>
32 #include <stdlib.h>
33 #include "conv.h"
34 #include "gprof.h"
35
36 void print_demangled_name(int, nltype *);
37 void striped_name(char *, nltype **);
38
39 extern long hz;
40
41 /*
42 * Symbols that must never be printed, no matter what.
43 */
44 char *splsym[] = {
45 PRF_ETEXT,
46 PRF_EXTSYM,
47 PRF_MEMTERM,
48 NULL
49 };
50
51 static bool is_special_sym(nltype *nlp);
52
53 const char *
demangled_name(nltype * selfp)54 demangled_name(nltype *selfp)
55 {
56 if (!Cflag)
57 return (selfp->name);
58
59 return (conv_demangle_name(selfp->name));
60 }
61
62 void
printprof(void)63 printprof(void)
64 {
65 nltype *np;
66 nltype **sortednlp;
67 int i, index;
68 int print_count = number_funcs_toprint;
69 bool print_flag = TRUE;
70 mod_info_t *mi;
71
72 actime = 0.0;
73 (void) printf("\f\n");
74 flatprofheader();
75
76 /*
77 * Sort the symbol table in by time
78 */
79 sortednlp = (nltype **) calloc(total_names, sizeof (nltype *));
80 if (sortednlp == (nltype **) 0) {
81 (void) fprintf(stderr,
82 "[printprof] ran out of memory for time sorting\n");
83 }
84
85 index = 0;
86 for (mi = &modules; mi; mi = mi->next) {
87 for (i = 0; i < mi->nname; i++)
88 sortednlp[index++] = &(mi->nl[i]);
89 }
90
91 qsort(sortednlp, total_names, sizeof (nltype *), timecmp);
92
93 for (index = 0; (index < total_names) && print_flag; index += 1) {
94 np = sortednlp[index];
95 flatprofline(np);
96 if (nflag) {
97 if (--print_count == 0)
98 print_flag = FALSE;
99 }
100 }
101 actime = 0.0;
102 free(sortednlp);
103 }
104
105 int
timecmp(const void * arg1,const void * arg2)106 timecmp(const void *arg1, const void *arg2)
107 {
108 nltype **npp1 = (nltype **)arg1;
109 nltype **npp2 = (nltype **)arg2;
110 double timediff;
111 long calldiff;
112
113 timediff = (*npp2)->time - (*npp1)->time;
114
115 if (timediff > 0.0)
116 return (1);
117
118 if (timediff < 0.0)
119 return (-1);
120
121 calldiff = (*npp2)->ncall - (*npp1)->ncall;
122
123 if (calldiff > 0)
124 return (1);
125
126 if (calldiff < 0)
127 return (-1);
128
129 return (strcmp((*npp1)->name, (*npp2)->name));
130 }
131
132 /*
133 * header for flatprofline
134 */
135 void
flatprofheader()136 flatprofheader()
137 {
138
139 if (bflag)
140 printblurb(FLAT_BLURB);
141
142 if (old_style) {
143 (void) printf(
144 "\ngranularity: each sample hit covers %d byte(s)",
145 (long)scale * sizeof (UNIT));
146 if (totime > 0.0) {
147 (void) printf(" for %.2f%% of %.2f seconds\n\n",
148 100.0/totime, totime / hz);
149 } else {
150 (void) printf(" no time accumulated\n\n");
151 /*
152 * this doesn't hurt since all the numerators will
153 * be zero.
154 */
155 totime = 1.0;
156 }
157 }
158
159 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
160 "% ", "cumulative", "self ", "", "self ", "total ", "");
161 (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
162 "time", "seconds ", "seconds", "calls",
163 "ms/call", "ms/call", "name");
164 }
165
166 void
flatprofline(nltype * np)167 flatprofline(nltype *np)
168 {
169 if (zflag == 0 && np->ncall == 0 && np->time == 0)
170 return;
171
172 /*
173 * Do not print certain special symbols, like PRF_EXTSYM, etc.
174 * even if zflag was on.
175 */
176 if (is_special_sym(np))
177 return;
178
179 actime += np->time;
180
181 (void) printf("%5.1f %10.2f %8.2f",
182 100 * np->time / totime, actime / hz, np->time / hz);
183
184 if (np->ncall != 0) {
185 (void) printf(" %8lld %8.2f %8.2f ", np->ncall,
186 1000 * np->time / hz / np->ncall,
187 1000 * (np->time + np->childtime) / hz / np->ncall);
188 } else {
189 if (!Cflag)
190 (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
191 else
192 (void) printf(" %8.8s %8.8s %8.8s ", "", "", "");
193 }
194
195 printname(np);
196
197 if (Cflag)
198 print_demangled_name(55, np);
199
200 (void) printf("\n");
201 }
202
203 void
gprofheader()204 gprofheader()
205 {
206
207 if (bflag)
208 printblurb(CALLG_BLURB);
209
210 if (old_style) {
211
212 (void) printf(
213 "\ngranularity: each sample hit covers %d byte(s)",
214 (long)scale * sizeof (UNIT));
215
216 if (printtime > 0.0) {
217 (void) printf(" for %.2f%% of %.2f seconds\n\n",
218 100.0/printtime, printtime / hz);
219 } else {
220 (void) printf(" no time propagated\n\n");
221 /*
222 * this doesn't hurt, since all the numerators
223 * will be 0.0
224 */
225 printtime = 1.0;
226 }
227 } else {
228 (void) printf(
229 "\ngranularity: each pc-hit is considered 1 tick");
230 if (hz != 1) {
231 (void) printf(" (@ %4.3f seconds per tick)",
232 (double)1.0 / hz);
233 }
234 (void) puts("\n\n");
235 }
236
237 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
238 "", "", "", "", "called", "total", "parents");
239 (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
240 "index", "%time", "self", "descendents",
241 "called", "self", "name", "index");
242 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
243 "", "", "", "", "called", "total", "children");
244 (void) printf("\n");
245 }
246
247 void
gprofline(nltype * np)248 gprofline(nltype *np)
249 {
250 char kirkbuffer[BUFSIZ];
251
252 (void) sprintf(kirkbuffer, "[%d]", np->index);
253 (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer,
254 100 * (np->propself + np->propchild) / printtime,
255 np->propself / hz, np->propchild / hz);
256
257 if ((np->ncall + np->selfcalls) != 0) {
258 (void) printf(" %7lld", np->ncall);
259
260 if (np->selfcalls != 0)
261 (void) printf("+%-7lld ", np->selfcalls);
262 else
263 (void) printf(" %7.7s ", "");
264 } else {
265 (void) printf(" %7.7s %7.7s ", "", "");
266 }
267
268 printname(np);
269
270 if (Cflag)
271 print_demangled_name(50, np);
272
273 (void) printf("\n");
274 }
275
276 static bool
is_special_sym(nltype * nlp)277 is_special_sym(nltype *nlp)
278 {
279 int i;
280
281 if (nlp->name == NULL)
282 return (FALSE);
283
284 for (i = 0; splsym[i]; i++)
285 if (strcmp(splsym[i], nlp->name) == 0)
286 return (TRUE);
287
288 return (FALSE);
289 }
290
291 void
printgprof(nltype ** timesortnlp)292 printgprof(nltype **timesortnlp)
293 {
294 int index;
295 nltype *parentp;
296 int print_count = number_funcs_toprint;
297 bool count_flag = TRUE;
298
299 /*
300 * Print out the structured profiling list
301 */
302 gprofheader();
303
304 for (index = 0; index < total_names + ncycle && count_flag; index++) {
305 parentp = timesortnlp[index];
306 if (zflag == 0 && parentp->ncall == 0 &&
307 parentp->selfcalls == 0 && parentp->propself == 0 &&
308 parentp -> propchild == 0)
309 continue;
310
311 if (!parentp->printflag)
312 continue;
313
314 /*
315 * Do not print certain special symbols, like PRF_EXTSYM, etc.
316 * even if zflag was on.
317 */
318 if (is_special_sym(parentp))
319 continue;
320
321 if (parentp->name == 0 && parentp->cycleno != 0) {
322 /*
323 * cycle header
324 */
325 printcycle(parentp);
326 printmembers(parentp);
327 } else {
328 printparents(parentp);
329 gprofline(parentp);
330 printchildren(parentp);
331 }
332
333 (void) printf("\n");
334 (void) printf(
335 "-----------------------------------------------\n");
336 (void) printf("\n");
337
338 if (nflag) {
339 --print_count;
340 if (print_count == 0)
341 count_flag = FALSE;
342 }
343 }
344 free(timesortnlp);
345 }
346
347 /*
348 * sort by decreasing propagated time
349 * if times are equal, but one is a cycle header,
350 * say that's first (e.g. less, i.e. -1).
351 * if one's name doesn't have an underscore and the other does,
352 * say the one is first.
353 * all else being equal, sort by names.
354 */
355 int
totalcmp(const void * arg1,const void * arg2)356 totalcmp(const void *arg1, const void *arg2)
357 {
358 nltype **npp1 = (nltype **)arg1;
359 nltype **npp2 = (nltype **)arg2;
360 nltype *np1 = *npp1;
361 nltype *np2 = *npp2;
362 double diff;
363
364 diff = (np1->propself + np1->propchild) -
365 (np2->propself + np2->propchild);
366
367 if (diff < 0.0)
368 return (1);
369 if (diff > 0.0)
370 return (-1);
371 if (np1->name == 0 && np1->cycleno != 0)
372 return (-1);
373 if (np2->name == 0 && np2->cycleno != 0)
374 return (1);
375 if (np1->name == 0)
376 return (-1);
377 if (np2->name == 0)
378 return (1);
379
380 if (*(np1->name) != '_' && *(np2->name) == '_')
381 return (-1);
382 if (*(np1->name) == '_' && *(np2->name) != '_')
383 return (1);
384 if (np1->ncall > np2->ncall)
385 return (-1);
386 if (np1->ncall < np2->ncall)
387 return (1);
388 return (strcmp(np1->name, np2->name));
389 }
390
391 void
printparents(nltype * childp)392 printparents(nltype *childp)
393 {
394 nltype *parentp;
395 arctype *arcp;
396 nltype *cycleheadp;
397
398 if (childp->cyclehead != 0)
399 cycleheadp = childp -> cyclehead;
400 else
401 cycleheadp = childp;
402
403 if (childp->parents == 0) {
404 (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
405 " <spontaneous>\n", "", "", "", "", "", "");
406 return;
407 }
408
409 sortparents(childp);
410
411 for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) {
412 parentp = arcp -> arc_parentp;
413 if (childp == parentp || (childp->cycleno != 0 &&
414 parentp->cycleno == childp->cycleno)) {
415 /*
416 * selfcall or call among siblings
417 */
418 (void) printf(
419 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
420 "", "", "", "", arcp->arc_count, "");
421 printname(parentp);
422
423 if (Cflag)
424 print_demangled_name(54, parentp);
425
426 (void) printf("\n");
427 } else {
428 /*
429 * regular parent of child
430 */
431 (void) printf(
432 "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "",
433 "", arcp->arc_time / hz, arcp->arc_childtime / hz,
434 arcp->arc_count, cycleheadp->ncall);
435 printname(parentp);
436
437 if (Cflag)
438 print_demangled_name(54, parentp);
439
440 (void) printf("\n");
441 }
442 }
443 }
444
445 void
printchildren(nltype * parentp)446 printchildren(nltype *parentp)
447 {
448 nltype *childp;
449 arctype *arcp;
450
451 sortchildren(parentp);
452
453 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
454 childp = arcp->arc_childp;
455 if (childp == parentp || (childp->cycleno != 0 &&
456 childp->cycleno == parentp->cycleno)) {
457 /*
458 * self call or call to sibling
459 */
460 (void) printf(
461 "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
462 "", "", "", "", arcp->arc_count, "");
463 printname(childp);
464
465 if (Cflag)
466 print_demangled_name(54, childp);
467
468 (void) printf("\n");
469 } else {
470 /*
471 * regular child of parent
472 */
473 if (childp->cyclehead)
474 (void) printf("%6.6s %5.5s %7.2f %11.2f "
475 "%7lld/%-7lld ", "", "",
476 arcp->arc_time / hz,
477 arcp->arc_childtime / hz, arcp->arc_count,
478 childp->cyclehead->ncall);
479 else
480 (void) printf("%6.6s %5.5s %7.2f %11.2f "
481 "%7lld %7.7s ",
482 "", "", arcp->arc_time / hz,
483 arcp->arc_childtime / hz, arcp->arc_count,
484 "");
485
486 printname(childp);
487
488 if (Cflag)
489 print_demangled_name(54, childp);
490
491 (void) printf("\n");
492 }
493 }
494 }
495
496 void
printname(nltype * selfp)497 printname(nltype *selfp)
498 {
499 const char *c;
500 c = demangled_name(selfp);
501
502 if (selfp->name != 0) {
503 if (!Cflag)
504 (void) printf("%s", selfp->name);
505 else
506 (void) printf("%s", c);
507
508 #ifdef DEBUG
509 if (debug & DFNDEBUG)
510 (void) printf("{%d} ", selfp->toporder);
511
512 if (debug & PROPDEBUG)
513 (void) printf("%5.2f%% ", selfp->propfraction);
514 #endif /* DEBUG */
515 }
516
517 if (selfp->cycleno != 0)
518 (void) printf("\t<cycle %d>", selfp->cycleno);
519
520 if (selfp->index != 0) {
521 if (selfp->printflag)
522 (void) printf(" [%d]", selfp->index);
523 else
524 (void) printf(" (%d)", selfp->index);
525 }
526 }
527
528 void
print_demangled_name(int n,nltype * selfp)529 print_demangled_name(int n, nltype *selfp)
530 {
531 char *c;
532 int i;
533
534 c = selfp->name;
535
536 if (strcmp(c, demangled_name(selfp)) == 0)
537 return;
538 else {
539 (void) printf("\n");
540 for (i = 1; i < n; i++)
541 (void) printf(" ");
542 (void) printf("[%s]", selfp->name);
543 }
544 }
545
546 void
sortchildren(nltype * parentp)547 sortchildren(nltype *parentp)
548 {
549 arctype *arcp;
550 arctype *detachedp;
551 arctype sorted;
552 arctype *prevp;
553
554 /*
555 * unlink children from parent,
556 * then insertion sort back on to sorted's children.
557 * *arcp the arc you have detached and are inserting.
558 * *detachedp the rest of the arcs to be sorted.
559 * sorted arc list onto which you insertion sort.
560 * *prevp arc before the arc you are comparing.
561 */
562 sorted.arc_childlist = 0;
563
564 /* LINTED: warning: assignment operator */
565 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
566 arcp;
567 /* LINTED: warning: assignment operator */
568 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) {
569 /*
570 * consider *arcp as disconnected
571 * insert it into sorted
572 */
573 for (prevp = &sorted; prevp->arc_childlist;
574 prevp = prevp->arc_childlist) {
575 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
576 break;
577 }
578
579 arcp->arc_childlist = prevp->arc_childlist;
580 prevp->arc_childlist = arcp;
581 }
582
583 /*
584 * reattach sorted children to parent
585 */
586 parentp->children = sorted.arc_childlist;
587 }
588
589 void
sortparents(nltype * childp)590 sortparents(nltype *childp)
591 {
592 arctype *arcp;
593 arctype *detachedp;
594 arctype sorted;
595 arctype *prevp;
596
597 /*
598 * unlink parents from child,
599 * then insertion sort back on to sorted's parents.
600 * *arcp the arc you have detached and are inserting.
601 * *detachedp the rest of the arcs to be sorted.
602 * sorted arc list onto which you insertion sort.
603 * *prevp arc before the arc you are comparing.
604 */
605 sorted.arc_parentlist = 0;
606
607 /* LINTED: warning: assignment operator */
608 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
609 arcp;
610 /* LINTED: warning: assignment operator */
611 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) {
612 /*
613 * consider *arcp as disconnected
614 * insert it into sorted
615 */
616 for (prevp = &sorted; prevp->arc_parentlist;
617 prevp = prevp->arc_parentlist) {
618 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
619 break;
620 }
621 arcp->arc_parentlist = prevp->arc_parentlist;
622 prevp->arc_parentlist = arcp;
623 }
624
625 /*
626 * reattach sorted arcs to child
627 */
628 childp->parents = sorted.arc_parentlist;
629 }
630
631 void
printcycle(nltype * cyclep)632 printcycle(nltype *cyclep)
633 {
634 char kirkbuffer[BUFSIZ];
635
636 (void) sprintf(kirkbuffer, "[%d]", cyclep->index);
637 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
638 100 * (cyclep->propself + cyclep->propchild) / printtime,
639 cyclep -> propself / hz, cyclep -> propchild / hz,
640 cyclep -> ncall);
641
642 if (cyclep->selfcalls != 0)
643 (void) printf("+%-7lld", cyclep->selfcalls);
644 else
645 (void) printf(" %7.7s", "");
646
647 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
648 cyclep->index);
649 }
650
651 /*
652 * print the members of a cycle
653 */
654 void
printmembers(nltype * cyclep)655 printmembers(nltype *cyclep)
656 {
657 nltype *memberp;
658
659 sortmembers(cyclep);
660
661 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
662 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
663 memberp->propself / hz, memberp->propchild / hz,
664 memberp->ncall);
665
666 if (memberp->selfcalls != 0)
667 (void) printf("+%-7lld", memberp->selfcalls);
668 else
669 (void) printf(" %7.7s", "");
670
671 (void) printf(" ");
672 printname(memberp);
673 if (Cflag)
674 print_demangled_name(54, memberp);
675 (void) printf("\n");
676 }
677 }
678
679 /*
680 * sort members of a cycle
681 */
682 void
sortmembers(nltype * cyclep)683 sortmembers(nltype *cyclep)
684 {
685 nltype *todo;
686 nltype *doing;
687 nltype *prev;
688
689 /*
690 * detach cycle members from cyclehead,
691 * and insertion sort them back on.
692 */
693 todo = cyclep->cnext;
694 cyclep->cnext = 0;
695
696 /* LINTED: warning: assignment operator */
697 for ((doing = todo) && (todo = doing->cnext);
698 doing;
699 /* LINTED: warning: assignment operator */
700 (doing = todo) && (todo = doing->cnext)) {
701 for (prev = cyclep; prev->cnext; prev = prev->cnext) {
702 if (membercmp(doing, prev->cnext) == GREATERTHAN)
703 break;
704 }
705 doing->cnext = prev->cnext;
706 prev->cnext = doing;
707 }
708 }
709
710 /*
711 * major sort is on propself + propchild,
712 * next is sort on ncalls + selfcalls.
713 */
714 int
membercmp(nltype * this,nltype * that)715 membercmp(nltype *this, nltype *that)
716 {
717 double thistime = this->propself + this->propchild;
718 double thattime = that->propself + that->propchild;
719 actype thiscalls = this->ncall + this->selfcalls;
720 actype thatcalls = that->ncall + that->selfcalls;
721
722 if (thistime > thattime)
723 return (GREATERTHAN);
724
725 if (thistime < thattime)
726 return (LESSTHAN);
727
728 if (thiscalls > thatcalls)
729 return (GREATERTHAN);
730
731 if (thiscalls < thatcalls)
732 return (LESSTHAN);
733
734 return (EQUALTO);
735 }
736
737 /*
738 * compare two arcs to/from the same child/parent.
739 * - if one arc is a self arc, it's least.
740 * - if one arc is within a cycle, it's less than.
741 * - if both arcs are within a cycle, compare arc counts.
742 * - if neither arc is within a cycle, compare with
743 * arc_time + arc_childtime as major key
744 * arc count as minor key
745 */
746 int
arccmp(arctype * thisp,arctype * thatp)747 arccmp(arctype *thisp, arctype *thatp)
748 {
749 nltype *thisparentp = thisp->arc_parentp;
750 nltype *thischildp = thisp->arc_childp;
751 nltype *thatparentp = thatp->arc_parentp;
752 nltype *thatchildp = thatp->arc_childp;
753 double thistime;
754 double thattime;
755
756 #ifdef DEBUG
757 if (debug & TIMEDEBUG) {
758 (void) printf("[arccmp] ");
759 printname(thisparentp);
760 (void) printf(" calls ");
761 printname(thischildp);
762 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time,
763 thisp->arc_childtime, thisp->arc_count,
764 thischildp->ncall);
765 (void) printf("[arccmp] ");
766 printname(thatparentp);
767 (void) printf(" calls ");
768 printname(thatchildp);
769 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time,
770 thatp->arc_childtime, thatp->arc_count,
771 thatchildp->ncall);
772 (void) printf("\n");
773 }
774 #endif /* DEBUG */
775
776 if (thisparentp == thischildp) {
777 /*
778 * this is a self call
779 */
780 return (LESSTHAN);
781 }
782
783 if (thatparentp == thatchildp) {
784 /*
785 * that is a self call
786 */
787 return (GREATERTHAN);
788 }
789
790 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
791 thisparentp->cycleno == thischildp->cycleno) {
792 /*
793 * this is a call within a cycle
794 */
795 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
796 thatparentp->cycleno == thatchildp->cycleno) {
797 /*
798 * that is a call within the cycle, too
799 */
800 if (thisp->arc_count < thatp->arc_count)
801 return (LESSTHAN);
802
803 if (thisp->arc_count > thatp->arc_count)
804 return (GREATERTHAN);
805
806 return (EQUALTO);
807 } else {
808 /*
809 * that isn't a call within the cycle
810 */
811 return (LESSTHAN);
812 }
813 } else {
814 /*
815 * this isn't a call within a cycle
816 */
817 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
818 thatparentp->cycleno == thatchildp->cycleno) {
819 /*
820 * that is a call within a cycle
821 */
822 return (GREATERTHAN);
823 } else {
824 /*
825 * neither is a call within a cycle
826 */
827 thistime = thisp->arc_time + thisp->arc_childtime;
828 thattime = thatp->arc_time + thatp->arc_childtime;
829
830 if (thistime < thattime)
831 return (LESSTHAN);
832
833 if (thistime > thattime)
834 return (GREATERTHAN);
835
836 if (thisp->arc_count < thatp->arc_count)
837 return (LESSTHAN);
838
839 if (thisp->arc_count > thatp->arc_count)
840 return (GREATERTHAN);
841
842 return (EQUALTO);
843 }
844 }
845 }
846
847 void
printblurb(char * blurbname)848 printblurb(char *blurbname)
849 {
850 FILE *blurbfile;
851 int input;
852
853 blurbfile = fopen(blurbname, "r");
854 if (blurbfile == NULL) {
855 perror(blurbname);
856 return;
857 }
858
859 while ((input = getc(blurbfile)) != EOF)
860 (void) putchar(input);
861
862 (void) fclose(blurbfile);
863 }
864
865 char *s1, *s2;
866
867 static int
namecmp(const void * arg1,const void * arg2)868 namecmp(const void *arg1, const void *arg2)
869 {
870 nltype **npp1 = (nltype **)arg1;
871 nltype **npp2 = (nltype **)arg2;
872
873 if (!Cflag)
874 return (strcmp((*npp1)->name, (*npp2)->name));
875 else {
876 striped_name(s1, npp1);
877 striped_name(s2, npp2);
878 return (strcmp(s1, s2));
879 }
880 }
881
882 void
striped_name(char * s,nltype ** npp)883 striped_name(char *s, nltype **npp)
884 {
885 const char *d;
886 char *c;
887
888 c = (char *)s;
889 d = demangled_name(*npp);
890
891 while ((*d != '(') && (*d != '\0')) {
892 if (*d != ':')
893 *c++ = *d++;
894 else
895 d++;
896 }
897 *c = '\0';
898 }
899
900 /*
901 * Checks if the current symbol name is the same as its neighbour and
902 * returns TRUE if it is.
903 */
904 static bool
does_clash(nltype ** nlp,int ndx,int nnames)905 does_clash(nltype **nlp, int ndx, int nnames)
906 {
907 /*
908 * same as previous (if there's one) ?
909 */
910 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
911 return (TRUE);
912
913 /*
914 * same as next (if there's one) ?
915 */
916 if ((ndx < (nnames - 1)) &&
917 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
918 return (TRUE);
919 }
920
921 return (FALSE);
922 }
923
924 void
printmodules()925 printmodules()
926 {
927 mod_info_t *mi;
928
929 (void) printf("\f\nObject modules\n\n");
930 for (mi = &modules; mi; mi = mi->next)
931 (void) printf(" %d: %s\n", mi->id, mi->name);
932 }
933
934 #define IDFMT(id) ((id) < 10 ? 1 : 2)
935 #define NMFMT(id) ((id) < 10 ? 17 : 16)
936
937 void
printindex()938 printindex()
939 {
940 nltype **namesortnlp;
941 nltype *nlp;
942 int index, nnames, todo, i, j;
943 char peterbuffer[BUFSIZ];
944 mod_info_t *mi;
945
946 /*
947 * Now, sort regular function name alphabetically
948 * to create an index.
949 */
950 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
951
952 if (namesortnlp == NULL)
953 (void) fprintf(stderr, "%s: ran out of memory for sorting\n",
954 whoami);
955
956 nnames = 0;
957 for (mi = &modules; mi; mi = mi->next) {
958 for (index = 0; index < mi->nname; index++) {
959 if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
960 (mi->nl[index]).time == 0) {
961 continue;
962 }
963
964 /*
965 * Do not print certain special symbols, like
966 * PRF_EXTSYM, etc. even if zflag was on.
967 */
968 if (is_special_sym(&(mi->nl[index])))
969 continue;
970
971 namesortnlp[nnames++] = &(mi->nl[index]);
972 }
973 }
974
975 if (Cflag) {
976 s1 = malloc(500 * sizeof (char));
977 s2 = malloc(500 * sizeof (char));
978 }
979
980 qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
981
982 for (index = 1, todo = nnames; index <= ncycle; index++)
983 namesortnlp[todo++] = &cyclenl[index];
984
985 (void) printf("\f\nIndex by function name\n\n");
986
987 if (!Cflag)
988 index = (todo + 2) / 3;
989 else
990 index = todo;
991
992 for (i = 0; i < index; i++) {
993 if (!Cflag) {
994 for (j = i; j < todo; j += index) {
995 nlp = namesortnlp[j];
996
997 if (nlp->printflag) {
998 (void) sprintf(peterbuffer,
999 "[%d]", nlp->index);
1000 } else {
1001 (void) sprintf(peterbuffer,
1002 "(%d)", nlp->index);
1003 }
1004
1005 if (j < nnames) {
1006 if (does_clash(namesortnlp,
1007 j, nnames)) {
1008 (void) printf(
1009 "%6.6s %*d:%-*.*s",
1010 peterbuffer,
1011 IDFMT(nlp->module->id),
1012 nlp->module->id,
1013 NMFMT(nlp->module->id),
1014 NMFMT(nlp->module->id),
1015 nlp->name);
1016 } else {
1017 (void) printf("%6.6s %-19.19s",
1018 peterbuffer, nlp->name);
1019 }
1020 } else {
1021 (void) printf("%6.6s ", peterbuffer);
1022 (void) sprintf(peterbuffer,
1023 "<cycle %d>", nlp->cycleno);
1024 (void) printf("%-19.19s", peterbuffer);
1025 }
1026 }
1027 } else {
1028 nlp = namesortnlp[i];
1029
1030 if (nlp->printflag)
1031 (void) sprintf(peterbuffer, "[%d]", nlp->index);
1032 else
1033 (void) sprintf(peterbuffer, "(%d)", nlp->index);
1034
1035 if (i < nnames) {
1036 const char *d = demangled_name(nlp);
1037
1038 if (does_clash(namesortnlp, i, nnames)) {
1039 (void) printf("%6.6s %d:%s\n",
1040 peterbuffer, nlp->module->id, d);
1041 } else
1042 (void) printf("%6.6s %s\n", peterbuffer,
1043 d);
1044
1045 if (d != nlp->name)
1046 (void) printf("%6.6s [%s]", "",
1047 nlp->name);
1048 } else {
1049 (void) printf("%6.6s ", peterbuffer);
1050 (void) sprintf(peterbuffer, "<cycle %d>",
1051 nlp->cycleno);
1052 (void) printf("%-33.33s", peterbuffer);
1053 }
1054 }
1055 (void) printf("\n");
1056 }
1057 free(namesortnlp);
1058 }
1059