#define DEBUG_CG 0
#define FILE_LEN VKI_PATH_MAX
-#define FN_LEN 256
/*------------------------------------------------------------*/
/*--- Options ---*/
typedef struct {
HChar* file;
- HChar* fn;
+ const HChar* fn;
Int line;
}
CodeLoc;
// 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) {
/*------------------------------------------------------------*/
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;
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) {
// 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;
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
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;
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);
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",
*/
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;
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);
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;
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 '/'.
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;
} 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)*/ {
!pDebugInfo ? "-" :
(*pDebugInfo) ? VG_(DebugInfo_get_filename)(*pDebugInfo) :
"(None)",
- fn_name);
+ *fn_name);
return result;
}
*/
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;
* 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;
}
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");
}
(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 */
/* 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);
}
/* -- 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? -- */
break;
case Addr_DataSym:
+ VG_(free)(ai->Addr.DataSym.name);
break;
case Addr_Variable:
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;
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,
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,
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 )
{
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
// 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;
-
- 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);
+ static HChar *bufwo; // buf with offset
+ static SizeT bufwo_szB;
+ SizeT need, len;
+
+ 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;
}
}
/* 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,
}
/* 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,
/* 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,
/* 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,
/* 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,
: 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;
}
}
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;
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.
}
/* 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) {
&& 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;
}
}
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;
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;
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????
// ??? 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.
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;
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);
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. */
}
// 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:
/* 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
// 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
}
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;
"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;
}
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");
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");
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;
}
// 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",
// "_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. */
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;
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);
}
// 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));
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++];
}
// 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),
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;
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;
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) {
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
// 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;
}
}
// 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;
}
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;
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
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,
{
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];
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);
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);
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);
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 */
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;
}
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. */
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,
/* 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 );
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,
* 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.
* (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
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
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 */
};
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 );
}
Seg* vseg;
XArray* descr1; /* XArray* of HChar */
XArray* descr2; /* XArray* of HChar */
- HChar datasym[96];
+ const HChar* datasym;
PtrdiffT datasymoff;
} Heap;
struct {
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);
= 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
/* 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;
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--;
}
// 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:
}
# 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;
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;
/* 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.
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 {
} 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 );
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
/* 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,
IRDirty* di;
Int i;
IRSB* sbOut;
- HChar fnname[100];
IRTypeEnv* tyenv = sbIn->tyenv;
Addr iaddr = 0, dst;
UInt ilen = 0;
*/
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",
}
// 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;
// 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 );
}
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;
// 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 {
}
# 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;
}
# 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;
}
# 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;