|
From: <sv...@va...> - 2008-01-11 07:24:38
|
Author: sewardj
Date: 2008-01-11 07:24:37 +0000 (Fri, 11 Jan 2008)
New Revision: 7338
Log:
Enhancements to debuginfo segment-lookup functions:
Change VG_(seginfo_sect_kind) so it also produces an object file
name as well as a VgSectKind. Adjust users accordingly. Make
use of this in Memcheck's address-describer.
Remove VG_(seginfo_sect_kind_name) and replace it with
VG_(pp_SectKind), so as to independently have a way to print
VgSectKinds without doing the address lookup.
Modified:
branches/DATASYMS/callgrind/bb.c
branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
branches/DATASYMS/exp-drd/drd_error.c
branches/DATASYMS/exp-drd/drd_main.c
branches/DATASYMS/include/pub_tool_debuginfo.h
branches/DATASYMS/memcheck/mc_main.c
Modified: branches/DATASYMS/callgrind/bb.c
===================================================================
--- branches/DATASYMS/callgrind/bb.c 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/callgrind/bb.c 2008-01-11 07:24:37 UTC (rev 7338)
@@ -141,7 +141,7 @@
new->jmp = (CJmpInfo*) &(new->instr[instr_count]);
new->instr_len = 0;
new->cost_count = 0;
- new->sect_kind = VG_(seginfo_sect_kind)(offset + obj->offset);
+ new->sect_kind = VG_(seginfo_sect_kind)(NULL, 0, offset + obj->offset);
new->fn = 0;
new->line = 0;
new->is_entry = 0;
Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-01-11 07:24:37 UTC (rev 7338)
@@ -1511,9 +1511,58 @@
return di->text_bias;
}
-VgSectKind VG_(seginfo_sect_kind)(Addr a)
+Int VG_(seginfo_syms_howmany) ( const DebugInfo *si )
{
+ return si->symtab_used;
+}
+
+void VG_(seginfo_syms_getidx) ( const DebugInfo *si,
+ Int idx,
+ /*OUT*/Addr* addr,
+ /*OUT*/Addr* tocptr,
+ /*OUT*/UInt* size,
+ /*OUT*/HChar** name,
+ /*OUT*/Bool* isText )
+{
+ vg_assert(idx >= 0 && idx < si->symtab_used);
+ if (addr) *addr = si->symtab[idx].addr;
+ if (tocptr) *tocptr = si->symtab[idx].tocptr;
+ if (size) *size = si->symtab[idx].size;
+ if (name) *name = (HChar*)si->symtab[idx].name;
+ if (isText) *isText = si->symtab[idx].isText;
+}
+
+
+/*------------------------------------------------------------*/
+/*--- SectKind query functions ---*/
+/*------------------------------------------------------------*/
+
+/* Convert a VgSectKind to a string, which must be copied if you want
+ to change it. */
+const HChar* VG_(pp_SectKind)( VgSectKind kind )
+{
+ switch (kind) {
+ case Vg_SectUnknown: return "Unknown";
+ case Vg_SectText: return "Text";
+ case Vg_SectData: return "Data";
+ case Vg_SectBSS: return "BSS";
+ case Vg_SectGOT: return "GOT";
+ case Vg_SectPLT: return "PLT";
+ case Vg_SectOPD: return "OPD";
+ default: vg_assert(0);
+ }
+}
+
+/* Given an address 'a', make a guess of which section of which object
+ it comes from. If name is non-NULL, then the last n_name-1
+ characters of the object's name is put in name[0 .. n_name-2], and
+ name[n_name-1] is set to zero (guaranteed zero terminated). */
+
+VgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
+ Addr a)
+{
DebugInfo* di;
+ VgSectKind res = Vg_SectUnknown;
for (di = debugInfo_list; di != NULL; di = di->next) {
@@ -1527,84 +1576,69 @@
di->bss_avma, di->bss_size);
if (di->text_size > 0
- && a >= di->text_avma && a < di->text_avma + di->text_size)
- return Vg_SectText;
-
+ && a >= di->text_avma && a < di->text_avma + di->text_size) {
+ res = Vg_SectText;
+ break;
+ }
if (di->data_size > 0
- && a >= di->data_avma && a < di->data_avma + di->data_size)
- return Vg_SectData;
-
+ && a >= di->data_avma && a < di->data_avma + di->data_size) {
+ res = Vg_SectData;
+ break;
+ }
if (di->bss_size > 0
- && a >= di->bss_avma && a < di->bss_avma + di->bss_size)
- return Vg_SectBSS;
-
+ && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
+ res = Vg_SectBSS;
+ break;
+ }
if (di->plt_size > 0
- && a >= di->plt_avma && a < di->plt_avma + di->plt_size)
- return Vg_SectPLT;
-
+ && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
+ res = Vg_SectPLT;
+ break;
+ }
if (di->got_size > 0
- && a >= di->got_avma && a < di->got_avma + di->got_size)
- return Vg_SectGOT;
-
+ && a >= di->got_avma && a < di->got_avma + di->got_size) {
+ res = Vg_SectGOT;
+ break;
+ }
if (di->opd_size > 0
- && a >= di->opd_avma && a < di->opd_avma + di->opd_size)
- return Vg_SectOPD;
-
+ && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
+ res = Vg_SectOPD;
+ break;
+ }
/* we could also check for .eh_frame, if anyone really cares */
}
- return Vg_SectUnknown;
-}
+ vg_assert( (di == NULL && res == Vg_SectUnknown)
+ || (di != NULL && res != Vg_SectUnknown) );
-Char* VG_(seginfo_sect_kind_name)(Addr a, Char* buf, UInt n_buf)
-{
- switch (VG_(seginfo_sect_kind)(a)) {
- case Vg_SectUnknown:
- VG_(snprintf)(buf, n_buf, "Unknown");
- break;
- case Vg_SectText:
- VG_(snprintf)(buf, n_buf, "Text");
- break;
- case Vg_SectData:
- VG_(snprintf)(buf, n_buf, "Data");
- break;
- case Vg_SectBSS:
- VG_(snprintf)(buf, n_buf, "BSS");
- break;
- case Vg_SectGOT:
- VG_(snprintf)(buf, n_buf, "GOT");
- break;
- case Vg_SectPLT:
- VG_(snprintf)(buf, n_buf, "PLT");
- break;
- case Vg_SectOPD:
- VG_(snprintf)(buf, n_buf, "OPD");
- break;
- default:
- vg_assert(0);
+ if (name) {
+
+ vg_assert(n_name >= 8);
+
+ if (di && di->filename) {
+ Int i, j;
+ Int fnlen = VG_(strlen)(di->filename);
+ Int start_at = 1 + fnlen - n_name;
+ if (start_at < 0) start_at = 0;
+ vg_assert(start_at < fnlen);
+ i = start_at; j = 0;
+ while (True) {
+ vg_assert(j >= 0 && j+1 < n_name);
+ vg_assert(i >= 0 && i <= fnlen);
+ name[j] = di->filename[i];
+ name[j+1] = 0;
+ if (di->filename[i] == 0) break;
+ i++; j++;
+ }
+ } else {
+ VG_(snprintf)(name, n_name, "%s", "???");
+ }
+
+ name[n_name-1] = 0;
}
- return buf;
-}
-Int VG_(seginfo_syms_howmany) ( const DebugInfo *si )
-{
- return si->symtab_used;
-}
+ return res;
-void VG_(seginfo_syms_getidx) ( const DebugInfo *si,
- Int idx,
- /*OUT*/Addr* addr,
- /*OUT*/Addr* tocptr,
- /*OUT*/UInt* size,
- /*OUT*/HChar** name,
- /*OUT*/Bool* isText )
-{
- vg_assert(idx >= 0 && idx < si->symtab_used);
- if (addr) *addr = si->symtab[idx].addr;
- if (tocptr) *tocptr = si->symtab[idx].tocptr;
- if (size) *size = si->symtab[idx].size;
- if (name) *name = (HChar*)si->symtab[idx].name;
- if (isText) *isText = si->symtab[idx].isText;
}
Modified: branches/DATASYMS/exp-drd/drd_error.c
===================================================================
--- branches/DATASYMS/exp-drd/drd_error.c 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/exp-drd/drd_error.c 2008-01-11 07:24:37 UTC (rev 7338)
@@ -132,10 +132,8 @@
{
Char filename[512];
Char soname[512];
- Char sect_kind_name[16];
-
- VG_(seginfo_sect_kind_name)(a, sect_kind_name,
- sizeof(sect_kind_name));
+ VgSectKind kind = VG_(seginfo_sect_kind)(NULL, 0, a);
+ const HChar* sect_kind_name = VG_(pp_SectKind)(kind);
VG_(strncpy)(filename, VG_(seginfo_filename)(sg), sizeof(filename));
filename[sizeof(filename) - 1] = 0;
make_path_relative(filename);
Modified: branches/DATASYMS/exp-drd/drd_main.c
===================================================================
--- branches/DATASYMS/exp-drd/drd_main.c 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/exp-drd/drd_main.c 2008-01-11 07:24:37 UTC (rev 7338)
@@ -524,7 +524,8 @@
switch (st->tag)
{
case Ist_IMark:
- instrument = VG_(seginfo_sect_kind)(st->Ist.IMark.addr) != Vg_SectPLT;
+ instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
+ != Vg_SectPLT;
break;
case Ist_AbiHint:
Modified: branches/DATASYMS/include/pub_tool_debuginfo.h
===================================================================
--- branches/DATASYMS/include/pub_tool_debuginfo.h 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/include/pub_tool_debuginfo.h 2008-01-11 07:24:37 UTC (rev 7338)
@@ -130,6 +130,9 @@
/*OUT*/UInt* size,
/*OUT*/HChar** name,
/*OUT*/Bool* isText );
+
+/* A simple enumeration to describe the 'kind' of various kinds of
+ segments that arise from the mapping of object files. */
typedef
enum {
Vg_SectUnknown,
@@ -142,9 +145,18 @@
}
VgSectKind;
-extern VgSectKind VG_(seginfo_sect_kind)(Addr);
+/* Convert a VgSectKind to a string, which must be copied if you want
+ to change it. */
+extern
+const HChar* VG_(pp_SectKind)( VgSectKind kind );
-extern Char* VG_(seginfo_sect_kind_name)(Addr a, Char* buf, UInt n_buf);
+/* Given an address 'a', make a guess of which section of which object
+ it comes from. If name is non-NULL, then the last n_name-1
+ characters of the object's name is put in name[0 .. n_name-2], and
+ name[n_name-1] is set to zero (guaranteed zero terminated). */
+extern
+VgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
+ Addr a);
#endif // __PUB_TOOL_DEBUGINFO_H
Modified: branches/DATASYMS/memcheck/mc_main.c
===================================================================
--- branches/DATASYMS/memcheck/mc_main.c 2008-01-10 17:54:50 UTC (rev 7337)
+++ branches/DATASYMS/memcheck/mc_main.c 2008-01-11 07:24:37 UTC (rev 7338)
@@ -2626,11 +2626,12 @@
/* The classification of a faulting address. */
typedef
enum {
- Addr_Undescribed, // as-yet unclassified
- Addr_Unknown, // classification yielded nothing useful
- Addr_Stack,
- Addr_Block,
- Addr_GlobalData
+ Addr_Undescribed, // as-yet unclassified
+ Addr_Unknown, // classification yielded nothing useful
+ Addr_Stack, // on a thread's stack
+ Addr_Block, // in malloc'd/free'd block
+ Addr_GlobalData, // in a global data sym
+ Addr_SectKind // last-ditch classification attempt
}
AddrTag;
@@ -2666,6 +2667,13 @@
OffT offset;
} GlobalData;
+ // Could only narrow it down to be the PLT/GOT/etc of a given
+ // object. Better than nothing, perhaps.
+ struct {
+ Char objname[64];
+ VgSectKind kind;
+ } SectKind;
+
// Classification yielded nothing useful.
struct { } Unknown;
@@ -2853,6 +2861,16 @@
xpost);
break;
+ case Addr_SectKind:
+ VG_(message)(Vg_UserMsg,
+ "%sAddress 0x%llx is in the %t segment of %t%s",
+ xpre,
+ (ULong)a,
+ VG_(pp_SectKind)(ai->Addr.SectKind.kind),
+ ai->Addr.SectKind.objname,
+ xpost);
+ break;
+
default:
VG_(tool_panic)("mc_pp_AddrInfo");
}
@@ -3343,9 +3361,10 @@
putting the result in ai. */
static void describe_addr ( Addr a, AddrInfo* ai )
{
- MC_Chunk* mc;
- ThreadId tid;
- Addr stack_min, stack_max;
+ MC_Chunk* mc;
+ ThreadId tid;
+ Addr stack_min, stack_max;
+ VgSectKind sect;
tl_assert(Addr_Undescribed == ai->tag);
@@ -3400,6 +3419,20 @@
[ sizeof(ai->Addr.GlobalData.name)-1 ] == 0);
return;
}
+ /* last ditch attempt at classification */
+ tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
+ VG_(memset)( &ai->Addr.SectKind.objname,
+ 0, sizeof(ai->Addr.SectKind.objname));
+ VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
+ sect = VG_(seginfo_sect_kind)( &ai->Addr.SectKind.objname[0],
+ sizeof(ai->Addr.SectKind.objname)-1, a);
+ if (sect != Vg_SectUnknown) {
+ ai->tag = Addr_SectKind;
+ ai->Addr.SectKind.kind = sect;
+ tl_assert( ai->Addr.SectKind.objname
+ [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
+ return;
+ }
/* Clueless ... */
ai->tag = Addr_Unknown;
return;
|