Merge r14202 from the BUF_REMOVAL branch to trunk.
This patch changes the interface and behaviour of VG_(demangle) and
VG_(maybe_Z_demangle). Instead of copying the demangled name into a
fixed sized buffer that is passed in from the caller (HChar *buf, Int n_buf),
the demangling functions will now return a pointer to the full-length
demangled name (HChar **result). It is the caller's responsiblilty to
make a copy if needed. 

This change in function parameters ripples upward
- first: to get_sym_name
- then to the convenience wrappers
  - VG_(get_fnname)
  - VG_(get_fnname_w_offset)
  - VG_(get_fnname_if_entry)
  - VG_(get_fnname_raw)
  - VG_(get_fnname_no_cxx_demangle)
  - VG_(get_datasym_and_offset)

The changes in foComplete then forces the arguments of
  - VG_(get_objname) to be changed as well

There are some issues regarding the ownership and persistence of
character strings to consider.
In general, the returned character string is owned by "somebody else"
which means the caller must not free it. Also, the caller must not 
modify the returned string as it possibly points to read only memory.
Additionally, the returned string is not necessarily persistent. Here are
the scenarios:
- the returned string is a demangled function name in which case the
  memory holding the string will be freed when the demangler is called again.
- the returned string hangs off of a DebugInfo structure in which case
  it will be freed when the DebugInfo is discarded
- the returned string hangs off of a segment in the address space manager
  in which case it may be overwritten when the segment is merged with
  another segment
So the rule of thunb here is: if in doubt strdup the string.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14664 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c
index 5ba3338..71efdea 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -58,7 +58,6 @@
 #define DEBUG_CG 0
 
 #define FILE_LEN              VKI_PATH_MAX
-#define FN_LEN                256
 
 /*------------------------------------------------------------*/
 /*--- Options                                              ---*/
@@ -102,7 +101,7 @@
 
 typedef struct {
    HChar* file;
-   HChar* fn;
+   const HChar* fn;
    Int    line;
 }
 CodeLoc;
@@ -195,7 +194,7 @@
 
 // Get a permanent string;  either pull it out of the string table if it's
 // been encountered before, or dup it and put it into the string table.
