]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
The semantic of the stack bounds is not consistent or is not described.
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Fri, 29 Aug 2014 22:53:19 +0000 (22:53 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Fri, 29 Aug 2014 22:53:19 +0000 (22:53 +0000)
At various places, there were either some assumption that the 'end'
boundary (highest address) was either not included, included,
or was the highest addressable word, or the highest addressable byte.
This e.g. was very visible when doing:
  ./vg-in-place -d -d ./helgrind/tests/tc01_simple_race|&grep regi
giving
  --24040:2:stacks     register 0xBEDB4000-0xBEDB4FFF as stack 0
  --24040:2:stacks     register 0x402C000-0x4A2C000 as stack 1
showing that the main stack end was (on x86) not the highest word
but the highest byte, while for the thread 1, the registered end
was a byte not part of the stack.

The attached patch ensures that stack bounds semantic are documented and
consistent. Also, some of the stack handling code is factorised.

The convention that the patch ensures and documents is:
start is the lowest addressable byte, end is the highest addressable byte.
(the words 'min' and 'max' have been kept when already used, as this wording is
consistent with the new semantic of start/end).

In various debug log, used brackets [ and ] to make clear that
both bounds are included.

The code to guess and register the client stack was duplicated
in all the platform specific syswrap-<plat>-<os>.c files.
Code has been factorised in syswrap-generic.c

The patch has been regression tested on
   x86, amd64, ppc32/64, s390x.
It has been compiled and one test run on arm64.
Not compiled/not tested on darwin, android, mips32/64, arm

More in details, the patch does the following:

coregrind/pub_core_aspacemgr.h
include/valgrind.h
include/pub_tool_machine.h
coregrind/pub_core_scheduler.h
coregrind/pub_core_stacks.h
  - document start/end semantic in various functions
 also in pub_tool_machine.h:
  - replaces unclear 'bottommost address' by 'lowest address'
    (unclear as stack bottom is or at least can be interpreted as
     the 'functional' bottom of the stack, which is the highest
      address for 'stack growing downwards').
coregrind/pub_core_initimg.h
  replace unclear clstack_top by clstack_end
coregrind/m_main.c
  updated to clstack_end

coregrind/pub_core_threadstate.h
  renamed client_stack_highest_word to client_stack_highest_byte
coregrind/m_scheduler/scheduler.c
  computes client_stack_highest_byte as the highest addressable byte
  Update comments in call to VG_(show_sched_status)
coregrind/m_machine.c
coregrind/m_stacktrace.c
  updated to client_stack_highest_byte, and switched
    stack_lowest/highest_word to stack_lowest/highest_byte accordingly

coregrind/m_stacks.c
  clarify semantic of start/end,
  added a comment to indicate why we invert start/end in register call
  (note that the code find_stack_by_addr was already assuming that
  end was included as the checks were doing e.g.
    sp >= i->start && sp <= i->end

coregrind/pub_core_clientstate.h
coregrind/m_clientstate.c
  renames Addr  VG_(clstk_base) to Addr  VG_(clstk_start_base)
    (start to indicate it is the lowest address, base suffix kept
     to indicate it is the initial lowest address).

coregrind/m_initimg/initimg-darwin.c
   updated to  VG_(clstk_start_base)
   replace unclear iicii.clstack_top by iicii.clstack_end
   updated clstack_max_size computation according to both bounds included.

coregrind/m_initimg/initimg-linux.c
   updated to  VG_(clstk_start_base)
   updated VG_(clstk_end) computation according to both bounds included.
   replace unclear iicii.clstack_top by iicii.clstack_end

coregrind/pub_core_aspacemgr.h
  extern Addr VG_(am_startup) : clarify semantic of the returned value
coregrind/m_aspacemgr/aspacemgr-linux.c
   removed a copy of a comment that was already in pub_core_aspacemgr.h
     (avoid double maintenance)
   renamed unclear suggested_clstack_top to suggested_clstack_end
    (note that here, it looks like suggested_clstack_top was already
     the last addressable byte)

* factorisation of the stack guessing and registration causes
  mechanical changes in the following files:
      coregrind/m_syswrap/syswrap-ppc64-linux.c
      coregrind/m_syswrap/syswrap-x86-darwin.c
      coregrind/m_syswrap/syswrap-amd64-linux.c
      coregrind/m_syswrap/syswrap-arm-linux.c
      coregrind/m_syswrap/syswrap-generic.c
      coregrind/m_syswrap/syswrap-mips64-linux.c
      coregrind/m_syswrap/syswrap-ppc32-linux.c
      coregrind/m_syswrap/syswrap-amd64-darwin.c
      coregrind/m_syswrap/syswrap-mips32-linux.c
      coregrind/m_syswrap/priv_syswrap-generic.h
      coregrind/m_syswrap/syswrap-x86-linux.c
      coregrind/m_syswrap/syswrap-s390x-linux.c
      coregrind/m_syswrap/syswrap-darwin.c
      coregrind/m_syswrap/syswrap-arm64-linux.c
 Some files to look at more in details:
  syswrap-darwin.c : the handling of sysctl(kern.usrstack) looked
    buggy to me, and has probably be made correct by the fact that
     VG_(clstk_end) is now the last addressable byte. However,unsure
    about this, as I could not find any documentation about
    sysctl(kern.usrstack). I only find several occurences on the web,
    showing that the result of this is page aligned, which I guess
    means it must be 1+ the last addressable byte.
  syswrap-x86-darwin.c and syswrap-amd64-darwin.c
   I suspect the code that was computing client_stack_highest_word
   was wrong, and the patch makes it correct.
  syswrap-mips64-linux.c
    not sure what to do for this code. This is the only code
    that was guessing the stack differently from others.
    Kept (almost) untouched. To be discussed with mips maintainers.

coregrind/pub_core_libcassert.h
coregrind/m_libcassert.c
  * void VG_(show_sched_status):
     renamed Bool valgrind_stack_usage to Bool stack_usage
     if stack_usage, shows both the valgrind stack usage and
     the client stack boundaries
coregrind/m_scheduler/scheduler.c
coregrind/m_gdbserver/server.c
coregrind/m_gdbserver/remote-utils.c
   Updated comments in callers to VG_(show_sched_status)

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14392

35 files changed:
coregrind/m_aspacemgr/aspacemgr-linux.c
coregrind/m_clientstate.c
coregrind/m_gdbserver/remote-utils.c
coregrind/m_gdbserver/server.c
coregrind/m_initimg/initimg-darwin.c
coregrind/m_initimg/initimg-linux.c
coregrind/m_libcassert.c
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_scheduler/scheduler.c
coregrind/m_stacks.c
coregrind/m_stacktrace.c
coregrind/m_syswrap/priv_syswrap-generic.h
coregrind/m_syswrap/syswrap-amd64-darwin.c
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-arm-linux.c
coregrind/m_syswrap/syswrap-arm64-linux.c
coregrind/m_syswrap/syswrap-darwin.c
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-mips32-linux.c
coregrind/m_syswrap/syswrap-mips64-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-ppc64-linux.c
coregrind/m_syswrap/syswrap-s390x-linux.c
coregrind/m_syswrap/syswrap-x86-darwin.c
coregrind/m_syswrap/syswrap-x86-linux.c
coregrind/pub_core_aspacemgr.h
coregrind/pub_core_clientstate.h
coregrind/pub_core_initimg.h
coregrind/pub_core_libcassert.h
coregrind/pub_core_scheduler.h
coregrind/pub_core_stacks.h
coregrind/pub_core_threadstate.h
include/pub_tool_machine.h
include/valgrind.h

index 30b61495b254b3c672384a009b3280368e55e80a..88951c973b821140cef2b83565d4f390c29e5a47 100644 (file)
@@ -1609,19 +1609,11 @@ static void read_maps_callback ( Addr addr, SizeT len, UInt prot,
    add_segment( &seg );
 }
 
-/* Initialise the address space manager, setting up the initial
-   segment list, and reading /proc/self/maps into it.  This must
-   be called before any other function.
-
-   Takes a pointer to the SP at the time V gained control.  This is
-   taken to be the highest usable address (more or less).  Based on
-   that (and general consultation of tea leaves, etc) return a
-   suggested end address for the client's stack. */
-
+/* See description in pub_core_aspacemgr.h */
 Addr VG_(am_startup) ( Addr sp_at_startup )
 {
    NSegment seg;
-   Addr     suggested_clstack_top;
+   Addr     suggested_clstack_end;
 
    aspacem_assert(sizeof(Word)   == sizeof(void*));
    aspacem_assert(sizeof(Addr)   == sizeof(void*));
@@ -1660,7 +1652,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    // 0x7fff:5c000000..0x7fff:ffe00000? is stack, dyld, shared cache
 # endif
 
-   suggested_clstack_top = -1; // ignored; Mach-O specifies its stack
+   suggested_clstack_end = -1; // ignored; Mach-O specifies its stack
 
 #else /* !defined(VGO_darwin) */
 
@@ -1690,7 +1682,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    aspacem_vStart -= 0x10000000; // 256M
 #  endif
 
-   suggested_clstack_top = aspacem_maxAddr - 16*1024*1024ULL
+   suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL
                                            + VKI_PAGE_SIZE;
 
 #endif /* #else of 'defined(VGO_darwin)' */
@@ -1699,7 +1691,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_maxAddr + 1));
    aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_cStart));
    aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_vStart));
