2 * Copyright (c) 1996-2004 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as "Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
42 /* $Id: RTcommon.c,v 1.50 2006/01/13 00:00:48 jodom Exp $ */
46 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
50 unsigned int DYNINSTobsCostLow;
51 unsigned int DYNINSThasInitialized;
52 unsigned DYNINST_max_num_threads;
53 struct DYNINST_bootstrapStruct DYNINST_bootstrap_info;
54 char gLoadLibraryErrorString[ERROR_STRING_LENGTH];
58 * Allocate the Dyninst heaps
60 * The IA-64 requires that instruction be 16-byte aligned, so we have to
61 * align the heaps if we want to use them for inferior RPCs.
63 #if defined(arch_ia64)
64 typedef struct { uint64_t low; uint64_t high; } ia64_bundle_t;
65 #define HEAP_TYPE ia64_bundle_t
66 #define ALIGN_ATTRIB __attribute((aligned))
68 #define HEAP_TYPE double
72 HEAP_TYPE DYNINSTglobalData[SYN_INST_BUF_SIZE/sizeof(HEAP_TYPE)] ALIGN_ATTRIB;
73 HEAP_TYPE DYNINSTstaticHeap_32K_lowmemHeap_1[32*1024/sizeof(HEAP_TYPE)] ALIGN_ATTRIB;
74 HEAP_TYPE DYNINSTstaticHeap_4M_anyHeap_1[4*1024*1024/sizeof(HEAP_TYPE)] ALIGN_ATTRIB;
78 * One some platforms we can tell when a fork or exec is occurring through
79 * system-provided events. On others we do it ourselves. Enumerated type
80 * defined in header file
82 DYNINST_synch_event_t DYNINST_synch_event_id = DSE_undefined;
83 void *DYNINST_synch_event_arg1;
86 * These variables are used to pass arguments into DYNINSTinit
87 * when it is called as an _init function
89 int libdyninstAPI_RT_init_localCause=-1;
90 int libdyninstAPI_RT_init_localPid=-1;
91 int libdyninstAPI_RT_init_maxthreads=-1;
93 int DYNINST_mutatorPid;
94 int DYNINSTdebugPrintRT;
95 int isMutatedExec = 0;
97 unsigned *DYNINST_tramp_guards;
99 tc_lock_t DYNINST_trace_lock;
102 * Init the FPU. We've seen bugs with Linux (e.g., Redhat 6.2 stock kernel on
103 * PIIIs) where processes started by Paradyn started with FPU uninitialized.
104 * DYNINSTdummydouble is global so the compiler won't optimize away FP code
107 double DYNINSTdummydouble = 4321.71;
108 static void initFPU()
111 DYNINSTdummydouble *= x;
114 static void initTrampGuards(unsigned maxthreads)
117 //We allocate maxthreads+1 because maxthreads is sometimes used as an
118 //error value to mean we don't know what thread this is. Sometimes used
119 //during the early setup phases.
120 DYNINST_tramp_guards = (unsigned *) malloc((maxthreads+1)*sizeof(unsigned));
121 for (i=0; i<maxthreads; i++)
123 DYNINST_tramp_guards[i] = 1;
128 * The Dyninst API arranges for this function to be called at the entry to
129 * main() via libdyninstAPI_RT_init (defined in RTposix.c and RTwinnt.c).
130 * libdyninstAPI_RT_init is called by one of the following methods:
131 * GCC: link with gcc -shared, and use __attribute__((constructor));
132 * AIX: ld with -binitfini:libdyninstAPI_RT_init
133 * Solaris: ld with -z initarray=libdyninstAPI_RT_init
134 * Linux: ld with -init libdyninstAPI_RT_init
135 * gcc with -Wl,-init -Wl,...
137 void DYNINSTinit(int cause, int pid, int maxthreads)
139 int calledByFork = 0, calledByAttach = 0;
142 tc_lock_init(&DYNINST_trace_lock);
143 DYNINST_mutatorPid = pid;
150 calledByFork = (cause == 2);
151 calledByAttach = (cause == 3);
152 DYNINSThasInitialized = 1;
153 DYNINST_max_num_threads = maxthreads;
156 assert(sizeof(int64_t) == 8);
157 assert(sizeof(int32_t) == 4);
159 RTprintf("%s\n", V_libdyninstAPI_RT);
160 initTrampGuards(DYNINST_max_num_threads);
162 #if defined(cap_async_events)
163 DYNINSTasyncConnect(DYNINST_mutatorPid);
165 DYNINSTos_init(calledByFork, calledByAttach);
166 DYNINST_initialize_index_list();
169 DYNINST_bootstrap_info.pid = dyn_pid_self();
170 DYNINST_bootstrap_info.ppid = pid;
171 DYNINST_bootstrap_info.event = cause;
176 * Does what it's called. Used by the paradyn daemon as a default in certain
177 * cases (MT in particular)
179 int DYNINSTreturnZero()
184 /* Used to instrument (and report) the entry of fork */
185 void DYNINST_instForkEntry() {
186 /* Set the state so the mutator knows what's up */
187 DYNINST_synch_event_id = DSE_forkEntry;
188 DYNINST_synch_event_arg1 = NULL;
191 /* Once the stop completes, clean up */
192 DYNINST_synch_event_id = DSE_undefined;
193 DYNINST_synch_event_arg1 = NULL;
197 /* Used to instrument (and report) the exit of fork */
198 void DYNINST_instForkExit(void *arg1) {
199 /* Set the state so the mutator knows what's up */
200 DYNINST_synch_event_id = DSE_forkExit;
201 DYNINST_synch_event_arg1 = arg1;
204 /* Once the stop completes, clean up */
205 DYNINST_synch_event_id = DSE_undefined;
206 DYNINST_synch_event_arg1 = NULL;
210 /* Used to instrument (and report) the entry of exec */
211 void DYNINST_instExecEntry(void *arg1) {
212 /* Set the state so the mutator knows what's up */
213 DYNINST_synch_event_id = DSE_execEntry;
214 DYNINST_synch_event_arg1 = arg1;
217 /* Once the stop completes, clean up */
218 DYNINST_synch_event_id = DSE_undefined;
219 DYNINST_synch_event_arg1 = NULL;
223 /* Used to instrument (and report) the exit of exec */
224 void DYNINST_instExecExit(void *arg1) {
225 /* Set the state so the mutator knows what's up */
226 DYNINST_synch_event_id = DSE_execExit;
227 DYNINST_synch_event_arg1 = arg1;
230 /* Once the stop completes, clean up */
231 DYNINST_synch_event_id = DSE_undefined;
232 DYNINST_synch_event_arg1 = NULL;
236 /* Used to instrument (and report) the entry of exit */
237 void DYNINST_instExitEntry(void *arg1) {
238 /* Set the state so the mutator knows what's up */
239 DYNINST_synch_event_id = DSE_exitEntry;
240 DYNINST_synch_event_arg1 = arg1;
243 /* Once the stop completes, clean up */
244 DYNINST_synch_event_id = DSE_undefined;
245 DYNINST_synch_event_arg1 = NULL;
248 /* Used to instrument (and report) the entry of exit */
249 void DYNINST_instLoadLibrary(void *arg1) {
250 /* Set the state so the mutator knows what's up */
251 DYNINST_synch_event_id = DSE_loadLibrary;
252 DYNINST_synch_event_arg1 = arg1;
255 /* Once the stop completes, clean up */
256 DYNINST_synch_event_id = DSE_undefined;
257 DYNINST_synch_event_arg1 = NULL;
261 * Used to report addresses of functions called at dynamic call sites
263 int DYNINSTasyncDynFuncCall (void * call_target, void *call_addr)
267 rtBPatch_asyncEventRecord ev;
268 BPatch_dynamicCallRecord call_ev;
270 result = tc_lock_lock(&DYNINST_trace_lock);
271 if (result == DYNINST_DEAD_LOCK)
273 fprintf(stderr, "[%s:%d] - Error in libdyninstAPI_RT: trace pipe deadlock\n",
278 ev.type = rtBPatch_dynamicCallEvent;
279 ev.pid = dyn_pid_self();
280 err = DYNINSTwriteEvent((void *) &ev, sizeof(rtBPatch_asyncEventRecord));
283 fprintf(stderr, "%s[%d]: write error\n",
288 call_ev.call_site_addr = call_addr;
289 call_ev.call_target = call_target;
290 err = DYNINSTwriteEvent((void *) &call_ev, sizeof(BPatch_dynamicCallRecord));
293 fprintf(stderr, "%s[%d]: write error\n",
299 tc_lock_unlock(&DYNINST_trace_lock);
303 int DYNINSTuserMessage(void *msg, unsigned int msg_size)
306 rtBPatch_asyncEventRecord ev;
308 result = tc_lock_lock(&DYNINST_trace_lock);
309 if (result == DYNINST_DEAD_LOCK)
311 fprintf(stderr, "[%s:%d] - Error in libdyninstAPI_RT: trace pipe deadlock\n",
316 ev.type = rtBPatch_userEvent;
317 ev.pid = dyn_pid_self();
319 err = DYNINSTwriteEvent((void *) &ev, sizeof(rtBPatch_asyncEventRecord));
322 fprintf(stderr, "%s[%d]: write error\n",
327 err = DYNINSTwriteEvent(msg, msg_size);
330 fprintf(stderr, "%s[%d]: write error\n",
336 tc_lock_unlock(&DYNINST_trace_lock);
340 int tc_lock_init(tc_lock_t *t)
343 t->tid = (dyntid_t) -1;
347 int tc_lock_unlock(tc_lock_t *t)
350 t->tid = (dyntid_t) -1;
354 int tc_lock_destroy(tc_lock_t *t)
357 t->tid = (dyntid_t) -1;
361 void dyninst_init_lock(dyninst_lock_t *lock)
364 lock->tid = (dyntid_t) -1;
367 void dyninst_free_lock(dyninst_lock_t *lock)
371 int dyninst_lock(dyninst_lock_t *lock)
373 return tc_lock_lock(lock);
376 void dyninst_unlock(dyninst_lock_t *lock)
378 tc_lock_unlock(lock);
381 unsigned dyninst_maxNumOfThreads()
383 #if !defined(cap_threads)
386 if (!DYNINSThasInitialized)
388 if (!DYNINST_multithread_capable)
390 return DYNINST_max_num_threads;