-static HChar* get_perm_string(HChar* s)
+static HChar* get_perm_string(const HChar* s)
 {
    HChar** s_ptr = VG_(OSetGen_Lookup)(stringTable, &s);
    if (s_ptr) {
@@ -213,7 +212,7 @@
 /*------------------------------------------------------------*/
 
 static void get_debug_info(Addr instr_addr, HChar file[FILE_LEN],
-                           HChar fn[FN_LEN], UInt* line)
+                           const HChar **fn, UInt* line)
 {
    HChar dir[FILE_LEN];
    Bool found_dirname;
@@ -223,14 +222,14 @@
                              dir,  FILE_LEN, &found_dirname,
                              line
                           );
-   Bool found_fn        = VG_(get_fnname)(instr_addr, fn, FN_LEN);
+   Bool found_fn        = VG_(get_fnname)(instr_addr, fn);
 
    if (!found_file_line) {
       VG_(strcpy)(file, "???");
       *line = 0;
    }
    if (!found_fn) {
-      VG_(strcpy)(fn,  "???");
+      *fn = "???";
    }
 
    if (found_dirname) {
@@ -254,12 +253,13 @@
 // Returns a pointer to the line CC, creates a new one if necessary.
 static LineCC* get_lineCC(Addr origAddr)
 {
-   HChar   file[FILE_LEN], fn[FN_LEN];
+   HChar   file[FILE_LEN];
+   const HChar *fn;
    UInt    line;
    CodeLoc loc;
    LineCC* lineCC;
 
-   get_debug_info(origAddr, file, fn, &line);
+   get_debug_info(origAddr, file, &fn, &line);
 
    loc.file = file;
    loc.fn   = fn;
@@ -1383,7 +1383,8 @@
    Int     i, fd;
    SysRes  sres;
    HChar    buf[512];
-   HChar   *currFile = NULL, *currFn = NULL;
+   HChar   *currFile = NULL;
+   const HChar *currFn = NULL;
    LineCC* lineCC;
 
    // Setup output filename.  Nb: it's important to do this now, ie. as late
diff --git a/callgrind/debug.c b/callgrind/debug.c
index 8876636..53dd7fa 100644
--- a/callgrind/debug.c
+++ b/callgrind/debug.c
@@ -374,7 +374,7 @@
 void CLG_(print_addr)(Addr addr)
 {
     HChar fl_buf[FILENAME_LEN];
-    HChar fn_buf[FN_NAME_LEN];
+    const HChar *fn_buf;
     const HChar* obj_name;
     DebugInfo* di;
     UInt ln, i=0, opos=0;
@@ -384,7 +384,7 @@
 	return;
     }
 
-    CLG_(get_debug_info)(addr, fl_buf, fn_buf, &ln, &di);
+    CLG_(get_debug_info)(addr, fl_buf, &fn_buf, &ln, &di);
 
     if (VG_(strcmp)(fn_buf,"???")==0)
 	VG_(printf)("%#lx", addr);
diff --git a/callgrind/fn.c b/callgrind/fn.c
index d602ac0..3102b52 100644
--- a/callgrind/fn.c
+++ b/callgrind/fn.c
@@ -330,7 +330,7 @@
 static void resize_fn_array(void);
 
 static __inline__ 
-fn_node* new_fn_node(HChar fnname[FILENAME_LEN],
+fn_node* new_fn_node(const HChar *fnname,
 		     file_node* file, fn_node* next)
 {
     fn_node* fn = (fn_node*) CLG_MALLOC("cl.fn.nfnnd.1",
@@ -374,7 +374,7 @@
  */
 static
 fn_node* get_fn_node_infile(file_node* curr_file_node,
-			    HChar fnname[FN_NAME_LEN])
+			    const HChar *fnname)
 {
     fn_node* curr_fn_node;
     UInt     fnname_hash;
@@ -404,7 +404,7 @@
 static __inline__
 fn_node* get_fn_node_inseg(DebugInfo* di,
 			   HChar filename[FILENAME_LEN],
-			   HChar fnname[FN_NAME_LEN])
+			   const HChar *fnname)
 {
   obj_node  *obj  = CLG_(get_obj_node)(di);
   file_node *file = CLG_(get_file_node)(obj, filename);
@@ -416,7 +416,7 @@
 
 Bool CLG_(get_debug_info)(Addr instr_addr,
 			 HChar file[FILENAME_LEN],
-			 HChar fn_name[FN_NAME_LEN], UInt* line_num,
+			 const HChar **fn_name, UInt* line_num,
 			 DebugInfo** pDebugInfo)
 {
   Bool found_file_line, found_fn, found_dirname, result = True;
@@ -436,8 +436,7 @@
 					       dir, FILENAME_LEN,
 					       &found_dirname,
 					       &line);
-   found_fn = VG_(get_fnname)(instr_addr,
-			      fn_name, FN_NAME_LEN);
+   found_fn = VG_(get_fnname)(instr_addr, fn_name);
 
    if (found_dirname) {
        // +1 for the '/'.
@@ -450,7 +449,7 @@
    if (!found_file_line && !found_fn) {
      CLG_(stat).no_debug_BBs++;
      VG_(strcpy)(file, "???");
-     VG_(strcpy)(fn_name,  "???");
+     *fn_name = "???";
      if (line_num) *line_num=0;
      result = False;
 
@@ -460,7 +459,7 @@
 
    } else if ( found_file_line && !found_fn) {
      CLG_(stat).file_line_debug_BBs++;
-     VG_(strcpy)(fn_name,  "???");
+     *fn_name = "???";
      if (line_num) *line_num=line;
 
    } else  /*(!found_file_line &&  found_fn)*/ {
@@ -474,7 +473,7 @@
 	    !pDebugInfo   ? "-" :
 	    (*pDebugInfo) ? VG_(DebugInfo_get_filename)(*pDebugInfo) :
 	    "(None)",
-	    fn_name);
+	    *fn_name);
 
   return result;
 }
@@ -488,7 +487,8 @@
  */
 fn_node* CLG_(get_fn_node)(BB* bb)
 {
-    HChar      filename[FILENAME_LEN], fnname[FN_NAME_LEN];
+    HChar      filename[FILENAME_LEN];
+    const HChar *fnname;
     DebugInfo* di;
     UInt       line_num;
     fn_node*   fn;
@@ -502,26 +502,27 @@
      * the BB according to debug information
      */
     CLG_(get_debug_info)(bb_addr(bb),
-			filename, fnname, &line_num, &di);
+			filename, &fnname, &line_num, &di);
 
     if (0 == VG_(strcmp)(fnname, "???")) {
 	int p;
-
+        static HChar buf[32];  // for sure large enough
 	/* Use address as found in library */
 	if (sizeof(Addr) == 4)
-	    p = VG_(sprintf)(fnname, "%#08lx", bb->offset);
+	    p = VG_(sprintf)(buf, "%#08lx", bb->offset);
 	else 	    
 	    // 64bit address
-	    p = VG_(sprintf)(fnname, "%#016lx", bb->offset);
+	    p = VG_(sprintf)(buf, "%#016lx", bb->offset);
 
-	VG_(sprintf)(fnname+p, "%s", 
+	VG_(sprintf)(buf + p, "%s", 
 		     (bb->sect_kind == Vg_SectData) ? " [Data]" :
 		     (bb->sect_kind == Vg_SectBSS)  ? " [BSS]"  :
 		     (bb->sect_kind == Vg_SectGOT)  ? " [GOT]"  :
 		     (bb->sect_kind == Vg_SectPLT)  ? " [PLT]"  : "");
+        fnname = buf;
     }
     else {
-      if (VG_(get_fnname_if_entry)(bb_addr(bb), fnname, FN_NAME_LEN))
+      if (VG_(get_fnname_if_entry)(bb_addr(bb), &fnname))
 	bb->is_entry = 1;
     }
 
@@ -532,7 +533,7 @@
     if (0 == VG_(strcmp)(fnname, "vgPlain___libc_freeres_wrapper")
 	&& exit_bb) {
       CLG_(get_debug_info)(bb_addr(exit_bb),
-			  filename, fnname, &line_num, &di);
+			  filename, &fnname, &line_num, &di);
 	
 	CLG_DEBUG(1, "__libc_freeres_wrapper renamed to _exit\n");
     }
@@ -543,7 +544,7 @@
 	(bb_addr(bb) >= runtime_resolve_addr) &&
 	(bb_addr(bb) < runtime_resolve_addr + runtime_resolve_length)) {
 	/* BB in runtime_resolve found by code check; use this name */
-	VG_(sprintf)(fnname, "_dl_runtime_resolve");
+      fnname = "_dl_runtime_resolve";
     }
 
     /* get fn_node struct for this function */
diff --git a/callgrind/global.h b/callgrind/global.h
index ff423b4..a32ba55 100644
--- a/callgrind/global.h
+++ b/callgrind/global.h
@@ -691,7 +691,7 @@
 
 /* from main.c */
 Bool CLG_(get_debug_info)(Addr, HChar filename[FILENAME_LEN],
-			 HChar fn_name[FN_NAME_LEN], UInt*, DebugInfo**);
+			 const HChar **fn_name, UInt*, DebugInfo**);
 void CLG_(collectBlockInfo)(IRSB* bbIn, UInt*, UInt*, Bool*);
 void CLG_(set_instrument_state)(const HChar*,Bool);
 void CLG_(dump_profile)(const HChar* trigger,Bool only_current_thread);
diff --git a/coregrind/m_addrinfo.c b/coregrind/m_addrinfo.c
index 95ec0fe..803bb3a 100644
--- a/coregrind/m_addrinfo.c
+++ b/coregrind/m_addrinfo.c
@@ -124,15 +124,12 @@
    }
    /* -- Have a look at the low level data symbols - perhaps it's in
       there. -- */
-   VG_(memset)( &ai->Addr.DataSym.name,
-                0, sizeof(ai->Addr.DataSym.name));
+   const HChar *name;
    if (VG_(get_datasym_and_offset)(
-             a, &ai->Addr.DataSym.name[0],
-             sizeof(ai->Addr.DataSym.name)-1,
+             a, &name,
              &ai->Addr.DataSym.offset )) {
+      ai->Addr.DataSym.name = VG_(strdup)("mc.da.dsname", name);
       ai->tag = Addr_DataSym;
-      vg_assert( ai->Addr.DataSym.name
-                    [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
       return;
    }
    /* -- Perhaps it's on a thread's stack? -- */
@@ -293,6 +290,7 @@
          break;
 
       case Addr_DataSym:
+         VG_(free)(ai->Addr.DataSym.name);
          break;
 
       case Addr_Variable:
@@ -384,7 +382,7 @@
                     xpost );
          if (ai->Addr.Stack.frameNo != -1 && ai->Addr.Stack.IP != 0) {
 #define     FLEN                256
-            HChar fn[FLEN];
+            const HChar *fn;
             Bool  hasfn;
             HChar file[FLEN];
             Bool  hasfile;
@@ -392,7 +390,6 @@
             Bool haslinenum;
             PtrdiffT offset;
 
-            hasfn = VG_(get_fnname)(ai->Addr.Stack.IP, fn, FLEN);
             if (VG_(get_inst_offset_in_function)( ai->Addr.Stack.IP,
                                                   &offset))
                haslinenum = VG_(get_linenum) (ai->Addr.Stack.IP - offset,
@@ -408,6 +405,8 @@
                              FLEN - VG_(strlen)(file) - 1);
             }
 
+            hasfn = VG_(get_fnname)(ai->Addr.Stack.IP, &fn);
+
             if (hasfn || hasfile)
                VG_(emit)( "%sin frame #%d, created by %s (%s)%s\n",
                           xpre,
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index 33bfe92..dbcee08 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -1729,11 +1729,18 @@
    C++ demangling, regardless of VG_(clo_demangle) -- probably because the
    call has come from VG_(get_fnname_raw)().  findText
    indicates whether we're looking for a text symbol or a data symbol
-   -- caller must choose one kind or the other. */
+   -- caller must choose one kind or the other.
+   Note: the string returned in *BUF is persistent as long as 
+   (1) the DebugInfo it belongs to is not discarded
+   (2) the segment containing the address is not merged with another segment
+   (3) the demangler is not invoked again
+   In other words: if in doubt, save it away.
+   Also, the returned string is owned by "somebody else". Callers must
+   not free it or modify it. */
 static
 Bool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
                     Bool do_below_main_renaming,
-                    Addr a, HChar* buf, Int nbuf,
+                    Addr a, const HChar** buf,
                     Bool match_anywhere_in_sym, Bool show_offset,
                     Bool findText, /*OUT*/PtrdiffT* offsetP )
 {
@@ -1742,12 +1749,14 @@
    PtrdiffT   offset;
 
    search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
-   if (di == NULL) 
+   if (di == NULL) {
+      *buf = "";
       return False;
+   }
 
    vg_assert(di->symtab[sno].pri_name);
    VG_(demangle) ( do_cxx_demangling, do_z_demangling,
-                   di->symtab[sno].pri_name, buf, nbuf );
+                   di->symtab[sno].pri_name, buf );
 
    /* Do the below-main hack */
    // To reduce the endless nuisance of multiple different names 
@@ -1755,31 +1764,31 @@
    // known incarnations of said into a single name, "(below main)", if
    // --show-below-main=yes.
    if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
-        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
+        Vg_FnNameBelowMain == VG_(get_fnname_kind)(*buf) )
    {
-      VG_(strncpy_safely)(buf, "(below main)", nbuf);
+     *buf = "(below main)";
    }
    offset = a - di->symtab[sno].avmas.main;
    if (offsetP) *offsetP = offset;
 
    if (show_offset && offset != 0) {
-      HChar    buf2[12];
-      HChar*   symend = buf + VG_(strlen)(buf);
-      HChar*   end = buf + nbuf;
-      Int      len;
+      static HChar *bufwo;      // buf with offset
+      static SizeT  bufwo_szB;
+      SizeT  need, len;
 
-      len = VG_(sprintf)(buf2, "%c%ld",
-			 offset < 0 ? '-' : '+',
-			 offset < 0 ? -offset : offset);
-      vg_assert(len < (Int)sizeof(buf2));
-
-      if (len < (end - symend)) {
-	 HChar *cp = buf2;
-	 VG_(memcpy)(symend, cp, len+1);
+      len = VG_(strlen)(*buf);
+      need = len + 1 + 19 + 1;
+      if (need > bufwo_szB) {
+        bufwo = ML_(dinfo_realloc)("get_sym_size", bufwo, need);
+        bufwo_szB = need;
       }
-   }
 
-   buf[nbuf-1] = 0; /* paranoia */
+      VG_(strcpy)(bufwo, *buf);
+      VG_(sprintf)(bufwo + len, "%c%ld",
+                   offset < 0 ? '-' : '+',
+                   offset < 0 ? -offset : offset);
+      *buf = bufwo;
+   }
 
    return True;
 }
@@ -1806,12 +1815,14 @@
 }
 
 /* This is available to tools... always demangle C++ names,
-   match anywhere in function, but don't show offsets. */
-Bool VG_(get_fnname) ( Addr a, HChar* buf, Int nbuf )
+   match anywhere in function, but don't show offsets.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
+Bool VG_(get_fnname) ( Addr a, const HChar** buf )
 {
    return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
                          /*below-main-renaming*/True,
-                         a, buf, nbuf,
+                         a, buf,
                          /*match_anywhere_in_fun*/True, 
                          /*show offset?*/False,
                          /*text syms only*/True,
@@ -1819,12 +1830,14 @@
 }
 
 /* This is available to tools... always demangle C++ names,
-   match anywhere in function, and show offset if nonzero. */
-Bool VG_(get_fnname_w_offset) ( Addr a, HChar* buf, Int nbuf )
+   match anywhere in function, and show offset if nonzero.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
+Bool VG_(get_fnname_w_offset) ( Addr a, const HChar** buf )
 {
    return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
                          /*below-main-renaming*/True,
-                         a, buf, nbuf,
+                         a, buf,
                          /*match_anywhere_in_fun*/True, 
                          /*show offset?*/True,
                          /*text syms only*/True,
@@ -1833,12 +1846,14 @@
 
 /* This is available to tools... always demangle C++ names,
    only succeed if 'a' matches first instruction of function,
-   and don't show offsets. */
-Bool VG_(get_fnname_if_entry) ( Addr a, HChar* buf, Int nbuf )
+   and don't show offsets.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
+Bool VG_(get_fnname_if_entry) ( Addr a, const HChar** buf )
 {
    return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
                          /*below-main-renaming*/True,
-                         a, buf, nbuf,
+                         a, buf,
                          /*match_anywhere_in_fun*/False, 
                          /*show offset?*/False,
                          /*text syms only*/True,
@@ -1847,12 +1862,14 @@
 
 /* This is only available to core... don't C++-demangle, don't Z-demangle,
    don't rename below-main, match anywhere in function, and don't show
-   offsets. */
-Bool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf )
+   offsets.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
+Bool VG_(get_fnname_raw) ( Addr a, const HChar** buf )
 {
    return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
                          /*below-main-renaming*/False,
-                         a, buf, nbuf,
+                         a, buf,
                          /*match_anywhere_in_fun*/True, 
                          /*show offset?*/False,
                          /*text syms only*/True,
@@ -1861,15 +1878,17 @@
 
 /* This is only available to core... don't demangle C++ names, but do
    do Z-demangling and below-main-renaming, match anywhere in function, and
-   don't show offsets. */
-Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf,
-                                       InlIPCursor* iipc )
+   don't show offsets.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
+Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, const HChar** buf,
+                                       const InlIPCursor* iipc )
 {
    if (is_bottom(iipc)) {
       // At the bottom (towards main), we describe the fn at eip.
       return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
                             /*below-main-renaming*/True,
-                            a, buf, nbuf,
+                            a, buf,
                             /*match_anywhere_in_fun*/True, 
                             /*show offset?*/False,
                             /*text syms only*/True,
@@ -1880,7 +1899,7 @@
          : NULL;
       vg_assert (next_inl);
       // The function we are in is called by next_inl.
-      VG_(snprintf)(buf, nbuf, "%s", next_inl->inlinedfn);
+      *buf = next_inl->inlinedfn;
       return True;
    }
 }
@@ -1891,17 +1910,17 @@
 Bool VG_(get_inst_offset_in_function)( Addr a,
                                        /*OUT*/PtrdiffT* offset )
 {
-   HChar fnname[64];
+   const HChar *fnname;
    return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
                          /*below-main-renaming*/False,
-                         a, fnname, 64,
+                         a, &fnname,
                          /*match_anywhere_in_sym*/True, 
                          /*show offset?*/False,
                          /*text syms only*/True,
                          offset );
 }
 
-Vg_FnNameKind VG_(get_fnname_kind) ( HChar* name )
+Vg_FnNameKind VG_(get_fnname_kind) ( const HChar* name )
 {
    if (VG_STREQ("main", name)) {
       return Vg_FnNameMain;
@@ -1926,14 +1945,12 @@
 
 Vg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
 {
-   // We don't need a big buffer;  all the special names are small.
-   #define BUFLEN 50
-   HChar buf[50];
+   const HChar *buf;
 
    // We don't demangle, because it's faster not to, and the special names
    // we're looking for won't be mangled.
-   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
-      buf[BUFLEN-1] = '\0';      // paranoia
+   if (VG_(get_fnname_raw) ( ip, &buf )) {
+
       return VG_(get_fnname_kind)(buf);
    } else {
       return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
@@ -1941,37 +1958,35 @@
 }
 
 /* Looks up data_addr in the collection of data symbols, and if found
-   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
-   which is guaranteed to be zero terminated.  Also data_addr's offset
-   from the symbol start is put into *offset. */
+   puts a pointer to its name into dname. The name is zero terminated.
+   Also data_addr's offset from the symbol start is put into *offset.
+   NOTE: See important comment about the persistence and memory ownership
+   of the return string at function get_sym_name */
 Bool VG_(get_datasym_and_offset)( Addr data_addr,
-                                  /*OUT*/HChar* dname, Int n_dname,
+                                  /*OUT*/const HChar** dname,
                                   /*OUT*/PtrdiffT* offset )
 {
-   Bool ok;
-   vg_assert(n_dname > 1);
-   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
+   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
                        /*below-main-renaming*/False,
-                       data_addr, dname, n_dname,
+                       data_addr, dname,
                        /*match_anywhere_in_sym*/True, 
                        /*show offset?*/False,
                        /*data syms only please*/False,
                        offset );
-   if (!ok)
-      return False;
-   dname[n_dname-1] = 0;
-   return True;
 }
 
 /* Map a code address to the name of a shared object file or the
-   executable.  Returns False if no idea; otherwise True.  Doesn't
-   require debug info.  Caller supplies buf and nbuf. */
-Bool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf )
+   executable.  Returns False if no idea; otherwise True.
+   Note: the string returned in *BUF is persistent as long as 
+   (1) the DebugInfo it belongs to is not discarded
+   (2) the segment containing the address is not merged with another segment
+*/
+Bool VG_(get_objname) ( Addr a, const HChar** buf )
 {
    DebugInfo* di;
    const NSegment *seg;
    const HChar* filename;
-   vg_assert(nbuf > 0);
+
    /* Look in the debugInfo_list to find the name.  In most cases we
       expect this to produce a result. */
    for (di = debugInfo_list; di != NULL; di = di->next) {
@@ -1979,8 +1994,7 @@
           && di->text_size > 0
           && di->text_avma <= a 
           && a < di->text_avma + di->text_size) {
-         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
-         buf[nbuf-1] = 0;
+         *buf = di->fsm.filename;
          return True;
       }
    }
@@ -1991,7 +2005,7 @@
       when running programs under wine. */
    if ( (seg = VG_(am_find_nsegment(a))) != NULL 
         && (filename = VG_(am_get_filename)(seg)) != NULL ) {
-      VG_(strncpy_safely)(buf, filename, nbuf);
+     *buf = filename;
       return True;
    }
    return False;
@@ -2220,11 +2234,11 @@
 
    vg_assert (!iipc || iipc->eip == eip);
 
-   static HChar buf_fn[BUF_LEN];
-   static HChar buf_obj[BUF_LEN];
+   static const HChar *buf_fn;
+   static const HChar *buf_obj;
    static HChar buf_srcloc[BUF_LEN];
    static HChar buf_dirname[BUF_LEN];
-   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
+   buf_srcloc[0] = buf_dirname[0] = 0;
 
    Bool  know_dirinfo = False;
    Bool  know_fnname;
@@ -2234,15 +2248,15 @@
    if (is_bottom(iipc)) {
       // At the bottom (towards main), we describe the fn at eip.
       know_fnname = VG_(clo_sym_offsets)
-                    ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
-                    : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
+                    ? VG_(get_fnname_w_offset) (eip, &buf_fn)
+                    : VG_(get_fnname) (eip, &buf_fn);
    } else {
       const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
          ? & iipc->di->inltab[iipc->next_inltab]
          : NULL;
       vg_assert (next_inl);
       // The function we are in is called by next_inl.
-      VG_(snprintf)(buf_fn, BUF_LEN, "%s", next_inl->inlinedfn);
+      buf_fn = next_inl->inlinedfn;  // FIXME: IS THIS SAFE ??
       know_fnname = True;
 
       // INLINED????
@@ -2253,7 +2267,7 @@
       // ??? Currently never showing an offset.
    }
 
-   know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
+   know_objname = VG_(get_objname)(eip, &buf_obj);
 
    if (is_top(iipc)) {
       // The source for the highest level is in the loctab entry.
@@ -2285,10 +2299,7 @@
       lineno = cur_inl->lineno;
       know_srcloc = True;
    }
-         
 
-   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
-   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
    buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
    buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
 
diff --git a/coregrind/m_debuginfo/misc.c b/coregrind/m_debuginfo/misc.c
index 25ea58e..57c91c6 100644
--- a/coregrind/m_debuginfo/misc.c
+++ b/coregrind/m_debuginfo/misc.c
@@ -68,6 +68,12 @@
    return dst;
 }
 
