]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
This patch decreases significantly the memory needed to store the lineloc info.
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Mon, 14 Jul 2014 21:20:57 +0000 (21:20 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Mon, 14 Jul 2014 21:20:57 +0000 (21:20 +0000)
On a big executable, the trunk needs:
dinfo: 134873088/71438336  max/curr mmap'd, 134607808/66717872 max/curr

With the patch, we have:
dinfo: 99065856/56836096  max/curr mmap'd,   97883776/51663656 max/curr

So, peak dinfo memory decreases by about 36Mb, and final by 15Mb.

(for info, valgrind 3.9.0 uses
dinfo: 158941184/109666304  max/curr mmap'd, 156775944/107590656 max/curr
So, compared to 3.9.0, dinfo peak decreases by about 40%, and the final
memory is divided by more than 2).

The memory decrease is obtained by:

* using a dedup pool to store filename/dirname pair for the loctab source/line
  information.
  As typically, there is not a lot of such pairs, typically a UShort is
  good enough to identify a fn/dn pair in a dedup pool.
  To avoid losing memory due to alignment, the fndn indexes are stored
  in a "parallel" array to the DiLoc loctab array, with entries having
  1, or 2 or 4 bytes according to the nr of fn/dn pairs in the dedup pool.
  See priv_storage.h comments for details.

  (there was a extensible WordArray local implementation in readdwarf.c.
   As with this change, we use an xarray, the local implementation was
   removed).

* the memory needed for --read-inline-info is slightly decreased (-2Mb)
  by removing the (unused) dirname from the DiInlLoc struct.
  Handling dirname for inlined function caller implies to rework
  the dwarf3 parser read_filename_table common to the var and inlinfo parser.
  Waiting for this to be done, the dirname component is removed from DiInlLoc.

* the stabs reader (readstabs.c) is broken since 3.9.0.
  For this change, the code has been updated to make it compile with the new
  DiLoc/FnDn dedup pool. As the code is completely broken, a vg_assert(0)
  has been put at the begin of the stabs reader.

* the pdb reader (readpdb.c) has been trivially updated and should still work.
  It has not been tested (how do we test this ?).
  A follow-up patch will be done to avoid doing too many calls to
  ML_(addFnDn) : instead of having one call per ML_(addLineInfo), one
  should have a single call done when reading the filename table.

This has also be tested in an outer/inner setup, to verify no
memory leak/bugs.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14158

NEWS
coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_storage.h
coregrind/m_debuginfo/readdwarf.c
coregrind/m_debuginfo/readdwarf3.c
coregrind/m_debuginfo/readelf.c
coregrind/m_debuginfo/readpdb.c
coregrind/m_debuginfo/readstabs.c
coregrind/m_debuginfo/storage.c

diff --git a/NEWS b/NEWS
index b8f48cee27052eda0838ca37520dc5fe95d173e1..1c85728beb2eb90d107530605fd1f2943ae1947a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,8 @@ Release 3.10.0 (?? ?????? 201?)
 * Error messages about fishy arguments (formerly known as silly arguments)
   now include a back-trace to aid debugging.
 
+* Reduction of memory used by Valgrind to read and store the debug information.
+
 * ==================== FIXED BUGS ====================
 
 The following bugs have been fixed or resolved.  Note that "n-i-bz"
index 13d27f0c3c47084d5b6f01000f9006840c906cce..85d3ca853597f8017cc38a30f1eae0b8a3c6aeb8 100644 (file)
@@ -217,6 +217,7 @@ static void free_DebugInfo ( DebugInfo* di )
    if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
    if (di->soname)       ML_(dinfo_free)(di->soname);
    if (di->loctab)       ML_(dinfo_free)(di->loctab);
+   if (di->loctab_fndn_ix) ML_(dinfo_free)(di->loctab_fndn_ix);
    if (di->inltab)       ML_(dinfo_free)(di->inltab);
    if (di->cfsi_base)    ML_(dinfo_free)(di->cfsi_base);
    if (di->cfsi_m_ix)    ML_(dinfo_free)(di->cfsi_m_ix);
@@ -240,6 +241,8 @@ static void free_DebugInfo ( DebugInfo* di )
 
    if (di->strpool)
       VG_(deleteDedupPA) (di->strpool);
+   if (di->fndnpool)
+      VG_(deleteDedupPA) (di->fndnpool);
 
    /* Delete the two admin arrays.  These lists exist primarily so
       that we can visit each object exactly once when we need to
@@ -1909,10 +1912,19 @@ Bool VG_(get_filename)( Addr a, HChar* filename, Int n_filename )
 {
    DebugInfo* si;
    Word       locno;
+   UInt       fndn_ix;
+   FnDn*      fndn;
+
    search_all_loctabs ( a, &si, &locno );
    if (si == NULL) 
       return False;
-   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
+   fndn_ix = ML_(fndn_ix) (si, locno);
+   if (fndn_ix == 0)
+      VG_(strncpy_safely)(filename, "???", n_filename);
+   else {
+      fndn = VG_(indexEltNumber) (si->fndnpool, fndn_ix);
+      VG_(strncpy_safely)(filename, fndn->filename, n_filename);
+   }
    return True;
 }
 
@@ -1940,6 +1952,8 @@ Bool VG_(get_filename_linenum) ( Addr a,
 {
    DebugInfo* si;
    Word       locno;
+   UInt       fndn_ix;
+   FnDn*      fndn = NULL;
 
    vg_assert( (dirname == NULL && dirname_available == NULL)
               ||
@@ -1954,17 +1968,22 @@ Bool VG_(get_filename_linenum) ( Addr a,
       return False;
    }
 
-   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
+   fndn_ix = ML_(fndn_ix)(si, locno);
+   if (fndn_ix == 0)
+      VG_(strncpy_safely)(filename, "???", n_filename);
+   else {
+      fndn = VG_(indexEltNumber) (si->fndnpool, fndn_ix);
+      VG_(strncpy_safely)(filename, fndn->filename, n_filename);
+   }
    *lineno = si->loctab[locno].lineno;
 
    if (dirname) {
       /* caller wants directory info too .. */
       vg_assert(n_dirname > 0);
-      if (si->loctab[locno].dirname) {
+      if (fndn_ix != 0 && fndn->dirname) {
          /* .. and we have some */
          *dirname_available = True;
-         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
-                                      n_dirname);
+         VG_(strncpy_safely)(dirname, fndn->dirname, n_dirname);
       } else {
          /* .. but we don't have any */
          *dirname_available = False;
@@ -2156,8 +2175,7 @@ HChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc)
       VG_(snprintf) (buf_srcloc, BUF_LEN, "%s", cur_inl->filename);
       lineno = cur_inl->lineno;
 
-      know_dirinfo = False; //INLINED TBD
-
+      know_dirinfo = False;
       know_srcloc = True;
    }
          
