Print this page
6375 Add native name demangling support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
| 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.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
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 + *
26 + * Copyright 2018 Jason King
27 + * Copyright 2018, Joyent, Inc.
25 28 */
26 29
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
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);
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
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 - int print_count = number_funcs_toprint;
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)
|
↓ open down ↓ |
207 lines elided |
↑ open up ↑ |
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 - int print_count = number_funcs_toprint;
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 }
|
↓ open down ↓ |
186 lines elided |
↑ open up ↑ |
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 - if (!Cflag)
504 - (void) printf("%s", selfp->name);
505 - else
506 - (void) printf("%s", c);
504 + (void) printf("%s", c);
507 505
508 506 #ifdef DEBUG
509 507 if (debug & DFNDEBUG)
510 508 (void) printf("{%d} ", selfp->toporder);
511 509
512 510 if (debug & PROPDEBUG)
513 511 (void) printf("%5.2f%% ", selfp->propfraction);
514 512 #endif /* DEBUG */
515 513 }
516 514
517 515 if (selfp->cycleno != 0)
518 516 (void) printf("\t<cycle %d>", selfp->cycleno);
519 517
520 518 if (selfp->index != 0) {
521 519 if (selfp->printflag)
522 520 (void) printf(" [%d]", selfp->index);
523 521 else
524 522 (void) printf(" (%d)", selfp->index);
525 523 }
524 +
525 + if (c != selfp->name)
526 + free((void *)c);
526 527 }
527 528
528 529 void
529 530 print_demangled_name(int n, nltype *selfp)
530 531 {
531 - char *c;
532 + char *c = (char *)demangled_name(selfp);
532 533 int i;
533 534
534 - c = selfp->name;
535 -
536 - if (strcmp(c, demangled_name(selfp)) == 0)
535 + if (c == selfp->name)
537 536 return;
538 - else {
539 - (void) printf("\n");
540 - for (i = 1; i < n; i++)
541 - (void) printf(" ");
542 - (void) printf("[%s]", selfp->name);
543 - }
537 +
538 + (void) printf("\n");
539 + for (i = 1; i < n; i++)
540 + (void) printf(" ");
541 + (void) printf("[%s]", selfp->name);
542 +
543 + free(c);
544 544 }
545 545
546 546 void
547 547 sortchildren(nltype *parentp)
548 548 {
549 549 arctype *arcp;
550 550 arctype *detachedp;
551 551 arctype sorted;
552 552 arctype *prevp;
553 553
554 554 /*
555 555 * unlink children from parent,
556 556 * then insertion sort back on to sorted's children.
557 557 * *arcp the arc you have detached and are inserting.
558 558 * *detachedp the rest of the arcs to be sorted.
559 559 * sorted arc list onto which you insertion sort.
560 560 * *prevp arc before the arc you are comparing.
561 561 */
562 562 sorted.arc_childlist = 0;
563 563
564 564 /* LINTED: warning: assignment operator */
565 565 for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist);
566 566 arcp;
567 567 /* LINTED: warning: assignment operator */
568 568 (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) {
569 569 /*
570 570 * consider *arcp as disconnected
571 571 * insert it into sorted
572 572 */
573 573 for (prevp = &sorted; prevp->arc_childlist;
574 574 prevp = prevp->arc_childlist) {
575 575 if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN)
576 576 break;
577 577 }
578 578
579 579 arcp->arc_childlist = prevp->arc_childlist;
580 580 prevp->arc_childlist = arcp;
581 581 }
582 582
583 583 /*
584 584 * reattach sorted children to parent
585 585 */
586 586 parentp->children = sorted.arc_childlist;
587 587 }
588 588
589 589 void
590 590 sortparents(nltype *childp)
591 591 {
592 592 arctype *arcp;
593 593 arctype *detachedp;
594 594 arctype sorted;
595 595 arctype *prevp;
596 596
597 597 /*
598 598 * unlink parents from child,
599 599 * then insertion sort back on to sorted's parents.
600 600 * *arcp the arc you have detached and are inserting.
601 601 * *detachedp the rest of the arcs to be sorted.
602 602 * sorted arc list onto which you insertion sort.
603 603 * *prevp arc before the arc you are comparing.
604 604 */
605 605 sorted.arc_parentlist = 0;
606 606
607 607 /* LINTED: warning: assignment operator */
608 608 for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist);
609 609 arcp;
610 610 /* LINTED: warning: assignment operator */
611 611 (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) {
612 612 /*
613 613 * consider *arcp as disconnected
614 614 * insert it into sorted
615 615 */
616 616 for (prevp = &sorted; prevp->arc_parentlist;
617 617 prevp = prevp->arc_parentlist) {
618 618 if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN)
619 619 break;
620 620 }
621 621 arcp->arc_parentlist = prevp->arc_parentlist;
622 622 prevp->arc_parentlist = arcp;
623 623 }
624 624
625 625 /*
626 626 * reattach sorted arcs to child
627 627 */
628 628 childp->parents = sorted.arc_parentlist;
629 629 }
630 630
631 631 void
632 632 printcycle(nltype *cyclep)
633 633 {
634 634 char kirkbuffer[BUFSIZ];
635 635
636 636 (void) sprintf(kirkbuffer, "[%d]", cyclep->index);
637 637 (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer,
638 638 100 * (cyclep->propself + cyclep->propchild) / printtime,
639 639 cyclep -> propself / hz, cyclep -> propchild / hz,
640 640 cyclep -> ncall);
641 641
642 642 if (cyclep->selfcalls != 0)
643 643 (void) printf("+%-7lld", cyclep->selfcalls);
644 644 else
645 645 (void) printf(" %7.7s", "");
646 646
647 647 (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno,
648 648 cyclep->index);
649 649 }
650 650
651 651 /*
652 652 * print the members of a cycle
653 653 */
654 654 void
655 655 printmembers(nltype *cyclep)
656 656 {
657 657 nltype *memberp;
658 658
659 659 sortmembers(cyclep);
660 660
661 661 for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) {
662 662 (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "",
663 663 memberp->propself / hz, memberp->propchild / hz,
664 664 memberp->ncall);
665 665
666 666 if (memberp->selfcalls != 0)
667 667 (void) printf("+%-7lld", memberp->selfcalls);
668 668 else
669 669 (void) printf(" %7.7s", "");
670 670
671 671 (void) printf(" ");
672 672 printname(memberp);
673 673 if (Cflag)
674 674 print_demangled_name(54, memberp);
675 675 (void) printf("\n");
676 676 }
677 677 }
678 678
679 679 /*
680 680 * sort members of a cycle
681 681 */
682 682 void
683 683 sortmembers(nltype *cyclep)
684 684 {
685 685 nltype *todo;
686 686 nltype *doing;
687 687 nltype *prev;
688 688
689 689 /*
690 690 * detach cycle members from cyclehead,
691 691 * and insertion sort them back on.
692 692 */
693 693 todo = cyclep->cnext;
694 694 cyclep->cnext = 0;
695 695
696 696 /* LINTED: warning: assignment operator */
697 697 for ((doing = todo) && (todo = doing->cnext);
698 698 doing;
699 699 /* LINTED: warning: assignment operator */
700 700 (doing = todo) && (todo = doing->cnext)) {
701 701 for (prev = cyclep; prev->cnext; prev = prev->cnext) {
702 702 if (membercmp(doing, prev->cnext) == GREATERTHAN)
703 703 break;
704 704 }
705 705 doing->cnext = prev->cnext;
706 706 prev->cnext = doing;
707 707 }
708 708 }
709 709
710 710 /*
711 711 * major sort is on propself + propchild,
712 712 * next is sort on ncalls + selfcalls.
713 713 */
714 714 int
715 715 membercmp(nltype *this, nltype *that)
716 716 {
717 717 double thistime = this->propself + this->propchild;
718 718 double thattime = that->propself + that->propchild;
719 719 actype thiscalls = this->ncall + this->selfcalls;
720 720 actype thatcalls = that->ncall + that->selfcalls;
721 721
722 722 if (thistime > thattime)
723 723 return (GREATERTHAN);
724 724
725 725 if (thistime < thattime)
726 726 return (LESSTHAN);
727 727
728 728 if (thiscalls > thatcalls)
729 729 return (GREATERTHAN);
730 730
731 731 if (thiscalls < thatcalls)
732 732 return (LESSTHAN);
733 733
734 734 return (EQUALTO);
735 735 }
736 736
737 737 /*
738 738 * compare two arcs to/from the same child/parent.
739 739 * - if one arc is a self arc, it's least.
740 740 * - if one arc is within a cycle, it's less than.
741 741 * - if both arcs are within a cycle, compare arc counts.
742 742 * - if neither arc is within a cycle, compare with
743 743 * arc_time + arc_childtime as major key
744 744 * arc count as minor key
745 745 */
746 746 int
747 747 arccmp(arctype *thisp, arctype *thatp)
748 748 {
749 749 nltype *thisparentp = thisp->arc_parentp;
750 750 nltype *thischildp = thisp->arc_childp;
751 751 nltype *thatparentp = thatp->arc_parentp;
752 752 nltype *thatchildp = thatp->arc_childp;
753 753 double thistime;
754 754 double thattime;
755 755
756 756 #ifdef DEBUG
757 757 if (debug & TIMEDEBUG) {
758 758 (void) printf("[arccmp] ");
759 759 printname(thisparentp);
760 760 (void) printf(" calls ");
761 761 printname(thischildp);
762 762 (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time,
763 763 thisp->arc_childtime, thisp->arc_count,
764 764 thischildp->ncall);
765 765 (void) printf("[arccmp] ");
766 766 printname(thatparentp);
767 767 (void) printf(" calls ");
768 768 printname(thatchildp);
769 769 (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time,
770 770 thatp->arc_childtime, thatp->arc_count,
771 771 thatchildp->ncall);
772 772 (void) printf("\n");
773 773 }
774 774 #endif /* DEBUG */
775 775
776 776 if (thisparentp == thischildp) {
777 777 /*
778 778 * this is a self call
779 779 */
780 780 return (LESSTHAN);
781 781 }
782 782
783 783 if (thatparentp == thatchildp) {
784 784 /*
785 785 * that is a self call
786 786 */
787 787 return (GREATERTHAN);
788 788 }
789 789
790 790 if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 &&
791 791 thisparentp->cycleno == thischildp->cycleno) {
792 792 /*
793 793 * this is a call within a cycle
794 794 */
795 795 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
796 796 thatparentp->cycleno == thatchildp->cycleno) {
797 797 /*
798 798 * that is a call within the cycle, too
799 799 */
800 800 if (thisp->arc_count < thatp->arc_count)
801 801 return (LESSTHAN);
802 802
803 803 if (thisp->arc_count > thatp->arc_count)
804 804 return (GREATERTHAN);
805 805
806 806 return (EQUALTO);
807 807 } else {
808 808 /*
809 809 * that isn't a call within the cycle
810 810 */
811 811 return (LESSTHAN);
812 812 }
813 813 } else {
814 814 /*
815 815 * this isn't a call within a cycle
816 816 */
817 817 if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 &&
818 818 thatparentp->cycleno == thatchildp->cycleno) {
819 819 /*
820 820 * that is a call within a cycle
821 821 */
822 822 return (GREATERTHAN);
823 823 } else {
824 824 /*
825 825 * neither is a call within a cycle
826 826 */
827 827 thistime = thisp->arc_time + thisp->arc_childtime;
828 828 thattime = thatp->arc_time + thatp->arc_childtime;
829 829
830 830 if (thistime < thattime)
831 831 return (LESSTHAN);
832 832
833 833 if (thistime > thattime)
834 834 return (GREATERTHAN);
835 835
836 836 if (thisp->arc_count < thatp->arc_count)
837 837 return (LESSTHAN);
838 838
839 839 if (thisp->arc_count > thatp->arc_count)
840 840 return (GREATERTHAN);
841 841
842 842 return (EQUALTO);
843 843 }
844 844 }
845 845 }
846 846
847 847 void
848 848 printblurb(char *blurbname)
849 849 {
850 850 FILE *blurbfile;
851 851 int input;
852 852
853 853 blurbfile = fopen(blurbname, "r");
854 854 if (blurbfile == NULL) {
|
↓ open down ↓ |
301 lines elided |
↑ open up ↑ |
855 855 perror(blurbname);
856 856 return;
857 857 }
858 858
859 859 while ((input = getc(blurbfile)) != EOF)
860 860 (void) putchar(input);
861 861
862 862 (void) fclose(blurbfile);
863 863 }
864 864
865 -char *s1, *s2;
866 -
867 865 static int
868 866 namecmp(const void *arg1, const void *arg2)
869 867 {
870 868 nltype **npp1 = (nltype **)arg1;
871 869 nltype **npp2 = (nltype **)arg2;
872 870
873 871 if (!Cflag)
874 872 return (strcmp((*npp1)->name, (*npp2)->name));
875 873 else {
876 - striped_name(s1, npp1);
877 - 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);
878 879 return (strcmp(s1, s2));
879 880 }
880 881 }
881 882
882 -void
883 -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)
884 887 {
885 - const char *d;
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 +{
912 + const char *name, *d;
886 913 char *c;
887 914
888 - c = (char *)s;
889 - d = demangled_name(*npp);
915 + name = d = demangled_name(*npp);
916 + adjust_size(sp, slenp, name);
917 + c = *sp;
890 918
891 919 while ((*d != '(') && (*d != '\0')) {
892 920 if (*d != ':')
893 921 *c++ = *d++;
894 922 else
895 923 d++;
896 924 }
897 925 *c = '\0';
926 +
927 + if ((*npp)->name != name)
928 + free((void *)name);
898 929 }
899 930
900 931 /*
901 932 * Checks if the current symbol name is the same as its neighbour and
902 933 * returns TRUE if it is.
903 934 */
904 935 static bool
905 936 does_clash(nltype **nlp, int ndx, int nnames)
906 937 {
907 938 /*
908 939 * same as previous (if there's one) ?
909 940 */
910 941 if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0))
911 942 return (TRUE);
912 943
913 944 /*
914 945 * same as next (if there's one) ?
915 946 */
916 947 if ((ndx < (nnames - 1)) &&
917 948 (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) {
918 949 return (TRUE);
919 950 }
920 951
921 952 return (FALSE);
922 953 }
923 954
924 955 void
925 956 printmodules()
926 957 {
927 958 mod_info_t *mi;
928 959
929 960 (void) printf("\f\nObject modules\n\n");
930 961 for (mi = &modules; mi; mi = mi->next)
931 962 (void) printf(" %d: %s\n", mi->id, mi->name);
932 963 }
933 964
934 965 #define IDFMT(id) ((id) < 10 ? 1 : 2)
935 966 #define NMFMT(id) ((id) < 10 ? 17 : 16)
936 967
937 968 void
938 969 printindex()
939 970 {
940 971 nltype **namesortnlp;
941 972 nltype *nlp;
942 973 int index, nnames, todo, i, j;
943 974 char peterbuffer[BUFSIZ];
944 975 mod_info_t *mi;
945 976
946 977 /*
947 978 * Now, sort regular function name alphabetically
948 979 * to create an index.
949 980 */
950 981 namesortnlp = calloc(total_names + ncycle, sizeof (nltype *));
951 982
952 983 if (namesortnlp == NULL)
953 984 (void) fprintf(stderr, "%s: ran out of memory for sorting\n",
954 985 whoami);
955 986
956 987 nnames = 0;
957 988 for (mi = &modules; mi; mi = mi->next) {
958 989 for (index = 0; index < mi->nname; index++) {
959 990 if (zflag == 0 && (mi->nl[index]).ncall == 0 &&
960 991 (mi->nl[index]).time == 0) {
961 992 continue;
962 993 }
963 994
964 995 /*
|
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
965 996 * Do not print certain special symbols, like
966 997 * PRF_EXTSYM, etc. even if zflag was on.
967 998 */
968 999 if (is_special_sym(&(mi->nl[index])))
969 1000 continue;
970 1001
971 1002 namesortnlp[nnames++] = &(mi->nl[index]);
972 1003 }
973 1004 }
974 1005
975 - if (Cflag) {
976 - s1 = malloc(500 * sizeof (char));
977 - s2 = malloc(500 * sizeof (char));
978 - }
979 -
980 1006 qsort(namesortnlp, nnames, sizeof (nltype *), namecmp);
981 1007
982 1008 for (index = 1, todo = nnames; index <= ncycle; index++)
983 1009 namesortnlp[todo++] = &cyclenl[index];
984 1010
985 1011 (void) printf("\f\nIndex by function name\n\n");
986 1012
987 1013 if (!Cflag)
988 1014 index = (todo + 2) / 3;
989 1015 else
990 1016 index = todo;
991 1017
992 1018 for (i = 0; i < index; i++) {
993 1019 if (!Cflag) {
994 1020 for (j = i; j < todo; j += index) {
995 1021 nlp = namesortnlp[j];
996 1022
997 1023 if (nlp->printflag) {
998 1024 (void) sprintf(peterbuffer,
999 1025 "[%d]", nlp->index);
1000 1026 } else {
1001 1027 (void) sprintf(peterbuffer,
1002 1028 "(%d)", nlp->index);
1003 1029 }
1004 1030
1005 1031 if (j < nnames) {
1006 1032 if (does_clash(namesortnlp,
1007 1033 j, nnames)) {
1008 1034 (void) printf(
1009 1035 "%6.6s %*d:%-*.*s",
1010 1036 peterbuffer,
1011 1037 IDFMT(nlp->module->id),
1012 1038 nlp->module->id,
1013 1039 NMFMT(nlp->module->id),
1014 1040 NMFMT(nlp->module->id),
1015 1041 nlp->name);
1016 1042 } else {
1017 1043 (void) printf("%6.6s %-19.19s",
1018 1044 peterbuffer, nlp->name);
1019 1045 }
1020 1046 } else {
1021 1047 (void) printf("%6.6s ", peterbuffer);
1022 1048 (void) sprintf(peterbuffer,
1023 1049 "<cycle %d>", nlp->cycleno);
1024 1050 (void) printf("%-19.19s", peterbuffer);
1025 1051 }
1026 1052 }
1027 1053 } else {
1028 1054 nlp = namesortnlp[i];
1029 1055
1030 1056 if (nlp->printflag)
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
1031 1057 (void) sprintf(peterbuffer, "[%d]", nlp->index);
1032 1058 else
1033 1059 (void) sprintf(peterbuffer, "(%d)", nlp->index);
1034 1060
1035 1061 if (i < nnames) {
1036 1062 const char *d = demangled_name(nlp);
1037 1063
1038 1064 if (does_clash(namesortnlp, i, nnames)) {
1039 1065 (void) printf("%6.6s %d:%s\n",
1040 1066 peterbuffer, nlp->module->id, d);
1041 - } else
1067 + } else {
1042 1068 (void) printf("%6.6s %s\n", peterbuffer,
1043 1069 d);
1070 + }
1044 1071
1045 - if (d != nlp->name)
1072 + if (d != nlp->name) {
1046 1073 (void) printf("%6.6s [%s]", "",
1047 1074 nlp->name);
1075 + free((void *)d);
1076 + }
1048 1077 } else {
1049 1078 (void) printf("%6.6s ", peterbuffer);
1050 1079 (void) sprintf(peterbuffer, "<cycle %d>",
1051 1080 nlp->cycleno);
1052 1081 (void) printf("%-33.33s", peterbuffer);
1053 1082 }
1054 1083 }
1055 1084 (void) printf("\n");
1056 1085 }
1057 1086 free(namesortnlp);
1058 1087 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX