]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Rework storage management in the Dwarf3 type and variable reader, to
authorJulian Seward <jseward@acm.org>
Fri, 22 Aug 2008 23:18:02 +0000 (23:18 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 22 Aug 2008 23:18:02 +0000 (23:18 +0000)
try and reduce its space consumption.  This change changes some long
linked lists into XArrays instead.

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

coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_d3basics.h
coregrind/m_debuginfo/priv_storage.h
coregrind/m_debuginfo/priv_tytypes.h
coregrind/m_debuginfo/readdwarf3.c
coregrind/m_debuginfo/tytypes.c

index d45a647547a641790ad2443da018033288b9ba16..9e4688d4ad1d187ce32a4b8711cf265f480dd58a 100644 (file)
@@ -192,10 +192,10 @@ DebugInfo* alloc_DebugInfo( const UChar* filename,
 /* Free a DebugInfo, and also all the stuff hanging off it. */
 static void free_DebugInfo ( DebugInfo* di )
 {
-   Word i, j;
+   Word i, j, n;
    struct strchunk *chunk, *next;
-   TyAdmin *admin1, *admin2;
-   GExpr *gexpr1, *gexpr2;
+   TyAdmin* admin;
+   GExpr* gexpr;
 
    vg_assert(di != NULL);
    if (di->filename)   ML_(dinfo_free)(di->filename);
@@ -212,13 +212,24 @@ static void free_DebugInfo ( DebugInfo* di )
    /* Delete the two admin lists.  These lists exist purely so that we
       can visit each object exactly once when we need to delete
       them. */
-   for (admin1 = di->admin_tyadmins; admin1; admin1 = admin2) {
-      admin2 = admin1->next;
-      ML_(delete_TyAdmin_and_payload)(admin1);
+   if (di->admin_tyadmins) {
+      n = VG_(sizeXA)(di->admin_tyadmins);
+      for (i = 0; i < n; i++) {
+         admin = (TyAdmin*)VG_(indexXA)(di->admin_tyadmins, i);
+         ML_(delete_payload_of_TyAdmin)(admin);
+      }
+      VG_(deleteXA)(di->admin_tyadmins);
+      di->admin_tyadmins = NULL;
    }
-   for (gexpr1 = di->admin_gexprs; gexpr1; gexpr1 = gexpr2) {
-      gexpr2 = gexpr1->next;
-      ML_(dinfo_free)(gexpr1);
+
+   if (di->admin_gexprs) {
+      n = VG_(sizeXA)(di->admin_gexprs);
+      for (i = 0; i < n; i++) {
+         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
+         ML_(dinfo_free)(gexpr);
+      }
+      VG_(deleteXA)(di->admin_gexprs);
+      di->admin_gexprs = NULL;
    }
 
    /* Dump the variable info.  This is kinda complex: we must take
index a445e097a046eff038af3b9d41f98a6f8afbaadd..3d3cb48eddbee9fa5db2df1d806e98dc11155b6f 100644 (file)
@@ -577,7 +577,6 @@ HChar* ML_(pp_DW_AT)       ( DW_AT attr );
 */
 typedef
    struct _GExpr { 
-      struct _GExpr* next;
       UChar payload[0];
    }
    GExpr;
index 51f0a1493604e1a8e0d873596eaf3b79ac6d6548..04799a6b7f8fd9a517d1549e15ff70f284bdf47c 100644 (file)
@@ -403,9 +403,9 @@ struct _DebugInfo {
       expressly for the purposes of visiting each object exactly once
       when we need to delete them. */
 
-   /* A list of TyAdmin structs, and the payloads that they refer
+   /* An array of TyAdmin structs, and the payloads that they refer
       to. */
-   TyAdmin* admin_tyadmins;
+   XArray* /* of TyAdmin */ admin_tyadmins;
 
    /* A list of guarded DWARF3 expressions. */
    GExpr*   admin_gexprs;
index 646de9729cc32613baf61f446cbadafd44507ec1..dcc6f40913c4b03520eb83fe90687d3c46e4580c 100644 (file)
@@ -52,7 +52,6 @@ typedef
 struct _TyAdmin {
    UWord      cuOff;
    void*      payload;
-   TyAdmin*   next;
    TyAdminTag tag;
 };
 
@@ -128,14 +127,16 @@ struct _Type {
    } Ty;
 };
 
-TyAdmin*  ML_(new_TyAdmin)  ( UWord cuOff, TyAdmin* next );
+TyAdmin*  ML_(new_TyAdmin)  ( UWord cuOff );
 TyAtom*   ML_(new_TyAtom)   ( UChar* name, Long value );
 TyField*  ML_(new_TyField)  ( UChar* name, Type* typeR, D3Expr* loc );
 TyBounds* ML_(new_TyBounds) ( void );
 Type*     ML_(new_Type)     ( void );
 D3Expr*   ML_(new_D3Expr)   ( UChar* bytes, UWord nbytes );
 
-void ML_(delete_TyAdmin_and_payload) ( TyAdmin* ad );
+/* Delete the payload attached to this TyAdmin, but not the TyAdmin
+   itself. */
+void ML_(delete_payload_of_TyAdmin) ( TyAdmin* );
 
 void ML_(pp_TyAdmin)  ( TyAdmin* admin );
 void ML_(pp_TyAtom)   ( TyAtom* atom );
index ec33bde82161c3482135949bcbd1c6c73f41b461..da4e8bcf5a9fd5c1f0591b7aa6c5f6873b7fe252 100644 (file)
@@ -630,7 +630,6 @@ static GExpr* make_singleton_GX ( UChar* block, UWord nbytes )
    vg_assert( &gx->payload[bytesReqd] 
               == ((UChar*)gx) + sizeof(GExpr) + bytesReqd );
 
-   gx->next = NULL;
    return gx;
 }
 
@@ -737,8 +736,6 @@ static GExpr* make_general_GX ( CUConst* cc,
 
    VG_(deleteXA)( xa );
 
-   gx->next = NULL;
-
    TRACE_D3("}\n");
 
    return gx;
@@ -1134,7 +1131,6 @@ void get_Form_contents ( /*OUT*/ULong* cts,
 
 typedef
    struct _TempVar {
-      struct _TempVar* next;
       UChar*  name; /* in DebugInfo's .strchunks */
       /* Represent ranges economically.  nRanges is the number of
          ranges.  Cases:
@@ -1387,8 +1383,8 @@ void read_filename_table( /*MOD*/D3VarParser* parser,
 
 
 __attribute__((noinline))
-static void parse_var_DIE ( /*OUT*/TempVar** tempvars,
-                            /*OUT*/GExpr** gexprs,
+static void parse_var_DIE ( /*MOD*/XArray* /* of TempVar* */ tempvars,
+                            /*MOD*/XArray* /* of GExpr* */ gexprs,
                             /*MOD*/D3VarParser* parser,
                             DW_TAG dtag,
                             UWord posn,
@@ -1545,9 +1541,7 @@ static void parse_var_DIE ( /*OUT*/TempVar** tempvars,
                  || (ctsMemSzB == 0 && ctsSzB > 0))) {
             fbGX = get_GX( cc, False/*td3*/, cts, ctsSzB, ctsMemSzB );
             vg_assert(fbGX);
-            vg_assert(!fbGX->next);
-            fbGX->next = *gexprs;
-            *gexprs = fbGX;
+            VG_(addToXA)(gexprs, &fbGX);
          }
       }
       /* Do we have something that looks sane? */
@@ -1621,9 +1615,7 @@ static void parse_var_DIE ( /*OUT*/TempVar** tempvars,
                  || (ctsMemSzB == 0 && ctsSzB > 0))) {
             gexpr = get_GX( cc, False/*td3*/, cts, ctsSzB, ctsMemSzB );
             vg_assert(gexpr);
-            vg_assert(!gexpr->next);
-            gexpr->next = *gexprs;
-            *gexprs = gexpr;
+            VG_(addToXA)(gexprs, &gexpr);
          }
          if (attr == DW_AT_type && ctsSzB > 0) {
             typeR = (Type*)(UWord)cts;
@@ -1748,8 +1740,7 @@ static void parse_var_DIE ( /*OUT*/TempVar** tempvars,
             tv->rngMany = VG_(cloneXA)( xa ); /* free when 'tv' freed */
          }
 
-         tv->next  = *tempvars;
-         *tempvars = tv;
+         VG_(addToXA)( tempvars, &tv );
 
          TRACE_D3("  Recording this variable, with %ld PC range(s)\n",
                   VG_(sizeXA)(xa) );
@@ -1963,7 +1954,7 @@ static void typestack_push ( CUConst* cc,
    it.
 */
 __attribute__((noinline))
-static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
+static void parse_type_DIE ( /*MOD*/XArray* /* of TyAdmin */ admin,
                              /*MOD*/D3TypeParser* parser,
                              DW_TAG dtag,
                              UWord posn,
@@ -1981,6 +1972,7 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
    TyField*  field  = NULL;
    D3Expr*   expr   = NULL;
    TyBounds* bounds = NULL;
+   TyAdmin   tyad;
 
    UWord saved_die_c_offset  = get_position_of_Cursor( c_die );
    UWord saved_abbv_c_offset = get_position_of_Cursor( c_abbv );
@@ -2488,9 +2480,11 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
    if (0) VG_(printf)("YYYY Acquire Type\n");
    vg_assert(type); vg_assert(!atom); vg_assert(!field);
    vg_assert(!expr); vg_assert(!bounds);
-   *admin            = ML_(new_TyAdmin)( posn, *admin );
-   (*admin)->payload = type;
-   (*admin)->tag     = TyA_Type;
+   VG_(memset)( &tyad, 0, sizeof(tyad) );
+   tyad.cuOff   = posn;
+   tyad.payload = type;
+   tyad.tag     = TyA_Type;
+   VG_(addToXA)( admin, &tyad );
    return;
    /*NOTREACHED*/
 
@@ -2498,9 +2492,11 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
    if (0) VG_(printf)("YYYY Acquire Atom\n");
    vg_assert(!type); vg_assert(atom); vg_assert(!field);
    vg_assert(!expr); vg_assert(!bounds);
-   *admin            = ML_(new_TyAdmin)( posn, *admin );
-   (*admin)->payload = atom;
-   (*admin)->tag     = TyA_Atom;
+   VG_(memset)( &tyad, 0, sizeof(tyad) );
+   tyad.cuOff   = posn;
+   tyad.payload = atom;
+   tyad.tag     = TyA_Atom;
+   VG_(addToXA)( admin, &tyad );
    return;
    /*NOTREACHED*/
 
@@ -2510,14 +2506,17 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
    vg_assert(!type); vg_assert(!atom); vg_assert(field); 
    /*vg_assert(expr);*/ vg_assert(!bounds);
    if (expr) {
-      *admin            = ML_(new_TyAdmin)( (UWord)D3_INVALID_CUOFF,
-                                            *admin );
-      (*admin)->payload = expr;
-      (*admin)->tag     = TyA_Expr;
-   }
-   *admin            = ML_(new_TyAdmin)( posn, *admin );
-   (*admin)->payload = field;
-   (*admin)->tag     = TyA_Field;
+      VG_(memset)( &tyad, 0, sizeof(tyad) );
+      tyad.cuOff   = (UWord)D3_INVALID_CUOFF;
+      tyad.payload = expr;
+      tyad.tag     = TyA_Expr;
+      VG_(addToXA)( admin, &tyad );
+   }
+   VG_(memset)( &tyad, 0, sizeof(tyad) );
+   tyad.cuOff   = posn;
+   tyad.payload = field;
+   tyad.tag     = TyA_Field;
+   VG_(addToXA)( admin, &tyad );
    return;
    /*NOTREACHED*/
 
@@ -2525,9 +2524,11 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
    if (0) VG_(printf)("YYYY Acquire Bounds\n");
    vg_assert(!type); vg_assert(!atom); vg_assert(!field);
    vg_assert(!expr); vg_assert(bounds);
-   *admin            = ML_(new_TyAdmin)( posn, *admin );
-   (*admin)->payload = bounds;
-   (*admin)->tag     = TyA_Bounds;
+   VG_(memset)( &tyad, 0, sizeof(tyad) );
+   tyad.cuOff   = posn;
+   tyad.payload = bounds;
+   tyad.tag     = TyA_Bounds;
+   VG_(addToXA)( admin, &tyad );
    return;
    /*NOTREACHED*/
 
@@ -2559,84 +2560,109 @@ static void parse_type_DIE ( /*OUT*/TyAdmin** admin,
 /*------------------------------------------------------------*/
 
 static Int cmp_D3TyAdmin_by_cuOff ( void* v1, void* v2 ) {
-   TyAdmin* a1 = *(TyAdmin**)v1;
-   TyAdmin* a2 = *(TyAdmin**)v2;
+   TyAdmin* a1 = (TyAdmin*)v1;
+   TyAdmin* a2 = (TyAdmin*)v2;
    if (a1->cuOff < a2->cuOff) return -1;
    if (a1->cuOff > a2->cuOff) return 1;
    return 0;
 }
 
-/* Look up 'cuOff' in 'map', to find the associated D3TyAdmin*.  Check
-   that the found D3TyAdmin has tag 'adtag'.  Sets *payload to be the
-   resulting payload pointer and returns True on success.
+/* Look up 'cuOff' in 'admin', to find the associated D3TyAdmin.
+   Check that the found D3TyAdmin has tag 'adtag'.  Sets *payload to
+   be the resulting payload pointer and returns True on success.
 
    Also, if 'allow_invalid' is True, then if cuOff is
    D3_INVALID_CUOFF, return NULL in *payload.
 
-   Otherwise (conceptually fails) and returns False. */
+   Otherwise (conceptually fails) and returns False.
+
+   Note that 'admin' has previously been sorted on its .cuOff fields,
+   so we can legitimately look up using them.
+ */
 __attribute__((noinline))
 static Bool resolve_binding ( /*OUT*/void** payload,
-                              XArray* map, void* cuOff,
+                              XArray* /* of TyAdmin */ admin, 
+                              void* cuOff,
                               TyAdminTag tag, 
                               Bool allow_invalid ) {
    Bool    found;
    Word    ixLo, ixHi;
-   TyAdmin dummy, *dummyP, *admin;
+   TyAdmin dummy, *tyad;
 
-   if (cuOff == D3_INVALID_CUOFF && allow_invalid) {
-      *payload = NULL;
-      return True;
+   if (cuOff == D3_INVALID_CUOFF) {
+      if (allow_invalid) {
+         *payload = NULL;
+         return True;
+      } else {
+         return False;
+      }
    }
 
+   /* Hence ... */
+   tl_assert(cuOff != D3_INVALID_CUOFF);
+
    VG_(memset)(&dummy, 0, sizeof(dummy));
    dummy.cuOff = (UWord)cuOff;
-   dummyP = &dummy;
-   found = VG_(lookupXA)( map, &dummyP, &ixLo, &ixHi );
+   found = VG_(lookupXA)( admin, &dummy, &ixLo, &ixHi );
    if (!found)
       return False;
    /* If this doesn't hold, we must have seen more than one DIE with
       the same cuOff(set).  Which isn't possible. */
    vg_assert(ixLo == ixHi);
-   admin = *(TyAdmin**)VG_(indexXA)( map, ixLo );
+   tyad = (TyAdmin*)VG_(indexXA)( admin, ixLo );
    /* All payload pointers should be non-NULL.  Ensured by assertion in
       loop in resolve_type_entities that creates 'map'.  Hence it is
       safe to return NULL to indicate 'not found'. */
-   vg_assert(admin->payload);
-   vg_assert(admin->cuOff == (UWord)cuOff); /* stay sane */
+   vg_assert(tyad->payload);
+   vg_assert(tyad->cuOff == (UWord)cuOff); /* stay sane */
 
-   if (admin->tag != tag)
+   if (tyad->tag != tag)
       return False;
 
-   *payload = admin->payload;
+   *payload = tyad->payload;
    return True;
 }
 
+
+/* First, we sort the 'admin' array by its .cuOff fields.  That means
+   we can now hand it to resolve_binding() above, which simply looks
+   up the payload associated with a given cuOff value by doing a
+   binary search in 'admin'.
+
+   There is a subtlety that some of the .cuOff fields in 'admin' are
+   D3_INVALID_CUOFF, and we don't want anybody to be able to look up
+   anything against that value.  Rather than filter those out, we
+   leave them in, sort as usual, but arrange so that resolve_binding()
+   never looks up a D3_INVALID_CUOFF value.
+
+   Having done the sorting, we then work through the payload fields of
+   'admin' and convert all cuOff values into real pointers, by looking
+   them up using resolve_binding().  That's the whole purpose of this
+   resolution mechanism.  We also resolve the type expressions on the
+   supplied 'vars' array. */
+
 __attribute__((noinline))
-static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
-                                    /*MOD*/TempVar* vars )
+static void resolve_type_entities ( /*MOD*/XArray* /* of TyAdmin */ admin,
+                                    /*MOD*/XArray* /* of TempVar* */ vars )
 {
    Bool     ok;
+   Word     i, n;
    void*    payload;
    TyAdmin* adp;
-   XArray* /* of D3TyAdmin* */ map;
 
-   map = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free),
-                     sizeof(TyAdmin*) );
-   for (adp = admin; adp; adp = adp->next) {
-      vg_assert(adp);
-      vg_assert(adp->payload != NULL);
-      if (adp->cuOff != (UWord)D3_INVALID_CUOFF) {
-         VG_(addToXA)( map, &adp );
-      }
-   }
+   tl_assert(admin);
+
+   n = VG_(sizeXA)( admin );
 
-   VG_(setCmpFnXA)( map, cmp_D3TyAdmin_by_cuOff );
+   VG_(setCmpFnXA)( admin, cmp_D3TyAdmin_by_cuOff );
    if (0) 
       VG_(printf)("XXXXXX sorting map with %d entries\n",
-                  (Int)VG_(sizeXA)(map));
-   VG_(sortXA)( map );
+                  (Int)VG_(sizeXA)(admin));
+   VG_(sortXA)( admin );
 
-   for (adp = admin; adp; adp = adp->next) {
+   for (i = 0; i < n; i++) {
+      adp = (TyAdmin*)VG_(indexXA)( admin, i );
+      vg_assert(adp);
       vg_assert(adp->payload);
       switch (adp->tag) {
       case TyA_Bounds: {
@@ -2661,7 +2687,7 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
          if ( (field->isStruct && (!field->loc)) 
               || ((!field->isStruct) && field->loc))
             goto baaad;
-         ok = resolve_binding( &payload, map, field->typeR,
+         ok = resolve_binding( &payload, admin, field->typeR,
                                TyA_Type, False/*!allow_invalid*/ );
          if (!ok) goto baaad;
          field->typeR = payload;
@@ -2681,7 +2707,7 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
                break;
             case Ty_TyDef:
                if (!ty->Ty.TyDef.name) goto baaad;
-               ok = resolve_binding( &payload, map,
+               ok = resolve_binding( &payload, admin,
                                      ty->Ty.TyDef.typeR, 
                                      TyA_Type,
                                      True/*allow_invalid*/ );
@@ -2690,7 +2716,7 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
                break;
             case Ty_PorR:
                if (ty->Ty.PorR.szB != sizeof(Word)) goto baaad;
-               ok = resolve_binding( &payload, map,
+               ok = resolve_binding( &payload, admin,
                                      ty->Ty.PorR.typeR, 
                                      TyA_Type,
                                      False/*!allow_invalid*/ );
@@ -2699,7 +2725,7 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
                break;
             case Ty_Array:
                if (!ty->Ty.Array.bounds) goto baaad;
-               ok = resolve_binding( &payload, map,
+               ok = resolve_binding( &payload, admin,
                                      ty->Ty.Array.typeR, 
                                      TyA_Type,
                                      False/*!allow_invalid*/ );
@@ -2721,7 +2747,7 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
             case Ty_Qual:
                if (ty->Ty.Qual.qual != 'C' 
                    && ty->Ty.Qual.qual != 'V') goto baaad;
-               ok = resolve_binding( &payload, map,
+               ok = resolve_binding( &payload, admin,
                                      ty->Ty.Qual.typeR, 
                                      TyA_Type,
                                      False/*!allow_invalid*/ );
@@ -2746,19 +2772,19 @@ static void resolve_type_entities ( /*MOD*/TyAdmin* admin,
    }
 
    /* Now resolve the variables list */
-   for (; vars; vars = vars->next) {
+   n = VG_(sizeXA)( vars );
+   for (i = 0; i < n; i++) {
+      TempVar* var = *(TempVar**)VG_(indexXA)( vars, i );
       payload = NULL;
-      ok = resolve_binding( &payload, map, vars->typeR,
+      ok = resolve_binding( &payload, admin, var->typeR,
                             TyA_Type, True/*allow_invalid*/ );
 
       if (0 && !ok)
          VG_(printf)("Can't resolve type reference 0x%lx\n",
-                     (UWord)vars->typeR);
+                     (UWord)var->typeR);
       //vg_assert(ok);
-      vars->typeR = payload;
+      var->typeR = payload;
    }
-
-   VG_(deleteXA)( map );
 }
 
 
@@ -2776,9 +2802,9 @@ static Int cmp_TempVar_by_dioff ( void* v1, void* v2 ) {
    return 0;
 }
 
-static void read_DIE ( /*OUT*/TyAdmin** admin,
-                       /*OUT*/TempVar** tempvars,
-                       /*OUT*/GExpr** gexprs,
+static void read_DIE ( /*MOD*/XArray* /* of TyAdmin */ admin,
+                       /*OUT*/XArray* /* of TempVar* */ tempvars,
+                       /*MOD*/XArray* /* of GExpr* */ gexprs,
                        /*MOD*/D3TypeParser* typarser,
                        /*MOD*/D3VarParser* varparser,
                        Cursor* c, Bool td3, CUConst* cc, Int level )
@@ -2895,9 +2921,11 @@ void new_dwarf3_reader_wrk (
    UChar* debug_loc_img,    SizeT debug_loc_sz
 )
 {
-   TyAdmin *admin, *adminp;
-   TempVar *tempvars, *varp, *varp2;
-   GExpr *gexprs, *gexpr;
+   XArray* /* of TyAdmin */ admin;
+   XArray* /* of GExpr* */ gexprs;
+   XArray* /* of TempVar* */ tempvars;
+   TempVar *varp, *varp2;
+   GExpr* gexpr;
    Cursor abbv; /* for showing .debug_abbrev */
    Cursor info; /* primary cursor for parsing .debug_info */
    Cursor ranges; /* for showing .debug_ranges */
@@ -2905,7 +2933,7 @@ void new_dwarf3_reader_wrk (
    D3VarParser varparser;
    Addr  dr_base;
    UWord dr_offset;
-   Word  i;
+   Word  i, j, n;
    Bool td3 = di->trace_symtab;
    XArray* /* of TempVar* */ dioff_lookup_tab;
    Bool text_biasing_borked;
@@ -3013,7 +3041,6 @@ void new_dwarf3_reader_wrk (
                dr_offset, w1 + dr_base, w2 + dr_base);
    }
 
-
    /* Display .debug_abbrev */
    init_Cursor( &abbv, debug_abbv_img, debug_abbv_sz, 0, barf, 
                 "Overrun whilst reading .debug_abbrev section" );
@@ -3058,23 +3085,27 @@ void new_dwarf3_reader_wrk (
       huge and presumably will not occur in any valid DWARF3 file --
       it would need to have a .debug_info section 4GB long for that to
       happen.  These type entries end up in the DebugInfo. */
-   admin = NULL;
-   { Type* tVoid = ML_(new_Type)();
+   admin = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), sizeof(TyAdmin) );
+   { TyAdmin tyad;
+     Type* tVoid = ML_(new_Type)();
      tVoid->tag = Ty_Void;
      tVoid->Ty.Void.isFake = True;
-     admin = ML_(new_TyAdmin)( (UWord)D3_FAKEVOID_CUOFF, admin );
-     admin->payload = tVoid;
-     admin->tag     = TyA_Type;
+     VG_(memset)( &tyad, 0, sizeof(tyad) );
+     tyad.cuOff   = (UWord)D3_FAKEVOID_CUOFF;
+     tyad.payload = tVoid;
+     tyad.tag     = TyA_Type;
+     VG_(addToXA)( admin, &tyad );
    }
 
    /* List of variables we're accumulating.  These don't end up in the
       DebugInfo; instead their contents are handed to ML_(addVar) and
       the list elements are then deleted. */
-   tempvars = NULL;
+   tempvars = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), 
+                          sizeof(TempVar*) );
 
    /* List of GExprs we're accumulating.  These wind up in the
       DebugInfo. */
-   gexprs = NULL;
+   gexprs = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), sizeof(GExpr*) );
 
    /* We need a D3TypeParser to keep track of partially constructed
       types.  It'll be discarded as soon as we've completed the CU,
@@ -3162,7 +3193,7 @@ void new_dwarf3_reader_wrk (
 
       /* Now read the one-and-only top-level DIE for this CU. */
       vg_assert(varparser.sp == 0);
-      read_DIE( &admin, &tempvars, &gexprs, &typarser, &varparser,
+      read_DIE( admin, tempvars, gexprs, &typarser, &varparser,
                 &info, td3, &cc, 0 );
 
       cu_offset_now = get_position_of_Cursor( &info );
@@ -3191,40 +3222,22 @@ void new_dwarf3_reader_wrk (
       varparser.filenameTable = NULL;
    }
 
-   /* Put the type entry list the right way round.  Not strictly
-      necessary, but makes it easier to read. */
-   vg_assert(admin);
-   if (admin) { 
-      TyAdmin *next, *prev = NULL;
-      for (adminp = admin; adminp; adminp = next) {
-         next = adminp->next;
-         adminp->next = prev;
-         prev = adminp;
-      }
-      admin = prev;
-   }
+   /* From here on we're post-processing the stuff we got
+      out of the .debug_info section. */
 
-   /* Put the variable list the right way round.  Not strictly
-      necessary, but makes it easier to read. */
-   if (tempvars) { 
-      TempVar *next, *prev = NULL;
-      for (varp = tempvars; varp; varp = next) {
-         next = varp->next;
-         varp->next = prev;
-         prev = varp;
+   if (td3) {
+      TRACE_D3("\n");
+      TRACE_D3("------ Acquired the following type entities: ------\n");
+      n = VG_(sizeXA)( admin );
+      for (i = 0; i < n; i++) {
+         TyAdmin* tyad = (TyAdmin*)VG_(indexXA)( admin, i );
+         TRACE_D3("   ");
+         ML_(pp_TyAdmin)( tyad );
+         TRACE_D3("\n");
       }
-      tempvars = prev;
-   }
-
-   TRACE_D3("\n");
-   TRACE_D3("------ Acquired the following type entities: ------\n");
-   for (adminp = admin; adminp; adminp = adminp->next) {
-      TRACE_D3("   ");
-      if (td3) ML_(pp_TyAdmin)( adminp );
       TRACE_D3("\n");
+      TRACE_D3("------ Resolving type entries ------\n");
    }
-   TRACE_D3("\n");
-   TRACE_D3("------ Resolving type entries ------\n");
 
    /* See "Comment_Regarding_DWARF3_Text_Biasing" above. */
    VG_(memset)( &ktb, 0, sizeof(ktb ));
@@ -3233,7 +3246,9 @@ void new_dwarf3_reader_wrk (
    ktb.text_bias   = di->text_bias;
 
    resolve_type_entities( admin, tempvars );
-   for (gexpr = gexprs; gexpr; gexpr = gexpr->next) {
+   n = VG_(sizeXA)( gexprs );
+   for (i = 0; i < n; i++) {
+      gexpr = *(GExpr**)VG_(indexXA)( gexprs, i );
       bias_GX( gexpr, &ktb );
    }
 
@@ -3242,26 +3257,35 @@ void new_dwarf3_reader_wrk (
 
    /* Park (pointers to) all the vars in an XArray, so we can look up
       abstract origins quickly.  The array is sorted (hence, looked-up
-      by) the .dioff fields.  Since the .dioffs should be instrictly
+      by) the .dioff fields.  Since the .dioffs should be in strictly
       ascending order, there is no need to sort the array after
       construction.  The ascendingness is however asserted for. */
    dioff_lookup_tab
       = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), 
                     sizeof(TempVar*) );
    vg_assert(dioff_lookup_tab);
-   varp2 = NULL;
-   for (varp = tempvars; varp; varp = varp->next) {
-      if (varp2)
+
+   n = VG_(sizeXA)( tempvars );
+   for (i = 0; i < n; i++) {
+      varp = *(TempVar**)VG_(indexXA)( tempvars, i );
+      if (i > 0) {
+         varp2 = *(TempVar**)VG_(indexXA)( tempvars, i-1 );
+         /* why should this hold?  Only, I think, because we've
+            constructed the array by reading .debug_info sequentially,
+            and so the array .dioff fields should reflect that, and be
+            strictly ascending. */
          vg_assert(varp2->dioff < varp->dioff);
+      }
       VG_(addToXA)( dioff_lookup_tab, &varp );
-      varp2 = varp;
    }
    VG_(setCmpFnXA)( dioff_lookup_tab, cmp_TempVar_by_dioff );
    VG_(sortXA)( dioff_lookup_tab ); /* POINTLESS; FIXME: rm */
 
    /* Now visit each var.  Collect up as much info as possible for
       each var and hand it to ML_(addVar). */
-   for (varp = tempvars; varp; varp = varp->next) {
+   n = VG_(sizeXA)( tempvars );
+   for (j = 0; j < n; j++) {
+      varp = *(TempVar**)VG_(indexXA)( tempvars, j );
 
       /* Possibly show .. */
       if (td3) {
@@ -3448,12 +3472,14 @@ void new_dwarf3_reader_wrk (
       barf("couldn't make sense of DWARF3 text-svma biasing; details above");
 
    /* Now free all the TempVars */
-   for (varp = tempvars; varp; varp = varp2) {
-      varp2 = varp->next;
+   n = VG_(sizeXA)( tempvars );
+   for (i = 0; i < n; i++) {
+      varp = *(TempVar**)VG_(indexXA)( tempvars, i );
       if (varp->rngMany)
          VG_(deleteXA)(varp->rngMany);
       ML_(dinfo_free)(varp);
    }
+   VG_(deleteXA)( tempvars );
    tempvars = NULL;
 
    /* And get rid of the temporary mapping table. */
index 73a72128d9dba1cf63f845aa3725e44ddb916240..6036ffcea230adcfcded31dabfdf095933010e36 100644 (file)
 #include "priv_tytypes.h"      /* self */
 
 
-TyAdmin* ML_(new_TyAdmin) ( UWord cuOff, TyAdmin* next ) {
+TyAdmin* ML_(new_TyAdmin) ( UWord cuOff ) {
    TyAdmin* admin = ML_(dinfo_zalloc)( sizeof(TyAdmin) );
    admin->cuOff = cuOff;
-   admin->next  = next;
    return admin;
 }
 TyAtom* ML_(new_TyAtom) ( UChar* name, Long value ) {
@@ -140,7 +139,8 @@ static void delete_Type ( Type* ty ) {
    }
 }
 
-void ML_(delete_TyAdmin_and_payload) ( TyAdmin* ad ) {
+void ML_(delete_payload_of_TyAdmin) ( TyAdmin* ad ) {
+   vg_assert(ad);
    vg_assert(ad->payload);
    switch (ad->tag) {
       case TyA_Type:   delete_Type(ad->payload);     break;
@@ -150,11 +150,9 @@ void ML_(delete_TyAdmin_and_payload) ( TyAdmin* ad ) {
       case TyA_Bounds: delete_TyBounds(ad->payload); break;
       default:         vg_assert(0);
    }
-   ML_(dinfo_free)(ad);
 }
 
 
-
 static void pp_XArray_of_pointersOrRefs ( XArray* xa ) {
    Word i;
    VG_(printf)("{");