+void* ML_(dinfo_realloc) ( const HChar* cc, void* ptr, SizeT new_size ) {
+   void* dst = VG_(arena_realloc)( VG_AR_DINFO, cc, ptr, new_size );
+   vg_assert(dst);
+   return dst;
+}
+
 static inline Bool host_is_little_endian ( void ) {
    UInt x = 0x76543210;
    UChar* p = (UChar*)(&x);
diff --git a/coregrind/m_debuginfo/priv_misc.h b/coregrind/m_debuginfo/priv_misc.h
index 0828290..7ca7614 100644
--- a/coregrind/m_debuginfo/priv_misc.h
+++ b/coregrind/m_debuginfo/priv_misc.h
@@ -44,6 +44,7 @@
 void   ML_(dinfo_free)( void* v );
 HChar* ML_(dinfo_strdup)( const HChar* cc, const HChar* str );
 void*  ML_(dinfo_memdup)( const HChar* cc, const void* str, SizeT nStr );
+void*  ML_(dinfo_realloc) ( const HChar* cc, void* ptr, SizeT new_size );
 void   ML_(dinfo_shrink_block)( void* ptr, SizeT szB );
 
 /* Extract (possibly unaligned) data of various sizes from a buffer. */
diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
index 8a22ca2..5ae2a5d 100644
--- a/coregrind/m_debuglog.c
+++ b/coregrind/m_debuglog.c
@@ -890,20 +890,18 @@
          }
 
 //         case 'y': { /* %y - print symbol */
-//            HChar buf[100];
-//            HChar *cp = buf;
 //            Addr a = va_arg(vargs, Addr);
 //
-//            if (flags & VG_MSG_PAREN)
-//               *cp++ = '(';
-//            if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
-//               if (flags & VG_MSG_PAREN) {
-//                  cp += VG_(strlen)(cp);
-//                  *cp++ = ')';
-//                  *cp = '\0';
+//            HChar *name;
+// 	      if (VG_(get_fnname_w_offset)(a, &name)) {
+//               HChar buf[1 + VG_strlen(name) + 1 + 1];
+// 	         if (flags & VG_MSG_PAREN) {
+//                  VG_(sprintf)(str, "(%s)", name):
+// 	         } else {
+//                  VG_(sprintf)(str, "%s", name):
 //               }
-//               ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
-//            }
+// 	         ret += myvprintf_str(send, flags, width, buf, 0);
+// 	      }
 //            break;
 //         }
          default:
diff --git a/coregrind/m_demangle/demangle.c b/coregrind/m_demangle/demangle.c
index 385ee8d..1054c14 100644
--- a/coregrind/m_demangle/demangle.c
+++ b/coregrind/m_demangle/demangle.c
@@ -83,36 +83,45 @@
 
 /* This is the main, standard demangler entry point. */
 
+/* Upon return, *RESULT will point to the demangled name.
+   The memory buffer that holds the demangled name is allocated on the
+   heap and will be deallocated in the next invocation. Conceptually,
+   that buffer is owned by VG_(demangle). That means two things:
+   (1) Users of VG_(demangle) must not free that buffer.
+   (2) If the demangled name needs to be stashed away for later use,
+       the contents of the buffer needs to be copied. It is not sufficient
+       to just store the pointer as it will point to deallocated memory
+       after the next VG_(demangle) invocation. */
 void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
-                     const HChar* orig, HChar* result, Int result_size )
+                     /* IN */  const HChar  *orig,
+                     /* OUT */ const HChar **result )
 {
-#  define N_ZBUF 4096
-   HChar* demangled = NULL;
-   HChar z_demangled[N_ZBUF];
-
    /* Possibly undo (2) */
    /* Z-Demangling was requested.  
       The fastest way to see if it's a Z-mangled name is just to attempt
       to Z-demangle it (with NULL for the soname buffer, since we're not
       interested in that). */
    if (do_z_demangling) {
-      if (VG_(maybe_Z_demangle)( orig, NULL,0,/*soname*/
-                                 z_demangled, N_ZBUF, NULL, NULL, NULL )) {
+      const HChar *z_demangled;
+
+      if (VG_(maybe_Z_demangle)( orig, NULL, /*soname*/
+                                 &z_demangled, NULL, NULL, NULL )) {
          orig = z_demangled;
       }
    }
 
    /* Possibly undo (1) */
    if (do_cxx_demangling && VG_(clo_demangle)) {
+      static HChar* demangled = NULL;
+
+      /* Free up previously demangled name */
+      if (demangled) VG_(arena_free) (VG_AR_DEMANGLE, demangled);
+
       demangled = ML_(cplus_demangle) ( orig, DMGL_ANSI | DMGL_PARAMS );
+
+      *result = (demangled == NULL) ? orig : demangled;
    } else {
-      demangled = NULL;
-   }
-   if (demangled) {
-      VG_(strncpy_safely)(result, demangled, result_size);
-      VG_(arena_free) (VG_AR_DEMANGLE, demangled);
-   } else {
-      VG_(strncpy_safely)(result, orig, result_size);
+      *result = orig;
    }
 
    // 13 Mar 2005: We used to check here that the demangler wasn't leaking
@@ -120,7 +129,6 @@
    // very rarely (ie. I've heard of it twice in 3 years), the demangler
    // does leak.  But, we can't do much about it, and it's not a disaster,
    // so we just let it slide without aborting or telling the user.
-#  undef N_ZBUF
 }
 
 
@@ -141,38 +149,48 @@
    function name part. */
 
 Bool VG_(maybe_Z_demangle) ( const HChar* sym, 
-                             /*OUT*/HChar* so, Int soLen,
-                             /*OUT*/HChar* fn, Int fnLen,
+                             /*OUT*/const HChar** so,
+                             /*OUT*/const HChar** fn,
                              /*OUT*/Bool* isWrap,
                              /*OUT*/Int*  eclassTag,
                              /*OUT*/Int*  eclassPrio )
 {
+   static HChar *sobuf;
+   static HChar *fnbuf;
+   static SizeT  buf_len = 0;
+
+   /* The length of the name after undoing Z-encoding is always smaller
+      than the mangled name. Making the soname and fnname buffers as large
+      as the demangled name is therefore always safe and overflow can never
+      occur. */
+   SizeT len = VG_(strlen)(sym) + 1;
+
+   if (buf_len < len) {
+      sobuf = VG_(arena_realloc)(VG_AR_DEMANGLE, "Z-demangle", sobuf, len);
+      fnbuf = VG_(arena_realloc)(VG_AR_DEMANGLE, "Z-demangle", fnbuf, len);
+      buf_len = len;
+   }
+   sobuf[0] = fnbuf[0] = '\0';
+
+   if (so) 
+     *so = sobuf;
+   *fn = fnbuf;
+
 #  define EMITSO(ch)                           \
       do {                                     \
          if (so) {                             \
-            if (soi >= soLen) {                \
-               so[soLen-1] = 0; oflow = True;  \
-            } else {                           \
-               so[soi++] = ch; so[soi] = 0;    \
-            }                                  \
+            sobuf[soi++] = ch; sobuf[soi] = 0; \
          }                                     \
       } while (0)
 #  define EMITFN(ch)                           \
       do {                                     \
-         if (fni >= fnLen) {                   \
-            fn[fnLen-1] = 0; oflow = True;     \
-         } else {                              \
-            fn[fni++] = ch; fn[fni] = 0;       \
-         }                                     \
+         fnbuf[fni++] = ch; fnbuf[fni] = 0;    \
       } while (0)
 
-   Bool error, oflow, valid, fn_is_encoded, is_VG_Z_prefixed;
+   Bool error, valid, fn_is_encoded, is_VG_Z_prefixed;
    Int  soi, fni, i;
 
-   vg_assert(soLen > 0 || (soLen == 0 && so == NULL));
-   vg_assert(fnLen > 0);
    error = False;
-   oflow = False;
    soi = 0;
    fni = 0;
 
@@ -329,12 +347,6 @@
                    "m_demangle: error Z-demangling: %s\n", sym);
       return False;
    }
