printgprof.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1990-1998 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "gprof.h"
extern int find_run_directory(char *, char *, char *, char **, char *);
void print_demangled_name(int, nltype *);
void striped_name(char *, nltype **);
extern char *demangle();
char *strstr();
char *parsename();
char name_buffer[512];
extern long hz;
/*
* Symbols that must never be printed, no matter what.
*/
char *splsym[] = {
0
};
char *
{
char *name;
if (!Cflag)
return (name);
}
void
{
int i, index;
int print_count = number_funcs_toprint;
bool print_flag = TRUE;
mod_info_t *mi;
actime = 0.0;
printf("\f\n");
/*
* Sort the symbol table in by time
*/
"[printprof] ran out of memory for time sorting\n");
}
index = 0;
}
(int(*)(const void *, const void *))timecmp);
if (nflag) {
if (--print_count == 0)
print_flag = FALSE;
}
}
actime = 0.0;
}
int
{
double timediff;
long calldiff;
if (timediff > 0.0)
return (1);
if (timediff < 0.0)
return (-1);
if (calldiff > 0)
return (1);
if (calldiff < 0)
return (-1);
}
/*
* header for flatprofline
*/
void
{
if (bflag)
if (old_style) {
printf("\ngranularity: each sample hit covers %d byte(s)",
if (totime > 0.0) {
printf(" for %.2f%% of %.2f seconds\n\n",
} else {
printf(" no time accumulated\n\n");
/*
* this doesn't hurt since all the numerators will
* be zero.
*/
totime = 1.0;
}
}
printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
"% ", "cumulative", "self ", "", "self ", "total ", "");
printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n",
"time", "seconds ", "seconds", "calls",
}
void
{
return;
/*
* Do not print certain special symbols, like PRF_EXTSYM, etc.
* even if zflag was on.
*/
if (is_special_sym(np))
return;
printf("%5.1f %10.2f %8.2f",
} else {
if (!Cflag)
else
}
if (Cflag)
printf("\n");
}
void
{
if (bflag)
if (old_style) {
printf("\ngranularity: each sample hit covers %d byte(s)",
if (printtime > 0.0) {
printf(" for %.2f%% of %.2f seconds\n\n",
} else {
printf(" no time propagated\n\n");
/*
* this doesn't hurt, since all the numerators
* will be 0.0
*/
printtime = 1.0;
}
} else {
printf("\ngranularity: each pc-hit is considered 1 tick");
if (hz != 1) {
printf(" (@ %4.3f seconds per tick)",
(double) 1.0 / hz);
}
puts("\n\n");
}
printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
"", "", "", "", "called", "total", "parents");
printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
"index", "%time", "self", "descendents",
"called", "self", "name", "index");
printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
"", "", "", "", "called", "total", "children");
printf("\n");
}
void
{
char kirkbuffer[BUFSIZ];
else
} else {
}
if (Cflag)
printf("\n");
}
static bool
{
int i;
return (FALSE);
for (i = 0; splsym[i]; i++)
return (TRUE);
return (FALSE);
}
void
{
int index;
int print_count = number_funcs_toprint;
bool count_flag = TRUE;
/*
* Print out the structured profiling list
*/
gprofheader();
continue;
continue;
/*
* Do not print certain special symbols, like PRF_EXTSYM, etc.
* even if zflag was on.
*/
if (is_special_sym(parentp))
continue;
/*
* cycle header
*/
} else {
}
printf("\n");
printf("-----------------------------------------------\n");
printf("\n");
if (nflag) {
--print_count;
if (print_count == 0)
count_flag = FALSE;
}
}
}
/*
* sort by decreasing propagated time
* if times are equal, but one is a cycle header,
* say that's first (e.g. less, i.e. -1).
* if one's name doesn't have an underscore and the other does,
* say the one is first.
* all else being equal, sort by names.
*/
int
{
double diff;
if (diff < 0.0)
return (1);
if (diff > 0.0)
return (-1);
return (-1);
return (1);
return (-1);
return (1);
return (-1);
return (1);
return (-1);
return (1);
}
void
{
else
cycleheadp = childp;
printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s"
" <spontaneous>\n", "", "", "", "", "", "");
return;
}
/*
* selfcall or call among siblings
*/
printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
if (Cflag)
printf("\n");
} else {
/*
* regular parent of child
*/
if (Cflag)
printf("\n");
}
}
}
void
{
/*
* self call or call to sibling
*/
printf("%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ",
if (Cflag)
printf("\n");
} else {
/*
* regular child of parent
*/
printf("%6.6s %5.5s %7.2f %11.2f "
"%7lld/%-7lld ", "", "",
else
printf("%6.6s %5.5s %7.2f %11.2f "
"%7lld %7.7s ",
"");
if (Cflag)
printf("\n");
}
}
}
void
{
char *c;
c = demangled_name(selfp);
if (!Cflag)
else
printf("%s", c);
#ifdef DEBUG
#endif DEBUG
}
else
}
}
void
{
char *c;
int i;
return;
else {
printf("\n");
for (i = 1; i < n; i++)
printf(" ");
}
}
char *exotic();
void
{
/*
* unlink children from parent,
* then insertion sort back on to sorted's children.
* *arcp the arc you have detached and are inserting.
* *detachedp the rest of the arcs to be sorted.
* sorted arc list onto which you insertion sort.
* *prevp arc before the arc you are comparing.
*/
sorted.arc_childlist = 0;
arcp;
/*
* consider *arcp as disconnected
* insert it into sorted
*/
break;
}
}
/*
* reattach sorted children to parent
*/
}
void
{
/*
* unlink parents from child,
* then insertion sort back on to sorted's parents.
* *arcp the arc you have detached and are inserting.
* *detachedp the rest of the arcs to be sorted.
* sorted arc list onto which you insertion sort.
* *prevp arc before the arc you are comparing.
*/
sorted.arc_parentlist = 0;
arcp;
/*
* consider *arcp as disconnected
* insert it into sorted
*/
break;
}
}
/*
* reattach sorted arcs to child
*/
}
void
{
char kirkbuffer[BUFSIZ];
else
}
/*
* print the members of a cycle
*/
void
{
else
printf(" ");
if (Cflag)
printf("\n");
}
}
/*
* sort members of a cycle
*/
void
{
/*
* detach cycle members from cyclehead,
* and insertion sort them back on.
*/
break;
}
}
}
/*
* major sort is on propself + propchild,
* next is sort on ncalls + selfcalls.
*/
int
{
return (GREATERTHAN);
return (LESSTHAN);
return (GREATERTHAN);
return (LESSTHAN);
return (EQUALTO);
}
/*
* - if one arc is a self arc, it's least.
* - if one arc is within a cycle, it's less than.
* - if both arcs are within a cycle, compare arc counts.
* - if neither arc is within a cycle, compare with
* arc_time + arc_childtime as major key
* arc count as minor key
*/
int
{
double thistime;
double thattime;
#ifdef DEBUG
printf("[arccmp] ");
printf(" calls ");
thischildp->ncall);
printf("[arccmp] ");
printf(" calls ");
thatchildp->ncall);
printf("\n");
}
#endif DEBUG
if (thisparentp == thischildp) {
/*
* this is a self call
*/
return (LESSTHAN);
}
if (thatparentp == thatchildp) {
/*
* that is a self call
*/
return (GREATERTHAN);
}
/*
* this is a call within a cycle
*/
/*
* that is a call within the cycle, too
*/
return (LESSTHAN);
return (GREATERTHAN);
return (EQUALTO);
} else {
/*
* that isn't a call within the cycle
*/
return (LESSTHAN);
}
} else {
/*
* this isn't a call within a cycle
*/
/*
* that is a call within a cycle
*/
return (GREATERTHAN);
} else {
/*
* neither is a call within a cycle
*/
return (LESSTHAN);
return (GREATERTHAN);
return (LESSTHAN);
return (GREATERTHAN);
return (EQUALTO);
}
}
}
void
printblurb(char *blurbname)
{
int input;
char blurb_directory[MAXPATHLEN];
char cwd[MAXPATHLEN];
cwd[0] = '.';
return;
} else {
}
return;
}
}
int
{
if (!Cflag)
else {
}
}
void
{
char *d, *c;
c = (char *)s;
d = demangled_name(*npp);
while ((*d != '(') && (*d != '\0')) {
if (*d != ':')
*c++ = *d++;
else
d++;
}
*c = '\0';
}
/*
* Checks if the current symbol name is the same as its neighbour and
* returns TRUE if it is.
*/
static bool
{
/*
* same as previous (if there's one) ?
*/
return (TRUE);
/*
* same as next (if there's one) ?
*/
return (TRUE);
}
return (FALSE);
}
void
{
mod_info_t *mi;
printf("\f\nObject modules\n\n");
}
void
{
char peterbuffer[BUFSIZ];
mod_info_t *mi;
/*
* Now, sort regular function name alphabetically
* to create an index.
*/
if (namesortnlp == NULL)
nnames = 0;
continue;
}
/*
* Do not print certain special symbols, like
* PRF_EXTSYM, etc. even if zflag was on.
*/
continue;
}
}
if (Cflag) {
}
(int(*)(const void *, const void *))namecmp);
printf("\f\nIndex by function name\n\n");
if (!Cflag)
else
for (i = 0; i < index; i++) {
if (!Cflag) {
nlp = namesortnlp[j];
} else {
}
if (j < nnames) {
if (does_clash(namesortnlp,
j, nnames)) {
printf("%6.6s %*d:%-*.*s",
} else {
printf("%6.6s %-19.19s",
}
} else {
}
}
} else {
nlp = namesortnlp[i];
else
if (i < nnames) {
char *d = demangled_name(nlp);
} else
} else {
}
}
printf("\n");
}
}
char dname[500];
char *
exotic(char *s)
{
char *name;
int i = 0, j;
char *p, *s1 = "static constructor function for ";
i = 0;
s += 7;
if ((p =
return (NULL);
}
}
}
} else {
p += 3;
*p = '\0';
}
for (i = 0; s1[i] != '\0'; i++)
j = i;
for (i = 0; s[i] != '\0'; i++)
dname[j + i] = s[i];
dname[j + i] = '\0';
return (dname);
}
char *s1 = "static destructor function for ";
i = 0;
s += 7;
if ((p =
return (NULL);
}
}
}
} else {
p += 3;
*p = '\0';
}
for (i = 0; s1[i] != '\0'; i++)
j = i;
for (i = 0; s[i] != '\0'; i++)
dname[j + i] = s[i];
dname[j + i] = '\0';
return (dname);
}
char *s1 = "virtual table for ";
s += 8;
return_p = '\0';
return (dname);
}
char *s1 = "pointer to the virtual table for ";
s += 8;
return_p = '\0';
return (return_p);
}
return (s);
}
char *
parsename(char *s)
{
char *d = name_buffer;
int len;
char c_init;
char *len_pointer = s;
*d = '\0';
strcat(d, "class ");
while (isdigit(*s))
s++;
c_init = *s;
*s = '\0';
*s = c_init;
/*
* only one class name
*/
if (*(s + len) == '\0') {
strcat(d, s);
return (d);
} else {
/*
* two classname %drootname__%dchildname
*/
char *child;
char *root;
int child_len;
char *child_len_p;
root = s;
child_len_p = child;
strcat(d, " in ");
return (d);
}
child++;
*child = '\0';
strcat(d, " derived from ");
return (d);
} else { /* %drootname__%dchildname__filename */
strcat(d, " derived from ");
strcat(d, " in ");
return (d);
}
}
}