-   aspacem_assert(VG_IS_PAGE_ALIGNED(suggested_clstack_top + 1));
+   aspacem_assert(VG_IS_PAGE_ALIGNED(suggested_clstack_end + 1));
 
    VG_(debugLog)(2, "aspacem", 
                     "              minAddr = 0x%010llx (computed)\n", 
@@ -1714,8 +1706,8 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
                     "               vStart = 0x%010llx (computed)\n", 
                     (ULong)aspacem_vStart);
    VG_(debugLog)(2, "aspacem", 
-                    "suggested_clstack_top = 0x%010llx (computed)\n", 
-                    (ULong)suggested_clstack_top);
+                    "suggested_clstack_end = 0x%010llx (computed)\n", 
+                    (ULong)suggested_clstack_end);
 
    if (aspacem_cStart > Addr_MIN) {
       init_resvn(&seg, Addr_MIN, aspacem_cStart-1);
@@ -1751,7 +1743,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    VG_(am_show_nsegments)(2, "With contents of /proc/self/maps");
 
    AM_SANITY_CHECK;
-   return suggested_clstack_top;
+   return suggested_clstack_end;
 }
 
 
index b251f1bf87acae08b2fe0b7ed987733d4ec80fd7..e1a6040ae4d1ca80873c1ede088b6448b4dc8195 100644 (file)
@@ -45,9 +45,9 @@
 // TODO: get rid of as many of these as possible.
 
 /* ***Initial*** lowest address of the stack segment of the main thread.
-   The main stack will grow if needed but VG_(clstk_base) will
+   The main stack will grow if needed but VG_(clstk_start_base) will
    not be changed according to the growth. */
-Addr  VG_(clstk_base)  = 0;
+Addr  VG_(clstk_start_base)  = 0;
 /* Initial highest address of the stack segment of the main thread. */
 Addr  VG_(clstk_end)   = 0;
 UWord VG_(clstk_id)    = 0;