-   if (oflow) {
-      /* It didn't fit.  Give up. */
-      VG_(message)(Vg_UserMsg,
-                   "m_demangle: oflow Z-demangling: %s\n", sym);
-      return False;
-   }
 
    return True;
 }
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index 2f02c81..7a801f5 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -325,13 +325,13 @@
 
 static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque)
 {
-   static HChar buf[ERRTXT_LEN];
+   const HChar *buf;
    InlIPCursor* iipc = VG_(new_IIPC)(ip);
    do {
-      if ( VG_(get_fnname_no_cxx_demangle) (ip, buf,  ERRTXT_LEN, iipc) ) {
+      if ( VG_(get_fnname_no_cxx_demangle) (ip, &buf, iipc) ) {
          VG_(printf_xml)("    <sframe> <fun>%pS</fun> </sframe>\n", buf);
       } else
-      if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
+      if ( VG_(get_objname)(ip, &buf) ) {
          VG_(printf_xml)("    <sframe> <obj>%pS</obj> </sframe>\n", buf);
       } else {
          VG_(printf_xml)("    <sframe> <obj>*</obj> </sframe>\n");
@@ -342,14 +342,14 @@
 
 static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV)
 {
-   static HChar buf[ERRTXT_LEN];
+   const HChar *buf;
    XArray* /* of HChar */ text = (XArray*)textV;
    InlIPCursor* iipc = VG_(new_IIPC)(ip);
    do {
-      if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN, iipc) ) {
+      if ( VG_(get_fnname_no_cxx_demangle) (ip, &buf, iipc) ) {
          VG_(xaprintf)(text, "   fun:%s\n", buf);
       } else
-      if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) {
+      if ( VG_(get_objname)(ip, &buf) ) {
          VG_(xaprintf)(text, "   obj:%s\n", buf);
       } else {
          VG_(xaprintf)(text, "   obj:*\n");
@@ -1619,17 +1619,19 @@
    if (ip2fo->names)            VG_(free)(ip2fo->names);
 }
 
-/* Grow ip2fo->names to ensure we have ERRTXT_LEN characters available
+/* Grow ip2fo->names to ensure we have NEEDED characters available
    in ip2fo->names and returns a pointer to the first free char. */
-static HChar* grow_names(IPtoFunOrObjCompleter* ip2fo)
+static HChar* grow_names(IPtoFunOrObjCompleter* ip2fo, SizeT needed)
 {
    if (ip2fo->names_szB 
-       < ip2fo->names_free + ERRTXT_LEN) {
+       < ip2fo->names_free + needed) {
+     if (needed < ERRTXT_LEN) needed = ERRTXT_LEN;
+
       ip2fo->names 
          = VG_(realloc)("foc_names",
                         ip2fo->names,
-                        ip2fo->names_szB + ERRTXT_LEN);
-      ip2fo->names_szB += ERRTXT_LEN;
+                        ip2fo->names_szB + needed);
+      ip2fo->names_szB += needed;
    }
    return ip2fo->names + ip2fo->names_free;
 }
@@ -1655,7 +1657,8 @@
 
    // Complete Fun name or Obj name for IP if not yet done.
    if ((*offsets)[ixInput] == -1) {
-      HChar* caller_name = grow_names(ip2fo);
+      const HChar* caller;
+
       (*offsets)[ixInput] = ip2fo->names_free;
       if (DEBUG_ERRORMGR) VG_(printf)("marking %s ixInput %d offset %d\n", 
                                       needFun ? "fun" : "obj",
@@ -1671,9 +1674,9 @@
          // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the
          // two of them need to be made to match.
          if (!VG_(get_fnname_no_cxx_demangle)(ip2fo->ips[ixInput],
-                                              caller_name, ERRTXT_LEN,
+                                              &caller,
                                               NULL))
-            VG_(strcpy)(caller_name, "???");
+            caller = "???";
       } else {
          /* Get the object name into 'caller_name', or "???"
             if unknown. */
@@ -1691,8 +1694,8 @@
             last_expand_pos_ips is the last offset in fun/obj where
             ips[pos_ips] has been expanded. */
 
-         if (!VG_(get_objname)(ip2fo->ips[pos_ips], caller_name, ERRTXT_LEN))
-            VG_(strcpy)(caller_name, "???");
+         if (!VG_(get_objname)(ip2fo->ips[pos_ips], &caller))
+            caller = "???";
 
          // Have all inlined calls pointing at this object name
          for (i = last_expand_pos_ips - ip2fo->n_offsets_per_ip[pos_ips] + 1;
@@ -1704,7 +1707,10 @@
                             i, ip2fo->names_free);
          }
       }
-      ip2fo->names_free += VG_(strlen)(caller_name) + 1;
+      SizeT  caller_len = VG_(strlen)(caller);
+      HChar* caller_name = grow_names(ip2fo, caller_len + 1);
+      VG_(strcpy)(caller_name, caller);
+      ip2fo->names_free += caller_len + 1;
       if (DEBUG_ERRORMGR) pp_ip2fo(ip2fo);
    }
 
@@ -1764,14 +1770,17 @@
          // However, computing this is mostly the same as finding
          // the function name. So, let's directly complete the function name.
          do {
-            HChar* caller_name = grow_names(ip2fo);
+            const HChar *caller;
             grow_offsets(ip2fo, ip2fo->n_expanded+1);
             ip2fo->fun_offsets[ip2fo->n_expanded] = ip2fo->names_free;
             if (!VG_(get_fnname_no_cxx_demangle)(IP, 
-                                                 caller_name, ERRTXT_LEN,
+                                                 &caller,
                                                  iipc))
-               VG_(strcpy)(caller_name, "???");
-            ip2fo->names_free += VG_(strlen)(caller_name) + 1;
+               caller = "???";
+            SizeT  caller_len = VG_(strlen)(caller);
+            HChar* caller_name = grow_names(ip2fo, caller_len + 1);
+            VG_(strcpy)(caller_name, caller);
+            ip2fo->names_free += caller_len + 1;
             ip2fo->n_expanded++;
             ip2fo->n_offsets_per_ip[ip2fo->n_ips_expanded]++;
          } while (VG_(next_IIPC)(iipc));
diff --git a/coregrind/m_gdbserver/m_gdbserver.c b/coregrind/m_gdbserver/m_gdbserver.c
index 6e10593..04aadbf 100644
--- a/coregrind/m_gdbserver/m_gdbserver.c
+++ b/coregrind/m_gdbserver/m_gdbserver.c
@@ -140,15 +140,21 @@
    oldest result. */
 static HChar* sym (Addr addr, Bool is_code)
 {
-   static HChar buf[2][200];
+   static HChar *buf[2];
    static int w = 0;
    PtrdiffT offset;
    if (w == 2) w = 0;
-   buf[w][0] = '\0';
+
    if (is_code) {
-      VG_(describe_IP) (addr, buf[w], 200, NULL);
+      HChar name[200];
+      VG_(describe_IP) (addr, name, 200, NULL);  // FIXME: get rid of name
+      if (buf[w]) VG_(free)(buf[w]);
+      buf[w] = VG_(strdup)("gdbserver sym", name);
    } else {
-      VG_(get_datasym_and_offset) (addr, buf[w], 200, &offset);
+      const HChar *name;
+      VG_(get_datasym_and_offset) (addr, &name, &offset);
+      if (buf[w]) VG_(free)(buf[w]);
+      buf[w] = VG_(strdup)("gdbserver sym", name);
    }
    return buf[w++];
 }
diff --git a/coregrind/m_gdbserver/valgrind-low-arm.c b/coregrind/m_gdbserver/valgrind-low-arm.c
index 68a5baa..be2be8a 100644
--- a/coregrind/m_gdbserver/valgrind-low-arm.c
+++ b/coregrind/m_gdbserver/valgrind-low-arm.c
@@ -144,13 +144,13 @@
 
    // pc aligned on 4 bytes. We need to use debug info.
    {
-      HChar fnname[200]; // ??? max size
+      const HChar *fnname;
       SymAVMAs avmas;
       // If this is a thumb instruction, we need to ask
       // the debug info with the bit0 set
       // (why can't debug info do that for us ???)
       // (why if this is a 4 bytes thumb instruction ???)
-      if (VG_(get_fnname_raw) (pc | 1, fnname, 200)) {
+      if (VG_(get_fnname_raw) (pc | 1, &fnname)) {
          if (VG_(lookup_symbol_SLOW)( "*", fnname, &avmas )) {
             dlog (1, "fnname %s lookupsym %p => %p %s.\n",
                   fnname, C2v(avmas.main), C2v(pc),
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 07122db..2d403ce 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -386,8 +386,6 @@
    topspecs list, and (2) figure out what new binding are now active,
    and, as a result, add them to the actives mapping. */
 
-#define N_DEMANGLED 256
-
 void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi )
 {
    Bool         ok, isWrap;
@@ -399,8 +397,8 @@
    const HChar*  sym_name_pri;
    const HChar** sym_names_sec;
    SymAVMAs     sym_avmas;
-   HChar        demangled_sopatt[N_DEMANGLED];
-   HChar        demangled_fnpatt[N_DEMANGLED];
+   const HChar* demangled_sopatt;
+   const HChar* demangled_fnpatt;
    Bool         check_ppcTOCs = False;
    Bool         isText;
    const HChar* newdi_soname;
@@ -518,8 +516,8 @@
       const HChar** names;
       for (names = names_init; *names; names++) {
          ok = VG_(maybe_Z_demangle)( *names,
-                                     demangled_sopatt, N_DEMANGLED,
-                                     demangled_fnpatt, N_DEMANGLED,
+                                     &demangled_sopatt,
+                                     &demangled_fnpatt,
                                      &isWrap, &becTag, &becPrio );
          /* ignore data symbols */
          if (!isText) {
@@ -552,6 +550,7 @@
             continue;
          }
 
+         HChar *replaced_sopatt = NULL;
          if (0 == VG_(strncmp) (demangled_sopatt, 
                                 VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN)) {
             /* This is a redirection for handling lib so synonyms. If we
@@ -577,8 +576,11 @@
                   // Found the demangle_sopatt synonym => replace it
                   first = last + 1;
                   last = advance_to_comma(first);
-                  VG_(strncpy)(demangled_sopatt, first, last - first);
-                  demangled_sopatt[last - first] = '\0';
+                  replaced_sopatt = dinfo_zalloc("redir.rnnD.5",
+                                                 last - first + 1);
+                  VG_(strncpy)(replaced_sopatt, first, last - first);
+                  replaced_sopatt[last - first] = '\0';
+                  demangled_sopatt = replaced_sopatt;
                   break;
                }
 
@@ -588,8 +590,7 @@
             }
             
             // If we have not replaced the sopatt, then skip the redir.
-            if (0 == VG_(strncmp) (demangled_sopatt, 
-                                   VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN))
+            if (replaced_sopatt == NULL)
                continue;
          }
 
@@ -629,8 +630,8 @@
          for (names = names_init; *names; names++) {
             ok = isText
                  && VG_(maybe_Z_demangle)( 
-                       *names, demangled_sopatt, N_DEMANGLED,
-                       demangled_fnpatt, N_DEMANGLED, &isWrap, NULL, NULL );
+                       *names, &demangled_sopatt,
+                       &demangled_fnpatt, &isWrap, NULL, NULL );
             if (!ok)
                /* not a redirect.  Ignore. */
                continue;
@@ -711,8 +712,6 @@
    handle_require_text_symbols(newdi);
 }
 
-#undef N_DEMANGLED
-
 /* Add a new target for an indirect function. Adds a new redirection
    for the indirection function with address old_from that redirects
    the ordinary function with address new_from to the target address
@@ -1704,13 +1703,17 @@
 static void show_active ( const HChar* left, const Active* act )
 {
    Bool ok;
-   HChar name1[64] = "";
-   HChar name2[64] = "";
-   name1[0] = name2[0] = 0;
-   ok = VG_(get_fnname_w_offset)(act->from_addr, name1, 64);
-   if (!ok) VG_(strcpy)(name1, "???");
-   ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64);
-   if (!ok) VG_(strcpy)(name2, "???");
+   const HChar *buf;
+ 
+   ok = VG_(get_fnname_w_offset)(act->from_addr, &buf);
+   if (!ok) buf = "???";
+   // Stash away name1
+   HChar name1[VG_(strlen)(buf) + 1];
+   VG_(strcpy)(name1, buf);
+
+   const HChar *name2;
+   ok = VG_(get_fnname_w_offset)(act->to_addr, &name2);
+   if (!ok) name2 = "???";
 
    VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> (%04d.%d) 0x%08llx %s\n", 
                              left, 
diff --git a/coregrind/m_sbprofile.c b/coregrind/m_sbprofile.c
index 197fff5..0be07dd 100644
--- a/coregrind/m_sbprofile.c
+++ b/coregrind/m_sbprofile.c
@@ -51,7 +51,6 @@
 {
    ULong score_cumul, score_cumul_saved, score_here;
    HChar buf_cumul[10], buf_here[10];
-   HChar name[64];
    Int   r; /* must be signed */
 
    HChar ecs_txt[50];
@@ -84,9 +83,10 @@
          continue;
       if (tops[r].score == 0)
          continue;
-      name[0] = 0;
-      VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
-      name[63] = 0;
+
+      const HChar *name;
+      VG_(get_fnname_w_offset)(tops[r].addr, &name);
+
       score_here = tops[r].score;
       score_cumul += score_here;
       VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
@@ -116,9 +116,10 @@
             continue;
          if (tops[r].score == 0)
             continue;
-         name[0] = 0;
-         VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
-         name[63] = 0;
+
+         const HChar *name;
+         VG_(get_fnname_w_offset)(tops[r].addr, &name);
+
          score_here = tops[r].score;
          score_cumul += score_here;
          VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
@@ -145,9 +146,10 @@
             continue;
          if (tops[r].score == 0)
             continue;
-         name[0] = 0;
-         VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
-         name[63] = 0;
+
+         const HChar *name;
+         VG_(get_fnname_w_offset)(tops[r].addr, &name);
+
          score_here = tops[r].score;
          VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
          VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index b4fb86d..cdecc15 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -717,15 +717,16 @@
       frame. */
    lr_is_first_RA = False;
    {
-#     define M_VG_ERRTXT 1000
-      HChar buf_lr[M_VG_ERRTXT], buf_ip[M_VG_ERRTXT];
+      const HChar *buf_lr, *buf_ip;
       /* The following conditional looks grossly inefficient and
          surely could be majorly improved, with not much effort. */
-      if (VG_(get_fnname_raw) (lr, buf_lr, M_VG_ERRTXT))
-         if (VG_(get_fnname_raw) (ip, buf_ip, M_VG_ERRTXT))
-            if (VG_(strncmp)(buf_lr, buf_ip, M_VG_ERRTXT))
+      if (VG_(get_fnname_raw) (lr, &buf_lr)) {
+         HChar buf_lr_copy[VG_(strlen)(buf_lr) + 1];
+         VG_(strcpy)(buf_lr_copy, buf_lr);
+         if (VG_(get_fnname_raw) (ip, &buf_ip))
+            if (VG_(strcmp)(buf_lr_copy, buf_ip))
                lr_is_first_RA = True;
-#     undef M_VG_ERRTXT
+      }
    }
 
    if (sps) sps[0] = fp; /* NB. not sp */
@@ -816,15 +817,16 @@
 
 static Bool in_same_fn ( Addr a1, Addr a2 )
 {
-#  define M_VG_ERRTXT 500
-   HChar buf_a1[M_VG_ERRTXT], buf_a2[M_VG_ERRTXT];
+   const HChar *buf_a1, *buf_a2;
    /* The following conditional looks grossly inefficient and
       surely could be majorly improved, with not much effort. */
-   if (VG_(get_fnname_raw) (a1, buf_a1, M_VG_ERRTXT))
-      if (VG_(get_fnname_raw) (a2, buf_a2, M_VG_ERRTXT))
-         if (VG_(strncmp)(buf_a1, buf_a2, M_VG_ERRTXT))
+   if (VG_(get_fnname_raw) (a1, &buf_a1)) {
+      HChar buf_a1_copy[VG_(strlen)(buf_a1) + 1];
+      VG_(strcpy)(buf_a1_copy, buf_a1);
+      if (VG_(get_fnname_raw) (a2, &buf_a2))
+         if (VG_(strcmp)(buf_a1_copy1, buf_a2))
             return True;
-#  undef M_VG_ERRTXT
+   }
    return False;
 }
 
diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
index 8469e7e..b5d10fb 100644
--- a/coregrind/m_translate.c
+++ b/coregrind/m_translate.c
@@ -1448,13 +1448,9 @@
    if ((kind == T_Redir_Wrap || kind == T_Redir_Replace)
        && (VG_(clo_verbosity) >= 2 || VG_(clo_trace_redir))) {
       Bool ok;
-      HChar name1[512] = "";
-      HChar name2[512] = "";
-      name1[0] = name2[0] = 0;
-      ok = VG_(get_fnname_w_offset)(nraddr, name1, sizeof(name1));
-      if (!ok) VG_(strcpy)(name1, "???");
-      ok = VG_(get_fnname_w_offset)(addr, name2, sizeof(name2));
-      if (!ok) VG_(strcpy)(name2, "???");
+      const HChar *buf;
+      const HChar *name2;
+
       /* Try also to get the soname (not the filename) of the "from"
          object.  This makes it much easier to debug redirection
          problems. */
@@ -1465,6 +1461,15 @@
          if (t)
             nraddr_soname = t;
       }
+
+      ok = VG_(get_fnname_w_offset)(nraddr, &buf);
+      if (!ok) buf = "???";
+      // Stash away name1
+      HChar name1[VG_(strlen)(buf) + 1];
+      VG_(strcpy)(name1, buf);
+      ok = VG_(get_fnname_w_offset)(addr, &name2);
+      if (!ok) name2 = "???";
+
       VG_(message)(Vg_DebugMsg, 
                    "REDIR: 0x%llx (%s:%s) redirected to 0x%llx (%s)\n",
                    nraddr, nraddr_soname, name1,
@@ -1477,8 +1482,6 @@
 
    /* If doing any code printing, print a basic block start marker */
    if (VG_(clo_trace_flags) || debugging_translation) {
-      HChar fnname[512] = "UNKNOWN_FUNCTION";
-      VG_(get_fnname_w_offset)(addr, fnname, 512);
       const HChar* objname = "UNKNOWN_OBJECT";
       OffT         objoff  = 0;
       DebugInfo*   di      = VG_(find_DebugInfo)( addr );
@@ -1487,6 +1490,10 @@
          objoff  = addr - VG_(DebugInfo_get_text_bias)(di);
       }
       vg_assert(objname);
+ 
+      const HChar *fnname;
+      Bool ok = VG_(get_fnname_w_offset)(addr, &fnname);
+      if (!ok) fnname = "UNKNOWN_FUNCTION";
       VG_(printf)(
          "==== SB %d (evchecks %lld) [tid %d] 0x%llx %s %s+0x%llx\n",
          VG_(get_bbs_translated)(), bbs_done, (Int)tid, addr,
diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h
index 23075b8..7618191 100644
--- a/coregrind/pub_core_debuginfo.h
+++ b/coregrind/pub_core_debuginfo.h
@@ -86,14 +86,14 @@
  * It should only be used in cases where the names of interest will have
  * particular (ie. non-mangled) forms, or the mangled form is acceptable. */
 extern
-Bool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf );
+Bool VG_(get_fnname_raw) ( Addr a, const HChar** buf );
 
 /* Like VG_(get_fnname), but without C++ demangling.  (But it does
  Z-demangling and below-main renaming.)
  iipc argument: same usage as in VG_(describe_IP) in pub_tool_debuginfo.h. */
 extern
-Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf,
-                                       InlIPCursor* iipc );
+Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, const HChar** buf,
+                                       const InlIPCursor* iipc );
 
 /* mips-linux only: find the offset of current address. This is needed for 
    stack unwinding for MIPS.
diff --git a/coregrind/pub_core_demangle.h b/coregrind/pub_core_demangle.h
index bf6c667..b7e1a8f 100644
--- a/coregrind/pub_core_demangle.h
+++ b/coregrind/pub_core_demangle.h
@@ -43,7 +43,7 @@
  * (2) undoes C++ demangling, if 'do_cxx_demangle' is True.  */
 extern 
 void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
-                     const HChar* orig, HChar* result, Int result_size );
+                     const HChar* orig, const HChar** result );
 
 /* Demangle a Z-encoded name as described in pub_tool_redir.h. 
    Z-encoded names are used by Valgrind for doing function 
@@ -59,11 +59,11 @@
 
 extern 
 Bool VG_(maybe_Z_demangle) ( const HChar* sym, 
-                             /*OUT*/HChar* so, Int soLen,
-                             /*OUT*/HChar* fn, Int fnLen,
-                             /*OUT*/Bool* isWrap,
-                             /*OUT*/Int*  eclassTag,
-                             /*OUT*/Int*  eclassPrio );
+                             /*OUT*/const HChar** so,    // may be NULL
+                             /*OUT*/const HChar** fn,
+                             /*OUT*/Bool* isWrap,        // may be NULL
+                             /*OUT*/Int*  eclassTag,     // may be NULL
+                             /*OUT*/Int*  eclassPrio );  // may be NULL
 
 #endif   // __PUB_CORE_DEMANGLE_H
 
diff --git a/exp-bbv/bbv_main.c b/exp-bbv/bbv_main.c
index 8926af4..c8759ae 100644
--- a/exp-bbv/bbv_main.c
+++ b/exp-bbv/bbv_main.c
@@ -87,15 +87,13 @@
    Int bbtrace_fd;          /* file descriptor */
 };
 
-#define FUNCTION_NAME_LENGTH 20
-
 struct BB_info {
    Addr       BB_addr;           /* used as key, must be first           */
    Int        n_instrs;          /* instructions in the basic block      */
    Int        block_num;         /* unique block identifier              */
    Int        *inst_counter;     /* times entered * num_instructions     */
    Bool       is_entry;          /* is this block a function entry point */
-   HChar      fn_name[FUNCTION_NAME_LENGTH];  /* Function block is in    */
+   const HChar *fn_name;         /* Function block is in                 */
 };
 
 
@@ -403,8 +401,9 @@
       bbInfo->block_num=block_num;
       block_num++;
          /* get function name and entry point information */
-      bbInfo->is_entry=VG_(get_fnname_if_entry)(origAddr, bbInfo->fn_name,
-                                                FUNCTION_NAME_LENGTH);
+      const HChar *fn_name;
+      bbInfo->is_entry=VG_(get_fnname_if_entry)(origAddr, &fn_name);
+      bbInfo->fn_name =VG_(strdup)("bbv_strings", fn_name);
          /* insert structure into table */
       VG_(OSetGen_Insert)( instr_info_table, bbInfo );
    }
diff --git a/exp-sgcheck/pc_common.c b/exp-sgcheck/pc_common.c
index 042a860..de6bb16 100644
--- a/exp-sgcheck/pc_common.c
+++ b/exp-sgcheck/pc_common.c
@@ -134,7 +134,7 @@
             Seg*     vseg;
             XArray*  descr1; /* XArray* of HChar */
             XArray*  descr2; /* XArray* of HChar */
-            HChar    datasym[96];
+            const HChar* datasym;
             PtrdiffT datasymoff;
          } Heap;
          struct {
@@ -657,9 +657,8 @@
       case XE_Heap: {
          Bool have_descr;
 
-         tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
          xe->XE.Heap.datasymoff = 0;
-         xe->XE.Heap.datasym[0] = 0;
+         xe->XE.Heap.datasym    = NULL;
 
          tl_assert(!xe->XE.Heap.descr1);
          tl_assert(!xe->XE.Heap.descr2);
@@ -671,7 +670,6 @@
             = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
                           VG_(free), sizeof(HChar) );
 
-         VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
          xe->XE.Heap.datasymoff = 0;
 
          have_descr
@@ -699,13 +697,13 @@
          /* If Dwarf3 info produced nothing useful, see at least if
             we can fish something useful out of the ELF symbol info. */
          if (!have_descr) {
+            const HChar *name;
             if (VG_(get_datasym_and_offset)(
-                   xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
-                   sizeof(xe->XE.Heap.datasym)-1,
+                   xe->XE.Heap.addr, &name,
                    &xe->XE.Heap.datasymoff )
                ) {
-               tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1] 
-                         == 0);
+              xe->XE.Heap.datasym =
+                 VG_(strdup)("pc.update_extra.Heap.datasym", name);
             }
          }
          break;
