blob: 2aceffe289c33446ce781b0522c47c326c9b5be8 [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardj85642922008-01-14 11:54:56 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
sewardj85642922008-01-14 11:54:56 +00004
bart09dc13f2009-02-14 15:13:31 +00005 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardj85642922008-01-14 11:54:56 +00006
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
bart09dc13f2009-02-14 15:13:31 +000026#include "drd_barrier.h"
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_clientreq.h"
28#include "drd_cond.h"
bart83c17802009-03-10 09:26:07 +000029#include "drd_load_store.h"
sewardjaf44c822007-11-25 14:01:38 +000030#include "drd_mutex.h"
bart09dc13f2009-02-14 15:13:31 +000031#include "drd_rwlock.h"
sewardj85642922008-01-14 11:54:56 +000032#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000033#include "drd_suppression.h" // drd_start_suppression()
34#include "drd_thread.h"
sewardjaf44c822007-11-25 14:01:38 +000035#include "pub_tool_basics.h" // Bool
bartb93846e2008-04-16 18:17:12 +000036#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
sewardjaf44c822007-11-25 14:01:38 +000037#include "pub_tool_libcassert.h"
38#include "pub_tool_libcassert.h" // tl_assert()
39#include "pub_tool_libcprint.h" // VG_(message)()
40#include "pub_tool_machine.h" // VG_(get_SP)()
41#include "pub_tool_threadstate.h"
42#include "pub_tool_tooliface.h" // VG_(needs_...)()
43
44
bart09dc13f2009-02-14 15:13:31 +000045/* Local function declarations. */
sewardjaf44c822007-11-25 14:01:38 +000046
bart09dc13f2009-02-14 15:13:31 +000047static
48Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret);
49static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid);
sewardjaf44c822007-11-25 14:01:38 +000050
sewardjaf44c822007-11-25 14:01:38 +000051
bart03ffb2e2009-02-15 10:36:32 +000052/* Function definitions. */
53
bart09dc13f2009-02-14 15:13:31 +000054/**
bart03ffb2e2009-02-15 10:36:32 +000055 * Tell the Valgrind core the address of the DRD function that processes
56 * client requests. Must be called before any client code is run.
bartf1ac71a2008-04-04 16:54:37 +000057 */
bart03ffb2e2009-02-15 10:36:32 +000058void DRD_(clientreq_init)(void)
bartf1ac71a2008-04-04 16:54:37 +000059{
bartbedfd232009-03-26 19:07:15 +000060 VG_(needs_client_requests)(DRD_(handle_client_request));
bartf1ac71a2008-04-04 16:54:37 +000061}
62
bart09dc13f2009-02-14 15:13:31 +000063/**
64 * DRD's handler for Valgrind client requests. The code below handles both
65 * DRD's public and tool-internal client requests.
66 */
67static
68Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret)
sewardjaf44c822007-11-25 14:01:38 +000069{
bartbedfd232009-03-26 19:07:15 +000070 UWord result = 0;
71 const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
bart0268dfa2008-03-11 20:10:21 +000072
bartbedfd232009-03-26 19:07:15 +000073 tl_assert(vg_tid == VG_(get_running_tid()));
74 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid);
sewardjaf44c822007-11-25 14:01:38 +000075
bartbedfd232009-03-26 19:07:15 +000076 switch (arg[0])
77 {
78 case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID:
79 result = vg_tid;
80 break;
sewardjaf44c822007-11-25 14:01:38 +000081
bartbedfd232009-03-26 19:07:15 +000082 case VG_USERREQ__DRD_GET_DRD_THREAD_ID:
83 result = drd_tid;
84 break;
bart5f57be92008-07-01 08:48:56 +000085
bartbedfd232009-03-26 19:07:15 +000086 case VG_USERREQ__DRD_START_SUPPRESSION:
87 DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client");
88 break;
sewardjaf44c822007-11-25 14:01:38 +000089
bartbedfd232009-03-26 19:07:15 +000090 case VG_USERREQ__DRD_FINISH_SUPPRESSION:
91 DRD_(finish_suppression)(arg[1], arg[1] + arg[2]);
92 break;
sewardjaf44c822007-11-25 14:01:38 +000093
bartbedfd232009-03-26 19:07:15 +000094 case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK:
95 {
96 const Addr topmost_sp = DRD_(highest_used_stack_address)(vg_tid);
bart0ff483d2008-04-06 13:08:32 +000097#if 0
bartbedfd232009-03-26 19:07:15 +000098 UInt nframes;
99 const UInt n_ips = 20;
100 Addr ips[n_ips], sps[n_ips], fps[n_ips];
101 Char desc[128];
102 unsigned i;
bart0ff483d2008-04-06 13:08:32 +0000103
bartbedfd232009-03-26 19:07:15 +0000104 nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, fps, 0);
bart0ff483d2008-04-06 13:08:32 +0000105
bartbedfd232009-03-26 19:07:15 +0000106 VG_(message)(Vg_DebugMsg, "thread %d/%d", vg_tid, drd_tid);
107 for (i = 0; i < nframes; i++)
108 {
109 VG_(describe_IP)(ips[i], desc, sizeof(desc));
110 VG_(message)(Vg_DebugMsg, "[%2d] sp 0x%09lx fp 0x%09lx ip %s",
111 i, sps[i], fps[i], desc);
112 }
bart0ff483d2008-04-06 13:08:32 +0000113#endif
bartbedfd232009-03-26 19:07:15 +0000114 DRD_(thread_set_stack_startup)(drd_tid, VG_(get_SP)(vg_tid));
115 DRD_(start_suppression)(topmost_sp, VG_(thread_get_stack_max)(vg_tid),
116 "stack top");
117 break;
118 }
sewardjaf44c822007-11-25 14:01:38 +0000119
bartbedfd232009-03-26 19:07:15 +0000120 case VG_USERREQ__DRD_START_NEW_SEGMENT:
121 DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1]));
122 break;
sewardjaf44c822007-11-25 14:01:38 +0000123
bartbedfd232009-03-26 19:07:15 +0000124 case VG_USERREQ__DRD_START_TRACE_ADDR:
125 DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]);
126 break;
bart005dc972008-03-29 14:42:59 +0000127
bartbedfd232009-03-26 19:07:15 +0000128 case VG_USERREQ__DRD_STOP_TRACE_ADDR:
129 DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]);
130 break;
bart5bd9f2d2008-03-03 20:31:58 +0000131
bartbedfd232009-03-26 19:07:15 +0000132 case VG_USERREQ__DRD_STOP_RECORDING:
133 DRD_(thread_stop_recording)(drd_tid);
134 break;
bartbf3a60c2008-04-04 19:10:21 +0000135
bartbedfd232009-03-26 19:07:15 +0000136 case VG_USERREQ__DRD_START_RECORDING:
137 DRD_(thread_start_recording)(drd_tid);
138 break;
bartbf3a60c2008-04-04 19:10:21 +0000139
bartbedfd232009-03-26 19:07:15 +0000140 case VG_USERREQ__SET_PTHREADID:
141 // pthread_self() returns 0 for programs not linked with libpthread.so.
142 if (arg[1] != INVALID_POSIX_THREADID)
143 DRD_(thread_set_pthreadid)(drd_tid, arg[1]);
144 break;
sewardjaf44c822007-11-25 14:01:38 +0000145
bartbedfd232009-03-26 19:07:15 +0000146 case VG_USERREQ__SET_JOINABLE:
147 DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]),
148 (Bool)arg[2]);
149 break;
sewardjaf44c822007-11-25 14:01:38 +0000150
bartbedfd232009-03-26 19:07:15 +0000151 case VG_USERREQ__POST_THREAD_JOIN:
152 tl_assert(arg[1]);
153 DRD_(thread_post_join)(drd_tid, DRD_(PtThreadIdToDrdThreadId)(arg[1]));
154 break;
sewardjaf44c822007-11-25 14:01:38 +0000155
bartbedfd232009-03-26 19:07:15 +0000156 case VG_USERREQ__PRE_THREAD_CANCEL:
157 tl_assert(arg[1]);
158 DRD_(thread_pre_cancel)(drd_tid);
159 break;
bart0f099cd2008-09-27 12:36:48 +0000160
bartbedfd232009-03-26 19:07:15 +0000161 case VG_USERREQ__POST_THREAD_CANCEL:
162 tl_assert(arg[1]);
163 break;
bart0f099cd2008-09-27 12:36:48 +0000164
bartbedfd232009-03-26 19:07:15 +0000165 case VG_USERREQ__PRE_MUTEX_INIT:
166 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
167 DRD_(mutex_init)(arg[1], arg[2]);
168 break;
bart0268dfa2008-03-11 20:10:21 +0000169
bartbedfd232009-03-26 19:07:15 +0000170 case VG_USERREQ__POST_MUTEX_INIT:
171 DRD_(thread_leave_synchr)(drd_tid);
172 break;
bart0268dfa2008-03-11 20:10:21 +0000173
bartbedfd232009-03-26 19:07:15 +0000174 case VG_USERREQ__PRE_MUTEX_DESTROY:
175 DRD_(thread_enter_synchr)(drd_tid);
176 break;
sewardjaf44c822007-11-25 14:01:38 +0000177
bartbedfd232009-03-26 19:07:15 +0000178 case VG_USERREQ__POST_MUTEX_DESTROY:
179 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
180 DRD_(mutex_post_destroy)(arg[1]);
181 break;
sewardjaf44c822007-11-25 14:01:38 +0000182
bartbedfd232009-03-26 19:07:15 +0000183 case VG_USERREQ__PRE_MUTEX_LOCK:
184 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
185 DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]);
186 break;
sewardjaf44c822007-11-25 14:01:38 +0000187
bartbedfd232009-03-26 19:07:15 +0000188 case VG_USERREQ__POST_MUTEX_LOCK:
189 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
190 DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/);
191 break;
sewardjaf44c822007-11-25 14:01:38 +0000192
bartbedfd232009-03-26 19:07:15 +0000193 case VG_USERREQ__PRE_MUTEX_UNLOCK:
194 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
195 DRD_(mutex_unlock)(arg[1], arg[2]);
196 break;
bart0268dfa2008-03-11 20:10:21 +0000197
bartbedfd232009-03-26 19:07:15 +0000198 case VG_USERREQ__POST_MUTEX_UNLOCK:
199 DRD_(thread_leave_synchr)(drd_tid);
200 break;
sewardjaf44c822007-11-25 14:01:38 +0000201
bartbedfd232009-03-26 19:07:15 +0000202 case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK:
203 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
204 DRD_(spinlock_init_or_unlock)(arg[1]);
205 break;
bartf4f05812008-07-07 08:10:56 +0000206
bartbedfd232009-03-26 19:07:15 +0000207 case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK:
208 DRD_(thread_leave_synchr)(drd_tid);
209 break;
sewardjaf44c822007-11-25 14:01:38 +0000210
bartbedfd232009-03-26 19:07:15 +0000211 case VG_USERREQ__PRE_COND_INIT:
212 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
213 DRD_(cond_pre_init)(arg[1]);
214 break;
bart3f4623e2008-07-07 16:53:07 +0000215
bartbedfd232009-03-26 19:07:15 +0000216 case VG_USERREQ__POST_COND_INIT:
217 DRD_(thread_leave_synchr)(drd_tid);
218 break;
bart3f4623e2008-07-07 16:53:07 +0000219
bartbedfd232009-03-26 19:07:15 +0000220 case VG_USERREQ__PRE_COND_DESTROY:
221 DRD_(thread_enter_synchr)(drd_tid);
222 break;
sewardjaf44c822007-11-25 14:01:38 +0000223
bartbedfd232009-03-26 19:07:15 +0000224 case VG_USERREQ__POST_COND_DESTROY:
225 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
226 DRD_(cond_post_destroy)(arg[1]);
227 break;
sewardjaf44c822007-11-25 14:01:38 +0000228
bartbedfd232009-03-26 19:07:15 +0000229 case VG_USERREQ__PRE_COND_WAIT:
230 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
231 {
232 const Addr cond = arg[1];
233 const Addr mutex = arg[2];
234 const MutexT mutex_type = arg[3];
235 DRD_(mutex_unlock)(mutex, mutex_type);
236 DRD_(cond_pre_wait)(cond, mutex);
237 }
238 break;
sewardjaf44c822007-11-25 14:01:38 +0000239
bartbedfd232009-03-26 19:07:15 +0000240 case VG_USERREQ__POST_COND_WAIT:
241 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
242 {
243 const Addr cond = arg[1];
244 const Addr mutex = arg[2];
245 const Bool took_lock = arg[3];
246 DRD_(cond_post_wait)(cond);
247 DRD_(mutex_post_lock)(mutex, took_lock, True);
248 }
249 break;
sewardjaf44c822007-11-25 14:01:38 +0000250
bartbedfd232009-03-26 19:07:15 +0000251 case VG_USERREQ__PRE_COND_SIGNAL:
252 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
253 DRD_(cond_pre_signal)(arg[1]);
254 break;
bart3f4623e2008-07-07 16:53:07 +0000255
bartbedfd232009-03-26 19:07:15 +0000256 case VG_USERREQ__POST_COND_SIGNAL:
257 DRD_(thread_leave_synchr)(drd_tid);
258 break;
sewardjaf44c822007-11-25 14:01:38 +0000259
bartbedfd232009-03-26 19:07:15 +0000260 case VG_USERREQ__PRE_COND_BROADCAST:
261 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
262 DRD_(cond_pre_broadcast)(arg[1]);
263 break;
bart3f4623e2008-07-07 16:53:07 +0000264
bartbedfd232009-03-26 19:07:15 +0000265 case VG_USERREQ__POST_COND_BROADCAST:
266 DRD_(thread_leave_synchr)(drd_tid);
267 break;
sewardjaf44c822007-11-25 14:01:38 +0000268
bartbedfd232009-03-26 19:07:15 +0000269 case VG_USERREQ__PRE_SEM_INIT:
270 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
271 DRD_(semaphore_init)(arg[1], arg[2], arg[3]);
272 break;
sewardj85642922008-01-14 11:54:56 +0000273
bartbedfd232009-03-26 19:07:15 +0000274 case VG_USERREQ__POST_SEM_INIT:
275 DRD_(thread_leave_synchr)(drd_tid);
276 break;
bart0268dfa2008-03-11 20:10:21 +0000277
bartbedfd232009-03-26 19:07:15 +0000278 case VG_USERREQ__PRE_SEM_DESTROY:
279 DRD_(thread_enter_synchr)(drd_tid);
280 break;
bart0268dfa2008-03-11 20:10:21 +0000281
bartbedfd232009-03-26 19:07:15 +0000282 case VG_USERREQ__POST_SEM_DESTROY:
283 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
284 DRD_(semaphore_destroy)(arg[1]);
285 break;
sewardj85642922008-01-14 11:54:56 +0000286
bartbedfd232009-03-26 19:07:15 +0000287 case VG_USERREQ__PRE_SEM_WAIT:
288 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
289 DRD_(semaphore_pre_wait)(arg[1]);
290 break;
bart28230a32008-02-29 17:27:03 +0000291
bartbedfd232009-03-26 19:07:15 +0000292 case VG_USERREQ__POST_SEM_WAIT:
293 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
294 DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]);
295 break;
sewardj85642922008-01-14 11:54:56 +0000296
bartbedfd232009-03-26 19:07:15 +0000297 case VG_USERREQ__PRE_SEM_POST:
298 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
299 DRD_(semaphore_pre_post)(drd_tid, arg[1]);
300 break;
sewardj85642922008-01-14 11:54:56 +0000301
bartbedfd232009-03-26 19:07:15 +0000302 case VG_USERREQ__POST_SEM_POST:
303 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
304 DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]);
305 break;
sewardj85642922008-01-14 11:54:56 +0000306
bartbedfd232009-03-26 19:07:15 +0000307 case VG_USERREQ__PRE_BARRIER_INIT:
308 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
309 DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]);
310 break;
sewardj85642922008-01-14 11:54:56 +0000311
bartbedfd232009-03-26 19:07:15 +0000312 case VG_USERREQ__POST_BARRIER_INIT:
313 DRD_(thread_leave_synchr)(drd_tid);
314 break;
bart0268dfa2008-03-11 20:10:21 +0000315
bartbedfd232009-03-26 19:07:15 +0000316 case VG_USERREQ__PRE_BARRIER_DESTROY:
317 DRD_(thread_enter_synchr)(drd_tid);
318 break;
bart0268dfa2008-03-11 20:10:21 +0000319
bartbedfd232009-03-26 19:07:15 +0000320 case VG_USERREQ__POST_BARRIER_DESTROY:
321 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
322 DRD_(barrier_destroy)(arg[1], arg[2]);
323 break;
sewardj85642922008-01-14 11:54:56 +0000324
bartbedfd232009-03-26 19:07:15 +0000325 case VG_USERREQ__PRE_BARRIER_WAIT:
326 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
327 DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]);
328 break;
sewardj85642922008-01-14 11:54:56 +0000329
bartbedfd232009-03-26 19:07:15 +0000330 case VG_USERREQ__POST_BARRIER_WAIT:
331 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
332 DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
333 break;
sewardj85642922008-01-14 11:54:56 +0000334
bartbedfd232009-03-26 19:07:15 +0000335 case VG_USERREQ__PRE_RWLOCK_INIT:
336 DRD_(rwlock_pre_init)(arg[1]);
337 break;
bart00344642008-03-01 15:27:41 +0000338
bartbedfd232009-03-26 19:07:15 +0000339 case VG_USERREQ__POST_RWLOCK_DESTROY:
340 DRD_(rwlock_post_destroy)(arg[1]);
341 break;
bart00344642008-03-01 15:27:41 +0000342
bartbedfd232009-03-26 19:07:15 +0000343 case VG_USERREQ__PRE_RWLOCK_RDLOCK:
344 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
345 DRD_(rwlock_pre_rdlock)(arg[1]);
346 break;
bart00344642008-03-01 15:27:41 +0000347
bartbedfd232009-03-26 19:07:15 +0000348 case VG_USERREQ__POST_RWLOCK_RDLOCK:
349 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
350 DRD_(rwlock_post_rdlock)(arg[1], arg[2]);
351 break;
bart00344642008-03-01 15:27:41 +0000352
bartbedfd232009-03-26 19:07:15 +0000353 case VG_USERREQ__PRE_RWLOCK_WRLOCK:
354 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
355 DRD_(rwlock_pre_wrlock)(arg[1]);
356 break;
bart00344642008-03-01 15:27:41 +0000357
bartbedfd232009-03-26 19:07:15 +0000358 case VG_USERREQ__POST_RWLOCK_WRLOCK:
359 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
360 DRD_(rwlock_post_wrlock)(arg[1], arg[2]);
361 break;
bart00344642008-03-01 15:27:41 +0000362
bartbedfd232009-03-26 19:07:15 +0000363 case VG_USERREQ__PRE_RWLOCK_UNLOCK:
364 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
365 DRD_(rwlock_pre_unlock)(arg[1]);
366 break;
bart0268dfa2008-03-11 20:10:21 +0000367
bartbedfd232009-03-26 19:07:15 +0000368 case VG_USERREQ__POST_RWLOCK_UNLOCK:
369 DRD_(thread_leave_synchr)(drd_tid);
370 break;
bart00344642008-03-01 15:27:41 +0000371
bartbedfd232009-03-26 19:07:15 +0000372 case VG_USERREQ__DRD_CLEAN_MEMORY:
373 if (arg[2] > 0)
374 DRD_(clean_memory)(arg[1], arg[2]);
375 break;
bart83c17802009-03-10 09:26:07 +0000376
bartbedfd232009-03-26 19:07:15 +0000377 default:
378 VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx",
379 arg[0], arg[1]);
380 tl_assert(0);
381 return False;
382 }
sewardjaf44c822007-11-25 14:01:38 +0000383
bartbedfd232009-03-26 19:07:15 +0000384 *ret = result;
385 return True;
sewardjaf44c822007-11-25 14:01:38 +0000386}
387
bart09dc13f2009-02-14 15:13:31 +0000388/**
bart03ffb2e2009-02-15 10:36:32 +0000389 * Walk the stack up to the highest stack frame, and return the stack pointer
390 * of the highest stack frame. It is assumed that there are no more than
391 * ten stack frames above the current frame. This should be no problem
392 * since this function is either called indirectly from the _init() function
393 * in vgpreload_exp-drd-*.so or from the thread wrapper for a newly created
394 * thread. See also drd_pthread_intercepts.c.
bart09dc13f2009-02-14 15:13:31 +0000395 */
bart03ffb2e2009-02-15 10:36:32 +0000396static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000397{
bartbedfd232009-03-26 19:07:15 +0000398 UInt nframes;
399 const UInt n_ips = 10;
400 UInt i;
401 Addr ips[n_ips], sps[n_ips];
402 Addr husa;
bart03ffb2e2009-02-15 10:36:32 +0000403
bartbedfd232009-03-26 19:07:15 +0000404 nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, 0, 0);
405 tl_assert(1 <= nframes && nframes <= n_ips);
bart03ffb2e2009-02-15 10:36:32 +0000406
bartbedfd232009-03-26 19:07:15 +0000407 /* A hack to work around VG_(get_StackTrace)()'s behavior that sometimes */
408 /* the topmost stackframes it returns are bogus (this occurs sometimes */
409 /* at least on amd64, ppc32 and ppc64). */
bart03ffb2e2009-02-15 10:36:32 +0000410
bartbedfd232009-03-26 19:07:15 +0000411 husa = sps[0];
bart03ffb2e2009-02-15 10:36:32 +0000412
bartbedfd232009-03-26 19:07:15 +0000413 tl_assert(VG_(thread_get_stack_max)(vg_tid)
414 - VG_(thread_get_stack_size)(vg_tid) <= husa
415 && husa < VG_(thread_get_stack_max)(vg_tid));
bart03ffb2e2009-02-15 10:36:32 +0000416
bartbedfd232009-03-26 19:07:15 +0000417 for (i = 1; i < nframes; i++)
418 {
bart03ffb2e2009-02-15 10:36:32 +0000419 if (sps[i] == 0)
bartbedfd232009-03-26 19:07:15 +0000420 break;
bart03ffb2e2009-02-15 10:36:32 +0000421 if (husa < sps[i] && sps[i] < VG_(thread_get_stack_max)(vg_tid))
bartbedfd232009-03-26 19:07:15 +0000422 husa = sps[i];
423 }
bart03ffb2e2009-02-15 10:36:32 +0000424
bartbedfd232009-03-26 19:07:15 +0000425 tl_assert(VG_(thread_get_stack_max)(vg_tid)
426 - VG_(thread_get_stack_size)(vg_tid) <= husa
427 && husa < VG_(thread_get_stack_max)(vg_tid));
bart03ffb2e2009-02-15 10:36:32 +0000428
bartbedfd232009-03-26 19:07:15 +0000429 return husa;
sewardjaf44c822007-11-25 14:01:38 +0000430}