index 599919cc51f226453df377f2a061f20528ee30f4..6ee1f7e0534162cd514712125c7d3bf6f2d5f718 100644 (file)
@@ -44,7 +44,7 @@ void sr_extended_perror (SysRes sr, const HChar *msg)
       Int i;
       vki_sigset_t cursigset;
       VG_(show_sched_status) (True,  // host_stacktrace
-                              True,  // valgrind_stack_usage
+                              True,  // stack_usage
                               True); // exited_threads
       VG_(sigprocmask) (0,           // dummy how.
                         NULL,        // do not change the sigmask
index d8d3a19f2925ec7fcfbdeae4821f68bf08ef175f..072bd686eb07ecabce03aea4cc042feab6469cfe 100644 (file)
@@ -398,7 +398,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
          break;
       case  5: /* scheduler */
          VG_(show_sched_status) (True,  // host_stacktrace
-                                 True,  // valgrind_stack_usage
+                                 True,  // stack_usage
                                  True); // exited_threads
          ret = 1;
          break;
index 89d858477f9c9951f6b054416a6b415a218d1e36..2ae934e4c2386c0783e26a080ad276e26c14f51f 100644 (file)
@@ -410,7 +410,7 @@ Addr setup_client_stack( void*  init_sp,
 
    /* Record stack extent -- needed for stack-change code. */
    /* GrP fixme really? */
-   VG_(clstk_base) = clstack_start;
+   VG_(clstk_start_base) = clstack_start;
    VG_(clstk_end)  = clstack_end;
 
    if (0)
@@ -548,18 +548,18 @@ IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
    //   p: load_client()     [for 'info']
    //   p: fix_environment() [for 'env']
    //--------------------------------------------------------------
-   iicii.clstack_top = info.stack_end - 1;
-   iifii.clstack_max_size = info.stack_end - info.stack_start;
+   iicii.clstack_end = info.stack_end;
+   iifii.clstack_max_size = info.stack_end - info.stack_start + 1;
    
    iifii.initial_client_SP = 
        setup_client_stack( iicii.argv - 1, env, &info, 
-                           iicii.clstack_top, iifii.clstack_max_size );
+                           iicii.clstack_end, iifii.clstack_max_size );
 
    VG_(free)(env);
 
    VG_(debugLog)(2, "initimg",
                  "Client info: "
-                 "initial_IP=%p initial_SP=%p stack=%p..%p\n", 
+                 "initial_IP=%p initial_SP=%p stack=[%p..%p]\n", 
                  (void*)(iifii.initial_client_IP),
                  (void*)(iifii.initial_client_SP),
                  (void*)(info.stack_start), 
index 2d942c16cef0c63cce574cfb9bbd152be7405f59..a8e7d277674adbc958d13878d56ba493746f2acf 100644 (file)
@@ -564,8 +564,8 @@ Addr setup_client_stack( void*  init_sp,
      vg_assert(!sr_isError(res)); 
 
      /* Record stack extent -- needed for stack-change code. */
-     VG_(clstk_base) = anon_start -inner_HACK;
-     VG_(clstk_end)  = VG_(clstk_base) + anon_size +inner_HACK -1;
+     VG_(clstk_start_base) = anon_start -inner_HACK;
+     VG_(clstk_end)  = VG_(clstk_start_base) + anon_size +inner_HACK -1;
 
    }
 
@@ -917,7 +917,7 @@ IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
       iifii.initial_client_SP
          = setup_client_stack( init_sp, env, 
                                &info, &iifii.client_auxv, 
-                               iicii.clstack_top, iifii.clstack_max_size );
+                               iicii.clstack_end, iifii.clstack_max_size );
 
       VG_(free)(env);
 
index 94f28a1218310be1919cdcaae34bb456f3a5e6ac..d48751f2840c7925b2420c84de36231f51eda024 100644 (file)
@@ -39,6 +39,8 @@
 #include "pub_core_libcassert.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"      // For VG_(gettid)()
+#include "pub_core_machine.h"
+#include "pub_core_stacks.h"
 #include "pub_core_stacktrace.h"
 #include "pub_core_syscall.h"
 #include "pub_core_tooliface.h"     // For VG_(details).{name,bug_reports_to}
@@ -294,7 +296,7 @@ void VG_(client_exit)( Int status )
 
 // Print the scheduler status.
 static void show_sched_status_wrk ( Bool host_stacktrace,
-                                    Bool valgrind_stack_usage,
+                                    Bool stack_usage,
                                     Bool exited_threads,
                                     UnwindStartRegs* startRegsIN)
 {
@@ -349,7 +351,19 @@ static void show_sched_status_wrk ( Bool host_stacktrace,
                   VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
       if (VG_(threads)[i].status != VgTs_Empty)
          VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
-      if (valgrind_stack_usage && stack != 0)
+      if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
+         Addr start, end;
+         
+         start = end = 0;
+         VG_(stack_limits)(VG_(threads)[i].client_stack_highest_byte,
+                           &start, &end);
+         if (start != end)
+            VG_(printf)("client stack range: [%p %p] client SP: %p\n",
+                        (void*)start, (void*)end, (void*)VG_(get_SP)(i));
+         else
+            VG_(printf)("client stack range: ???????\n");
+      }
+      if (stack_usage && stack != 0)
           VG_(printf)("valgrind stack top usage: %ld of %ld\n",
                       VG_STACK_ACTIVE_SZB 
                       - VG_(am_get_VgStack_unused_szB)(stack,
@@ -360,11 +374,11 @@ static void show_sched_status_wrk ( Bool host_stacktrace,
 }
 
 void VG_(show_sched_status) ( Bool host_stacktrace,
-                              Bool valgrind_stack_usage,
+                              Bool stack_usage,
                               Bool exited_threads)
 {
    show_sched_status_wrk (host_stacktrace,
-                          valgrind_stack_usage,
+                          stack_usage,
                           exited_threads,
                           NULL);
 }
@@ -374,7 +388,7 @@ static void report_and_quit ( const HChar* report,
                               UnwindStartRegs* startRegsIN )
 {
    show_sched_status_wrk (True,  // host_stacktrace
-                          False, // valgrind_stack_usage
+                          False, // stack_usage
                           False, // exited_threads
                           startRegsIN);
    VG_(printf)(
@@ -485,7 +499,7 @@ void VG_(unimplemented) ( const HChar* msg )
    VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
    VG_(umsg)("\n");
    VG_(show_sched_status)(False,  // host_stacktrace
-                          False,  // valgrind_stack_usage
+                          False,  // stack_usage
                           False); // exited_threads
    VG_(exit)(1);
 }
index 1c767b6228187fa0db1a80d2fa9ca3cfe93d7a59..42d8ce8fd6cd0360f1e48b65e471191c651faf35 100644 (file)
@@ -380,7 +380,7 @@ Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
       if (VG_(threads)[i].status != VgTs_Empty) {
          *tid       = i;
          *stack_min = VG_(get_SP)(i);
-         *stack_max = VG_(threads)[i].client_stack_highest_word;
+         *stack_max = VG_(threads)[i].client_stack_highest_byte;
          return True;
       }
    }
@@ -391,7 +391,7 @@ Addr VG_(thread_get_stack_max)(ThreadId tid)
 {
    vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
    vg_assert(VG_(threads)[tid].status != VgTs_Empty);
-   return VG_(threads)[tid].client_stack_highest_word;
+   return VG_(threads)[tid].client_stack_highest_byte;
 }
 
 SizeT VG_(thread_get_stack_size)(ThreadId tid)
index 796c9ebf60b13d572fdf931e6d8722c471f31fa8..7fdc3a72dfec543f81b1b35c0556002638f41e94 100644 (file)
@@ -1649,7 +1649,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE);
    vg_assert(VKI_PAGE_SIZE     == (1 << VKI_PAGE_SHIFT));
    vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT));
-   the_iicii.clstack_top = VG_(am_startup)( the_iicii.sp_at_startup );
+   the_iicii.clstack_end = VG_(am_startup)( the_iicii.sp_at_startup );
    VG_(debugLog)(1, "main", "Address space manager is running\n");
 
    //--------------------------------------------------------------
@@ -2365,7 +2365,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    //--------------------------------------------------------------
    // register client stack
    //--------------------------------------------------------------
-   VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
+   VG_(clstk_id) = VG_(register_stack)(VG_(clstk_start_base), VG_(clstk_end));
 
    //--------------------------------------------------------------
    // Show the address space state so far
index 0ee14166c84663ac2685a09e5b53652876eecb77..c25a75971d787a0316a96c8b98870c6cf7139a7f 100644 (file)
@@ -620,7 +620,7 @@ ThreadId VG_(scheduler_init_phase1) ( void )
 
       VG_(threads)[i].status                    = VgTs_Empty;
       VG_(threads)[i].client_stack_szB          = 0;
-      VG_(threads)[i].client_stack_highest_word = (Addr)NULL;
+      VG_(threads)[i].client_stack_highest_byte = (Addr)NULL;
       VG_(threads)[i].err_disablement_level     = 0;
       VG_(threads)[i].thread_name               = NULL;
    }
