Old STABS code is still being compiled, but never used. Remove it.

Since valgrind 3.9.0 the STABS support was already disabled completely.
But the code was still there being compiled and we were still searching
for stabs sections in binaries. Completely remove all sources, tests and
references. Add a note to coregrind/m_debuginfo/README.txt to mention
the old code can be found in the subversion repository.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14550 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index 25cf832..de374fd 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,7 @@
 where XXXXXX is the bug number as listed below.
 
 339020 ppc64: memcheck/tests/ppc64/power_ISA2_05 failing in nightly build
+n-i-bz Old STABS code is still being compiled, but never used. Remove it.
 
 
 Release 3.10.0 (10 September 2014)
diff --git a/cachegrind/docs/cg-manual.xml b/cachegrind/docs/cg-manual.xml
index 0f61e0a..6c87638 100644
--- a/cachegrind/docs/cg-manual.xml
+++ b/cachegrind/docs/cg-manual.xml
@@ -623,23 +623,6 @@
   </listitem>
 
   <listitem>
-    <para>Files with more than 65,535 lines cause difficulties
-    for the Stabs-format debug info reader.  This is because the line
-    number in the <computeroutput>struct nlist</computeroutput>
-    defined in <filename>a.out.h</filename> under Linux is only a
-    16-bit value.  Valgrind can handle some files with more than
-    65,535 lines correctly by making some guesses to identify
-    line number overflows.  But some cases are beyond it, in
-    which case you'll get a warning message explaining that
-    annotations for the file might be incorrect.</para>
-    
-    <para>If you are using GCC 3.1 or later, this is most likely
-    irrelevant, since GCC switched to using the more modern DWARF2 
-    format by default at version 3.1.  DWARF2 does not have any such
-    limitations on line numbers.</para>
-  </listitem>
-
-  <listitem>
     <para>If you compile some files with
     <option>-g</option> and some without, some
     events that take place in a file without debug info could be
diff --git a/configure.ac b/configure.ac
index 863cd7e..f2872c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1781,25 +1781,6 @@
 CFLAGS=$safe_CFLAGS
 
 
-# does this compiler support -gstabs ?
-
-AC_MSG_CHECKING([if gcc accepts -gstabs])
-
-safe_CFLAGS=$CFLAGS
-CFLAGS="-gstabs"
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
-  return 0;
-]])], [
-ac_have_gstabs=yes
-AC_MSG_RESULT([yes])
-], [
-ac_have_gstabs=no
-AC_MSG_RESULT([no])
-])
-CFLAGS=$safe_CFLAGS
-AM_CONDITIONAL([HAVE_GSTABS], [test x$ac_have_gstabs = xyes])
-
-
 # does this compiler support nested functions ?
 
 AC_MSG_CHECKING([if gcc accepts nested functions])
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 361bd73..fe2a031 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -22,7 +22,6 @@
 
 
 EXTRA_DIST = \
-	m_debuginfo/UNUSED_STABS.txt \
 	m_debuginfo/README.txt \
 	m_gdbserver/README_DEVELOPERS \
 	docs/vgdb-manpage.xml
@@ -216,7 +215,6 @@
 	m_debuginfo/priv_misc.h	\
 	m_debuginfo/priv_storage.h	\
 	m_debuginfo/priv_tytypes.h      \
-	m_debuginfo/priv_readstabs.h	\
 	m_debuginfo/priv_readpdb.h	\
 	m_debuginfo/priv_d3basics.h	\
 	m_debuginfo/priv_readdwarf.h	\
@@ -323,7 +321,6 @@
 	m_debuginfo/readexidx.c \
 	m_debuginfo/readmacho.c \
 	m_debuginfo/readpdb.c \
-	m_debuginfo/readstabs.c \
 	m_debuginfo/storage.c \
 	m_debuginfo/tytypes.c \
 	m_debuginfo/image.c \
diff --git a/coregrind/m_debuginfo/README.txt b/coregrind/m_debuginfo/README.txt
index ea96ba9..34b9579 100644
--- a/coregrind/m_debuginfo/README.txt
+++ b/coregrind/m_debuginfo/README.txt
@@ -1,13 +1,13 @@
 
 On 4 Apr 06, the debuginfo reader (m_debuginfo) was majorly cleaned up
-and restructured.  It has been a bit of a tangle for a while.  The new
-structure looks like this:
+and restructured.  It has been a bit of a tangle for a while.  On 18 Sep 14
+the STABS support was completely removed. The new structure looks like this:
 
                   debuginfo.c 
   
                    readelf.c
 
-        readdwarf.c        readstabs.c
+                  readdwarf.c
 
                    storage.c
 
@@ -17,38 +17,33 @@
 maintaining/searching arrays of symbols, line-numbers, and Dwarf CF 
 info records.
 
-readdwarf.c and readstabs.c parse the relevant kind of info and 
-call storage.c to store the results.
+readdwarf.c parses the relevant kind of info and call storage.c to
+store the results.
 
 readelf.c reads ELF format, hands syms directly to storage.c,
-then delegates to readdwarf.c/readstabs.c for debug info.  All 
-straightforward.
+then delegates to readdwarf.c for debug info.  All straightforward.
 
 debuginfo.c is the top-level file, and is quite small.
 
-There are 3 goals to this:
+There are 2 goals to this:
 
 (1) Generally tidy up something which needs tidying up
 
 (2) Introduce more modularity, so as to make it easier to add
     readers for other formats, if needed
 
-(3) Simplify the stabs reader.
-
 Rationale for (1) and (2) are obvious.
 
