Support runtime specification of the history counter type by whatever

generated the gmon data.  The support is currently limited to what is
easy to implement and/or needed:

    signedess: signed or insigned
    size: 8, 16, 32 or 64 bits
    format: a binary integer in gprof's format (gprof is not a cross-tool).

High-resolution kernel profiling uses signed 64-bit counters.  Normal
kernel profiling and user profiling use unsigned 16-bit counters but
should use 32-bit ones.
This commit is contained in:
bde 2002-03-06 11:25:58 +00:00
parent 7d69422196
commit acab62a802
2 changed files with 51 additions and 18 deletions

View File

@ -46,6 +46,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <err.h>
#include <limits.h>
#include "gprof.h"
static int valcmp(const void *, const void *);
@ -302,12 +303,20 @@ openpfile(filename)
filename, rate, "incompatible with clock rate", hz);
done();
}
if ( gmonhdr.histcounter_type == 0 ) {
/* Historical case. The type was u_short (2 bytes in practice). */
histcounter_type = 16;
histcounter_size = 2;
} else {
histcounter_type = gmonhdr.histcounter_type;
histcounter_size = abs(histcounter_type) / CHAR_BIT;
}
s_lowpc = (unsigned long) gmonhdr.lpc;
s_highpc = (unsigned long) gmonhdr.hpc;
lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2;
highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2;
sampbytes = gmonhdr.ncnt - size;
nsamples = sampbytes / sizeof (UNIT);
nsamples = sampbytes / histcounter_size;
# ifdef DEBUG
if ( debug & SAMPLEDEBUG ) {
printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n",
@ -374,7 +383,7 @@ dumpsum( sumfile )
/*
* dump the samples
*/
if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) {
if (fwrite(samples, histcounter_size, nsamples, sfile) != nsamples) {
perror( sumfile );
done();
}
@ -422,20 +431,47 @@ readsamples(pfile)
FILE *pfile;
{
register i;
UNIT sample;
intmax_t sample;
if (samples == 0) {
samples = (UNIT *) calloc(sampbytes, sizeof (UNIT));
samples = (double *) calloc(nsamples, sizeof(double));
if (samples == 0) {
warnx("no room for %d sample pc's", sampbytes / sizeof (UNIT));
warnx("no room for %d sample pc's", nsamples);
done();
}
}
for (i = 0; i < nsamples; i++) {
fread(&sample, sizeof (UNIT), 1, pfile);
fread(&sample, histcounter_size, 1, pfile);
if (feof(pfile))
break;
samples[i] += sample;
switch ( histcounter_type ) {
case -8:
samples[i] += *(int8_t *)&sample;
break;
case 8:
samples[i] += *(u_int8_t *)&sample;
break;
case -16:
samples[i] += *(int16_t *)&sample;
break;
case 16:
samples[i] += *(u_int16_t *)&sample;
break;
case -32:
samples[i] += *(int32_t *)&sample;
break;
case 32:
samples[i] += *(u_int32_t *)&sample;
break;
case -64:
samples[i] += *(int64_t *)&sample;
break;
case 64:
samples[i] += *(u_int64_t *)&sample;
break;
default:
err(1, "unsupported histogram counter type %d", histcounter_type);
}
}
if (i != nsamples) {
warnx("unexpected EOF after reading %d/%d samples", --i , nsamples );
@ -478,7 +514,7 @@ readsamples(pfile)
asgnsamples()
{
register int j;
UNIT ccnt;
double ccnt;
double time;
unsigned long pcl, pch;
register int i;
@ -498,7 +534,7 @@ asgnsamples()
time = ccnt;
# ifdef DEBUG
if ( debug & SAMPLEDEBUG ) {
printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %d\n" ,
printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %.0f\n" ,
pcl , pch , ccnt );
}
# endif DEBUG

View File

@ -89,11 +89,8 @@ typedef int bool;
*/
long hz;
#ifdef GPROF4
typedef int64_t UNIT;
#else
typedef u_short UNIT; /* unit of profiling */
#endif
size_t histcounter_size;
int histcounter_type;
char *a_outname;
#define A_OUTNAME "a.out"
@ -207,8 +204,8 @@ int ncycle; /* number of cycles discovered */
* Backward compatible old style header
*/
struct ophdr {
UNIT *lpc;
UNIT *hpc;
u_short *lpc;
u_short *hpc;
int ncnt;
};
@ -218,11 +215,11 @@ int debug;
* Each discretized pc sample has
* a count of the number of samples in its range
*/
UNIT *samples;
double *samples;
unsigned long s_lowpc; /* lowpc from the profile file */
unsigned long s_highpc; /* highpc from the profile file */
unsigned long lowpc, highpc; /* range profiled, in UNIT's */
unsigned long lowpc, highpc; /* range profiled, in historical units */
unsigned sampbytes; /* number of bytes of samples */
int nsamples; /* number of samples */
double actime; /* accumulated time thus far for putprofline */