@@ -656,8 +656,8 @@ void VG_(scheduler_init_phase2) ( ThreadId tid_main,
    vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
    vg_assert(VG_IS_PAGE_ALIGNED(clstack_size));
 
-   VG_(threads)[tid_main].client_stack_highest_word 
-      = clstack_end + 1 - sizeof(UWord);
+   VG_(threads)[tid_main].client_stack_highest_byte 
+      = clstack_end;
    VG_(threads)[tid_main].client_stack_szB 
       = clstack_size;
 
@@ -2167,7 +2167,7 @@ void scheduler_sanity ( ThreadId tid )
          VG_(printf)("\n------------ Sched State at %d ms ------------\n",
                      (Int)now);
          VG_(show_sched_status)(True,  // host_stacktrace
-                                True,  // valgrind_stack_usage
+                                True,  // stack_usage
                                 True); // exited_threads);
       }
    }
index d96f70e423f745926e832f37c4b85bf8386505ea..d1165476a9d0bd58c7dadd85aa7edb9ac5e96c85 100644 (file)
@@ -87,8 +87,8 @@
  */
 typedef struct _Stack {
    UWord id;
-   Addr start;
-   Addr end;
+   Addr start; // Lowest stack byte, included.
+   Addr end;   // Highest stack byte, included.
    struct _Stack *next;
 } Stack;
 
@@ -183,6 +183,9 @@ UWord VG_(register_stack)(Addr start, Addr end)
    Stack *i;
 
    if (start > end) {
+      /* If caller provides addresses in reverse order, swap them.
+         Ugly but not doing that breaks backward compatibility with
+         (user) code registering stacks with start/end inverted . */
       Addr t = end;
       end = start;
       start = t;
@@ -199,7 +202,7 @@ UWord VG_(register_stack)(Addr start, Addr end)
       current_stack = i;
    }
 