-Re (3), the stabs reader has for a good year contained a sophisticated
-and impressive parser for stabs strings, with the aim of recording in 
-detail the types of variables (I think) (Jeremy's work).  Unfortunately 
-that has caused various segfaults reading stabs info in the past few months
-(#77869, #117936, #119914, #120345 and another to do with deeply nested
-template types).
+Originally there was also goal (3) Simplify the stabs reader.
+But stabs support was broken since 3.9.0 and completely removed in 3.10.0.
 
 The worst thing is that it is the stabs type reader that is crashing,
 not the stabs line-number reader, but the type info is only used by
-Helgrind, which is looking pretty dead at the moment.  So I have lifed
-out the type-reader code and put it in UNUSED_STABS.txt for safe
-storage, just leaving the line-number reader in place.
+Helgrind, which is looking pretty dead at the moment. Old versions
+of the stabs type reader can be found in the subversion repository
+as m_debuginfo/UNUSED_STABS.txt, the stabs line-number reader was in
+m_debuginfo/readstabs.c. The old version of this file explained more
+about the setup.
 
 If Helgrind ever does come back to life we will need to reinstate the
 type storage/reader stuff but with DWARF as its primary target.
diff --git a/coregrind/m_debuginfo/UNUSED_STABS.txt b/coregrind/m_debuginfo/UNUSED_STABS.txt
deleted file mode 100644
index 3879026..0000000
--- a/coregrind/m_debuginfo/UNUSED_STABS.txt
+++ /dev/null
@@ -1,1483 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Extract type info from debug info.                symtypes.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2005 Julian Seward
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "pub_core_basics.h"
-#include "pub_core_debuginfo.h"
-#include "pub_core_debuglog.h"    // For VG_(debugLog_vprintf)
-#include "pub_core_libcbase.h"
-#include "pub_core_libcassert.h"
-#include "pub_core_libcprint.h"
-#include "pub_core_libcsignal.h"
-#include "pub_core_machine.h"
-#include "pub_core_mallocfree.h"
-
-#include "priv_symtypes.h"
-
-typedef enum {
-   TyUnknown,			/* unknown type */
-   TyUnresolved,		/* unresolved type */
-   TyError,			/* error type */
-
-   TyVoid,			/* void */
-
-   TyInt,			/* integer */
-   TyBool,			/* boolean */
-   TyChar,			/* character */
-   TyFloat,			/* float */
-
-   TyRange,			/* type subrange */
-
-   TyEnum,			/* enum */
-
-   TyPointer,			/* pointer */
-   TyArray,			/* array */
-   TyStruct,			/* structure/class */
-   TyUnion,			/* union */
-
-   TyTypedef			/* typedef */
-} TyKind;
-
-static const Char *ppkind(TyKind k)
-{
-   switch(k) {
-#define S(x)	case x:		return #x
-      S(TyUnknown);
-      S(TyUnresolved);
-      S(TyError);
-      S(TyVoid);
-      S(TyInt);
-      S(TyBool);
-      S(TyChar);
-      S(TyRange);
-      S(TyFloat);
-      S(TyEnum);
-      S(TyPointer);
-      S(TyArray);
-      S(TyStruct);
-      S(TyUnion);
-      S(TyTypedef);
-#undef S
-   default:
-      return "Ty???";
-   }
-}
-
-/* struct/union field */
-typedef struct _StField {
-   UInt		offset;		/* offset into structure (0 for union) (in bits) */
-   UInt		size;		/* size (in bits) */
-   SymType	*type;		/* type of element */
-   Char	*name;			/* name of element */
-} StField;
-
-/* enum tag */
-typedef struct _EnTag {
-   const Char   *name;		/* name */
-   UInt		val;		/* value */
-} EnTag;
-
-struct _SymType {
-   TyKind	kind;			/* type descriminator */
-   UInt		size;			/* sizeof(type) */
-   Char		*name;			/* useful name */
-
-   union {
-      /* TyInt,TyBool,TyChar */
-      struct {
-	 Bool		issigned;	/* signed or not */
-      } t_scalar;
-
-      /* TyFloat */
-      struct {
-	 Bool		isdouble;	/* is double prec */
-      } t_float;
-
-      /* TyRange */
-      struct {
-	 Int		min;
-	 Int		max;
-	 SymType	*type;
-      } t_range;
-
-      /* TyPointer */
-      struct {
-	 SymType	*type;		/* *type */
-      } t_pointer;
-
-      /* TyArray */
-      struct {
-	 SymType	*idxtype;
-	 SymType	*type;
-      } t_array;
-
-      /* TyEnum */
-      struct {
-	 UInt		ntag;		/* number of tags */
-	 EnTag		*tags;		/* tags */
-      } t_enum;
-
-      /* TyStruct, TyUnion */
-      struct {
-	 UInt		nfield;		/* number of fields */
-	 UInt		nfieldalloc;	/* number of fields allocated */
-	 StField	*fields;	/* fields */
-      } t_struct;
-
-      /* TyTypedef */
-      struct {
-	 SymType	*type;		/* type */
-      } t_typedef;
-
-      /* TyUnresolved - reference to unresolved type */
-      struct {
-	 /* some kind of symtab reference */
-	 SymResolver	*resolver;	/* symtab reader's resolver */
-	 void		*data;		/* data for resolver */
-      } t_unresolved;
-   } u;
-};
-
-
-Bool ML_(st_isstruct)(SymType *ty)
-{
-   return ty->kind == TyStruct;
-}
-
-Bool ML_(st_isunion)(SymType *ty)
-{
-   return ty->kind == TyUnion;
-}
-
-Bool ML_(st_isenum)(SymType *ty)
-{
-   return ty->kind == TyEnum;
-}
-
-static inline SymType *alloc(SymType *st)
-{
-   if (st == NULL) {
-      st = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*st));
-      st->kind = TyUnknown;
-      st->name = NULL;
-   }
-
-   return st;
-}
-
-static void resolve(SymType *st)
-{
-   if (st->kind != TyUnresolved)
-      return;
-
-   (*st->u.t_unresolved.resolver)(st, st->u.t_unresolved.data);
-
-   if (st->kind == TyUnresolved)
-      st->kind = TyError;
-}
-
-SymType *ML_(st_mkunresolved)(SymType *st, SymResolver *resolver, void *data)
-{
-   st = alloc(st);
-   
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-
-   st->kind = TyUnresolved;
-   st->size = 0;
-   st->u.t_unresolved.resolver = resolver;
-   st->u.t_unresolved.data = data;
-
-   return st;
-}
-
-void ML_(st_unresolved_setdata)(SymType *st, SymResolver *resolver, void *data)
-{
-   if (st->kind != TyUnresolved)
-      return;
-
-   st->u.t_unresolved.resolver = resolver;
-   st->u.t_unresolved.data = data;
-}
-
-Bool ML_(st_isresolved)(SymType *st)
-{
-   return st->kind != TyUnresolved;
-}
-
-void ML_(st_setname)(SymType *st, Char *name)
-{
-   if (st->name != NULL)
-      st->name = name;
-}
-
-SymType *ML_(st_mkvoid)(SymType *st)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-   
-   st->kind = TyVoid;
-   st->size = 1;		/* for address calculations */
-   st->name = "void";
-   return st;
-}
-
-SymType *ML_(st_mkint)(SymType *st, UInt size, Bool isSigned)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-   
-   st->kind = TyInt;
-   st->size = size;
-   st->u.t_scalar.issigned = isSigned;
-
-   return st;
-}
-
-SymType *ML_(st_mkfloat)(SymType *st, UInt size)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-   
-   st->kind = TyFloat;
-   st->size = size;
-   st->u.t_scalar.issigned = True;
-
-   return st;
-}
-
-SymType *ML_(st_mkbool)(SymType *st, UInt size)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-   
-   st->kind = TyBool;
-   st->size = size;
-
-   return st;
-}
-
-
-SymType *ML_(st_mkpointer)(SymType *st, SymType *ptr)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-
-   st->kind = TyPointer;
-   st->size = sizeof(void *);
-   st->u.t_pointer.type = ptr;
-
-   return st;
-}
-
-SymType *ML_(st_mkrange)(SymType *st, SymType *ty, Int min, Int max)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-
-   st->kind = TyRange;
-   st->size = 0;		/* ? */
-   st->u.t_range.type = ty;
-   st->u.t_range.min = min;
-   st->u.t_range.max = max;
-
-   return st;
-}
-
-SymType *ML_(st_mkstruct)(SymType *st, UInt size, UInt nfields)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyStruct);
-
-   vg_assert(st->kind != TyStruct || st->u.t_struct.nfield == 0);
-
-   st->kind = TyStruct;
-   st->size = size;
-   st->u.t_struct.nfield = 0;
-   st->u.t_struct.nfieldalloc = nfields;
-   if (nfields != 0)
-      st->u.t_struct.fields = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StField) * nfields);
-   else
-      st->u.t_struct.fields = NULL;
-   
-   return st;
-}
-
-SymType *ML_(st_mkunion)(SymType *st, UInt size, UInt nfields)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyUnion);
-
-   vg_assert(st->kind != TyUnion || st->u.t_struct.nfield == 0);
-
-   st->kind = TyUnion;
-   st->size = size;
-   st->u.t_struct.nfield = 0;
-   st->u.t_struct.nfieldalloc = nfields;
-   if (nfields != 0)
-      st->u.t_struct.fields = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StField) * nfields);
-   else
-      st->u.t_struct.fields = NULL;
-
-   return st;
-}
-
-void ML_(st_addfield)(SymType *st, Char *name, SymType *type, UInt off, UInt size)
-{
-   StField *f;
-
-   vg_assert(st->kind == TyStruct || st->kind == TyUnion);
-
-   if (st->u.t_struct.nfieldalloc == st->u.t_struct.nfield) {
-      StField *n = VG_(arena_malloc)(VG_AR_SYMTAB, 
-				     sizeof(StField) * (st->u.t_struct.nfieldalloc + 2));
-      VG_(memcpy)(n, st->u.t_struct.fields, sizeof(*n) * st->u.t_struct.nfield);
-      if (st->u.t_struct.fields != NULL)
-	 VG_(arena_free)(VG_AR_SYMTAB, st->u.t_struct.fields);
-      st->u.t_struct.nfieldalloc++;
-      st->u.t_struct.fields = n;
-   }
-
-   f = &st->u.t_struct.fields[st->u.t_struct.nfield++];
-   f->name = name;
-   f->type = type;
-   f->offset = off;
-   f->size = size;
-}
-
-
-SymType *ML_(st_mkenum)(SymType *st, UInt ntags)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyEnum);
-
-   st->kind = TyEnum;
-   st->u.t_enum.ntag = 0;
-   st->u.t_enum.tags = NULL;
-   
-   return st;
-}
-
-SymType *ML_(st_mkarray)(SymType *st, SymType *idxtype, SymType *type)
-{
-   st = alloc(st);
-
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
-
-   st->kind = TyArray;
-   st->u.t_array.type = type;
-   st->u.t_array.idxtype = idxtype;
-   
-   return st;
-}
-
-SymType *ML_(st_mktypedef)(SymType *st, Char *name, SymType *type)
-{
-   st = alloc(st);
-
-   vg_assert(st != type);
-   vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown ||
-	     st->kind == TyStruct || st->kind == TyUnion ||
-	     st->kind == TyTypedef);
-   
-   st->kind = TyTypedef;
-   st->name = name;
-   st->u.t_typedef.type = type;
-
-   return st;
-}
-
-
-SymType *ML_(st_basetype)(SymType *type, Bool do_resolve)
-{
-   while (type->kind == TyTypedef || (do_resolve && type->kind == TyUnresolved)) {
-      if (do_resolve)
-	 resolve(type);
-
-      if (type->kind == TyTypedef)
-	 type = type->u.t_typedef.type;
-   }
-
-   return type;
-}
-
-UInt ML_(st_sizeof)(SymType *ty)
-{
-   return ty->size;
-}
-
-#ifndef TEST
-/*
-  Hash of visited addresses, so we don't get stuck in loops.  It isn't
-  simply enough to keep track of addresses, since we need to interpret
-  the memory according to the type.  If a given location has multiple
-  pointers with different types (for example, void * and struct foo *),
-  then we need to look at it under each type.
-*/
-struct visited {
-   Addr		a;
-   SymType	*ty;
-   struct visited *next;
-};
-
-#define VISIT_HASHSZ	1021
-
-static struct visited *visit_hash[VISIT_HASHSZ];
-
-static inline Bool test_visited(Addr a, SymType *type)
-{
-   struct visited *v;
-   UInt b = (UInt)a % VISIT_HASHSZ;
-   Bool ret = False;
-
-   for(v = visit_hash[b]; v != NULL; v = v->next) {
-      if (v->a == a && v->ty == type) {
-	 ret = True;
-	 break;
-      }
-   }
-   
-   return ret;
-}
-
-static Bool has_visited(Addr a, SymType *type)
-{
-   static const Bool debug = False;
-   Bool ret;
-
-   ret = test_visited(a, type);
-
-   if (!ret) {
-      UInt b = (UInt)a % VISIT_HASHSZ;
-      struct visited * v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
-
-      v->a = a;
-      v->ty = type;
-      v->next = visit_hash[b];
-      visit_hash[b] = v;
-   }
-   
-   if (debug)
-      VG_(printf)("has_visited(a=%p, ty=%p) -> %d\n", a, type, ret);
-
-   return ret;
-}
-
-static void clear_visited(void)
-{
-   UInt i;
-   
-   for(i = 0; i < VISIT_HASHSZ; i++) {
-      struct visited *v, *n;
-      for(v = visit_hash[i]; v != NULL; v = n) {
-	 n = v->next;
-	 VG_(arena_free)(VG_AR_SYMTAB, v);
-      }
-      visit_hash[i] = NULL;
-   }
-}
-
-static 
-void bprintf(void (*send)(HChar, void*), void *send_arg, const Char *fmt, ...)
-{
-   va_list vargs;
-
-   va_start(vargs, fmt);
-   VG_(debugLog_vprintf)(send, send_arg, fmt, vargs);
-   va_end(vargs);
-}
-
-#define SHADOWCHUNK	0	/* no longer have a core allocator */
-
-#if SHADOWCHUNK
-static ShadowChunk *findchunk(Addr a)
-{
-   Bool find(ShadowChunk *sc) {
-      return a >= sc->data && a < (sc->data+sc->size);
-   }
-   return VG_(any_matching_mallocd_ShadowChunks)(find);
-}
-#endif
-
-static struct vki_sigaction sigbus_saved;
-static struct vki_sigaction sigsegv_saved;
-static vki_sigset_t  blockmask_saved;
-static jmp_buf valid_addr_jmpbuf;
-
-static void valid_addr_handler(int sig)
-{
-   //VG_(printf)("OUCH! %d\n", sig);
-   __builtin_longjmp(valid_addr_jmpbuf, 1);
-}
-
-/* catch badness signals because we're going to be
-   playing around in untrusted memory */
-static void setup_signals(void)
-{
-   Int res;
-   struct vki_sigaction sigbus_new;
-   struct vki_sigaction sigsegv_new;
-   vki_sigset_t         unblockmask_new;
-
-   /* Temporarily install a new sigsegv and sigbus handler, and make
-      sure SIGBUS, SIGSEGV and SIGTERM are unblocked.  (Perhaps the
-      first two can never be blocked anyway?)  */
-
-   sigbus_new.ksa_handler = valid_addr_handler;
-   sigbus_new.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
-   sigbus_new.sa_restorer = NULL;
-   res = VG_(sigemptyset)( &sigbus_new.sa_mask );
-   vg_assert(res == 0);
-
-   sigsegv_new.ksa_handler = valid_addr_handler;
-   sigsegv_new.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
-   sigsegv_new.sa_restorer = NULL;
-   res = VG_(sigemptyset)( &sigsegv_new.sa_mask );
-   vg_assert(res == 0+0);
-
-   res =  VG_(sigemptyset)( &unblockmask_new );
-   res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGBUS );
-   res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGSEGV );
-   res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGTERM );
-   vg_assert(res == 0+0+0);
-
-   res = VG_(sigaction)( VKI_SIGBUS, &sigbus_new, &sigbus_saved );
-   vg_assert(res == 0+0+0+0);
-
-   res = VG_(sigaction)( VKI_SIGSEGV, &sigsegv_new, &sigsegv_saved );
-   vg_assert(res == 0+0+0+0+0);
-
-   res = VG_(sigprocmask)( VKI_SIG_UNBLOCK, &unblockmask_new, &blockmask_saved );
-   vg_assert(res == 0+0+0+0+0+0);
-}
-
-static void restore_signals(void)
-{
-   Int res;
-
-   /* Restore signal state to whatever it was before. */
-   res = VG_(sigaction)( VKI_SIGBUS, &sigbus_saved, NULL );
-   vg_assert(res == 0 +0);
-
-   res = VG_(sigaction)( VKI_SIGSEGV, &sigsegv_saved, NULL );
-   vg_assert(res == 0 +0 +0);
-
-   res = VG_(sigprocmask)( VKI_SIG_SETMASK, &blockmask_saved, NULL );
-   vg_assert(res == 0 +0 +0 +0);
-}
-
-/* if false, setup and restore signals for every access */
-#define LAZYSIG		1
-
-static Bool is_valid_addr(Addr a)
-{
-   static SymType faulted = { TyError };
-   static const Bool debug = False;
-   volatile Bool ret = False;
-
-   if ((a > VKI_PAGE_SIZE) && !test_visited(a, &faulted)) {
-      if (!LAZYSIG)
-	 setup_signals();
-   
-      if (__builtin_setjmp(valid_addr_jmpbuf) == 0) {
-	 volatile UInt *volatile ptr = (volatile UInt *)a;
-
-	 *ptr;
-
-	 ret = True;
-      } else {
-	 /* cache bad addresses in visited table */
-	 has_visited(a, &faulted);
-	 ret = False;
-      }
-
-      if (!LAZYSIG)
-	 restore_signals();
-   }
-
-   if (debug)
-      VG_(printf)("is_valid_addr(%p) -> %d\n", a, ret);
-
-   return ret;
-}
-
-static Int free_varlist(Variable *list)
-{
-   Variable *next;
-   Int count = 0;
-
-   for(; list != NULL; list = next) {
-      next = list->next;
-      count++;
-      if (list->name)
-	 VG_(arena_free)(VG_AR_SYMTAB, list->name);
-      VG_(arena_free)(VG_AR_SYMTAB, list);
-   }
-   return count;
-}
-
-/* Composite: struct, union, array
-   Non-composite: everything else
- */
-static inline Bool is_composite(SymType *ty)
-{
-   switch(ty->kind) {
-   case TyUnion:
-   case TyStruct:
-   case TyArray:
-      return True;
-
-   default:
-      return False;
-   }
-}
-
-/* There's something at the end of the rainbow */
-static inline Bool is_followable(SymType *ty)
-{
-   return ty->kind == TyPointer || is_composite(ty);
-}
-
-/* Result buffer */
-static Char *describe_addr_buf;
-static UInt describe_addr_bufidx;
-static UInt describe_addr_bufsz;
-
-/* Add a character to the result buffer */
-static void describe_addr_addbuf(HChar c,void *p) {
-   if ((describe_addr_bufidx+1) >= describe_addr_bufsz) {
-      Char *n;
-    
-      if (describe_addr_bufsz == 0)
-         describe_addr_bufsz = 8;
-      else
-         describe_addr_bufsz *= 2;
-    
-      /* use tool malloc so that the tool can free it */
-      n = VG_(malloc)(describe_addr_bufsz);
-      if (describe_addr_buf != NULL && describe_addr_bufidx != 0)
-         VG_(memcpy)(n, describe_addr_buf, describe_addr_bufidx);
-      if (describe_addr_buf != NULL)
-         VG_(free)(describe_addr_buf);
-      describe_addr_buf = n;
-   }
-   describe_addr_buf[describe_addr_bufidx++] = c;
-   describe_addr_buf[describe_addr_bufidx] = '\0';
-}
-
-#define MAX_PLY		7	/* max depth we go */
-#define MAX_ELEMENTS	5000	/* max number of array elements we scan */
-#define MAX_VARS	10000	/* max number of variables total traversed */
-
-static const Bool memaccount = False; /* match creates to frees */
-static const Bool debug = False;
-
-/* Add a new variable to the list */
-static Bool newvar(Char *name, SymType *ty, Addr valuep, UInt size,
-                   Variable *var, Int *numvars, Int *created,
-                   Variable **newlist, Variable **newlistend) {
-   Variable *v;
-
-   /* have we been here before? */
-   if (has_visited(valuep, ty))
-      return False;
-	    
-   /* are we too deep? */
-   if (var->distance > MAX_PLY)
-      return False;
-
-   /* have we done too much? */
-   if ((*numvars)-- == 0)
-      return False;
-
-   if (memaccount)
-      (*created)++;
-	    
-   v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
-
-   if (name)
-      v->name = VG_(arena_strdup)(VG_AR_SYMTAB, name);
-   else
-      v->name = NULL;
-   v->type = ML_(st_basetype)(ty, False);
-   v->valuep = valuep;
-   v->size = size == -1 ? ty->size : size;
-   v->container = var;
-   v->distance = var->distance + 1;
-   v->next = NULL;
-
-   if (*newlist == NULL)
-      *newlist = *newlistend = v;
-   else {
-      (*newlistend)->next = v;
-      *newlistend = v;
-   }
-	    
-   if (debug)
-      VG_(printf)("    --> %d: name=%s type=%p(%s %s) container=%p &val=%p\n", 
-                  v->distance, v->name, v->type, ppkind(v->type->kind), 
-                  v->type->name ? (char *)v->type->name : "",
-                  v->container, v->valuep);
-   return True;
-}
-
-static void genstring(Variable *v, Variable *inner, Int *len, Char **ep,
-                      Char **sp) {
-   Variable *c = v->container;
-
-   if (c != NULL)
-      genstring(c, v, len, ep, sp);
-
-   if (v->name != NULL) {
-      *len = VG_(strlen)(v->name);
-      VG_(memcpy)(*ep, v->name, *len);
-      (*ep) += *len;
-   }
-
-   switch(v->type->kind) {
-   case TyPointer:
-      /* pointer-to-structure/union handled specially */
-      if (inner == NULL ||
-          !(inner->type->kind == TyStruct || inner->type->kind == TyUnion)) {
-         *--(*sp) = '*';
-         *--(*sp) = '(';
-	 *(*ep)++ = ')';
-      }
-      break;
-
-   case TyStruct:
-   case TyUnion:
-      if (c && c->type->kind == TyPointer) {
-         *(*ep)++ = '-';
-         *(*ep)++ = '>';
-      } else
-         *(*ep)++ = '.';
-      break;
-
-   default:
-      break;
-   }
-}
-
-Char *VG_(describe_addr)(ThreadId tid, Addr addr)
-{
-   Addr eip;			/* thread's EIP */
-   Variable *list;		/* worklist */
-   Variable *keeplist;		/* container variables */
-   Variable *found;		/* the chain we found */
-   Int created=0, freed=0;
-   Int numvars = MAX_VARS;
-
-   describe_addr_buf = NULL;
-   describe_addr_bufidx = 0;
-   describe_addr_bufsz = 0;
-
-   clear_visited();
-
-   found = NULL;
-   keeplist = NULL;
-
-   eip = VG_(get_IP)(tid);
-   list = ML_(get_scope_variables)(tid);
-
-   if (memaccount) {
-      Variable *v;
-
-      for(v = list; v != NULL; v = v->next)
-	 created++;
-   }
-
-   if (debug) {
-      Char file[100];
-      Int line;
-      if (!VG_(get_filename_linenum)(eip, file, sizeof(file), 
-                                          NULL, 0, NULL, &line))
-	 file[0] = 0;
-      VG_(printf)("describing address %p for tid=%d @ %s:%d\n", addr, tid, file, line);
-   }
-
-   if (LAZYSIG)
-      setup_signals();
-
-   /* breadth-first traversal of all memory visible to the program at
-      the current point */
-   while(list != NULL && found == NULL) {
-      Variable **prev = &list;
-      Variable *var, *next;
-      Variable *newlist = NULL, *newlistend = NULL;
-
-      if (debug)
-	 VG_(printf)("----------------------------------------\n");
-
-      for(var = list; var != NULL; var = next) {
-	 SymType *type = var->type;
-	 Bool keep = False;
-
-	 next = var->next;
-
-	 if (debug)
-	    VG_(printf)("  %d: name=%s type=%p(%s %s) container=%p &val=%p\n", 
-			var->distance, var->name, 
-			var->type, ppkind(var->type->kind), 
-			var->type->name ? (char *)var->type->name : "",
-			var->container, var->valuep);
-   
-	 if (0 && has_visited(var->valuep, var->type)) {
-	    /* advance prev; we're keeping this one on the doomed list */
-	    prev = &var->next;
-	    continue;
-	 }
-
-	 if (!is_composite(var->type) && 
-	     addr >= var->valuep && addr < (var->valuep + var->size)) {
-	    /* at hit - remove it from the list, add it to the
-	       keeplist and set found */
-	    found = var;
-	    *prev = var->next;
-	    var->next = keeplist;
-	    keeplist = var;
-	    break;
-	 }
-
-	 type = ML_(st_basetype)(type, True);
-	 
-	 switch(type->kind) {
-	 case TyUnion:
-	 case TyStruct: {
-	    Int i;
-
-	    if (debug)
-	       VG_(printf)("    %d fields\n", type->u.t_struct.nfield);
-	    for(i = 0; i < type->u.t_struct.nfield; i++) {
-	       StField *f = &type->u.t_struct.fields[i];
-	       if(newvar(f->name, f->type, var->valuep + (f->offset / 8),
-                         (f->size + 7) / 8, var, &numvars, &created, &newlist,
-                         &newlistend))
-                  keep = True;
-	    }
-	    break;
-	 }
-
-	 case TyArray: {
-	    Int i; 
-	    Int offset;		/* offset of index for non-0-based arrays */
-	    Int min, max;	/* range of indicies we care about (0 based) */
-	    SymType *ty = type->u.t_array.type;
-	    vg_assert(type->u.t_array.idxtype->kind == TyRange);
-
-	    offset = type->u.t_array.idxtype->u.t_range.min;
-	    min = 0;
-	    max = type->u.t_array.idxtype->u.t_range.max - offset;
-
-	    if ((max-min+1) == 0) {
-#if SHADOWCHUNK
-	       /* zero-sized array - look at allocated memory */
-	       ShadowChunk *sc = findchunk(var->valuep);
-
-	       if (sc != NULL) {
-		  max = ((sc->data + sc->size - var->valuep) / ty->size) + min;
-		  if (debug)
-		     VG_(printf)("    zero sized array: using min=%d max=%d\n",
-				 min, max);
-	       }
-#endif
-	    }
-
-	    /* If this array's elements can't take us anywhere useful,
-	       just look to see if an element itself is being pointed
-	       to; otherwise just skip the whole thing */
-	    if (!is_followable(ty)) {
-	       UInt sz = ty->size * (max+1);
-
-	       if (debug)
-		  VG_(printf)("    non-followable array (sz=%d): checking addr %p in range %p-%p\n",
-			      sz, addr, var->valuep, (var->valuep + sz));
-	       if (ty->size > 0 && addr >= var->valuep && addr <= (var->valuep + sz))
-		  min = max = (addr - var->valuep) / ty->size;
-	       else
-		  break;
-	    }
-
-	    /* truncate array if it's too big */
-	    if (max-min+1 > MAX_ELEMENTS)
-	       max = min+MAX_ELEMENTS;
-	    
-	    if (debug)
-	       VG_(printf)("    array index %d - %d\n", min, max);
-	    for(i = min; i <= max; i++) {
-	       Char b[10];
-	       VG_(sprintf)(b, "[%d]", i+offset);
-	       if(newvar(b, ty, var->valuep + (i * ty->size), -1, var,
-                         &numvars, &created, &newlist, &newlistend))
-                  keep = True;
-	    }
-
-	    break;
-	 }
-
-	 case TyPointer:
-	    /* follow */
-	    /* XXX work out a way of telling whether a pointer is
-	       actually a decayed array, and treat it accordingly */
-	    if (is_valid_addr(var->valuep))
-	       if(newvar(NULL, type->u.t_pointer.type, *(Addr *)var->valuep,
-                         -1, var, &numvars, &created, &newlist, &newlistend))
-                  keep = True;
-	    break;
-
-	 case TyUnresolved:
-	    VG_(printf)("var %s is unresolved (type=%p)\n", var->name, type);
-	    break;
-
-	 default:
-	    /* Simple non-composite, non-pointer type */
-	    break;
-	 }
-	 
-	 if (keep) {
-	    /* ironically, keep means remove it from the list */
-	    *prev = next;
-	    
-	    /* being kept - add it if not already there */
-	    if (keeplist != var) {
-	       var->next = keeplist;
-	       keeplist = var;
-	    }
-	 } else {
-	    /* advance prev; we're keeping it on the doomed list */
-	    prev = &var->next;
-	 }
-      }
-
-      /* kill old list */
-      freed += free_varlist(list);
-      list = NULL;
-
-      if (found) {
-	 /* kill new list too */
-	 freed += free_varlist(newlist);
-	 newlist = newlistend = NULL;
-      } else {
-	 /* new list becomes old list */
-	 list = newlist;
-      }
-   }
-
-   if (LAZYSIG)
-      restore_signals();
-
-   if (found != NULL) {
-      Int len = 0;
-      Char file[100];
-      Int line;
-
-      /* Try to generate an idiomatic C-like expression from what
-	 we've found. */
-
-      {
-	 Variable *v;
-	 for(v = found; v != NULL; v = v->container) {
-	    if (debug)
-	       VG_(printf)("v=%p (%s) %s\n",
-			   v, v->name ? v->name : (Char *)"",
-			   ppkind(v->type->kind));
-	    
-	    len += (v->name ? VG_(strlen)(v->name) : 0) + 5;
-	 }
-      }
-
-      /* now that we know how long the expression will be
-	 (approximately) build it up */
-      {
-	 Char expr[len*2];
-	 Char *sp = &expr[len];	/* pointer at start of string */
-	 Char *ep = sp;		/* pointer at end of string */
-	 Bool ptr = True;
-
-	 /* If the result is already a pointer, just use that as the
-            value, otherwise generate &(...) around the expression. */
-         if (found->container && found->container->type->kind == TyPointer) {
-            vg_assert(found->name == NULL);
-
-	    found->name = found->container->name;
-	    found->container->name = NULL;
-	    found->container = found->container->container;
-	 } else {
-            bprintf(describe_addr_addbuf, 0, "&(");
-	    ptr = False;
-	 }
-
-	 genstring(found, NULL, &len, &ep, &sp);
-
-	 if (!ptr)
-	    *ep++ = ')';
-
-	 *ep++ = '\0';
-
-	 bprintf(describe_addr_addbuf, 0, sp);
-
-	 if (addr != found->valuep)
-	    bprintf(describe_addr_addbuf, 0, "+%d", addr - found->valuep);
-
-	 if (VG_(get_filename_linenum)(eip, file, sizeof(file), 
-                                            NULL, 0, NULL, &line))
-	    bprintf(describe_addr_addbuf, 0, " at %s:%d", file, line, addr);
-      }
-   }
-
-   freed += free_varlist(keeplist);
-
-   if (memaccount)
-      VG_(printf)("created %d, freed %d\n", created, freed);
-
-   clear_visited();
-
-   if (debug)
-      VG_(printf)("returning buf=%s\n", describe_addr_buf);
-
-   return describe_addr_buf;
-}
-#endif /* TEST */
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                          ---*/
-/*--------------------------------------------------------------------*/
-
-/*--------------------------------------------------------------------*/
-/*--- Header for symbol table stuff.                 priv_symtab.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2005 Julian Seward
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __PRIV_SYMTAB_H
-#define __PRIV_SYMTAB_H
-
-/* A structure to hold an ELF symbol (very crudely). */
-typedef 
-   struct { 
-      Addr addr;   /* lowest address of entity */
-      UInt size;   /* size in bytes */
-      Char *name;  /* name */
-      Addr tocptr; /* ppc64-linux only: value that R2 should have */
-   }
-   RiSym;
-
-/* Line count at which overflow happens, due to line numbers being stored as
- * shorts in `struct nlist' in a.out.h. */
-#define LINENO_OVERFLOW (1 << (sizeof(short) * 8))
-
-#define LINENO_BITS     20
-#define LOC_SIZE_BITS  (32 - LINENO_BITS)
-#define MAX_LINENO     ((1 << LINENO_BITS) - 1)
-
-/* Unlikely to have any lines with instruction ranges > 4096 bytes */
-#define MAX_LOC_SIZE   ((1 << LOC_SIZE_BITS) - 1)
-
-/* Number used to detect line number overflows;  if one line is 60000-odd
- * smaller than the previous, is was probably an overflow.  
- */
-#define OVERFLOW_DIFFERENCE     (LINENO_OVERFLOW - 5000)
-
-/* A structure to hold addr-to-source info for a single line.  There can be a
- * lot of these, hence the dense packing. */
-typedef
-   struct {
-      /* Word 1 */
-      Addr   addr;                  /* lowest address for this line */
-      /* Word 2 */
-      UShort size:LOC_SIZE_BITS;    /* byte size; we catch overflows of this */
-      UInt   lineno:LINENO_BITS;    /* source line number, or zero */
-      /* Word 3 */
-      Char*  filename;              /* source filename */
-      /* Word 4 */
-      Char*  dirname;               /* source directory name */
-   }
-   RiLoc;
-
-
-/* A structure to hold a set of variables in a particular scope */
-typedef struct _Scope Scope;	/* a set of symbols in one scope */
-typedef struct _Sym Sym;	/* a single symbol */
-typedef struct _ScopeRange ScopeRange; /* a range of code addreses a scope covers */
-
-typedef enum {
-      SyESPrel,			/* on the stack (relative to ESP) */
-      SyEBPrel,			/* on the stack (relative to EBP) */
-      SyReg,			/* in a register */
-      SyType,			/* a type definition */
-      SyStatic,			/* a static variable */
-      SyGlobal,			/* a global variable (XXX any different to static
-				   in an outer scope?) */
-} SyKind;
-
-struct _Sym {
-   SymType	*type;		/* type */
-   Char		*name;		/* name */
-   SyKind	kind;		/* kind of symbol */
-
-   /* a value, depending on kind */
-   union {
-      OffT	offset;		/* offset on stack (-ve -> ebp; +ve -> esp) */
-      Int	regno;		/* register number */
-      Addr	addr;		/* static or global address */
-   } u;
-};
-
-struct _Scope {
-   Scope	*outer;		/* outer (containing) scope */
-   UInt		nsyms;		/* number of symbols in this scope */
-   UInt		depth;		/* depth of scope */
-   Sym	        *syms;		/* the symbols */
-};
-
-/* A structure to map a scope to a range of code addresses; scopes may
-   be broken into multiple ranges (before and after a nested scope) */
-struct _ScopeRange {
-   Addr		addr;			/* start address of this scope */
-   Int		size;			/* length of scope */
-   Scope       *scope;			/* symbols in scope */
-};
-
-#define STRCHUNKSIZE	(64*1024)
-
-
-/* A structure to summarise CFI summary info for the code address
-   range [base .. base+len-1].  In short, if you know (sp,fp,ip) at
-   some point and ip is in the range [base .. base+len-1], it tells
-   you how to calculate (sp,fp) for the caller of the current
-   frame and also ra, the return address of the current frame.
-
-   First off, calculate CFA, the Canonical Frame Address, thusly:
-
-     cfa = if cfa_sprel then sp+cfa_off else fp+cfa_off
-
-   Once that is done, the previous frame's sp/fp values and this
-   frame's ra value can be calculated like this:
-
-      old_sp/fp/ra
-         = case sp/fp/ra_how of
-              CFIR_UNKNOWN   -> we don't know, sorry
-              CFIR_SAME      -> same as it was before (sp/fp only)
-              CFIR_CFAREL    -> cfa + sp/fp/ra_off
-              CFIR_MEMCFAREL -> *( cfa + sp/fp/ra_off )
-*/
-
-#define CFIR_UNKNOWN   ((UChar)0)
-#define CFIR_SAME      ((UChar)1)
-#define CFIR_CFAREL    ((UChar)2)
-#define CFIR_MEMCFAREL ((UChar)3)
-
-typedef
-   struct {
-      Addr  base;
-      UInt  len;
-      Bool  cfa_sprel;
-      UChar ra_how; /* a CFIR_ value */
-      UChar sp_how; /* a CFIR_ value */
-      UChar fp_how; /* a CFIR_ value */
-      Int   cfa_off;
-      Int   ra_off;
-      Int   sp_off;
-      Int   fp_off;
-   }
-   CfiSI;
-
-extern void ML_(ppCfiSI)   ( CfiSI* );
-
-
-/* A structure which contains information pertaining to one mapped
-   text segment.  This type is exported only abstractly - in
-   pub_tool_debuginfo.h. */
-struct _SegInfo {
-   struct _SegInfo* next;	/* list of SegInfos */
-
-   Int	  ref;
-
-   /* Description of the mapped segment. */
-   Addr   start;
-   UInt   size;
-   Char*  filename; /* in mallocville */
-   OffT   foffset;
-   Char*  soname;
-
-   /* An expandable array of symbols. */
-   RiSym* symtab;
-   UInt   symtab_used;
-   UInt   symtab_size;
-   /* An expandable array of locations. */
-   RiLoc* loctab;
-   UInt   loctab_used;
-   UInt   loctab_size;
-   /* An expandable array of scope ranges. */
-   ScopeRange *scopetab;
-   UInt        scopetab_used;
-   UInt        scopetab_size;
-   /* An expandable array of CFI summary info records.  Also includes
-      summary address bounds, showing the min and max address covered
-      by any of the records, as an aid to fast searching. */
-   CfiSI* cfisi;
-   UInt   cfisi_used;
-   UInt   cfisi_size;
-   Addr   cfisi_minaddr;
-   Addr   cfisi_maxaddr;
-
-   /* Expandable arrays of characters -- the string table.
-      Pointers into this are stable (the arrays are not reallocated)
-    */
-   struct strchunk {
-      UInt   strtab_used;
-      struct strchunk *next;
-      Char   strtab[STRCHUNKSIZE];
-   }      *strchunks;
-
-   /* offset    is what we need to add to symbol table entries
-      to get the real location of that symbol in memory.
-   */
-   OffT   offset;
-
-   /* Bounds of data, BSS, PLT, GOT and OPD (for ppc64-linux) so that
-      tools can see what section an address is in.  In the running image! */
-   Addr	  plt_start_vma;
-   UInt   plt_size;
-   Addr   got_start_vma;
-   UInt   got_size;
-   Addr   opd_start_vma;
-   UInt   opd_size;
-   Addr   data_start_vma;
-   UInt   data_size;
-   Addr   bss_start_vma;
-   UInt   bss_size;
-
-   /* data used by stabs parser */
-   struct _StabTypeTab	*stab_typetab;
-};
-
-extern
-Char *ML_(addStr) ( SegInfo* si, Char* str, Int len );
-
-extern
-void ML_(addScopeInfo) ( SegInfo* si, Addr this, Addr next, Scope *scope);
-
-extern
-void ML_(addLineInfo) ( SegInfo* si, 
-                        Char* filename, 
-                        Char* dirname,  /* NULL is allowable */
-                        Addr this, Addr next, Int lineno, Int entry);
-
-extern
-void ML_(addCfiSI) ( SegInfo* si, CfiSI* cfisi );
-
-/* Non-fatal -- use vg_panic if terminal. */
-extern
-void ML_(symerr) ( Char* msg );
-
-/* --------------------
-   Stabs reader
-   -------------------- */
-extern
-void ML_(read_debuginfo_stabs) ( SegInfo* si,
-				 UChar* stabC,   Int stab_sz, 
-				 UChar* stabstr, Int stabstr_sz );
-
-/* --------------------
-   DWARF2 reader
-   -------------------- */
-extern
-void ML_(read_debuginfo_dwarf2) 
-        ( SegInfo* si,
-          UChar* debuginfo,   Int debug_info_sz,  /* .debug_info */
-          UChar* debugabbrev,                     /* .debug_abbrev */
-          UChar* debugline,   Int debug_line_sz,  /* .debug_line */
-          UChar* debugstr );
-
-/* --------------------
-   DWARF1 reader
-   -------------------- */
-extern
-void ML_(read_debuginfo_dwarf1) ( SegInfo* si, 
-                                  UChar* dwarf1d, Int dwarf1d_sz, 
-                                  UChar* dwarf1l, Int dwarf1l_sz );
-
-/* --------------------
-   CFI reader
-   -------------------- */
-extern
-void ML_(read_callframe_info_dwarf2) 
-    ( /*OUT*/SegInfo* si, UChar* ehframe, Int ehframe_sz, Addr ehframe_addr );
-
-
-#endif   // __PRIV_SYMTAB_H
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                          ---*/
-/*--------------------------------------------------------------------*/
-
-/*--------------------------------------------------------------------*/
-/*--- Intra-Valgrind interfaces for symtypes.c.    priv_symtypes.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2005 Julian Seward
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __PRIV_SYMTYPES_H
-#define __PRIV_SYMTYPES_H
-
-/* Lets try to make these opaque */
-typedef struct _SymType SymType;
-
-/* ------------------------------------------------------------
-   Constructors for various SymType nodes
-   ------------------------------------------------------------ */
-
-/* Find the basetype for a given type: that is, if type is a typedef,
-   return the typedef'd type.  If resolve is true, it will resolve
-   unresolved symbols.  If type is not a typedef, then this is just
-   returns type.
-*/
-SymType *ML_(st_basetype)(SymType *type, Bool resolve);
-
-void ML_(st_setname)(SymType *ty, Char *name);
-
-typedef void (SymResolver)(SymType *, void *);
-
-/* Create an unresolved type */
-SymType *ML_(st_mkunresolved)(SymType *, SymResolver *resolve, void *data);
-
-/* update an unresolved type's data */
-void ML_(st_unresolved_setdata)(SymType *, SymResolver *resolve, void *data);
-
-Bool ML_(st_isresolved)(SymType *);
-UInt ML_(st_sizeof)(SymType *);
-
-/* Unknown type (unparsable) */
-SymType *ML_(st_mkunknown)(SymType *);
-
-SymType *ML_(st_mkvoid)(SymType *);
-
-SymType *ML_(st_mkint)(SymType *, UInt size, Bool isSigned);
-SymType *ML_(st_mkbool)(SymType *, UInt size);
-SymType *ML_(st_mkchar)(SymType *, Bool isSigned);
-SymType *ML_(st_mkfloat)(SymType *, UInt size);
-SymType *ML_(st_mkdouble)(SymType *, UInt size);
-
-SymType *ML_(st_mkpointer)(SymType *, SymType *);
-SymType *ML_(st_mkrange)(SymType *, SymType *, Int min, Int max);
-
-SymType *ML_(st_mkstruct)(SymType *, UInt size, UInt nfields);
-SymType *ML_(st_mkunion)(SymType *, UInt size, UInt nfields);
-void ML_(st_addfield)(SymType *, Char *name, SymType *, UInt off, UInt size);
-
-SymType *ML_(st_mkenum)(SymType *, UInt ntags);
-SymType *ML_(st_addtag)(SymType *, Char *name, Int val);
-
-SymType *ML_(st_mkarray)(SymType *, SymType *idxtype, SymType *artype);
-
-SymType *ML_(st_mktypedef)(SymType *, Char *name, SymType *type);
-
-Bool ML_(st_isstruct)(SymType *);
-Bool ML_(st_isunion)(SymType *);
-Bool ML_(st_isenum)(SymType *);
-
-/* ------------------------------------------------------------
-   Interface with symtab.c
-   ------------------------------------------------------------ */
-
-/* Typed value */
-typedef struct _Variable Variable;
-
-struct _Variable {
-   Char		*name;		/* name */
-   SymType	*type;		/* type of value */
-   Addr		valuep;		/* pointer to value */
-   UInt		size;		/* size of value */
-   UInt		distance;	/* "distance" from site of interest */
-   Variable	*next;
-   Variable	*container;
-};
-
-Variable *ML_(get_scope_variables)(ThreadId tid);
-
-#endif // __PRIV_SYMTYPES_H
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                          ---*/
-/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index 33e16d6..d081f27 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -57,7 +57,6 @@
 #include "priv_tytypes.h"
 #include "priv_storage.h"
 #include "priv_readdwarf.h"