index 000d5f15a5f894c251d9d76162b5b106445e3be2..817efaed9f29b5e0ca4191864f4d45287448e833 100644 (file)
@@ -103,6 +103,15 @@ typedef
  */
 #define OVERFLOW_DIFFERENCE     (LINENO_OVERFLOW - 5000)
 
+/* Filename and Dirname pair. FnDn are stored in di->fndnpool
+   and are allocated using VG_(allocFixedEltDedupPA).
+   The filename/dirname strings are themselves stored in di->strpool. */
+typedef
+   struct {
+      const HChar* filename;     /* source filename */
+      const HChar* dirname;      /* source directory name */
+   } FnDn;
+
 /* A structure to hold addr-to-source info for a single line.  There
   can be a lot of these, hence the dense packing. */
 typedef
@@ -112,10 +121,6 @@ typedef
       /* Word 2 */
       UShort size:LOC_SIZE_BITS; /* # bytes; we catch overflows of this */
       UInt   lineno:LINENO_BITS; /* source line number, or zero */
-      /* Word 3 */
-      const HChar* filename;     /* source filename */
-      /* Word 4 */
-      const HChar* dirname;      /* source directory name */
    }
    DiLoc;
 
@@ -123,7 +128,10 @@ typedef
 #define MAX_LEVEL     ((1 << LEVEL_BITS) - 1)
 
 /* A structure to hold addr-to-inlined fn info.  There
-  can be a lot of these, hence the dense packing. */
+   can be a lot of these, hence the dense packing.
+   Only caller source filename and lineno are stored.
+   Handling dirname should be done using fndn_ix technique
+   similar to  ML_(addLineInfo). */
 typedef
    struct {
       /* Word 1 */
@@ -135,8 +143,6 @@ typedef
       /* Word 4 */
       const HChar* filename;     /* caller source filename */
       /* Word 5 */
-      const HChar* dirname;      /* caller source directory name */
-      /* Word 6 */
       UInt   lineno:LINENO_BITS; /* caller line number */
       UShort level:LEVEL_BITS;   /* level of inlining */
    }
