Improve address description for address in the stack.
--read-var-info=yes is very memory and cpu intensive.
This patch ensures that even witout --read-var-info=yes that
the frame where the address point is reported in the address
description.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13991 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index 0f78103..d94c4bd 100644
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,10 @@
* ==================== OTHER CHANGES ====================
+* Address description logic has been improved and is now common
+ between memcheck and helgrind, resulting in better address
+ descriptions for some error messages.
+
* New and modified GDB server monitor features:
- The GDB server monitor command 'v.info location <address>'
diff --git a/coregrind/m_addrinfo.c b/coregrind/m_addrinfo.c
index bcf6913..6339331 100644
--- a/coregrind/m_addrinfo.c
+++ b/coregrind/m_addrinfo.c
@@ -40,11 +40,11 @@
#include "pub_core_mallocfree.h"
#include "pub_core_machine.h"
#include "pub_core_options.h"
+#include "pub_core_stacktrace.h"
void VG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai )
{
ThreadId tid;
- Addr stack_min, stack_max;
VgSectKind sect;
/* -- Perhaps the variable type/location data describes it? -- */
@@ -94,12 +94,45 @@
return;
}
/* -- Perhaps it's on a thread's stack? -- */
- VG_(thread_stack_reset_iter)(&tid);
- while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
- if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
- ai->tag = Addr_Stack;
- ai->Addr.Stack.tid = tid;
- return;
+ {
+ Addr stack_min, stack_max;
+ VG_(thread_stack_reset_iter)(&tid);
+ while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
+ if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
+ Addr ips[VG_(clo_backtrace_size)],
+ sps[VG_(clo_backtrace_size)];
+ UInt n_frames;
+ UInt f;
+
+ ai->tag = Addr_Stack;
+ ai->Addr.Stack.tid = tid;
+ ai->Addr.Stack.IP = 0;
+ ai->Addr.Stack.frameNo = -1;
+ /* It is on thread tid stack. Build a stacktrace, and
+ find the frame sp[f] .. sp[f+1] where the address is.
+ Store the found frameNo and the corresponding IP in
+ the description.
+ When description is printed, IP will be translated to
+ the function name containing IP.
+ Before accepting to describe addr with sp[f] .. sp[f+1],
+ we verify the sp looks sane: reasonably sized frame,
+ inside the stack.
+ We could check the ABI required alignment for sp (what is it?)
+ is respected, except for the innermost stack pointer ? */
+ n_frames = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
+ sps, NULL, 0/*first_ip_delta*/ );
+ for (f = 0; f < n_frames-1; f++) {
+ if (sps[f] <= a && a < sps[f+1]
+ && sps[f+1] - sps[f] <= 0x4000000 // 64 MB, arbitrary
+ && sps[f+1] <= stack_max
+ && sps[f] >= stack_min - VG_STACK_REDZONE_SZB) {
+ ai->Addr.Stack.frameNo = f;
+ ai->Addr.Stack.IP = ips[f];
+ break;
+ }
+ }
+ return;
+ }
}
}
@@ -223,6 +256,41 @@
case Addr_Stack:
VG_(emit)( "%sAddress 0x%llx is on thread %d's stack%s\n",
xpre, (ULong)a, ai->Addr.Stack.tid, xpost );
+ if (ai->Addr.Stack.frameNo != -1 && ai->Addr.Stack.IP != 0) {
+#define FLEN 256
+ HChar fn[FLEN];
+ Bool hasfn;
+ HChar file[FLEN];
+ Bool hasfile;
+ UInt linenum;
+ 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,
+ &linenum);
+ else
+ haslinenum = False;
+
+ hasfile = VG_(get_filename)(ai->Addr.Stack.IP, file, FLEN);
+ if (hasfile && haslinenum) {
+ HChar strlinenum[10];
+ VG_(snprintf) (strlinenum, 10, ":%d", linenum);
+ VG_(strncat) (file, strlinenum,
+ FLEN - VG_(strlen)(file) - 1);
+ }
+
+ if (hasfn || hasfile)
+ VG_(emit)( "%sin frame #%d, created by %s (%s)%s\n",
+ xpre,
+ ai->Addr.Stack.frameNo,
+ hasfn ? fn : "???",
+ hasfile ? file : "???",
+ xpost );
+#undef FLEN
+ }
break;
case Addr_Block: {
diff --git a/include/pub_tool_addrinfo.h b/include/pub_tool_addrinfo.h
index 342465a..bcfe2fd 100644
--- a/include/pub_tool_addrinfo.h
+++ b/include/pub_tool_addrinfo.h
@@ -85,9 +85,15 @@
// As-yet unclassified.
struct { } Undescribed;
- // On a stack.
+ // On a stack. tid indicates which thread's stack?
+ // IP is the address of an instruction of the function where the
+ // stack address was. 0 if not found.
+ // frameNo is the frame nr of the call where the stack address was.
+ // -1 if not found.
struct {
- ThreadId tid; // Which thread's stack?
+ ThreadId tid;
+ Addr IP;
+ Int frameNo;
} Stack;
// This covers heap blocks (normal and from mempools), user-defined
diff --git a/memcheck/tests/badfree.stderr.exp b/memcheck/tests/badfree.stderr.exp
index a3ea7a4..b518703 100644
--- a/memcheck/tests/badfree.stderr.exp
+++ b/memcheck/tests/badfree.stderr.exp
@@ -7,4 +7,5 @@
at 0x........: free (vg_replace_malloc.c:...)
by 0x........: main (badfree.c:15)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (badfree.c:7)
diff --git a/memcheck/tests/badfree3.stderr.exp b/memcheck/tests/badfree3.stderr.exp
index f276c35..2e1a4bf 100644
--- a/memcheck/tests/badfree3.stderr.exp
+++ b/memcheck/tests/badfree3.stderr.exp
@@ -7,4 +7,5 @@
at 0x........: free (coregrind/vg_replace_malloc.c:...)
by 0x........: main (memcheck/tests/badfree.c:15)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (badfree.c:7)
diff --git a/memcheck/tests/linux/rfcomm.stderr.exp b/memcheck/tests/linux/rfcomm.stderr.exp
index 4df935b..293ae2b 100644
--- a/memcheck/tests/linux/rfcomm.stderr.exp
+++ b/memcheck/tests/linux/rfcomm.stderr.exp
@@ -2,6 +2,7 @@
...
by 0x........: main (rfcomm.c:40)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (rfcomm.c:25)
Uninitialised value was created by a stack allocation
at 0x........: main (rfcomm.c:25)
@@ -9,6 +10,7 @@
...
by 0x........: main (rfcomm.c:44)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (rfcomm.c:25)
Uninitialised value was created by a stack allocation
at 0x........: main (rfcomm.c:25)
@@ -16,6 +18,7 @@
...
by 0x........: main (rfcomm.c:48)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (rfcomm.c:25)
Uninitialised value was created by a stack allocation
at 0x........: main (rfcomm.c:25)
diff --git a/memcheck/tests/sendmsg.stderr.exp b/memcheck/tests/sendmsg.stderr.exp
index 38e20c5..3a6d156 100644
--- a/memcheck/tests/sendmsg.stderr.exp
+++ b/memcheck/tests/sendmsg.stderr.exp
@@ -2,5 +2,6 @@
at 0x........: sendmsg (in /...libc...)
by 0x........: main (sendmsg.c:45)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (sendmsg.c:12)
sendmsg: 6
diff --git a/memcheck/tests/x86-linux/scalar.stderr.exp b/memcheck/tests/x86-linux/scalar.stderr.exp
index 2114db9..9ed5406 100644
--- a/memcheck/tests/x86-linux/scalar.stderr.exp
+++ b/memcheck/tests/x86-linux/scalar.stderr.exp
@@ -891,6 +891,7 @@
...
by 0x........: main (scalar.c:394)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (scalar.c:28)
Syscall param old_select(readfds) points to unaddressable byte(s)
...
@@ -984,6 +985,7 @@
...
by 0x........: main (scalar.c:429)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (scalar.c:28)
-----------------------------------------------------
91: __NR_munmap 2s 0m
@@ -2385,11 +2387,13 @@
...
by 0x........: main (scalar.c:834)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (scalar.c:28)
Syscall param sigaltstack(oss) points to unaddressable byte(s)
...
by 0x........: main (scalar.c:834)
Address 0x........ is on thread 1's stack
+ in frame #1, created by main (scalar.c:28)
-----------------------------------------------------
187: __NR_sendfile 4s 1m
diff --git a/memcheck/tests/xml1.stderr.exp b/memcheck/tests/xml1.stderr.exp
index b6cb890..3eba805 100644
--- a/memcheck/tests/xml1.stderr.exp
+++ b/memcheck/tests/xml1.stderr.exp
@@ -334,6 +334,7 @@
</frame>
</stack>
<auxwhat>Address 0x........ is on thread 1's stack</auxwhat>
+ <auxwhat>in frame #1, created by frame3 (xml1.c:7)</auxwhat>
</error>
<error>