This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Tracking down gprof's 64K symbol limit


Jim Panetta reported that gprof choked on programs with
more than 64K symbols, and provided a nice little test case;
see http://sources.redhat.com/ml/bug-glibc/2001-07/msg00131.html

I went looking at the glibc sources to see what was the matter.
It seems that when running Jim's test case, profiling is aborted 
in mcount.c at this point:
        /*
         *  first time traversing this arc
         */
        toindex = ++p->tos[0].link;
        if (toindex >= p->tolimit) 
            goto overflow;

p here is a pointer to the global _gmonparam.  
_gmonparam.tolimit was set in __monstartup in gmon.c:

 else if (p->tolimit > MAXARCS)
    p->tolimit = MAXARCS;

MAXARCS is defined in sys/gmon.h:

#define MAXARCS         ((1 << (8 * sizeof(HISTCOUNTER))) - 2)

That line seems misleading.  HISTCOUNTER is supposedly
the type of the histogram bucket, but it's being used
to derive a limit on the table _gmonparam.tos[].  

As an exercise in understanding the code,
I made a little patch against redhat 7.3's glibc-2.2.5 to use a defined
type for all variables used as indices into _gmonparam.tos[],
and redefined MAXARCS in terms of that type. 
This patch should not have any effect but to make it more
obvious where the 64K limit comes from.  Here's the patch:


--- glibc-2.2.5/gmon/sys/gmon.h.orig    Wed Jun 26 20:17:40 2002
+++ glibc-2.2.5/gmon/sys/gmon.h Wed Jun 26 20:41:48 2002
@@ -96,17 +96,25 @@
 #define    HASHFRACTION    2

 /*
+ * The type used to represent indices into gmonparam.tos[].
+ */
+#define    ARCINDEX    u_short
+
+/*
  * percent of text space to allocate for tostructs with a minimum.
  */
 #define ARCDENSITY 2
 #define MINARCS        50
-#define MAXARCS        ((1 << (8 * sizeof(HISTCOUNTER))) - 2)
+/*
+ * Maximum number of arcs we can represent.
+ */
+#define MAXARCS        ((1 << (8 * sizeof(ARCINDEX))) - 2)

 struct tostruct {
    u_long  selfpc;
    long    count;
-   u_short link;
-   u_short pad;
+   ARCINDEX    link;
+   u_short pad;        /* can we nuke this, and make ARCINDEX u_int32? */
 };

 /*
@@ -132,7 +140,7 @@
    long int    state;
    u_short     *kcount;
    u_long      kcountsize;
-   u_short     *froms;
+   ARCINDEX    *froms;
    u_long      fromssize;
    struct tostruct *tos;
    u_long      tossize;
--- glibc-2.2.5/gmon/gmon.c.orig    Wed Jun 26 20:44:13 2002
+++ glibc-2.2.5/gmon/gmon.c Wed Jun 26 20:47:14 2002
@@ -212,7 +212,8 @@
   u_char tag = GMON_TAG_CG_ARC;
   struct gmon_cg_arc_record raw_arc[NARCS_PER_WRITEV]
     __attribute__ ((aligned (__alignof__ (char*))));
-  int from_index, to_index, from_len;
+  ARCINDEX from_index, to_index;
+  int from_len;
   u_long frompc;
   struct iovec iov[2 * NARCS_PER_WRITEV];
   int nfilled;
--- glibc-2.2.5/gmon/mcount.c.orig  Wed Jun 26 20:44:18 2002
+++ glibc-2.2.5/gmon/mcount.c   Wed Jun 26 20:45:45 2002
@@ -57,10 +57,10 @@
  */
 _MCOUNT_DECL(frompc, selfpc)   /* _mcount; may be static, inline, etc */
 {
-   register u_short *frompcindex;
+   register ARCINDEX *frompcindex;
    register struct tostruct *top, *prevtop;
    register struct gmonparam *p;
-   register long toindex;
+   register ARCINDEX toindex;
    int i;

    p = &_gmonparam;

glibc compiles fine with the patch, and seems to work (it should,
since there weren't any real semantic changes).

As an experiment, I then changed ARCINDEX to u_long... and voila,
now running the test case does produce a gmon.out.  
I have a feeling the resulting gmon.out might be in the proper format,
as the ARCINDEX type is never written to disk.  But running gprof on
this file yields the error
gprof: gmon.out: unexpected EOF after reading 820794 of 1491392 samples
so something's still a bit amiss.

I'm encouraged that perhaps it won't be too much work to
actually solve the limit question.  One more quiet day of adding
print statements, perhaps.
- Dan

p.s. Call me a wimp, but the way I'm testing this is by
installing the Red Hat source RPM for glibc, building it,
and then compiling Jim Panetta's test case statically linked against
the resulting glibc.  MUCH easier than figuring out how
to build glibc from scratch.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]