@@ -812,8 +818,14 @@ struct _DebugInfo {
    DiSym*  symtab;
    UWord   symtab_used;
    UWord   symtab_size;
-   /* An expandable array of locations. */
+   /* Two expandable arrays, storing locations and their filename/dirname. */
    DiLoc*  loctab;
+   UInt    sizeof_fndn_ix;  /* Similar use as sizeof_cfsi_m_ix below. */
+   void*   loctab_fndn_ix;  /* loctab[i] filename/dirname is identified by
+                               loctab_fnindex_ix[i] (an index in di->fndnpool)
+                               0 means filename/dirname unknown.
+                               The void* is an UChar* or UShort* or UInt*
+                               depending on sizeof_fndn_ix. */
    UWord   loctab_used;
    UWord   loctab_size;
    /* An expandable array of inlined fn info.
@@ -838,16 +850,16 @@ struct _DebugInfo {
 
       For each base in cfsi_base, an index into cfsi_m_pool is stored
       in cfsi_m_ix array. The size of cfsi_m_ix is equal to
-      cfsi_size*sizeof_ix. The used portion of cfsi_m_ix is
-      cfsi_m_ix[0] till cfsi_m_ix[(cfsi_used-1)*sizeof_ix].
+      cfsi_size*sizeof_cfsi_m_ix. The used portion of cfsi_m_ix is
+      cfsi_m_ix[0] till cfsi_m_ix[(cfsi_used-1)*sizeof_cfsi_m_ix].
 
       cfsi_base[i] gives the base address of a code range covered by
       some CF Info. The corresponding CF Info is identified by an index
       in cfsi_m_pool. The DiCfSI_m index in cfsi_m_pool corresponding to
       cfsi_base[i] is given
-        by ((UChar*) cfsi_m_ix)[i] if sizeof_ix == 1
-        by ((UShort*)cfsi_m_ix)[i] if sizeof_ix == 2
-        by ((UInt*)  cfsi_m_ix)[i] if sizeof_ix == 4.
+        by ((UChar*) cfsi_m_ix)[i] if sizeof_cfsi_m_ix == 1
+        by ((UShort*)cfsi_m_ix)[i] if sizeof_cfsi_m_ix == 2
+        by ((UInt*)  cfsi_m_ix)[i] if sizeof_cfsi_m_ix == 4.
 
       The end of the code range starting at cfsi_base[i] is given by
       cfsi_base[i+1]-1 (or cfsi_maxavma for  cfsi_base[cfsi_used-1]).
@@ -875,8 +887,8 @@ struct _DebugInfo {
       records require any expression nodes, they are stored in
       cfsi_exprs. */
    Addr* cfsi_base;
-   UInt  sizeof_ix; /* size in byte of the indexes stored in cfsi_m_ix. */
-   void* cfsi_m_ix; /* Each index occupies sizeof_ix bytes. */
+   UInt  sizeof_cfsi_m_ix; /* size in byte of indexes stored in cfsi_m_ix. */
+   UInt* cfsi_m_ix; /* Each index occupies sizeof_cfsi_m_ix bytes. */
 
    DiCfSI* cfsi_rd; /* Only used during reading, NULL once info is read. */
                                    
@@ -900,6 +912,10 @@ struct _DebugInfo {
       into this are stable (the memory is not reallocated). */
    DedupPoolAlloc *strpool;
 
+   /* Pool of FnDn -- filename and dirname.
+      Elements in the pool are allocated using VG_(allocFixedEltDedupPA). */
+   DedupPoolAlloc *fndnpool;
+
    /* Variable scope information, as harvested from Dwarf3 files.
 
       In short it's an
@@ -953,18 +969,30 @@ struct _DebugInfo {
    to ensure that's OK. */
 extern void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym );
 
-/* Add a line-number record to a DebugInfo. */
+/* Add a filename/dirname pair to a DebugInfo and returns the index
+   in the fndnpool fixed pool. */
+extern UInt ML_(addFnDn) (struct _DebugInfo* di,
+                          const HChar* filename, 
+                          const HChar* dirname);  /* NULL is allowable */
+
+/* Returns the fndn_ix for the LineInfo locno in di->loctab.
+   0 if filename/dirname are unknown. */
+extern UInt ML_(fndn_ix) (struct _DebugInfo* di, Word locno);
+
+/* Add a line-number record to a DebugInfo.
+   fndn_ix is an index in di->fndnpool, allocated using  ML_(addFnDn).
+   Give a 0 index for a unknown filename/dirname pair. */
 extern
 void ML_(addLineInfo) ( struct _DebugInfo* di, 
-                        const HChar* filename, 
-                        const HChar* dirname,  /* NULL is allowable */
+                        UInt fndn_ix,
                         Addr this, Addr next, Int lineno, Int entry);
 
 /* Add a call inlined record to a DebugInfo.
    A call to the below means that inlinedfn code has been
    inlined, resulting in code from [addr_lo, addr_hi[.
    Note that addr_hi is excluded, i.e. is not part of the inlined code.
-   The call that caused this inlining is in filename/dirname/lineno
+   The call that caused this inlining is in filename/lineno (dirname
+   is not recorded).
    In case of nested inlining, a small level indicates the call
    is closer to main that a call with a higher level. */
 extern
@@ -972,7 +1000,6 @@ void ML_(addInlInfo) ( struct _DebugInfo* di,
                        Addr addr_lo, Addr addr_hi,
                        const HChar* inlinedfn,
                        const HChar* filename, 
-                       const HChar* dirname,  /* NULL is allowable */
                        Int lineno, UShort level);
 
 /* Add a CFI summary record.  The supplied DiCfSI_m is copied. */
index c6e9ebeb83a3b4b030ef579c8dac38f85e257cde..91c1493e3fe64f8fd10de72ac5d35afe356072ec 100644 (file)
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
-/*------------------------------------------------------------*/
-/*--- Expanding arrays of words, for holding file name and ---*/
-/*--- directory name arrays.                               ---*/
-/*------------------------------------------------------------*/
-
-typedef
-   struct {
-      Word* tab;
-      UInt  tab_size;
-      UInt  tab_used;
-   }
-   WordArray;
-
-static void init_WordArray ( WordArray* wa )
-{
-   wa->tab      = NULL;
-   wa->tab_size = 0;
-   wa->tab_used = 0;
-}
-
-static void free_WordArray ( WordArray* wa )
-{
-   if (wa->tab) {
-      vg_assert(wa->tab_size > 0);
-      ML_(dinfo_free)(wa->tab);
-   }
-   init_WordArray(wa);
-}
-
-static void addto_WordArray ( WordArray* wa, Word w )
+/* The below "safe_*ix" functions allow to resist to malformed dwarf info:
+   if dwarf info contains wrong file or dirname indexes, these are (silently!)
+   ignored. */
+
+/* if xa_ix is a valid index in fndn_ix_xa,
+    return the element (i.e. the UInt indexing in fndnpool).
+   If xa_ix is invalid, return 0 (i.e. the "null" element in fndnpool). */
+static UInt safe_fndn_ix (XArray* fndn_ix_xa, Int xa_ix)
 {
-   UInt  new_size, i;
-   Word* new_tab;
-
-   if (0) VG_(printf)("<<ADD %p (new sz = %d) >>\n", 
-                      (HChar*)w, wa->tab_used+1);
-
-   if (wa->tab_used < wa->tab_size) {
-      /* fine */
-   } else {
-      /* expand array */
-      if (0) VG_(printf)("EXPAND ARRAY from %d\n", wa->tab_size);
-      vg_assert(wa->tab_used == wa->tab_size);
-      vg_assert( (wa->tab_size == 0 && wa->tab == NULL)
-                 || (wa->tab_size != 0 && wa->tab != NULL) );
-      new_size = wa->tab_size == 0 ? 8 : 2 * wa->tab_size;
-      new_tab  = ML_(dinfo_zalloc)("di.aWA.1", new_size * sizeof(Word));
-      vg_assert(new_tab != NULL);
-      for (i = 0; i < wa->tab_used; i++)
-         new_tab[i] = wa->tab[i];
-      wa->tab_size = new_size;
-      if (wa->tab)
-         ML_(dinfo_free)(wa->tab);
-      wa->tab = new_tab;
-   }
-
-   vg_assert(wa->tab_used < wa->tab_size);
-   vg_assert(wa->tab_size > 0);
-   wa->tab[wa->tab_used] = w;
-   wa->tab_used++;
+   if (xa_ix < 0) return 0;
+   if (xa_ix >= VG_(sizeXA) (fndn_ix_xa)) return 0;
+   return *(UInt*)VG_(indexXA) ( fndn_ix_xa, xa_ix );
 }
 
-static Word index_WordArray ( /*OUT*/Bool* inRange, WordArray* wa, Int i )
+/* if xa_ix is a valid index in dirname_xa,
+    return the element (i.e. the HChar*).
+   If xa_ix is invalid, return NULL. */
+static HChar* safe_dirname_ix (XArray* dirname_xa, Int xa_ix)
 {
-   vg_assert(inRange);
-   if (i >= 0 && i < wa->tab_used) {
-      *inRange = True;
-      return wa->tab[i];
-   } else {
-      *inRange = False;
-      return 0;
-   }
+   if (xa_ix < 0) return NULL;
+   if (xa_ix >= VG_(sizeXA) (dirname_xa)) return NULL;
+   return *(HChar**)VG_(indexXA) ( dirname_xa, xa_ix );
 }
 
-
 /*------------------------------------------------------------*/
 /*--- Read DWARF2 format line number info.                 ---*/
 /*------------------------------------------------------------*/
@@ -296,26 +245,6 @@ void reset_state_machine ( Int is_stmt )
    state_machine_regs.end_sequence = 0;
 }
 