-#include "priv_readstabs.h"
 #if defined(VGO_linux)
 # include "priv_readelf.h"
 # include "priv_readdwarf3.h"
diff --git a/coregrind/m_debuginfo/priv_readstabs.h b/coregrind/m_debuginfo/priv_readstabs.h
deleted file mode 100644
index 2432f86..0000000
--- a/coregrind/m_debuginfo/priv_readstabs.h
+++ /dev/null
@@ -1,55 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Read 'stabs' format debug info.             priv_readstabs.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2013 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __PRIV_READSTABS_H
-#define __PRIV_READSTABS_H
-
-#include "pub_core_basics.h"      // UChar
-#include "pub_core_debuginfo.h"   // DebugInfo
-
-/*
-   Stabs reader greatly improved by Nick Nethercote, Apr 02.
-   This module was also extensively hacked on by Jeremy Fitzhardinge
-   and Tom Hughes.
-*/
-
-/* --------------------
-   Stabs reader
-   -------------------- */
-extern
-void ML_(read_debuginfo_stabs) ( DebugInfo* di,
-                                 UChar* stabC,   Int stab_sz,
-                                 HChar* stabstr, Int stabstr_sz );
-
-#endif /* ndef __PRIV_READSTABS_H */
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                          ---*/
-/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index d3f646a..36db845 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -50,7 +50,6 @@
 #include "priv_readelf.h"          /* self */
 #include "priv_readdwarf.h"        /* 'cos ELF contains DWARF */
 #include "priv_readdwarf3.h"