-   VG_(debugLog)(2, "stacks", "register %p-%p as stack %lu\n",
+   VG_(debugLog)(2, "stacks", "register [%p-%p] as stack %lu\n",
                     (void*)start, (void*)end, i->id);
 
    return i->id;
@@ -246,9 +249,11 @@ void VG_(change_stack)(UWord id, Addr start, Addr end)
 
    while (i) {
       if (i->id == id) {
-         VG_(debugLog)(2, "stacks", "change stack %lu from %p-%p to %p-%p\n",
+         VG_(debugLog)(2, "stacks", 
+                       "change stack %lu from [%p-%p] to [%p-%p]\n",
                        id, (void*)i->start, (void*)i->end,
                            (void*)start,    (void*)end);
+         /* FIXME : swap start/end like VG_(register_stack) ??? */
          i->start = start;
          i->end = end;
          return;
@@ -271,7 +276,6 @@ void VG_(stack_limits)(Addr SP, Addr *start, Addr *end )
    }
 }
 
-
 /* complaints_stack_switch reports that SP has changed by more than some
    threshold amount (by default, 2MB).  We take this to mean that the
    application is switching to a new stack, for whatever reason.
index 64e1ac465b70c0795b5b04294ed00af43c30b100..be171b5f74c167a5ee35da65dfb5bce6d77fbe9b 100644 (file)
@@ -1395,8 +1395,8 @@ UInt VG_(get_StackTrace) ( ThreadId tid,
    VG_(memset)( &startRegs, 0, sizeof(startRegs) );
    VG_(get_UnwindStartRegs)( &startRegs, tid );
 
-   Addr stack_highest_word = VG_(threads)[tid].client_stack_highest_word;
-   Addr stack_lowest_word  = 0;
+   Addr stack_highest_byte = VG_(threads)[tid].client_stack_highest_byte;
+   Addr stack_lowest_byte  = 0;
 
 #  if defined(VGP_x86_linux)
    /* Nasty little hack to deal with syscalls - if libc is using its
@@ -1428,7 +1428,7 @@ UInt VG_(get_StackTrace) ( ThreadId tid,
 
    /* See if we can get a better idea of the stack limits */
    VG_(stack_limits)( (Addr)startRegs.r_sp,
-                      &stack_lowest_word, &stack_highest_word );
+                      &stack_lowest_byte, &stack_highest_byte );
 
    /* Take into account the first_ip_delta. */
    startRegs.r_pc += (Long)(Word)first_ip_delta;
@@ -1436,13 +1436,13 @@ UInt VG_(get_StackTrace) ( ThreadId tid,
    if (0)
       VG_(printf)("tid %d: stack_highest=0x%08lx ip=0x%010llx "
                   "sp=0x%010llx\n",
-                 tid, stack_highest_word,
+                 tid, stack_highest_byte,
                   startRegs.r_pc, startRegs.r_sp);
 
    return VG_(get_StackTrace_wrk)(tid, ips, max_n_ips, 
                                        sps, fps,
                                        &startRegs,
-                                       stack_highest_word);
+                                       stack_highest_byte);
 }
 
 static void printIpDesc(UInt n, Addr ip, void* uu_opaque)
index 598e27d3fa494d000d251d7eca94eda3bced4e94..b3372f3a5e1ab0ac237012d5a7c8f5f3a24f2936 100644 (file)
 #include "priv_types_n_macros.h"  // DECL_TEMPLATE
 
 
+/* Guess the client stack from the segment in which sp is mapped.
+   Register the guessed stack using VG_(register_stack).
+   Setup tst client_stack_highest_byte and client_stack_szB.
+   If sp is not in a mapped segment, does nothing. */
+extern void ML_(guess_and_register_stack) (Addr sp, ThreadState* tst);
+
 // Return true if address range entirely contained within client
 // address space.
 extern