-/* Look up a directory name, or return NULL if unknown. */
-static
-HChar* lookupDir ( Int filename_index,
-                   WordArray* fnidx2dir,
-                   WordArray* dirnames )
-{
-   Bool inRange;
-   Word diridx, dirname;
-
-   diridx = index_WordArray( &inRange, fnidx2dir, filename_index );
-   if (!inRange) goto bad;
-
-   dirname = index_WordArray( &inRange, dirnames, (Int)diridx );
-   if (!inRange) goto bad;
-
-   return (HChar*)dirname;
-  bad:
-   return NULL;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
@@ -323,9 +252,7 @@ HChar* lookupDir ( Int filename_index,
    accordingly. */
 static 
 void process_extended_line_op( struct _DebugInfo* di,
-                               WordArray* filenames, 
-                               WordArray* dirnames, 
-                               WordArray* fnidx2dir, 
+                               XArray* fndn_ix_xa,
                                DiCursor* data, Int is_stmt)
 {
    UInt len = step_leb128U(data);
@@ -349,17 +276,10 @@ void process_extended_line_op( struct _DebugInfo* di,
 
          if (state_machine_regs.is_stmt) {
             if (state_machine_regs.last_address) {
-               Bool inRange = False;
-               const HChar* filename
-                  = (HChar*)index_WordArray( &inRange, filenames, 
-                                             state_machine_regs.last_file);
-               if (!inRange || !filename)
-                  filename = "???";
                ML_(addLineInfo) (
-                  di, 
-                  filename, 
-                  lookupDir( state_machine_regs.last_file,
-                             fnidx2dir, dirnames ),
+                  di,
+                  safe_fndn_ix (fndn_ix_xa,
+                                state_machine_regs.last_file),
                   di->text_debug_bias + state_machine_regs.last_address, 
                   di->text_debug_bias + state_machine_regs.address, 
                   state_machine_regs.last_line, 0
@@ -383,7 +303,8 @@ void process_extended_line_op( struct _DebugInfo* di,
 
       case DW_LNE_define_file: {
          HChar* name = ML_(cur_step_strdup)(data, "di.pelo.1");
-         addto_WordArray( filenames, (Word)ML_(addStr)(di,name,-1) );
+         UInt fndn_ix = ML_(addFnDn) (di, name, NULL);
+         VG_(addToXA) (fndn_ix_xa, &fndn_ix);
          ML_(dinfo_free)(name);
          (void)step_leb128U(data); // ignored: dir index
          (void)step_leb128U(data); // ignored: mod time
@@ -425,55 +346,48 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
    Int            i;
    DebugLineInfo  info;
    Bool           is64;
-   WordArray      filenames;
-   WordArray      dirnames;
-   WordArray      fnidx2dir;
+   XArray*        fndn_ix_xa; /* xarray of UInt fndn_ix */
+   UInt           fndn_ix;
+   XArray*        dirname_xa;   /* xarray of HChar* dirname */
+   HChar*         dirname;
 
    DiCursor       external = theBlock;
    DiCursor       data = theBlock;
 
-   /* filenames is an array of file names harvested from the DWARF2
-      info.  Entry [0] is NULL and is never referred to by the state
-      machine.
+   /* fndn_ix_xa is an xarray of fndn_ix (indexes in di->fndnpool) which
+      are build from file names harvested from the DWARF2
+      info.  Entry [0] is the "null" pool index and is never referred to
+      by the state machine.
 
-      Similarly, dirnames is an array of directory names.  Entry [0]
+      Similarly, dirname_xa is an xarray of directory names.  Entry [0]
       is also NULL and denotes "we don't know what the path is", since
       that is different from "the path is the empty string".  Unlike
-      the file name table, the state machine does refer to entry [0],
+      the fndn_ix_xa table, the state machine does refer to entry [0],
       which basically means "." ("the current directory of the
       compilation", whatever that means, according to the DWARF3
       spec.)
-
-      fnidx2dir is an array of indexes into the dirnames table.
-      (confused yet?)  filenames[] and fnidx2dir[] are indexed
-      together.  That is, for some index i in the filename table, then
-
-         the filename  is filenames[i]
-         the directory is dirnames[ fnidx2dir[i] ] */
+   */
 
    /* Fails due to gcc padding ...
    vg_assert(sizeof(DWARF2_External_LineInfo)
              == sizeof(DWARF2_Internal_LineInfo));
    */
 
-   init_WordArray(&filenames);
-   init_WordArray(&dirnames);
-   init_WordArray(&fnidx2dir);
+   dirname_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.1", ML_(dinfo_free),
+                            sizeof(HChar*) );
+   fndn_ix_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.2", ML_(dinfo_free),
+                            sizeof(UInt) );
 
    /* DWARF2 starts numbering filename entries at 1, so we need to
-      add a dummy zeroth entry to the table.  The zeroth dirnames
-      entry denotes 'current directory of compilation' so we might
-      as well make the fnidx2dir zeroth entry denote that. 
-   */
-   addto_WordArray( &filenames, (Word)NULL );
+      add a dummy zeroth entry to the table. */
+   fndn_ix = 0; // 0 is the "null" index in a fixed pool.
+   VG_(addToXA) (fndn_ix_xa, &fndn_ix);
 
    if (ML_(cur_is_valid)(ui->compdir))
-      addto_WordArray( &dirnames,
-                       (Word)ML_(addStrFromCursor)(di, ui->compdir) );
+      dirname = ML_(addStrFromCursor)(di, ui->compdir);
    else
-      addto_WordArray( &dirnames, (Word)ML_(addStr)(di, ".", -1) );
-
-   addto_WordArray( &fnidx2dir, (Word)0 );  /* compilation dir */
+      dirname = ML_(addStr)(di, ".", -1);
+   VG_(addToXA) (dirname_xa, &dirname);
 
    info.li_length = step_initial_length_field( &external, &is64 );
    if (di->ddump_line)
@@ -629,12 +543,14 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
          VG_(strcat)(buf, "/");
          VG_(strcat)(buf, data_str);
          vg_assert(VG_(strlen)(buf) < NBUF);
-         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,buf,-1) );
+         dirname = ML_(addStr)(di,buf,-1);
+         VG_(addToXA) (dirname_xa, &dirname);
          if (0) VG_(printf)("rel path  %s\n", buf);
          ML_(dinfo_free)(compdir_str);
       } else {
          /* just use 'data'. */
-         addto_WordArray( &dirnames, (Word)ML_(addStr)(di,data_str,-1) );
+         dirname = ML_(addStr)(di,data_str,-1);
+         VG_(addToXA) (dirname_xa, &dirname);
          if (0) VG_(printf)("abs path  %s\n", data_str);
       }
 
@@ -655,8 +571,7 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
    data = ML_(cur_plus)(data, 1);
 
    /* Read the contents of the File Name table.  This produces a bunch
-      of file names, and for each, an index to the corresponding
-      directory name entry. */
+      of fndn_ix in fndn_ix_xa. */
    if (di->ddump_line) {
       VG_(printf)(" The File Name Table:\n");
       VG_(printf)("  Entry     Dir     Time    Size    Name\n");
@@ -668,8 +583,10 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
       Int    diridx  = step_leb128U(&data);
       Int    uu_time = step_leb128U(&data); /* unused */
       Int    uu_size = step_leb128U(&data); /* unused */
-      addto_WordArray( &filenames, (Word)ML_(addStr)(di,name,-1) );
-      addto_WordArray( &fnidx2dir, (Word)diridx );
+
+      dirname = safe_dirname_ix( dirname_xa, diridx );
+      fndn_ix = ML_(addFnDn) (di, name, dirname);
+      VG_(addToXA) (fndn_ix_xa, &fndn_ix);
       if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
       if (di->ddump_line)
          VG_(printf)("  %d\t%d\t%d\t%d\t%s\n", 
@@ -720,17 +637,10 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
          if (state_machine_regs.is_stmt) {
             /* only add a statement if there was a previous boundary */
             if (state_machine_regs.last_address) {
-               Bool inRange = False;
-               const HChar* filename
-                  = (HChar*)index_WordArray( &inRange, &filenames, 
-                                             state_machine_regs.last_file);
-               if (!inRange || !filename)
-                  filename = "???";
                ML_(addLineInfo)(
-                  di, 
-                  filename,
-                  lookupDir( state_machine_regs.last_file,
-                             &fnidx2dir, &dirnames ),
+                  di,
+                  safe_fndn_ix (fndn_ix_xa,
+                                state_machine_regs.last_file),
                   di->text_debug_bias + state_machine_regs.last_address, 
                   di->text_debug_bias + state_machine_regs.address, 
                   state_machine_regs.last_line, 
@@ -748,7 +658,7 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
       switch (op_code) {
          case DW_LNS_extended_op:
             process_extended_line_op (
-                       di, &filenames, &dirnames, &fnidx2dir,
+                       di, fndn_ix_xa,
                        &data, info.li_default_is_stmt);
             break;
 
@@ -758,17 +668,10 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
             if (state_machine_regs.is_stmt) {
                /* only add a statement if there was a previous boundary */
                if (state_machine_regs.last_address) {
-                  Bool inRange = False;
-                  const HChar* filename
-                     = (HChar*)index_WordArray( &inRange, &filenames,
-                                                state_machine_regs.last_file );
-                  if (!inRange || !filename)
-                     filename = "???";
                   ML_(addLineInfo)(
-                     di, 
-                     filename,
-                     lookupDir( state_machine_regs.last_file,
-                                &fnidx2dir, &dirnames ),
+                     di,
+                     safe_fndn_ix (fndn_ix_xa,
+                                   state_machine_regs.last_file), 
                      di->text_debug_bias + state_machine_regs.last_address, 
                      di->text_debug_bias + state_machine_regs.address,
                      state_machine_regs.last_line, 
@@ -887,9 +790,8 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
       VG_(printf)("\n");
 
   out:
-   free_WordArray(&filenames);
-   free_WordArray(&dirnames);
-   free_WordArray(&fnidx2dir);
+   VG_(deleteXA)(dirname_xa);
+   VG_(deleteXA)(fndn_ix_xa);
 }
 
 ////////////////////////////////////////////////////////////////////
index a3c0a0f0732a993afb6120af041fbafbe2d5c988..0dd49df129aaf6ca17a11d52c62835477abc16b9 100644 (file)
@@ -2600,7 +2600,6 @@ static Bool parse_inl_DIE (
                              ip_lo, ip_hi1, 
                              get_inlFnName (inlinedfn_abstract_origin, cc, td3),
                              caller_filename,
-                             NULL, // INLINED TBD dirname ?????
                              caller_lineno, level);
          }
       } else if (have_range) {
@@ -2622,7 +2621,6 @@ static Bool parse_inl_DIE (
                              // included.
                              inlfnname,
                              caller_filename,
-                             NULL, // INLINED TBD dirname ?????
                              caller_lineno, level);
          }
          VG_(deleteXA)( ranges );
index c57ac228a8e754c128878b71cbbf206a8a83a59c..9c69750aabcce392b55775ccacf154d5c7cd0c3a 100644 (file)
@@ -1453,6 +1453,7 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
    vg_assert(!di->cfsi_rd);
    vg_assert(!di->cfsi_exprs);
    vg_assert(!di->strpool);
+   vg_assert(!di->fndnpool);
    vg_assert(!di->soname);
 
    {
index 3824a33e31c0e6014e4b3f5336b6d2b7b6fe7bf2..6d2ccd1387c05968c2a2c3b803a1a342fea787a5 100644 (file)
@@ -1630,7 +1630,11 @@ static ULong DEBUG_SnarfLinetab(
                         ((const unsigned short *)(pnt2.ui + linecount))[j],
                         startaddr, endaddr );
                   ML_(addLineInfo)(
-                     di, fnmstr, dirstr, startaddr, endaddr,
+                     di, 
+                     ML_(addFnDn) (di, // fndnTBD
+                                   fnmstr,
+                                   dirstr), 
+                     startaddr, endaddr,
                      ((const unsigned short *)(pnt2.ui + linecount))[j], j );
                   n_lines_read++;
                }
@@ -1767,7 +1771,10 @@ static ULong codeview_dump_linetab2(
             if (debug)
                VG_(printf)("%s  line %d: %08lx to %08lx\n",
                            pfx, lbh->l[i].lineno ^ 0x80000000, svma_s, svma_e);
-            ML_(addLineInfo)( di, filename, dirname,
+            ML_(addLineInfo)( di, 
+                              ML_(addFnDn) (di, // fndnTBD
+                                            filename,
+                                            dirname),
                               bias + svma_s,
                               bias + svma_e + 1,
                               lbh->l[i].lineno ^ 0x80000000, 0 );
@@ -1781,7 +1788,10 @@ static ULong codeview_dump_linetab2(
             VG_(printf)("%s  line %d: %08lx to %08lx\n",
                         pfx, lbh->l[ lbh->nlines-1  ].lineno ^ 0x80000000,
                         svma_s, svma_e);
-          ML_(addLineInfo)( di, filename, dirname,
+          ML_(addLineInfo)( di, 
+                            ML_(addFnDn) (di, // fndnTBD
+                                          filename,
+                                          dirname),
                             bias + svma_s,
                             bias + svma_e + 1,
                             lbh->l[lbh->nlines-1].lineno ^ 0x80000000, 0 );
index 736ae820f819fc0f7b500744908d177486d46da9..e9892dc91b0051488df072688b27fa41e85cb088 100644 (file)
@@ -124,6 +124,12 @@ void ML_(read_debuginfo_stabs) ( DebugInfo* di,
       Bool     first;         /* first line in function */
    } line = { 0, 0, 0, 0, False };
 
+   vg_assert (0);
+   /* Stab reader broken since debuginfo server (revision 13440)
+      See #if 0 for call to  ML_(read_debuginfo_stabs) in readelf.c.
+      If ever it is repaired, file.name above should be replaced by a fndn_ix
+      for performance reasons. */
+
    /* Ok.  It all looks plausible.  Go on and read debug data. 
          stab kinds: 100   N_SO     a source file name
                       68   N_SLINE  a source line number
@@ -270,7 +276,11 @@ void ML_(read_debuginfo_stabs) ( DebugInfo* di,
 
             if (line.addr != 0) {
                /* finish off previous line */
-               ML_(addLineInfo)(di, file.name, NULL, line.addr,
+               ML_(addLineInfo)(di, 
+                                ML_(addFnDn) (di,
+                                              file.name,
+                                              NULL),
+                                line.addr,
                                 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
             }
 
@@ -294,7 +304,11 @@ void ML_(read_debuginfo_stabs) ( DebugInfo* di,
 
             if (line.addr != 0) {
                /* there was a previous */
-               ML_(addLineInfo)(di, file.name, NULL, line.addr,
+               ML_(addLineInfo)(di, 
+                                ML_(addFnDn)(di,
+                                             file.name,
+                                             NULL), 
+                                line.addr,
                                 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
             }
 
@@ -353,7 +367,11 @@ void ML_(read_debuginfo_stabs) ( DebugInfo* di,
             }
 
             if (line.addr) {
-               ML_(addLineInfo)(di, file.name, NULL, line.addr,
+               ML_(addLineInfo)(di, 
+                                ML_(addFnDn) (di,
+                                              file.name,
+                                              NULL),
+                                line.addr,
                                 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
                line.addr = 0;
             }
index 78bcdf6b35d938043a75af07a402e38e49ff0316..c2bbe8289feacdd88b93e07b33b70b2dba48e0d3 100644 (file)
@@ -252,6 +252,24 @@ HChar* ML_(addStr) ( struct _DebugInfo* di, const HChar* str, Int len )
    return p;
 }
 
+UInt ML_(addFnDn) (struct _DebugInfo* di,
+                   const HChar* filename, 
+                   const HChar* dirname)
+{
+   FnDn fndn;
+   UInt fndn_ix;
+
+   if (UNLIKELY(di->fndnpool == NULL))
+      di->fndnpool = VG_(newDedupPA)(500,
+                                     vg_alignof(FnDn),
+                                     ML_(dinfo_zalloc),
+                                     "di.storage.addFnDn.1",
+                                     ML_(dinfo_free));
+   fndn.filename = ML_(addStr)(di, filename, -1);
+   fndn.dirname = dirname ? ML_(addStr)(di, dirname, -1) : NULL;
+   fndn_ix = VG_(allocFixedEltDedupPA) (di->fndnpool, sizeof(FnDn), &fndn);
+   return fndn_ix;
+}
 
 /* Add a string to the string table of a DebugInfo, by copying the
    string from the given DiCursor.  Measures the length of the string
@@ -301,32 +319,101 @@ void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym )
    vg_assert(di->symtab_used <= di->symtab_size);
 }
 
+UInt ML_(fndn_ix) (struct _DebugInfo* di, Word locno)
+{
+   UInt fndn_ix;
+
+   switch(di->sizeof_fndn_ix) {
+      case 1: fndn_ix = ((UChar*)  di->loctab_fndn_ix)[locno]; break;
+      case 2: fndn_ix = ((UShort*) di->loctab_fndn_ix)[locno]; break;
+      case 4: fndn_ix = ((UInt*)   di->loctab_fndn_ix)[locno]; break;
+      default: vg_assert(0);
+   }
+   return fndn_ix;
+}
+
+static inline void set_fndn_ix (struct _DebugInfo* di, Word locno, UInt fndn_ix)
+{
+   Word i;
+
+   switch(di->sizeof_fndn_ix) {
+      case 1: 
+         if (LIKELY (fndn_ix <= 255)) {
+            ((UChar*) di->loctab_fndn_ix)[locno] = fndn_ix;
+            return;
+         }
+         {
+            UChar* old = (UChar*) di->loctab_fndn_ix;
+            UShort* new = ML_(dinfo_zalloc)( "di.storage.sfix.1",
+                                             di->loctab_size * 2 );
+            for (i = 0; i < di->loctab_used; i++)
+               new[i] = old[i];
+            ML_(dinfo_free)(old);
+            di->sizeof_fndn_ix = 2;
+            di->loctab_fndn_ix = new;
+         }
+         // Fallthrough
+
+      case 2:
+         if (LIKELY (fndn_ix <= 65535)) {
+            ((UShort*) di->loctab_fndn_ix)[locno] = fndn_ix;
+            return;
+         }
+         {
+            UShort* old = (UShort*) di->loctab_fndn_ix;
+            UInt* new = ML_(dinfo_zalloc)( "di.storage.sfix.2",
+                                           di->loctab_size * 4 );
+            for (i = 0; i < di->loctab_used; i++)
+               new[i] = old[i];
+            ML_(dinfo_free)(old);
+            di->sizeof_fndn_ix = 4;
+            di->loctab_fndn_ix = new;
+         }
+         // Fallthrough
+
+      case 4:
+         ((UInt*) di->loctab_fndn_ix)[locno] = fndn_ix;
+         return;
+
+      default: vg_assert(0);
+   }
+}
 
 /* Add a location to the location table. 
 */
-static void addLoc ( struct _DebugInfo* di, DiLoc* loc )
+static void addLoc ( struct _DebugInfo* di, DiLoc* loc, UInt fndn_ix )
 {
-   UInt   new_sz, i;
-   DiLoc* new_tab;
-
    /* Zero-sized locs should have been ignored earlier */
    vg_assert(loc->size > 0);
 
    if (di->loctab_used == di->loctab_size) {
+      UInt   new_sz;
+      DiLoc* new_loctab;
+      void*  new_loctab_fndn_ix;
+
       new_sz = 2 * di->loctab_size;
       if (new_sz == 0) new_sz = 500;
-      new_tab = ML_(dinfo_zalloc)( "di.storage.addLoc.1",
-                                   new_sz * sizeof(DiLoc) );
+      new_loctab = ML_(dinfo_zalloc)( "di.storage.addLoc.1",
+                                      new_sz * sizeof(DiLoc) );
+      if (di->sizeof_fndn_ix == 0)
+         di->sizeof_fndn_ix = 1; // To start with.
+      new_loctab_fndn_ix = ML_(dinfo_zalloc)( "di.storage.addLoc.2",
+                                              new_sz * di->sizeof_fndn_ix );
       if (di->loctab != NULL) {
-         for (i = 0; i < di->loctab_used; i++)
-            new_tab[i] = di->loctab[i];
+         VG_(memcpy)(new_loctab, di->loctab,
+                     di->loctab_used * sizeof(DiLoc));
+         VG_(memcpy)(new_loctab_fndn_ix, di->loctab_fndn_ix,
+                     di->loctab_used * di->sizeof_fndn_ix);
          ML_(dinfo_free)(di->loctab);
+         ML_(dinfo_free)(di->loctab_fndn_ix);
       }
-      di->loctab = new_tab;
+      di->loctab = new_loctab;
+      di->loctab_fndn_ix = new_loctab_fndn_ix;
       di->loctab_size = new_sz;
    }
 
    di->loctab[di->loctab_used] = *loc;
+   set_fndn_ix (di, di->loctab_used, fndn_ix);
    di->loctab_used++;
    vg_assert(di->loctab_used <= di->loctab_size);
 }
@@ -341,6 +428,7 @@ static void shrinkLocTab ( struct _DebugInfo* di )
    if (new_sz == di->loctab_size) return;
    vg_assert(new_sz < di->loctab_size);
    ML_(dinfo_shrink_block)( di->loctab, new_sz * sizeof(DiLoc));
+   ML_(dinfo_shrink_block)( di->loctab_fndn_ix, new_sz * di->sizeof_fndn_ix);
    di->loctab_size = new_sz;
 }
 
@@ -348,8 +436,7 @@ static void shrinkLocTab ( struct _DebugInfo* di )
 /* Top-level place to call to add a source-location mapping entry.
 */
 void ML_(addLineInfo) ( struct _DebugInfo* di,
-                        const HChar* filename,
-                        const HChar* dirname, /* NULL == directory is unknown */
+                        UInt     fndn_ix,
                         Addr     this,
                         Addr     next,
                         Int      lineno,
@@ -363,10 +450,13 @@ void ML_(addLineInfo) ( struct _DebugInfo* di,
    /* Ignore zero-sized locs */
    if (this == next) return;
 
-   if (debug)
-      VG_(printf)( "  src %s %s line %d %#lx-%#lx\n",
-                   dirname ? dirname : "(unknown)",
-                   filename, lineno, this, next );
+   if (debug) {
+      FnDn *fndn = VG_(indexEltNumber) (di->fndnpool, fndn_ix);
+      VG_(printf)( "  src ix %u %s %s line %d %#lx-%#lx\n",
+                   fndn_ix, 
+                   fndn->dirname ? fndn->dirname : "(unknown)",
+                   fndn->filename, lineno, this, next );
+   }
 
    /* Maximum sanity checking.  Some versions of GNU as do a shabby
     * job with stabs entries; if anything looks suspicious, revert to
@@ -435,14 +525,12 @@ void ML_(addLineInfo) ( struct _DebugInfo* di,
    loc.addr      = this;
    loc.size      = (UShort)size;
    loc.lineno    = lineno;
-   loc.filename  = filename;
-   loc.dirname   = dirname;
 
    if (0) VG_(message)(Vg_DebugMsg, 
-                      "addLoc: addr %#lx, size %lu, line %d, file %s\n",
-                      this,size,lineno,filename);
+                      "addLoc: addr %#lx, size %lu, line %d, fndn_ix %u\n",
+                      this,size,lineno,fndn_ix);
 
-   addLoc ( di, &loc );
+   addLoc ( di, &loc, fndn_ix );
 }
 
 /* Add an inlined call info to the inlined call table. 
@@ -494,7 +582,6 @@ void ML_(addInlInfo) ( struct _DebugInfo* di,
                        Addr addr_lo, Addr addr_hi,
                        const HChar* inlinedfn,
                        const HChar* filename, 
-                       const HChar* dirname,  /* NULL is allowable */
                        Int lineno, UShort level)
 {
    DiInlLoc inl;
@@ -532,16 +619,14 @@ void ML_(addInlInfo) ( struct _DebugInfo* di,
    inl.inlinedfn = inlinedfn;
    // caller:
    inl.filename  = filename;
-   inl.dirname   = dirname;
    inl.lineno    = lineno;
    inl.level     = level;
 
    if (0) VG_(message)
              (Vg_DebugMsg, 
               "addInlInfo: fn %s inlined as addr_lo %#lx,addr_hi %#lx,"
-              "caller %s:%d (dir %s)\n",
-              inlinedfn, addr_lo, addr_hi, filename, lineno, 
-              dirname ? dirname : "???");
+              "caller %s:%d\n",
+              inlinedfn, addr_lo, addr_hi, filename, lineno);
 
    addInl ( di, &inl );
 }
@@ -551,7 +636,7 @@ DiCfSI_m* ML_(get_cfsi_m) (struct _DebugInfo* di, UInt pos)
    UInt cfsi_m_ix;
 
    vg_assert(pos >= 0 && pos < di->cfsi_used);
-   switch (di->sizeof_ix) {
+   switch (di->sizeof_cfsi_m_ix) {
       case 1: cfsi_m_ix = ((UChar*)  di->cfsi_m_ix)[pos]; break;
       case 2: cfsi_m_ix = ((UShort*) di->cfsi_m_ix)[pos]; break;
       case 4: cfsi_m_ix = ((UInt*)   di->cfsi_m_ix)[pos]; break;
@@ -1743,33 +1828,72 @@ static void canonicaliseSymtab ( struct _DebugInfo* di )
 }
 
 
-/* Sort the location table by starting address.  Mash the table around
-   so as to establish the property that addresses are in order and the
-   ranges do not overlap.  This facilitates using binary search to map
-   addresses to locations when we come to query the table.
-*/
-static Int compare_DiLoc ( const void* va, const void* vb ) 
+static DiLoc* sorting_loctab = NULL;
+static Int compare_DiLoc_via_ix ( const void* va, const void* vb ) 
 {
-   const DiLoc* a = va;
-   const DiLoc* b = vb;
+   const DiLoc* a = &sorting_loctab[*(UInt*)va];
+   const DiLoc* b = &sorting_loctab[*(UInt*)vb];
    if (a->addr < b->addr) return -1;
    if (a->addr > b->addr) return  1;
    return 0;
 }
+static void sort_loctab_and_loctab_fndn_ix (struct _DebugInfo* di )
+{
+   /* We have to sort the array loctab by addr
+      together with its "parallel" array loctab_fndn_ix.
+      We first build sort_ix : an array of indexes in loctab,
+      that we sort by loctab address. Then we can reorder both
+      arrays according to sort_ix. */
+   UInt *sort_ix = ML_(dinfo_zalloc)("di.storage.six",
+                                     di->loctab_used*sizeof(UInt));
+   Word i, j, k;
+
+   for (i = 0; i < di->loctab_used; i++) sort_ix[i] = i;
+   sorting_loctab = di->loctab;
+   VG_(ssort)(sort_ix, di->loctab_used, 
+              sizeof(*sort_ix), compare_DiLoc_via_ix);
+   sorting_loctab = NULL;
+
+   // Permute in place, using the sort_ix.
+   for (i=0; i < di->loctab_used; i++) {
+      DiLoc tmp_diloc;
+      UInt  tmp_fndn_ix;
+
+      if (i == sort_ix[i])
+         continue; // i already at the good place
+
+      tmp_diloc = di->loctab[i];
+      tmp_fndn_ix = ML_(fndn_ix)(di, i);
+      j = i;
+      for (;;) {
+         k = sort_ix[j];
+         sort_ix[j] = j;
+         if (k == i)
+            break;
+         di->loctab[j] = di->loctab[k];
+         set_fndn_ix (di, j, ML_(fndn_ix)(di, k));
+         j = k;
+      }
+      di->loctab[j] = tmp_diloc;
+      set_fndn_ix (di, j, tmp_fndn_ix);
+   }
+   ML_(dinfo_free)(sort_ix);
+}
 
+/* Sort the location table by starting address.  Mash the table around
+   so as to establish the property that addresses are in order and the
+   ranges do not overlap.  This facilitates using binary search to map
+   addresses to locations when we come to query the table.
+*/
 static void canonicaliseLoctab ( struct _DebugInfo* di )
 {
    Word i, j;
 
-#  define SWAP(ty,aa,bb) \
-      do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
-
    if (di->loctab_used == 0)
       return;
 
-   /* Sort by start address. */
-   VG_(ssort)(di->loctab, di->loctab_used, 
-                          sizeof(*di->loctab), compare_DiLoc);
+   /* sort loctab and loctab_fndn_ix by addr. */
+   sort_loctab_and_loctab_fndn_ix (di);
 
    /* If two adjacent entries overlap, truncate the first. */
    for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
@@ -1794,8 +1918,10 @@ static void canonicaliseLoctab ( struct _DebugInfo* di )
    j = 0;
    for (i = 0; i < (Word)di->loctab_used; i++) {
       if (di->loctab[i].size > 0) {
-         if (j != i)
+         if (j != i) {
             di->loctab[j] = di->loctab[i];
+            set_fndn_ix(di, j, ML_(fndn_ix)(di, i));
+         }
          j++;
       }
    }
@@ -1803,11 +1929,15 @@ static void canonicaliseLoctab ( struct _DebugInfo* di )
 
    /* Ensure relevant postconditions hold. */
    for (i = 0; i < ((Word)di->loctab_used)-1; i++) {
-      /* 
-      VG_(printf)("%d   (%d) %d 0x%x\n", 
-                   i, di->loctab[i+1].confident, 
-                   di->loctab[i+1].size, di->loctab[i+1].addr );
-      */
+      if (0)
+         VG_(printf)("%lu  0x%p  lno:%d sz:%d fndn_ix:%d  i+1 0x%p\n", 
+                     i,
+                     (void*)di->loctab[i].addr,
+                     di->loctab[i].lineno, 
+                     di->loctab[i].size,
+                     ML_(fndn_ix)(di, i),
+                     (void*)di->loctab[i+1].addr);
+      
       /* No zero-sized symbols. */
       vg_assert(di->loctab[i].size > 0);
       /* In order. */
@@ -1816,7 +1946,6 @@ static void canonicaliseLoctab ( struct _DebugInfo* di )
       vg_assert(di->loctab[i].addr + di->loctab[i].size - 1
                 < di->loctab[i+1].addr);
    }
-#  undef SWAP
 
    /* Free up unused space at the end of the table. */
    shrinkLocTab(di);
@@ -2024,16 +2153,16 @@ void ML_(finish_CFSI_arrays) ( struct _DebugInfo* di )
    sz_cfsi_m_pool = VG_(sizeDedupPA)(di->cfsi_m_pool);
    vg_assert (sz_cfsi_m_pool > 0);
    if (sz_cfsi_m_pool <= 255)
-      di->sizeof_ix = 1;
+      di->sizeof_cfsi_m_ix = 1;
    else if (sz_cfsi_m_pool <= 65535)
-      di->sizeof_ix = 2;
+      di->sizeof_cfsi_m_ix = 2;
    else
-      di->sizeof_ix = 4;
+      di->sizeof_cfsi_m_ix = 4;
 
    di->cfsi_base = ML_(dinfo_zalloc)( "di.storage.finCfSI.1",
                                        new_used * sizeof(Addr) );
    di->cfsi_m_ix = ML_(dinfo_zalloc)( "di.storage.finCfSI.2",
-                                      new_used * sizeof(UChar)*di->sizeof_ix);
+                                      new_used * sizeof(UChar)*di->sizeof_cfsi_m_ix);
 
    pos = 0;
    f_mergeables = 0;
@@ -2055,7 +2184,7 @@ void ML_(finish_CFSI_arrays) ( struct _DebugInfo* di )
          if (sep > 1) {
             f_holes++;
             di->cfsi_base[pos] = prev_max + 1;
-            switch (di->sizeof_ix) {
+            switch (di->sizeof_cfsi_m_ix) {
                case 1: ((UChar*) di->cfsi_m_ix)[pos] = 0; break;
                case 2: ((UShort*)di->cfsi_m_ix)[pos] = 0; break;
                case 4: ((UInt*)  di->cfsi_m_ix)[pos] = 0; break;
@@ -2067,7 +2196,7 @@ void ML_(finish_CFSI_arrays) ( struct _DebugInfo* di )
 
       // Insert the cfsi entry i.
       di->cfsi_base[pos] = di->cfsi_rd[i].base;
-      switch (di->sizeof_ix) {
+      switch (di->sizeof_cfsi_m_ix) {
          case 1: ((UChar*) di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
          case 2: ((UShort*)di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
          case 4: ((UInt*)  di->cfsi_m_ix)[pos] = di->cfsi_rd[i].cfsi_m_ix; break;
@@ -2097,10 +2226,11 @@ void ML_(canonicaliseTables) ( struct _DebugInfo* di )
    ML_(canonicaliseCFI) ( di );
    if (di->cfsi_m_pool)
       VG_(freezeDedupPA) (di->cfsi_m_pool, ML_(dinfo_shrink_block));
-   /// TBD prepare cfsi_base and cfsi_m_ix
    canonicaliseVarInfo ( di );
    if (di->strpool)
       VG_(freezeDedupPA) (di->strpool, ML_(dinfo_shrink_block));
+   if (di->fndnpool)
+      VG_(freezeDedupPA) (di->fndnpool, ML_(dinfo_shrink_block));
 }