-#include "priv_readstabs.h"        /* and stabs, if we're unlucky */
 #include "priv_readexidx.h"
 
 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
@@ -2320,8 +2319,6 @@
       DiSlice dynsym_escn         = DiSlice_INVALID; // .dynsym
       DiSlice debuglink_escn      = DiSlice_INVALID; // .gnu_debuglink
       DiSlice debugaltlink_escn   = DiSlice_INVALID; // .gnu_debugaltlink
-      DiSlice stab_escn           = DiSlice_INVALID; // .stab         (stabs) 
-      DiSlice stabstr_escn        = DiSlice_INVALID; // .stabstr      (stabs) 
       DiSlice debug_line_escn     = DiSlice_INVALID; // .debug_line   (dwarf2)
       DiSlice debug_info_escn     = DiSlice_INVALID; // .debug_info   (dwarf2)
       DiSlice debug_types_escn    = DiSlice_INVALID; // .debug_types  (dwarf4)
@@ -2405,9 +2402,6 @@
          FIND(".gnu_debuglink",     debuglink_escn)
          FIND(".gnu_debugaltlink",  debugaltlink_escn)
 
-         FIND(".stab",              stab_escn)
-         FIND(".stabstr",           stabstr_escn)
-
          FIND(".debug_line",        debug_line_escn)
          FIND(".debug_info",        debug_info_escn)
          FIND(".debug_types",       debug_types_escn)
