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:
parent
7d69422196
commit
acab62a802
@ -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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user