diff --git a/exp-sgcheck/sg_main.c b/exp-sgcheck/sg_main.c
index f4ae81b..f6f5fc4 100644
--- a/exp-sgcheck/sg_main.c
+++ b/exp-sgcheck/sg_main.c
@@ -1926,10 +1926,10 @@
 
    if (0)
    { Word d = callee->depth;
-     HChar fnname[80];
+     const HChar *fnname;
      Bool ok;
      Addr ip = ip_post_call_insn;
-     ok = VG_(get_fnname_w_offset)( ip, fnname, sizeof(fnname) );
+     ok = VG_(get_fnname_w_offset)( ip, &fnname );
      while (d > 0) {
         VG_(printf)(" ");
         d--;
diff --git a/exp-sgcheck/tests/bad_percentify.c b/exp-sgcheck/tests/bad_percentify.c
index 3fb73ee..360cd0d 100644
--- a/exp-sgcheck/tests/bad_percentify.c
+++ b/exp-sgcheck/tests/bad_percentify.c
@@ -493,20 +493,20 @@
          }
 
 //         case 'y': { /* %y - print symbol */
-//            Char buf[100];
-//            Char *cp = buf;
 //            Addr a = va_arg(vargs, Addr);
 //
-//            if (flags & VG_MSG_PAREN)
-//               *cp++ = '(';
-//            if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
-//               if (flags & VG_MSG_PAREN) {
-//                  cp += local_strlen(cp);
-//                  *cp++ = ')';
-//                  *cp = '\0';
+//
+//
+//            HChar *name;
+// 	      if (VG_(get_fnname_w_offset)(a, &name)) {
+//               HChar buf[1 + VG_strlen(name) + 1 + 1];
+// 	         if (flags & VG_MSG_PAREN) {
+//                  VG_(sprintf)(str, "(%s)", name):
+// 	         } else {
+//                  VG_(sprintf)(str, "%s", name):
 //               }
-//               ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
-//            }
+// 	         ret += myvprintf_str(send, flags, width, buf, 0);
+// 	      }
 //            break;
 //         }
          default:
diff --git a/exp-sgcheck/tests/hackedbz2.c b/exp-sgcheck/tests/hackedbz2.c
index 2f32769..f012d7a 100644
--- a/exp-sgcheck/tests/hackedbz2.c
+++ b/exp-sgcheck/tests/hackedbz2.c
@@ -1244,18 +1244,18 @@
 	 }
 #        if 0
 	 case 'y': { /* %y - print symbol */
-	    Char buf[100];
-	    Char *cp = buf;
 	    Addr a = va_arg(vargs, Addr);
 
-	    if (flags & VG_MSG_PAREN)
-	       *cp++ = '(';
-	    if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+
+
+            HChar *name;
+	    if (VG_(get_fnname_w_offset)(a, &name)) {
+               HChar buf[1 + VG_strlen(name) + 1 + 1];
 	       if (flags & VG_MSG_PAREN) {
-		  cp += VG_(strlen)(cp);
-		  *cp++ = ')';
-		  *cp = '\0';
-	       }
+                  VG_(sprintf)(str, "(%s)", name):
+	       } else {
+                  VG_(sprintf)(str, "%s", name):
+               }
 	       ret += myvprintf_str(send, flags, width, buf, 0);
 	    }
 	    break;