@@ -2530,7 +2524,7 @@
          Addr     rw_dsvma_limit = 0;
          PtrdiffT rw_dbias = 0;
 
-         Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
+         Bool need_symtab, need_dwarf2, need_dwarf1;
 
          if (phdr_dnent == 0
              || !ML_(img_valid)(dimg, phdr_dioff,
@@ -2600,7 +2594,6 @@
          }
 
          need_symtab = (symtab_escn.img == NULL);
-         need_stabs  = (stab_escn.img == NULL);
          need_dwarf2 = (debug_info_escn.img == NULL);
          need_dwarf1 = (dwarf1d_escn.img == NULL);
 
@@ -2693,8 +2686,6 @@
             /* NEEDED?        NAME             ElfSec */
             FIND(need_symtab, ".symtab",       symtab_escn)
             FIND(need_symtab, ".strtab",       strtab_escn)
-            FIND(need_stabs,  ".stab",         stab_escn)
-            FIND(need_stabs,  ".stabstr",      stabstr_escn)
             FIND(need_dwarf2, ".debug_line",   debug_line_escn)
             FIND(need_dwarf2, ".debug_info",   debug_info_escn)
             FIND(need_dwarf2, ".debug_types",  debug_types_escn)
@@ -2885,27 +2876,6 @@
                                           False/*!is_ehframe*/ );
       }
 
