diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index 5ba33388b..71efdea26 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 typedef struct { HChar* file; - HChar* fn; + const HChar* fn; Int line; } CodeLoc; @@ -195,7 +194,7 @@ static Word stringCmp( const void* key, const void* elem ) // 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 HChar* get_perm_string(HChar* s) /*------------------------------------------------------------*/ 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 @@ static void get_debug_info(Addr instr_addr, HChar file[FILE_LEN], 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 @@ static void get_debug_info(Addr instr_addr, HChar file[FILE_LEN], // 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 @@ static void fprint_CC_table_and_calc_totals(void) 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 887663610..53dd7fa00 100644 --- a/callgrind/debug.c +++ b/callgrind/debug.c @@ -374,7 +374,7 @@ void CLG_(print_bbcc_cost)(int s, BBCC* bbcc) 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 @@ void CLG_(print_addr)(Addr addr) 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 d602ac0e4..3102b526b 100644 --- a/callgrind/fn.c +++ b/callgrind/fn.c @@ -330,7 +330,7 @@ file_node* CLG_(get_file_node)(obj_node* curr_obj_node, 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 @@ fn_node* new_fn_node(HChar fnname[FILENAME_LEN], */ 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 @@ fn_node* get_fn_node_infile(file_node* curr_file_node, 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 @@ fn_node* get_fn_node_inseg(DebugInfo* di, 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 @@ Bool CLG_(get_debug_info)(Addr instr_addr, 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 @@ Bool CLG_(get_debug_info)(Addr instr_addr, 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 @@ Bool CLG_(get_debug_info)(Addr instr_addr, } 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 @@ Bool CLG_(get_debug_info)(Addr instr_addr, !pDebugInfo ? "-" : (*pDebugInfo) ? VG_(DebugInfo_get_filename)(*pDebugInfo) : "(None)", - fn_name); + *fn_name); return result; } @@ -488,7 +487,8 @@ static BB* exit_bb = 0; */ 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 @@ fn_node* CLG_(get_fn_node)(BB* bb) * 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 @@ fn_node* CLG_(get_fn_node)(BB* bb) 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 @@ fn_node* CLG_(get_fn_node)(BB* bb) (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 ff423b4bc..a32ba5574 100644 --- a/callgrind/global.h +++ b/callgrind/global.h @@ -691,7 +691,7 @@ void CLG_(init_eventsets)(void); /* 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 95ec0fe60..803bb3a9d 100644 --- a/coregrind/m_addrinfo.c +++ b/coregrind/m_addrinfo.c @@ -124,15 +124,12 @@ void VG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai ) } /* -- 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 @@ void VG_(clear_addrinfo) ( AddrInfo* ai) break; case Addr_DataSym: + VG_(free)(ai->Addr.DataSym.name); break; case Addr_Variable: @@ -384,7 +382,7 @@ static void pp_addrinfo_WRK ( Addr a, const AddrInfo* ai, Bool mc, 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 @@ static void pp_addrinfo_WRK ( Addr a, const AddrInfo* ai, Bool mc, 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 @@ static void pp_addrinfo_WRK ( Addr a, const AddrInfo* ai, Bool mc, 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 33bfe924e..dbcee080e 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -1729,11 +1729,18 @@ static void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi, 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 @@ Bool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling, 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 @@ Bool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling, // 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 @@ Addr VG_(get_tocptr) ( Addr guest_code_addr ) } /* 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 @@ Bool VG_(get_fnname) ( Addr a, HChar* buf, Int nbuf ) } /* 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 @@ Bool VG_(get_fnname_w_offset) ( Addr a, HChar* buf, Int nbuf ) /* 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 @@ Bool VG_(get_fnname_if_entry) ( Addr a, HChar* buf, Int nbuf ) /* 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 @@ Bool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf ) /* 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 @@ Bool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf, : 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_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf, 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) ( HChar* name ) 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 @@ Vg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip ) } /* 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 @@ Bool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf ) && 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 @@ Bool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf ) 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 @@ HChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc) 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 @@ HChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc) 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 @@ HChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc) // ??? 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 @@ HChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc) 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 25ea58ea8..57c91c6dd 100644 --- a/coregrind/m_debuginfo/misc.c +++ b/coregrind/m_debuginfo/misc.c @@ -68,6 +68,12 @@ void* ML_(dinfo_memdup) ( const HChar* cc, const void* str, SizeT nStr ) { 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 0828290c1..7ca7614a4 100644 --- a/coregrind/m_debuginfo/priv_misc.h +++ b/coregrind/m_debuginfo/priv_misc.h @@ -44,6 +44,7 @@ void* ML_(dinfo_zalloc)( const HChar* cc, SizeT szB ); 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 8a22ca253..5ae2a5df1 100644 --- a/coregrind/m_debuglog.c +++ b/coregrind/m_debuglog.c @@ -890,20 +890,18 @@ VG_(debugLog_vprintf) ( } // 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 385ee8dd7..1054c147b 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 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling, // 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 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling, 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 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym, "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 2f02c8145..7a801f59b 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -325,13 +325,13 @@ static Bool eq_Error ( VgRes res, const Error* e1, const Error* e2 ) 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)(" %pS \n", buf); } else - if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { + if ( VG_(get_objname)(ip, &buf) ) { VG_(printf_xml)(" %pS \n", buf); } else { VG_(printf_xml)(" * \n"); @@ -342,14 +342,14 @@ static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque) 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 @@ static void clearIPtoFunOrObjCompleter ( const Supp *su, 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 @@ static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo, // 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 @@ static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo, // "_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 @@ static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo, 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 @@ static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo, 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 @@ static void expandInput (IPtoFunOrObjCompleter* ip2fo, UWord ixInput ) // 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 6e10593fb..04aadbf83 100644 --- a/coregrind/m_gdbserver/m_gdbserver.c +++ b/coregrind/m_gdbserver/m_gdbserver.c @@ -140,15 +140,21 @@ static void call_gdbserver ( ThreadId tid , CallReason reason); 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 68a5baa89..be2be8a45 100644 --- a/coregrind/m_gdbserver/valgrind-low-arm.c +++ b/coregrind/m_gdbserver/valgrind-low-arm.c @@ -144,13 +144,13 @@ Addr thumb_pc (Addr pc) // 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 07122db28..2d403ce8d 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -386,8 +386,6 @@ static HChar const* advance_to_comma ( HChar const* c ) { 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) // 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) } // 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) 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 @@ void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi ) 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_spec ( const HChar* left, const Spec* spec ) 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 197fff51c..0be07dd9c 100644 --- a/coregrind/m_sbprofile.c +++ b/coregrind/m_sbprofile.c @@ -51,7 +51,6 @@ void show_SB_profile ( const SBProfEntry tops[], UInt n_tops, { 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 @@ void show_SB_profile ( const SBProfEntry tops[], UInt n_tops, 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 @@ void show_SB_profile ( const SBProfEntry tops[], UInt n_tops, 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 @@ void show_SB_profile ( const SBProfEntry tops[], UInt n_tops, 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 b4fb86da7..cdecc1566 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -717,15 +717,16 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, 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 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, 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 8469e7eaf..b5d10fbb2 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -1448,13 +1448,9 @@ Bool VG_(translate) ( ThreadId tid, 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 @@ Bool VG_(translate) ( ThreadId tid, 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 @@ Bool VG_(translate) ( ThreadId tid, /* 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 @@ Bool VG_(translate) ( ThreadId tid, 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 23075b853..761819153 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -86,14 +86,14 @@ extern void VG_(di_discard_ALL_debuginfo)( void ); * 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 bf6c667ee..b7e1a8fec 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 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling, 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 8926af46b..c8759ae6d 100644 --- a/exp-bbv/bbv_main.c +++ b/exp-bbv/bbv_main.c @@ -87,15 +87,13 @@ struct thread_info { 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 @@ static IRSB* bbv_instrument ( VgCallbackClosure* closure, 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 042a86077..de6bb16ce 100644 --- a/exp-sgcheck/pc_common.c +++ b/exp-sgcheck/pc_common.c @@ -134,7 +134,7 @@ typedef 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 @@ UInt pc_update_Error_extra ( const Error* err ) 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 @@ UInt pc_update_Error_extra ( const Error* err ) = 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 @@ UInt pc_update_Error_extra ( const Error* err ) /* 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 f4ae81bf7..f6f5fc418 100644 --- a/exp-sgcheck/sg_main.c +++ b/exp-sgcheck/sg_main.c @@ -1926,10 +1926,10 @@ void shadowStack_new_frame ( ThreadId tid, 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 3fb73eee3..360cd0dfe 100644 --- a/exp-sgcheck/tests/bad_percentify.c +++ b/exp-sgcheck/tests/bad_percentify.c @@ -493,20 +493,20 @@ VG_(debugLog_vprintf) ( } // 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 2f327690c..f012d7a4c 100644 --- a/exp-sgcheck/tests/hackedbz2.c +++ b/exp-sgcheck/tests/hackedbz2.c @@ -1244,18 +1244,18 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) } # 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 ce2c232d3..84afdde69 100644 --- a/include/pub_tool_addrinfo.h +++ b/include/pub_tool_addrinfo.h @@ -153,10 +153,10 @@ struct _AddrInfo { 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 f47669e6c..0940b3dc3 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 @@ extern Bool VG_(get_filename_linenum) 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 @@ typedef } 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 @@ extern Vg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip ); 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 @@ Bool VG_(get_data_description)( /* 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 f76998f8e..485707c4f 100644 --- a/lackey/lk_main.c +++ b/lackey/lk_main.c @@ -660,7 +660,6 @@ IRSB* lk_instrument ( VgCallbackClosure* closure, IRDirty* di; Int i; IRSB* sbOut; - HChar fnname[100]; IRTypeEnv* tyenv = sbIn->tyenv; Addr iaddr = 0, dst; UInt ilen = 0; @@ -750,8 +749,9 @@ IRSB* lk_instrument ( VgCallbackClosure* closure, */ 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 da58bb665..cdd73b498 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -355,7 +355,7 @@ static void init_ignore_fns(void) } // 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 @@ static void sanity_check_SXTree(SXPt* sxpt) // 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 Bool fn_should_be_ignored(Addr ip) 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 @@ Int get_IPs( ThreadId tid, Bool exclude_first_entry, Addr ips[]) // 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 26fe16175..b4b238fe8 100644 --- a/memcheck/tests/origin5-bz2.c +++ b/memcheck/tests/origin5-bz2.c @@ -1237,18 +1237,18 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) } # 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 7d835e0f8..c04f68446 100644 --- a/memcheck/tests/varinfo6.c +++ b/memcheck/tests/varinfo6.c @@ -1275,18 +1275,18 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) } # 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 739e68f93..79cb93325 100644 --- a/perf/bz2.c +++ b/perf/bz2.c @@ -1237,18 +1237,16 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) } # 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;