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>