-      /* Read the stabs and/or dwarf2 debug information, if any.  It
-         appears reading stabs stuff on amd64-linux doesn't work, so
-         we ignore it.  On s390x stabs also doesnt work and we always
-         have the dwarf info in the eh_frame.  We also segfault on
-         ppc64-linux when reading stabs, so skip that.  ppc32-linux
-         seems OK though.  Also skip on Android. */
-#     if !defined(VGP_amd64_linux) \
-         && !defined(VGP_s390x_linux) \
-         && !defined(VGP_ppc64be_linux) \
-         && !defined(VGP_ppc64le_linux) \
-         && !defined(VGPV_arm_linux_android) \
-         && !defined(VGPV_x86_linux_android) \
-         && !defined(VGP_mips64_linux)
-      // JRS 31 July 2014: stabs reading is currently broken and
-      // therefore deactivated.
-      //if (stab_img && stabstr_img) {
-      //   ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz, 
-      //                                   stabstr_img, stabstr_sz );
-      //}
-#     endif
-
       /* TOPLEVEL */
       /* jrs 2006-01-01: icc-8.1 has been observed to generate
          binaries without debug_str sections.  Don't preclude
diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c
index 32be819..9c31802 100644
--- a/coregrind/m_debuginfo/readmacho.c
+++ b/coregrind/m_debuginfo/readmacho.c
@@ -55,7 +55,6 @@
 #include "priv_readmacho.h"
 #include "priv_readdwarf.h"
 #include "priv_readdwarf3.h"
-#include "priv_readstabs.h"
 
 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
 #include <mach-o/loader.h>
@@ -708,7 +707,7 @@
    struct _DebugInfoMapping* rw_map = NULL;
 
    /* mmap the object file to look for di->soname and di->text_bias 
-      and uuid and nlist and STABS */
+      and uuid and nlist */
 
    /* This should be ensured by our caller (that we're in the accept
       state). */