diff --git a/include/pub_tool_addrinfo.h b/include/pub_tool_addrinfo.h
index ce2c232..84afdde 100644
--- a/include/pub_tool_addrinfo.h
+++ b/include/pub_tool_addrinfo.h
@@ -153,10 +153,10 @@
          ExeContext* freed_at;      // might be null_ExeContext.
       } Block;
 
-      // In a global .data symbol.  This holds the first 127 chars of
+      // In a global .data symbol.  This holds
       // the variable's name (zero terminated), plus a (memory) offset.
       struct {
-         HChar    name[128];
+         HChar   *name;
          PtrdiffT offset;
       } DataSym;
 
diff --git a/include/pub_tool_debuginfo.h b/include/pub_tool_debuginfo.h
index f47669e..0940b3d 100644
--- a/include/pub_tool_debuginfo.h
+++ b/include/pub_tool_debuginfo.h
@@ -40,14 +40,14 @@
 /* Get the file/function/line number of the instruction at address
    'a'.  For these four, if debug info for the address is found, it
    copies the info into the buffer/UInt and returns True.  If not, it
-   returns False and nothing is copied.  VG_(get_fnname) always
+   returns False.  VG_(get_fnname) always
    demangles C++ function names.  VG_(get_fnname_w_offset) is the
    same, except it appends "+N" to symbol names to indicate offsets.  */
 extern Bool VG_(get_filename) ( Addr a, HChar* filename, Int n_filename );