index 77a583edf38a6566a8b1942931f4012a43478f32..b51b652169d3c0a1946111da6f85079885213a2f 100644 (file)
@@ -373,7 +373,7 @@ void pthread_hijack(Addr self, Addr kport, Addr func, Addr func_arg,
    if ((flags & 0x01000000) == 0) {
       // kernel allocated stack - needs mapping
       Addr stack = VG_PGROUNDUP(sp) - stacksize;
-      tst->client_stack_highest_word = stack+stacksize;
+      tst->client_stack_highest_byte = stack+stacksize-1;
       tst->client_stack_szB = stacksize;
 
       // pthread structure
@@ -547,7 +547,7 @@ void wqthread_hijack(Addr self, Addr kport, Addr stackaddr, Addr workitem,
       record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "wqthread-%p");
       
       // kernel allocated stack - needs mapping
-      tst->client_stack_highest_word = stack+stacksize;
+      tst->client_stack_highest_byte = stack+stacksize-1;
       tst->client_stack_szB = stacksize;
 
       // GrP fixme scheduler lock?!
index 92e9d5502bc38500613b7f0430ff4e93ea17a4ae..02d5a469b63c085d9cea9d118996d4f07de46adf 100644 (file)
@@ -210,7 +210,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ptst = VG_(get_ThreadState)(ptid);
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    Long         rax;
    vki_sigset_t blockall, savedmask;
@@ -264,27 +263,7 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)((Addr)rsp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(rsp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-
-      if (debug)
-        VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-                    ctid, seg->start, VG_PGROUNDUP(rsp));
-   } else {
-      VG_(message)(Vg_UserMsg,
-                   "!? New thread %d starts with RSP(%#lx) unmapped\n",
-                  ctid, rsp);
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (rsp, ctst);
 
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  If the clone
index 7680ad0a34a7783cc9e0c349ed239e9aa0d062d2..b91edcc2c010c77238a177b28ffcc81fb437ced7 100644 (file)
@@ -177,7 +177,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    UInt r0;
    UWord *stack;
-   NSegment const* seg;
    SysRes res;
    vki_sigset_t blockall, savedmask;
 
@@ -215,20 +214,7 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   seg = VG_(am_find_nsegment)((Addr)sp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-   
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-   
-      if (debug)
-         VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-         ctid, seg->start, VG_PGROUNDUP(sp));
-   } else {
-      VG_(message)(Vg_UserMsg, "!? New thread %d starts with sp+%#lx) unmapped\n", ctid, sp);
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (sp, ctst);
 
    vg_assert(VG_(owns_BigLock_LL)(ptid));
    VG_TRACK ( pre_thread_ll_create, ptid, ctid );
index 063898a26bdf28316b30eb467222b21726ccbbaa..6ebfc7eac373fcc643ced843ff142436df02fd1e 100644 (file)
@@ -226,7 +226,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ptst = VG_(get_ThreadState)(ptid);
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    ULong        x0;
    vki_sigset_t blockall, savedmask;
@@ -280,28 +279,7 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that xsp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)((Addr)child_xsp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(child_xsp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-   
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-   
-      if (debug)
-         VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-         ctid, seg->start, VG_PGROUNDUP(child_xsp));
-   } else {
-      VG_(message)(
-         Vg_UserMsg,
-         "!? New thread %d starts with sp+%#lx) unmapped\n", ctid, child_xsp
-      );
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack)(child_xsp, ctst);
 
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  If the clone
index 0af2a9cae5a39e26b25bd37d1ddf51e0aca51b54..a736f39abfaa4770ce27baff012415a30aba46d6 100644 (file)
@@ -174,26 +174,7 @@ Addr allocstack ( ThreadId tid )
 
 void find_stack_segment(ThreadId tid, Addr sp)
 {
-   /* We don't really know where the client stack is, because it's
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   const NSegment *seg = VG_(am_find_nsegment)(sp);
-   if (seg && seg->kind != SkResvn) {
-      tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
-      tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
-
-      if (1)
-         VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-                     tid, seg->start, VG_PGROUNDUP(sp));
-   } else {
-       VG_(printf)("couldn't find user stack\n");
-      VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
-                   tid, sp);
-      tst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (sp, VG_(get_ThreadState)(tid));
 }
 
 
@@ -3783,6 +3764,10 @@ PRE(__sysctl)
             Addr *oldp = (Addr *)ARG3;
             size_t *oldlenp = (size_t *)ARG4;
             if (oldlenp) {
+               // According to some searches on the net, it looks like USRSTACK
+               // gives the address of the byte following the highest byte of the stack
+               // As VG_(clstk_end) is the address of the highest addressable byte, we
+               // add +1.
                Addr stack_end = VG_(clstk_end)+1;
                size_t oldlen = *oldlenp;
                // always return actual size
index d9df953dc6f497ef4aa3da3afce9969bd70f4db9..4fd4e50ad11f92d618b3898e0590b94eaba9adbc 100644 (file)
@@ -60,6 +60,7 @@
 #include "pub_core_syswrap.h"
 #include "pub_core_tooliface.h"
 #include "pub_core_ume.h"
+#include "pub_core_stacks.h"
 
 #include "priv_types_n_macros.h"
 #include "priv_syswrap-generic.h"
 #include "config.h"
 
 
+void ML_(guess_and_register_stack) (Addr sp, ThreadState* tst)
+{
+   Bool debug = False;
+   NSegment const* seg;
+
+   /* We don't really know where the client stack is, because its
+      allocated by the client.  The best we can do is look at the
+      memory mappings and try to derive some useful information.  We
+      assume that sp starts near its highest possible value, and can
+      only go down to the start of the mmaped segment. */
+   seg = VG_(am_find_nsegment)(sp);
+   if (seg && seg->kind != SkResvn) {
+      tst->client_stack_highest_byte = (Addr)VG_PGROUNDUP(sp)-1;
+      tst->client_stack_szB = tst->client_stack_highest_byte - seg->start + 1;
+
+      VG_(register_stack)(seg->start, tst->client_stack_highest_byte);
+
+      if (debug)
+        VG_(printf)("tid %d: guessed client stack range [%#lx-%#lx]\n",
+                    tst->tid, seg->start, tst->client_stack_highest_byte);
+   } else {
+      VG_(message)(Vg_UserMsg,
+                   "!? New thread %d starts with SP(%#lx) unmapped\n",
+                  tst->tid, sp);
+      tst->client_stack_highest_byte = 0;
+      tst->client_stack_szB  = 0;
+   }
+}
+
 /* Returns True iff address range is something the client can
    plausibly mess with: all of it is either already belongs to the
    client or is free or a reservation. */
index c0cd811bfcd5a008bce0d120a40f6bcc0cf8bd2c..5888841d768bf5ead6e12610ba3ebcf05ba858f3 100644 (file)
@@ -248,7 +248,6 @@ static SysRes do_clone (ThreadId ptid,
    ThreadState * ctst = VG_ (get_ThreadState) (ctid);
    UInt ret = 0;
    UWord * stack;
-   NSegment const *seg;
    SysRes res;
    vki_sigset_t blockall, savedmask;
 
@@ -283,22 +282,8 @@ static SysRes do_clone (ThreadId ptid,
       See #226116. */ 
 
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
-   seg = VG_ (am_find_nsegment) ((Addr) sp);
 
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr) VG_PGROUNDUP (sp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-      VG_ (register_stack) (seg->start, ctst->client_stack_highest_word);
-      if (debug)
-         VG_ (printf) ("tid %d: guessed client stack range %#lx-%#lx\n",
-
-      ctid, seg->start, VG_PGROUNDUP (sp));
-   } else {
-      VG_ (message) (Vg_UserMsg,
-                     "!? New thread %d starts with sp+%#lx) unmapped\n",
-                     ctid, sp);
-      ctst->client_stack_szB = 0;
-   }
+   ML_(guess_and_register_stack) (sp, ctst);
 
    VG_TRACK (pre_thread_ll_create, ptid, ctid);
    if (flags & VKI_CLONE_SETTLS) {
index fb5067c39376161c19f36abdf0c4078ba83b1b41..3d5cb7df3e8a5c7981e72fd71c3044ce8fcc9644 100644 (file)
@@ -232,10 +232,12 @@ static SysRes do_clone ( ThreadId ptid,
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
    seg = VG_(am_find_nsegment)((Addr)sp);
 
+   // FIXME mips64: the below differs significantly from the code
+   // factorised in syswrap-generic.c e.g. does not round sp ????
    if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = sp;
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
+      ctst->client_stack_highest_byte = sp;
+      ctst->client_stack_szB = ctst->client_stack_highest_byte - seg->start + 1;
+      VG_(register_stack)(seg->start, ctst->client_stack_highest_byte);
       if (debug)
         VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
                     ctid, seg->start, sp /* VG_PGROUNDUP (sp) */ );
index c79156c41f18282f23821b397cfc57d8fd27b289..9b4edf14a6c795080cae7c2e012d1edc45989061 100644 (file)
@@ -244,7 +244,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    ULong        word64;
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    vki_sigset_t blockall, savedmask;
 
@@ -310,27 +309,7 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)(sp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-
-      if (debug)
-        VG_(printf)("\ntid %d: guessed client stack range %#lx-%#lx\n",
-                    ctid, seg->start, VG_PGROUNDUP(sp));
-   } else {
-      VG_(message)(Vg_UserMsg,
-                   "!? New thread %d starts with R1(%#lx) unmapped\n",
-                  ctid, sp);
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (sp, ctst);
 
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  If the clone
index b67cf30885724cc3bffd32b421a8b1ba30711fc9..d660833463ad171307b8460933fede40b6f698f3 100644 (file)
@@ -394,7 +394,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    ULong        word64;
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    vki_sigset_t blockall, savedmask;
 
@@ -460,27 +459,7 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)(sp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-
-      if (debug)
-        VG_(printf)("\ntid %d: guessed client stack range %#lx-%#lx\n",
-                    ctid, seg->start, VG_PGROUNDUP(sp));
-   } else {
-      VG_(message)(Vg_UserMsg,
-                   "!? New thread %d starts with R1(%#lx) unmapped\n",
-                  ctid, sp);
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (sp, ctst);
 
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  If the clone
index 664c6ffa2493ef3cc3f287827edb31beb9816524..ee852d4f570f24bb5fb4c24b67f2c17d6c89b0fe 100644 (file)
@@ -216,7 +216,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ptst = VG_(get_ThreadState)(ptid);
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    ULong        r2;
    vki_sigset_t blockall, savedmask;
@@ -262,27 +261,7 @@ static SysRes do_clone ( ThreadId ptid,
    /* have the parents thread group */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)((Addr)sp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-
-      if (debug)
-        VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-                    ctid, seg->start, VG_PGROUNDUP(sp));
-   } else {
-      VG_(message)(Vg_UserMsg,
-                   "!? New thread %d starts with SP(%#lx) unmapped\n",
-                  ctid, sp);
-      ctst->client_stack_szB  = 0;
-   }
+   ML_(guess_and_register_stack) (sp, ctst);
 
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  If the clone
index b7c8241dc38a8b5b0683feb7e3ad8f3ba53aebc4..b4a6f63b71f089844b8d2fd6fa5aa787499ce777 100644 (file)
@@ -314,7 +314,7 @@ void pthread_hijack(Addr self, Addr kport, Addr func, Addr func_arg,
    if ((flags & 0x01000000) == 0) {
       // kernel allocated stack - needs mapping
       Addr stack = VG_PGROUNDUP(sp) - stacksize;
-      tst->client_stack_highest_word = stack+stacksize;
+      tst->client_stack_highest_byte = stack+stacksize-1;
       tst->client_stack_szB = stacksize;
 
       // pthread structure
@@ -475,7 +475,7 @@ void wqthread_hijack(Addr self, Addr kport, Addr stackaddr, Addr workitem,
       record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "wqthread-%p");
       
       // kernel allocated stack - needs mapping
-      tst->client_stack_highest_word = stack+stacksize;
+      tst->client_stack_highest_byte = stack+stacksize-1;
       tst->client_stack_szB = stacksize;
 
       // GrP fixme scheduler lock?!
index c07c628c948610ce5a32016ff3a4595292d7d26a..2ec4d1ae720851deac2499a93fb4cbd7ba170246 100644 (file)
@@ -217,7 +217,6 @@ static SysRes do_clone ( ThreadId ptid,
    ThreadState* ptst = VG_(get_ThreadState)(ptid);
    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    UWord*       stack;
-   NSegment const* seg;
    SysRes       res;
    Int          eax;
    vki_sigset_t blockall, savedmask;
@@ -275,28 +274,8 @@ static SysRes do_clone ( ThreadId ptid,
       See #226116. */
    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
 
-   /* We don't really know where the client stack is, because its
-      allocated by the client.  The best we can do is look at the
-      memory mappings and try to derive some useful information.  We
-      assume that esp starts near its highest possible value, and can
-      only go down to the start of the mmaped segment. */
-   seg = VG_(am_find_nsegment)((Addr)esp);
-   if (seg && seg->kind != SkResvn) {
-      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
-      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
-
-      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
-
-      if (debug)
-        VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
-                    ctid, seg->start, VG_PGROUNDUP(esp));
-   } else {
-      VG_(message)(Vg_UserMsg,
-                   "!? New thread %d starts with ESP(%#lx) unmapped\n",
-                  ctid, esp);
-      ctst->client_stack_szB  = 0;
-   }
-
+   ML_(guess_and_register_stack) (esp, ctst);
+   
    /* Assume the clone will succeed, and tell any tool that wants to
       know that this thread has come into existence.  We cannot defer
       it beyond this point because sys_set_thread_area, just below,
index 4dd62cb503e8b970cd35a7a170ee4edc3b076033..890ac3a03f50c00ce4b7417adce808476514178a 100644 (file)
@@ -58,7 +58,7 @@
    Takes a pointer to the SP at the time V gained control.  This is
    taken to be the highest usable address (more or less).  Based on
    that (and general consultation of tea leaves, etc) return a
-   suggested end address for the client's stack. */
+   suggested end address (highest addressable byte) for the client's stack. */
 extern Addr VG_(am_startup) ( Addr sp_at_startup );
 
 
index 64ec16191784dc2fdee2d5a4720cacbd7df9082b..dc93d1fd72031c581fd2d0f13ab7b776235fc181 100644 (file)
@@ -42,8 +42,9 @@
 
 // Address space globals
 
-extern Addr  VG_(clstk_base);   // client stack range
-extern Addr  VG_(clstk_end);
+// client stack range
+extern Addr  VG_(clstk_start_base); // *Initial* lowest byte address
+extern Addr  VG_(clstk_end);        // Highest byte address
 extern UWord VG_(clstk_id);      // client stack id
 
 /* linux only: where is the client auxv ? */
index a9a8ab394c297fae6de7daf38eb426ff8e9276fa..5623498812b8e01c98731edf42b3b0ba3ddcb10d 100644 (file)
@@ -72,7 +72,7 @@ struct _IICreateImageInfo {
    /* ------ Mandatory fields ------ */
    const HChar*  toolname;
    Addr    sp_at_startup;
-   Addr    clstack_top;
+   Addr    clstack_end; // Highest stack addressable byte
    /* ------ Per-OS fields ------ */
    HChar** argv;
    HChar** envp;
@@ -96,7 +96,7 @@ struct _IICreateImageInfo {
    /* ------ Mandatory fields ------ */
    const HChar*  toolname;
    Addr    sp_at_startup;
-   Addr    clstack_top;
+   Addr    clstack_end; // highest stack addressable byte
    /* ------ Per-OS fields ------ */
    HChar** argv;
    HChar** envp;
index de4b3ccfc6c53062e19d125670644e9164a14cb3..6e1df85a906d3f4386350bd28bd459ec36d85a6f 100644 (file)
@@ -83,11 +83,13 @@ extern void VG_(unimplemented) ( const HChar* msg )
    Mostly for debugging V.
    The following activates optional output:
      host_stacktrace : shows the host stacktrace.
-     valgrind_stack_usage : shows how much of the valgrind stack was used.
+     stack_usage True means:
+                   shows how much of the valgrind stack was used.
+                   shows the client stack range
      exited_thread_slots : show information for thread slots that were used
         but the thread has now exited. */
 extern void VG_(show_sched_status) ( Bool host_stacktrace,
-                                     Bool valgrind_stack_usage,
+                                     Bool stack_usage,
                                      Bool exited_threads);
 
 #endif   // __PUB_CORE_LIBCASSERT_H
index 6b24aeb8a41a3e01c91ae5e9e5058a92a64bd78a..aa9cf041ef5cd3fbc7a8c7e432b10ea999cdf03f 100644 (file)
@@ -96,7 +96,8 @@ extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
 extern ThreadId VG_(scheduler_init_phase1) ( void );
 
 // Initialise, phase 2.  Is passed the extent of the root thread's
-// client stack and the root ThreadId decided on by phase 1.
+// client stack end (highest addressable byte) and the root ThreadId
+// decided on by phase 1.
 extern void VG_(scheduler_init_phase2) ( ThreadId main_tid, 
                                          Addr     clstack_end, 
                                          SizeT    clstack_size );
index 71bdfcaa937f541b53b33abf1ca07b18533a9024..31f5f72975ef05fc9ba8125e0eabbd55a0380ab1 100644 (file)
 // purposes of detecting stack switches.
 //--------------------------------------------------------------------
 
+/* Convention for start and end:
+   'start' is the lowest address, 'end' is the highest address.
+   'start' and 'end' bytes are included in the stack.
+   In other words, the stack is the byte interval ['start', 'end']
+   (both bounds are included).
+
+   Note: for compatibility reasons, VG_(register_stack) accepts
+   'start' bigger than 'end' and will (transparently) swap 'start/end'
+   to register the stack. */
 extern UWord VG_(register_stack)   ( Addr start, Addr end );
 extern void  VG_(deregister_stack) ( UWord id );
 extern void  VG_(change_stack)     ( UWord id, Addr start, Addr end );
index c2ebb1c8981b9a8e3301365a1206342322cf996e..bd1bc06ed9f746d7aa8aef9c2f058cb1cfc75be4 100644 (file)
@@ -341,11 +341,11 @@ typedef struct {
    /* The allocated size of this thread's stack */
    SizeT client_stack_szB;
 
-   /* Address of the highest legitimate word in this stack.  This is
+   /* Address of the highest legitimate byte in this stack.  This is
       used for error messages only -- not critical for execution
       correctness.  Is is set for all stacks, specifically including
       ThreadId == 1 (the main thread). */
-   Addr client_stack_highest_word;
+   Addr client_stack_highest_byte;
 
    /* Alternate signal stack */
    vki_stack_t altstack;
index 0f004f1df4ffa40c0a9b5320885c83a1f0e55269..c80d49b29654938e7d6ece3750ab7589d68f970c 100644 (file)
@@ -142,17 +142,21 @@ extern void VG_(apply_to_GP_regs)(void (*f)(ThreadId tid,
 // Returns False at the end.  'tid' is the iterator and you can only
 // safely change it by making calls to these functions.
 extern void VG_(thread_stack_reset_iter) ( /*OUT*/ThreadId* tid );
+// stack_min is the address of the lowest stack byte,
+// stack_max is the address of the highest stack byte.
+// In other words, the live stack is [stack_min, stack_max].
 extern Bool VG_(thread_stack_next)       ( /*MOD*/ThreadId* tid,
                                            /*OUT*/Addr* stack_min, 
                                            /*OUT*/Addr* stack_max );
 
-// Returns .client_stack_highest_word for the given thread
+// Returns .client_stack_highest_byte for the given thread
+// i.e. the highest addressable byte of the stack.
 extern Addr VG_(thread_get_stack_max) ( ThreadId tid );
 
 // Returns how many bytes have been allocated for the stack of the given thread
 extern SizeT VG_(thread_get_stack_size) ( ThreadId tid );
 
-// Returns the bottommost address of the alternate signal stack.
+// Returns the lowest address of the alternate signal stack.
 // See also the man page of sigaltstack().
 extern Addr VG_(thread_get_altstack_min) ( ThreadId tid );
 
index a65f03a1a754a58f486eef1a83f755b79853d107..6954d751d5eb0c4f47b9f05622a92e00a9609d7a 100644 (file)
@@ -6507,7 +6507,9 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
                                VG_USERREQ__MEMPOOL_EXISTS,        \
                                pool, 0, 0, 0, 0)
 
-/* Mark a piece of memory as being a stack. Returns a stack id. */
+/* Mark a piece of memory as being a stack. Returns a stack id.
+   start is the lowest addressable stack byte, end is the highest
+   addressable stack byte. */
 #define VALGRIND_STACK_REGISTER(start, end)                       \
     (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
                                VG_USERREQ__STACK_REGISTER,        \
@@ -6519,7 +6521,9 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
                                     id, 0, 0, 0, 0)
 
-/* Change the start and end address of the stack id. */
+/* Change the start and end address of the stack id.
+   start is the new lowest addressable stack byte, end is the new highest
+   addressable stack byte. */
 #define VALGRIND_STACK_CHANGE(id, start, end)                     \
     VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE,     \
                                     id, start, end, 0, 0)