diff --git a/coregrind/m_debuginfo/readstabs.c b/coregrind/m_debuginfo/readstabs.c
deleted file mode 100644
index 0882f45..0000000
--- a/coregrind/m_debuginfo/readstabs.c
+++ /dev/null
@@ -1,423 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Read stabs debug info.                           readstabs.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2013 Julian Seward
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-/*
-   Stabs reader greatly improved by Nick Nethercote, Apr 02.
-   This module was also extensively hacked on by Jeremy Fitzhardinge
-   and Tom Hughes.
-*/
-
-/* "on Linux (except android), or on Darwin" */
-#if (defined(VGO_linux) && \
-    !(defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
-      || defined(VGPV_mips32_linux_android)) \
-    || defined(VGO_darwin))
-
-#include "pub_core_basics.h"
-#include "pub_core_debuginfo.h"
-#include "pub_core_libcbase.h"
-#include "pub_core_libcassert.h"
-#include "pub_core_libcprint.h"
-#include "pub_core_xarray.h"
-#include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
-#include "priv_image.h"
-#include "priv_tytypes.h"
-#include "priv_d3basics.h"
-#include "priv_storage.h"
-#include "priv_readstabs.h"        /* self */
-
-/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
-#if defined(VGO_linux)
-/* stabs symbol list entry definition. */
-struct nlist {
-  union {
-    char *n_name;
-    struct nlist *n_next;
-    long n_strx;
-  } n_un;
-  unsigned char n_type;
-  char n_other;
-  short n_desc;
-  unsigned long n_value;
-};
-#elif defined(VGO_darwin)
-#  include <mach-o/nlist.h>
-#  define n_other n_sect
-#  if VG_WORDSIZE == 8
-#     define nlist nlist_64
-#  endif
-#else
-#  error "Unknown OS"
-#endif
-/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
-
-/*------------------------------------------------------------*/
-/*--- Read STABS format debug info.                        ---*/
-/*------------------------------------------------------------*/
-
-/* Stabs entry types, from:
- *   The "stabs" debug format
- *   Menapace, Kingdon and MacKenzie
- *   Cygnus Support
- */
-typedef enum { N_UNDEF = 0,	/* undefined symbol, new stringtab  */
-	       N_GSYM  = 32,    /* Global symbol                    */
-               N_FUN   = 36,    /* Function start or end            */
-               N_STSYM = 38,    /* Data segment file-scope variable */
-               N_LCSYM = 40,    /* BSS segment file-scope variable  */
-               N_RSYM  = 64,    /* Register variable                */
-               N_SLINE = 68,    /* Source line number               */
-               N_SO    = 100,   /* Source file path and name        */
-               N_LSYM  = 128,   /* Stack variable or type           */
-	       N_BINCL = 130,	/* Beginning of an include file	    */
-               N_SOL   = 132,   /* Include file name                */
-	       N_PSYM  = 160,   /* Function parameter               */
-	       N_EINCL = 162,	/* End of an include file           */
-               N_LBRAC = 192,   /* Start of lexical block           */
-	       N_EXCL  = 194,	/* Placeholder for an include file  */
-               N_RBRAC = 224    /* End   of lexical block           */
-             } stab_types;
-      
-
-/* Read stabs-format debug info.  This is all rather horrible because
-   stabs is a underspecified, kludgy hack.
-*/
-void ML_(read_debuginfo_stabs) ( DebugInfo* di,
-                                 UChar* stabC,   Int stab_sz, 
-                                 HChar* stabstr, Int stabstr_sz )
-{
-   Int    i;
-   Int    n_stab_entries;
-   struct nlist* stab = (struct nlist*)stabC;
-   HChar *next_stabstr = NULL;
-   /* state for various things */
-   struct {
-      Addr     start;         /* start address */
-      Addr     end;           /* end address */
-      Int      line;          /* first line */
-   } func = { 0, 0, -1 };
-   struct {
-      HChar   *name;
-      Bool     same;
-   } file = { NULL, True };
-   struct {
-      Int      prev;          /* prev line */
-      Int      no;            /* current line */
-      Int      ovf;           /* line wrap */
-      Addr     addr;          /* start of this line */
-      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
-                      36   N_FUN    start of a function
-
-      In this loop, we maintain a current file name, updated as 
-      N_SO/N_SOLs appear, and a current function base address, 
-      updated as N_FUNs appear.  Based on that, address ranges for 
-      N_SLINEs are calculated, and stuffed into the line info table.
-
-      Finding the instruction address range covered by an N_SLINE is
-      complicated;  see the N_SLINE case below.
-   */
-   file.name     = ML_(addStr)(di,"???", -1);
-
-   n_stab_entries = stab_sz/(int)sizeof(struct nlist);
-
-   TRACE_SYMTAB("\n--- Reading STABS (%d entries) ---\n", n_stab_entries);
-
-   for (i = 0; i < n_stab_entries; i++) {
-      const struct nlist *st = &stab[i];
-      HChar *string;
-
-      TRACE_SYMTAB("%2d  type=%d   othr=%d   desc=%d   "
-                   "value=0x%x   strx=%d  %s\n", i,
-                   st->n_type, st->n_other, st->n_desc, 
-                   (Int)st->n_value,
-                   (Int)st->n_un.n_strx, 
-                   stabstr + st->n_un.n_strx );
-
-      /* handle continued string stabs */
-      {
-         Int   qbuflen = 0;
-         Int   qidx = 0;
-         HChar* qbuf = NULL;
-         Int   qlen;
-         Bool  qcontinuing = False;
-         UInt  qstringidx;
-
-         qstringidx = st->n_un.n_strx;
-         string = stabstr + qstringidx;
-         qlen = VG_(strlen)(string);
-
-         while (string 
-                && qlen > 0 
-                && (qcontinuing || string[qlen-1] == '\\')) {
-            /* Gak, we have a continuation. Skip forward through
-               subsequent stabs to gather all the parts of the
-               continuation.  Increment i, but keep st pointing at
-               current stab. */
-
-            qcontinuing = string[qlen-1] == '\\';
-
-            /* remove trailing \ */
-            while (string[qlen-1] == '\\' && qlen > 0)
-               qlen--;
-
-            TRACE_SYMTAB("cont: found extension string: \"%s\" "
-                         "len=%d(%c) idx=%d buflen=%d\n", 
-                         string, qlen, string[qlen-1], qidx, qbuflen);
-
-            /* XXX this is silly.  The si->strtab should have a way of
-               appending to the last added string... */
-            if ((qidx + qlen) >= qbuflen) {
-               HChar *n;
-               
-               if (qbuflen == 0)
-                  qbuflen = 16;
-               while ((qidx + qlen) >= qbuflen)
-                  qbuflen *= 2;
-               n = ML_(dinfo_zalloc)("di.readstabs.rds.1", qbuflen);
-               VG_(memcpy)(n, qbuf, qidx);
-               
-               if (qbuf != NULL)
-                  ML_(dinfo_free)(qbuf);
-               qbuf = n;
-            }
-
-            VG_(memcpy)(&qbuf[qidx], string, qlen);
-            qidx += qlen;
-            if (di->trace_symtab) {
-               qbuf[qidx] = '\0';
-               TRACE_SYMTAB("cont: working buf=\"%s\"\n", qbuf);
-            }
-
-            i++;
-            if (i >= n_stab_entries)
-               break;
-
-            if (stab[i].n_un.n_strx) {
-               string = stabstr + stab[i].n_un.n_strx;
-               qlen = VG_(strlen)(string);
-            } else {
-               string = NULL;
-               qlen = 0;
-            }
-         }
-
-         if (qbuf != NULL) {
-            i--;                        /* overstepped */
-            string = ML_(addStr)(di, qbuf, qidx);
-            ML_(dinfo_free)(qbuf);
-            TRACE_SYMTAB("cont: made composite: \"%s\"\n", string);
-         }
-      }
-
-      switch(st->n_type) {
-         case N_UNDEF:
-            /* new string table base */
-            if (next_stabstr != NULL) {
-               stabstr_sz -= next_stabstr - stabstr;
-               stabstr = next_stabstr;
-               if (stabstr_sz <= 0) {
-                  VG_(printf)(" @@ bad stabstr size %d\n", stabstr_sz);
-                  return;
-               }
-            }
-            next_stabstr = stabstr + st->n_value;
-            break;
-
-         case N_BINCL: {
-            break;
-         }
-
-         case N_EINCL:
-            break;
-
-         case N_EXCL:
-            break;
-
-         case N_SOL:                /* sub-source (include) file */
-            if (line.ovf != 0) 
-               VG_(message)(Vg_UserMsg, 
-                            "Warning: file %s is very big (> 65535 lines) "
-                            "Line numbers and annotation for this file might "
-                            "be wrong.  Sorry.\n",
-                            file.name);
-            /* FALLTHROUGH */
-
-         case N_SO: {                /* new source file */
-            HChar *nm = string;
-            UInt len = VG_(strlen)(nm);
-            Addr addr = func.start + st->n_value;
-
-            if (line.addr != 0) {
-               /* finish off previous line */
-               ML_(addLineInfo)(di, 
-                                ML_(addFnDn) (di,
-                                              file.name,
-                                              NULL),
-                                line.addr,
-                                addr, line.no + line.ovf * LINENO_OVERFLOW, i);
-            }
-
-            /* reset line state */
-            line.ovf = 0;            
-            line.addr = 0;
-            line.prev = 0;
-            line.no = 0;
-
-            if (len > 0 && nm[len-1] != '/') {
-               file.name = ML_(addStr)(di, nm, -1);
-               TRACE_SYMTAB("new source: %s\n", file.name);
-            } else if (len == 0)
-               file.name = ML_(addStr)(di, "?1\0", -1);
-
-            break;
-         }
-
-         case N_SLINE: {        /* line info */
-            Addr addr = func.start + st->n_value;
-
-            if (line.addr != 0) {
-               /* there was a previous */
-               ML_(addLineInfo)(di, 
-                                ML_(addFnDn)(di,
-                                             file.name,
-                                             NULL), 
-                                line.addr,
-                                addr, line.no + line.ovf * LINENO_OVERFLOW, i);
-            }
-
-            line.addr = addr;
-            line.prev = line.no;
-            line.no = (Int)((UShort)st->n_desc);
-
-            if (line.prev > line.no + OVERFLOW_DIFFERENCE && file.same) {
-               VG_(message)(Vg_DebugMsg, 
-                  "Line number overflow detected (%d --> %d) in %s\n", 
-                  line.prev, line.no, file.name);
-               line.ovf++;
-            }
-            file.same = True;
-
-            /* This is pretty horrible.  If this is the first line of
-               the function, then bind any unbound symbols to the arg
-               scope, since they're probably arguments. */
-            if (line.first) {
-               line.first = False;
-               
-               /* remember first line of function */
-               if (func.start != 0) {
-                  func.line = line.no;
-               }
-            }
-            break;
-         }
-
-         case N_FUN: {                /* function start/end */
-            Addr addr = 0;        /* end address for prev line/scope */
-
-            /* if this the end of the function or we haven't
-               previously finished the previous function... */
-            if (*string == '\0' || func.start != 0) {
-               /* end of function */
-               line.first = False;
-
-               /* end line at end of function */
-               addr = func.start + st->n_value;
-
-               /* now between functions */
-               func.start = 0;
-
-               // XXXX DEAD POINT XXXX
-            }
-
-            if (*string != '\0') {
-               /* new function */
-               line.first = True;
-
-               /* line ends at start of next function */
-               addr = di->text_debug_bias + st->n_value;
-
-               func.start = addr;
-            }
-
-            if (line.addr) {
-               ML_(addLineInfo)(di, 
-                                ML_(addFnDn) (di,
-                                              file.name,
-                                              NULL),
-                                line.addr,
-                                addr, line.no + line.ovf * LINENO_OVERFLOW, i);
-               line.addr = 0;
-            }
-
-            //DEAD POINT
-            //DEAD POINT
-            break;
-         }
-
-         case N_LBRAC: {
-            /* open new scope */
-            // DEAD POINT
-            break;
-         }
-
-         case N_RBRAC: {
-            /* close scope */
-            // DEAD POINT
-            break;
-         }
-
-         case N_GSYM:                /* global variable */
-         case N_STSYM:                /* static in data segment */
-         case N_LCSYM:                /* static in bss segment */
-         case N_PSYM:                /* function parameter */
-         case N_LSYM:                /* stack variable */
-         case N_RSYM:                  /* register variable */
-            break;
-      }
-   }
-}
-
-#endif /* (defined(VGO_linux) && !defined(VGPV_*_linux_android)) \
-          || defined(VGO_darwin) */
-
-/*--------------------------------------------------------------------*/
-/*--- end                                                          ---*/
-/*--------------------------------------------------------------------*/
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index f82b5e4..e529a53 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -93,8 +93,6 @@
 		custom_alloc.stderr.exp-s390x-mvc \
 	custom-overlap.stderr.exp custom-overlap.vgtest \
 	deep-backtrace.vgtest deep-backtrace.stderr.exp \
-	deep_templates.vgtest \
-	deep_templates.stdout.exp deep_templates.stderr.exp \
 	demangle.stderr.exp demangle.vgtest \
 	describe-block.stderr.exp describe-block.vgtest \
 	descr_belowsp.vgtest descr_belowsp.stderr.exp \
@@ -377,10 +375,6 @@
 check_PROGRAMS += reach_thread_register
 endif
 
-if HAVE_GSTABS
-check_PROGRAMS += deep_templates
-endif
-
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
 
@@ -397,9 +391,6 @@
 
 leak_cpp_interior_SOURCES	= leak_cpp_interior.cpp
 
-deep_templates_SOURCES	= deep_templates.cpp
-deep_templates_CXXFLAGS	= $(AM_CFLAGS) -O -gstabs
-
 demangle_SOURCES = demangle.cpp
 
 dw4_CFLAGS		= $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section
diff --git a/memcheck/tests/deep_templates.cpp b/memcheck/tests/deep_templates.cpp
deleted file mode 100644
index db49bfe..0000000
--- a/memcheck/tests/deep_templates.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-
-/* Point of this test is to generate some very long 'stabs' debug
-   strings, via the use of these exponentially large template types.
-   When compiled with -gstabs, this causes 3.1.1 to segfault at
-   startup.
-*/
-
-#include <stdio.h>
-
-template <class T, class U>
-class Stack
-{
-   public:
-      Stack(int = 10) { size=5; top=6; stackPtr=(T*)6;  }; 
-      ~Stack() { }
-      int push(const T&, const U&); 
-      int popT(T&);
-      int popU(U&);
-      int isEmpty() const { return top == -1; } 
-      int isFull() const { return top == size - 1; } 
-   private:
-      int size;
-      int top;  
-      T* stackPtr;  
-} ;
-
-typedef  Stack<int,char>  Foo;
-typedef  Stack<Foo,Foo>  Foo2;
-typedef  Stack<Foo2,Foo2> Foo3;
-typedef  Stack<Foo3,Foo3> Foo4;
-typedef  Stack<Foo4,Foo4> Foo5;
-typedef  Stack<Foo5,Foo5> Foo6;
-typedef  Stack<Foo6,Foo6> Foo7;
-typedef  Stack<Foo7,Foo7> Foo8;
-typedef  Stack<Foo8,Foo8> Foo9;
-typedef  Stack<Foo9,Foo9> Foo10;
-typedef  Stack<Foo10,Foo10> Foo11;
-typedef  Stack<Foo11,Foo11> Foo12;
-
-int main ( int argc, char** argv )
-{
-  Stack<Foo12,Foo12> * x = new Stack<Foo12,Foo12>(3);
-  if (x == NULL)
-    printf("It's NULL (?!)\n");
-  else
-    printf("It's not NULL.  How DULL.\n");
-  delete x;
-  return 0;
-}
diff --git a/memcheck/tests/deep_templates.stderr.exp b/memcheck/tests/deep_templates.stderr.exp
deleted file mode 100644
index e69de29..0000000
--- a/memcheck/tests/deep_templates.stderr.exp
+++ /dev/null
diff --git a/memcheck/tests/deep_templates.stdout.exp b/memcheck/tests/deep_templates.stdout.exp
deleted file mode 100644
index 33820a0..0000000
--- a/memcheck/tests/deep_templates.stdout.exp
+++ /dev/null
@@ -1 +0,0 @@
-It's not NULL.  How DULL.
diff --git a/memcheck/tests/deep_templates.vgtest b/memcheck/tests/deep_templates.vgtest
deleted file mode 100644
index 210e34f..0000000
--- a/memcheck/tests/deep_templates.vgtest
+++ /dev/null
@@ -1,3 +0,0 @@
-prereq: test -e ./deep_templates
-prog: deep_templates
-vgopts: -q