-extern Bool VG_(get_fnname)   ( Addr a, HChar* fnname,   Int n_fnname   );
+extern Bool VG_(get_fnname)   ( Addr a, const HChar** fnname );
 extern Bool VG_(get_linenum)  ( Addr a, UInt* linenum );
 extern Bool VG_(get_fnname_w_offset)
-                              ( Addr a, HChar* fnname,   Int n_fnname   );
+                              ( Addr a, const HChar** fnname );
 
 /* This one is the most general.  It gives filename, line number and
    optionally directory name.  filename and linenum may not be NULL.
@@ -74,7 +74,7 @@
    a particular function.  Nb: if an executable/shared object is stripped
    of its symbols, this function will not be able to recognise function
    entry points within it. */
-extern Bool VG_(get_fnname_if_entry) ( Addr a, HChar* fnname, Int n_fnname );
+extern Bool VG_(get_fnname_if_entry) ( Addr a, const HChar** fnname );
 
 typedef
    enum {
@@ -84,7 +84,7 @@
    } Vg_FnNameKind;           //   Such names are often filtered.
 
 /* Indicates what kind of fnname it is. */
-extern Vg_FnNameKind VG_(get_fnname_kind) ( HChar* name );
+extern Vg_FnNameKind VG_(get_fnname_kind) ( const HChar* name );
 
 /* Like VG_(get_fnname_kind), but takes a code address. */
 extern Vg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip );
@@ -94,7 +94,7 @@
    which is guaranteed to be zero terminated.  Also data_addr's offset
    from the symbol start is put into *offset. */
 extern Bool VG_(get_datasym_and_offset)( Addr data_addr,
-                                         /*OUT*/HChar* dname, Int n_dname,
+                                         /*OUT*/const HChar** dname,
                                          /*OUT*/PtrdiffT* offset );
 
 /* Try to form some description of DATA_ADDR by looking at the DWARF3
@@ -118,7 +118,7 @@
 
 /* Succeeds if the address is within a shared object or the main executable.
    It doesn't matter if debug info is present or not. */
-extern Bool VG_(get_objname)  ( Addr a, HChar* objname, Int n_objname );
+extern Bool VG_(get_objname)  ( Addr a, const HChar** objname );
 
 
 /* Cursor allowing to describe inlined function calls at an IP,
diff --git a/lackey/lk_main.c b/lackey/lk_main.c
index f76998f..485707c 100644
--- a/lackey/lk_main.c
+++ b/lackey/lk_main.c
@@ -660,7 +660,6 @@
    IRDirty*   di;
    Int        i;
    IRSB*      sbOut;
-   HChar      fnname[100];
    IRTypeEnv* tyenv = sbIn->tyenv;
    Addr       iaddr = 0, dst;
    UInt       ilen = 0;
@@ -750,8 +749,9 @@
                 */
                tl_assert(clo_fnname);
                tl_assert(clo_fnname[0]);
+               const HChar *fnname;
                if (VG_(get_fnname_if_entry)(st->Ist.IMark.addr, 
-                                            fnname, sizeof(fnname))
+                                            &fnname)
                    && 0 == VG_(strcmp)(fnname, clo_fnname)) {
                   di = unsafeIRDirty_0_N( 
                           0, "add_one_func_call", 
diff --git a/massif/ms_main.c b/massif/ms_main.c
index da58bb6..cdd73b4 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -355,7 +355,7 @@
 }
 
 // Determines if the named function is a member of the XArray.
-static Bool is_member_fn(XArray* fns, const HChar* fnname)
+static Bool is_member_fn(const XArray* fns, const HChar* fnname)
 {
    HChar** fn_ptr;
    Int i;
@@ -817,9 +817,9 @@
 // Determine if the given IP belongs to a function that should be ignored.
 static Bool fn_should_be_ignored(Addr ip)
 {
-   static HChar buf[BUF_LEN];
+   const HChar *buf;
    return
-      ( VG_(get_fnname)(ip, buf, BUF_LEN) && is_member_fn(ignore_fns, buf)
+      ( VG_(get_fnname)(ip, &buf) && is_member_fn(ignore_fns, buf)
       ? True : False );
 }
 
@@ -832,7 +832,6 @@
 static
 Int get_IPs( ThreadId tid, Bool exclude_first_entry, Addr ips[])
 {
-   static HChar buf[BUF_LEN];
    Int n_ips, i, n_alloc_fns_removed;
    Int overestimate;
    Bool redo;
@@ -871,7 +870,8 @@
       // because VG_(get_fnname) is expensive.
       n_alloc_fns_removed = ( exclude_first_entry ? 1 : 0 );
       for (i = n_alloc_fns_removed; i < n_ips; i++) {
-         if (VG_(get_fnname)(ips[i], buf, BUF_LEN)) {
+         const HChar *buf;
+         if (VG_(get_fnname)(ips[i], &buf)) {
             if (is_member_fn(alloc_fns, buf)) {
                n_alloc_fns_removed++;
             } else {
diff --git a/memcheck/tests/origin5-bz2.c b/memcheck/tests/origin5-bz2.c
index 26fe161..b4b238f 100644
--- a/memcheck/tests/origin5-bz2.c
+++ b/memcheck/tests/origin5-bz2.c
@@ -1237,18 +1237,18 @@
 	 }
 #        if 0
 	 case 'y': { /* %y - print symbol */
-	    Char buf[100];
-	    Char *cp = buf;
 	    Addr a = va_arg(vargs, Addr);
 
-	    if (flags & VG_MSG_PAREN)
-	       *cp++ = '(';
-	    if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+
+
+            HChar *name;
+	    if (VG_(get_fnname_w_offset)(a, &name)) {
+               HChar buf[1 + VG_strlen(name) + 1 + 1];
 	       if (flags & VG_MSG_PAREN) {
-		  cp += VG_(strlen)(cp);
-		  *cp++ = ')';
-		  *cp = '\0';
-	       }
+                  VG_(sprintf)(str, "(%s)", name):
+	       } else {
+                  VG_(sprintf)(str, "%s", name):
+               }
 	       ret += myvprintf_str(send, flags, width, buf, 0);
 	    }
 	    break;
diff --git a/memcheck/tests/varinfo6.c b/memcheck/tests/varinfo6.c
index 7d835e0..c04f684 100644
--- a/memcheck/tests/varinfo6.c
+++ b/memcheck/tests/varinfo6.c
@@ -1275,18 +1275,18 @@
 	 }
 #        if 0
 	 case 'y': { /* %y - print symbol */
-	    Char buf[100];
-	    Char *cp = buf;
 	    Addr a = va_arg(vargs, Addr);
 
-	    if (flags & VG_MSG_PAREN)
-	       *cp++ = '(';
-	    if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+
+
+            HChar *name;
+	    if (VG_(get_fnname_w_offset)(a, &name)) {
+               HChar buf[1 + VG_strlen(name) + 1 + 1];
 	       if (flags & VG_MSG_PAREN) {
-		  cp += VG_(strlen)(cp);
-		  *cp++ = ')';
-		  *cp = '\0';
-	       }
+                  VG_(sprintf)(str, "(%s)", name):
+	       } else {
+                  VG_(sprintf)(str, "%s", name):
+               }
 	       ret += myvprintf_str(send, flags, width, buf, 0);
 	    }
 	    break;
diff --git a/perf/bz2.c b/perf/bz2.c
index 739e68f..79cb933 100644
--- a/perf/bz2.c
+++ b/perf/bz2.c
@@ -1237,18 +1237,16 @@
 	 }
 #        if 0
 	 case 'y': { /* %y - print symbol */
-	    Char buf[100];
-	    Char *cp = buf;
 	    Addr a = va_arg(vargs, Addr);
 
-	    if (flags & VG_MSG_PAREN)
-	       *cp++ = '(';
-	    if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+            HChar *name;
+	    if (VG_(get_fnname_w_offset)(a, &name)) {
+               HChar buf[1 + VG_strlen(name) + 1 + 1];
 	       if (flags & VG_MSG_PAREN) {
-		  cp += VG_(strlen)(cp);
-		  *cp++ = ')';
-		  *cp = '\0';
-	       }
+                  VG_(sprintf)(str, "(%s)", name):
+	       } else {
+                  VG_(sprintf)(str, "%s", name):
+               }
 	       ret += myvprintf_str(send, flags, width, buf, 0);
 	    }
 	    break;