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