rebased to master after sw 3rd party completed
[dyninst.git] / dyninstAPI_RT / src / RTlinux.c
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 /************************************************************************
32  * $Id: RTlinux.c,v 1.54 2008/04/11 23:30:44 legendre Exp $
33  * RTlinux.c: mutatee-side library function specific to Linux
34  ************************************************************************/
35
36 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
37 #include "dyninstAPI_RT/src/RTthread.h"
38 #include "dyninstAPI_RT/src/RTcommon.h"
39 #include <assert.h>
40 #include <stdio.h>
41 #include <errno.h>
42 #include <unistd.h>
43
44 #if !defined(DYNINST_RT_STATIC_LIB)
45 #include <dlfcn.h>
46 #endif
47
48 #include <sys/types.h>
49 #include <sys/syscall.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <sys/mman.h>
54 #include <link.h>
55
56 #if defined(DYNINST_RT_STATIC_LIB)
57 /*
58  * The weak symbol here removes the dependence of the static version of this
59  * library on pthread_self. If pthread_self is available, then it will be
60  * linked.  Otherwise, the linker will ignore it.
61  */
62 #pragma weak pthread_self
63 extern pthread_t pthread_self(void);
64 #else
65 #include <pthread.h>
66 #endif
67
68 extern double DYNINSTstaticHeap_512K_lowmemHeap_1[];
69 extern double DYNINSTstaticHeap_16M_anyHeap_1[];
70 extern unsigned long sizeOfLowMemHeap1;
71 extern unsigned long sizeOfAnyHeap1;
72
73 static struct trap_mapping_header *getStaticTrapMap(unsigned long addr);
74
75 #if defined(arch_power) && defined(arch_64bit) && defined(os_linux)
76 unsigned long DYNINSTlinkSave;
77 unsigned long DYNINSTtocSave;
78 #endif
79
80 /************************************************************************
81  * void DYNINSTbreakPoint(void)
82  *
83  * stop oneself.
84 ************************************************************************/
85
86 #ifndef SYS_tkill
87 #define SYS_tkill 238
88 #endif
89
90 int t_kill(int pid, int sig) {
91     static int has_tkill = 1;
92     long int result = 0;
93     if (has_tkill) {
94         result = syscall(SYS_tkill, pid, sig);
95         if (result == -1 && errno == ENOSYS) {
96             has_tkill = 0;
97         }
98     }
99     if (!has_tkill) {
100         result = kill(pid, sig);
101     }
102
103     return (result == 0);
104 }
105
106 void DYNINSTbreakPoint()
107 {
108    /* We set a global flag here so that we can tell
109       if we're ever in a call to this when we get a
110       SIGBUS */
111    if (DYNINSTstaticMode)
112       return;
113
114    DYNINST_break_point_event = 1;
115    while (DYNINST_break_point_event)  {
116       t_kill(dyn_lwp_self(), DYNINST_BREAKPOINT_SIGNUM);
117    }
118    /* Mutator resets to 0... */
119 }
120
121 static int failed_breakpoint = 0;
122 void uncaught_breakpoint(int sig)
123 {
124    (void)sig; /* unused parameter */
125    failed_breakpoint = 1;
126 }
127
128 void DYNINSTlinuxBreakPoint()
129 {
130    struct sigaction act, oldact;
131    int result;
132
133    if (DYNINSTstaticMode)
134       return;
135
136    memset(&oldact, 0, sizeof(struct sigaction));
137    memset(&act, 0, sizeof(struct sigaction));
138
139    result = sigaction(DYNINST_BREAKPOINT_SIGNUM, NULL, &act);
140    if (result == -1) {
141       perror("DyninstRT library failed sigaction1");
142       return;
143    }
144    act.sa_handler = uncaught_breakpoint;
145
146    result = sigaction(DYNINST_BREAKPOINT_SIGNUM, &act, &oldact);
147    if (result == -1) {
148       perror("DyninstRT library failed sigaction2");
149       return;
150    }
151
152    DYNINST_break_point_event = 1;
153    failed_breakpoint = 0;
154    kill(dyn_lwp_self(), DYNINST_BREAKPOINT_SIGNUM);
155    if (failed_breakpoint) {
156       DYNINST_break_point_event = 0;
157       failed_breakpoint = 0;
158    }
159
160    result = sigaction(DYNINST_BREAKPOINT_SIGNUM, &oldact, NULL);
161    if (result == -1) {
162       perror("DyninstRT library failed sigaction3");
163       return;
164    }
165 }
166
167 void DYNINSTsafeBreakPoint()
168 {
169    if (DYNINSTstaticMode)
170       return;
171
172     DYNINST_break_point_event = 2; /* Not the same as above */
173     //    while (DYNINST_break_point_event)
174     kill(dyn_lwp_self(), SIGSTOP);
175 }
176
177 void mark_heaps_exec() {
178         /* Grab the page size, to align the heap pointer. */
179         long int pageSize = sysconf( _SC_PAGESIZE );
180         if( pageSize == 0 || pageSize == - 1 ) {
181                 fprintf( stderr, "*** Failed to obtain page size, guessing 16K.\n" );
182                 perror( "mark_heaps_exec" );
183                 pageSize = 1024 * 16;
184                 } /* end pageSize initialization */
185
186         /* Align the heap pointer. */
187         unsigned long int alignedHeapPointer = (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1;
188         alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1);
189         unsigned long int adjustedSize = (unsigned long int) DYNINSTstaticHeap_16M_anyHeap_1 - alignedHeapPointer + sizeOfAnyHeap1;
190
191         /* Make the heap's page executable. */
192         int result = mprotect( (void *) alignedHeapPointer, (size_t) adjustedSize, PROT_READ | PROT_WRITE | PROT_EXEC );
193         if( result != 0 ) {
194                 fprintf( stderr, "%s[%d]: Couldn't make DYNINSTstaticHeap_16M_anyHeap_1 executable!\n", __FILE__, __LINE__);
195                 perror( "mark_heaps_exec" );
196                 }
197         RTprintf( "*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, alignedHeapPointer + adjustedSize );
198
199         /* Mark _both_ heaps executable. */
200         alignedHeapPointer = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1;
201         alignedHeapPointer = (alignedHeapPointer) & ~(pageSize - 1);
202         adjustedSize = (unsigned long int) DYNINSTstaticHeap_512K_lowmemHeap_1 - alignedHeapPointer + sizeOfLowMemHeap1;
203
204         /* Make the heap's page executable. */
205         result = mprotect( (void *) alignedHeapPointer, (size_t) adjustedSize, PROT_READ | PROT_WRITE | PROT_EXEC );
206         if( result != 0 ) {
207                 fprintf( stderr, "%s[%d]: Couldn't make DYNINSTstaticHeap_512K_lowmemHeap_1 executable!\n", __FILE__, __LINE__ );
208                 perror( "mark_heaps_exec" );
209                 }
210         RTprintf( "*** Marked memory from 0x%lx to 0x%lx executable.\n", alignedHeapPointer, alignedHeapPointer + adjustedSize );
211         } /* end mark_heaps_exec() */
212
213 /************************************************************************
214  * void DYNINSTos_init(void)
215  *
216  * OS initialization function
217 ************************************************************************/
218 int DYNINST_sysEntry;
219
220 #if !defined(DYNINST_RT_STATIC_LIB)
221 /*
222  * For now, removing dependence of static version of this library
223  * on libdl.
224  */
225 typedef struct dlopen_args {
226   const char *libname;
227   int mode;
228   void *result;
229   void *caller;
230 } dlopen_args_t;
231
232 void *(*DYNINST_do_dlopen)(dlopen_args_t *) = NULL;
233
234 static int get_dlopen_error() {
235    char *err_str;
236    err_str = dlerror();
237    if (err_str) {
238       strncpy(gLoadLibraryErrorString, err_str, (size_t) ERROR_STRING_LENGTH);
239       return 1;
240    }
241    else {
242       sprintf(gLoadLibraryErrorString,"unknown error with dlopen");
243       return 0;
244    }
245    return 0;
246 }
247
248 int DYNINSTloadLibrary(char *libname)
249 {
250    void *res;
251    gLoadLibraryErrorString[0]='\0';
252    res = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
253    if (res)
254    {
255       return 1;
256    }
257
258    get_dlopen_error();
259 #if defined(arch_x86)
260    /* dlopen on recent glibcs has a "security check" so that
261       only registered modules can call it. Unfortunately, progs
262       that don't include libdl break this check, so that we
263       can only call _dl_open (the dlopen worker function) from
264       within glibc. We do this by calling do_dlopen
265       We fool this check by calling an addr written by the
266       mutator */
267    if (strstr(gLoadLibraryErrorString, "invalid caller") != NULL &&
268        DYNINST_do_dlopen != NULL) {
269       dlopen_args_t args;
270       args.libname = libname;
271       args.mode = RTLD_NOW | RTLD_GLOBAL;
272       args.result = 0;
273       args.caller = (void *)DYNINST_do_dlopen;
274       // There's a do_dlopen function in glibc. However, it's _not_
275       // exported; thus, getting the address is a bit of a pain.
276
277       (*DYNINST_do_dlopen)(&args);
278       // Duplicate the above
279       if (args.result != NULL)
280       {
281          return 1;
282       }
283       else
284          get_dlopen_error();
285    }
286 #endif
287    return 0;
288 }
289 #endif
290
291 //Define this value so that we can compile on a system that doesn't have
292 // gettid and still run on one that does.
293 #if !defined(SYS_gettid)
294
295 #if defined(arch_x86)
296 #define SYS_gettid 224
297 #elif defined(arch_x86_64)
298 #define SYS_gettid 186
299 #endif
300
301 #endif
302
303 int dyn_lwp_self()
304 {
305    static int gettid_not_valid = 0;
306    int result;
307
308    if (gettid_not_valid)
309       return getpid();
310
311    result = syscall((long int) SYS_gettid);
312    if (result == -1 && errno == ENOSYS)
313    {
314       gettid_not_valid = 1;
315       return getpid();
316    }
317    return result;
318 }
319
320 int dyn_pid_self()
321 {
322    return getpid();
323 }
324
325 dyntid_t (*DYNINST_pthread_self)(void);
326
327 dyntid_t dyn_pthread_self()
328 {
329    dyntid_t me;
330    if (DYNINSTstaticMode) {
331 #if defined(DYNINST_RT_STATIC_LIB)
332        /* This special case is necessary because the static
333         * version of libc doesn't define a version of pthread_self
334         * unlike the shared version of the library.
335         */
336        if( !pthread_self ) {
337            return (dyntid_t) DYNINST_SINGLETHREADED;
338        }
339 #endif
340       return (dyntid_t) pthread_self();
341    }
342    if (!DYNINST_pthread_self) {
343       return (dyntid_t) DYNINST_SINGLETHREADED;
344    }
345    me = (*DYNINST_pthread_self)();
346    return (dyntid_t) me;
347 }
348
349 /*
350    We reserve index 0 for the initial thread. This value varies by
351    platform but is always constant for that platform. Wrap that
352    platform-ness here.
353 */
354 int DYNINST_am_initial_thread( dyntid_t tid ) {
355         (void)tid; /* unused parameter */
356         if( dyn_lwp_self() == getpid() ) {
357                 return 1;
358    }
359         return 0;
360 } /* end DYNINST_am_initial_thread() */
361
362 #if defined(cap_mutatee_traps)
363
364 #include <ucontext.h>
365
366 // Register numbers experimentally verified
367
368 #if defined(arch_x86)
369   #define UC_PC(x) x->uc_mcontext.gregs[14]
370 #elif defined(arch_x86_64)
371   #if defined(MUTATEE_32)
372     #define UC_PC(x) x->uc_mcontext.gregs[14]
373   #else // 64-bit
374     #define UC_PC(x) x->uc_mcontext.gregs[16]
375   #endif // amd-64
376 #elif defined(arch_power)
377   #if defined(arch_64bit)
378     #define UC_PC(x) x->uc_mcontext.regs->gpr[32]
379   #else // 32-bit
380     #define UC_PC(x) x->uc_mcontext.uc_regs->gregs[32]
381   #endif // power
382 #elif defined(arch_aarch64)
383         //#warning "UC_PC: in aarch64, pc is not directly accessable."
384         //aarch64 pc is not one of 31 GPRs, but an independent reg
385         #define UC_PC(x) x->uc_mcontext.pc
386 #endif // UC_PC
387
388 extern volatile unsigned long dyninstTrapTableUsed;
389 extern volatile unsigned long dyninstTrapTableVersion;
390 extern volatile trapMapping_t *dyninstTrapTable;
391 extern volatile unsigned long dyninstTrapTableIsSorted;
392
393 /**
394  * This comment is now obsolete, left for historic purposes
395  *
396  * Called by the SIGTRAP handler, dyninstTrapHandler.  This function is
397  * closly intwined with dyninstTrapHandler, don't modify one without
398  * understanding the other.
399  *
400  * This function sets up the calling context that was passed to the
401  * SIGTRAP handler so that control will be redirected to our instrumentation
402  * when we do the setcontext call.
403  *
404  * There are a couple things that make this more difficult than it should be:
405  *   1. The OS provided calling context is similar to the GLIBC calling context,
406  *      but not compatible.  We'll create a new GLIBC compatible context and
407  *      copy the possibly stomped registers from the OS context into it.  The
408  *      incompatiblities seem to deal with FP and other special purpose registers.
409  *   2. setcontext doesn't restore the flags register.  Thus dyninstTrapHandler
410  *      will save the flags register first thing and pass us its value in the
411  *      flags parameter.  We'll then push the instrumentation entry and flags
412  *      onto the context's stack.  Instead of transfering control straight to the
413  *      instrumentation, we'll actually go back to dyninstTrapHandler, which will
414  *      do a popf/ret to restore flags and go to instrumentation.  The 'retPoint'
415  *      parameter is the address in dyninstTrapHandler the popf/ret can be found.
416  **/
417
418 void dyninstTrapHandler(int sig, siginfo_t *sg, ucontext_t *context)
419 {
420    void *orig_ip;
421    void *trap_to;
422    (void)sig; /* unused parameter */
423    (void)sg; /* unused parameter */
424
425    orig_ip = (void *) UC_PC(context);
426    assert(orig_ip);
427    // Find the new IP we're going to and substitute. Leave everything else untouched.
428    if (DYNINSTstaticMode) {
429       unsigned long zero = 0;
430       unsigned long one = 1;
431       struct trap_mapping_header *hdr = getStaticTrapMap((unsigned long) orig_ip);
432       assert(hdr);
433       volatile trapMapping_t *mapping = &(hdr->traps[0]);
434       trap_to = dyninstTrapTranslate(orig_ip,
435                                      (unsigned long *) &hdr->num_entries,
436                                      &zero,
437                                      &mapping,
438                                      &one);
439    }
440    else {
441       trap_to = dyninstTrapTranslate(orig_ip,
442                                      &dyninstTrapTableUsed,
443                                      &dyninstTrapTableVersion,
444                                      &dyninstTrapTable,
445                                      &dyninstTrapTableIsSorted);
446
447    }
448    UC_PC(context) = (long) trap_to;
449 }
450
451 #if defined(cap_binary_rewriter)
452
453 extern struct r_debug _r_debug;
454 DLLEXPORT struct r_debug _r_debug __attribute__ ((weak));
455
456 /* Verify that the r_debug variable is visible */
457 void r_debugCheck() { assert(_r_debug.r_map); }
458
459 #define NUM_LIBRARIES 512 //Important, max number of rewritten libraries
460
461 #define WORD_SIZE (8 * sizeof(unsigned))
462 #define NUM_LIBRARIES_BITMASK_SIZE (1 + NUM_LIBRARIES / WORD_SIZE)
463 struct trap_mapping_header *all_headers[NUM_LIBRARIES];
464
465 static unsigned all_headers_current[NUM_LIBRARIES_BITMASK_SIZE];
466 static unsigned all_headers_last[NUM_LIBRARIES_BITMASK_SIZE];
467
468 #if !defined(arch_x86_64) || defined(MUTATEE_32)
469 typedef Elf32_Dyn ElfX_Dyn;
470 #else
471 typedef Elf64_Dyn ElfX_Dyn;
472 #endif
473
474 struct trap_mapping_header *getStaticTrapMap(unsigned long addr);
475
476 static int parse_libs();
477 static int parse_link_map(struct link_map *l);
478 static void clear_unloaded_libs();
479
480 static void set_bit(unsigned *bit_mask, int bit, char value);
481 //static char get_bit(unsigned *bit_mask, int bit);
482 static void clear_bitmask(unsigned *bit_mask);
483 static unsigned get_next_free_bitmask(unsigned *bit_mask, int last_pos);
484 static unsigned get_next_set_bitmask(unsigned *bit_mask, int last_pos);
485
486 static tc_lock_t trap_mapping_lock;
487
488 static struct trap_mapping_header *getStaticTrapMap(unsigned long addr)
489 {
490 #if !defined (arch_aarch64)
491    struct trap_mapping_header *header;
492    int i;
493
494    tc_lock_lock(&trap_mapping_lock);
495    parse_libs();
496
497    i = -1;
498    for (;;) {
499       i = get_next_set_bitmask(all_headers_current, i);
500       assert(i >= 0 && i <= NUM_LIBRARIES);
501       if (i == NUM_LIBRARIES) {
502          header = NULL;
503          rtdebug_printf("%s[%d]:  getStaticTrapMap: returning NULL\n", __FILE__, __LINE__);
504          goto done;
505       }
506       header = all_headers[i];
507       if (addr >= header->low_entry && addr <= header->high_entry) {
508          goto done;
509       }
510    }
511  done:
512    tc_lock_unlock(&trap_mapping_lock);
513    return header;
514 #else
515         assert(0);
516         return NULL;
517 #endif
518 }
519
520 static int parse_libs()
521 {
522    struct link_map *l_current;
523
524    l_current = _r_debug.r_map;
525    if (!l_current) {
526         rtdebug_printf("%s[%d]:  parse_libs: _r_debug.r_map was not set\n", __FILE__, __LINE__);
527        return -1;
528    }
529
530    clear_bitmask(all_headers_current);
531    while (l_current) {
532       parse_link_map(l_current);
533       l_current = l_current->l_next;
534    }
535    clear_unloaded_libs();
536
537    return 0;
538 }
539
540 //parse_link_map return values
541 #define PARSED 0
542 #define NOT_REWRITTEN 1
543 #define ALREADY_PARSED 2
544 #define ERROR_INTERNAL -1
545 #define ERROR_FULL -2
546 static int parse_link_map(struct link_map *l)
547 {
548    ElfX_Dyn *dynamic_ptr;
549    struct trap_mapping_header *header;
550    unsigned int i, new_pos;
551
552    dynamic_ptr = (ElfX_Dyn *) l->l_ld;
553    if (!dynamic_ptr)
554       return -1;
555
556    assert(sizeof(dynamic_ptr->d_un.d_ptr) == sizeof(void *));
557    for (; dynamic_ptr->d_tag != DT_NULL && dynamic_ptr->d_tag != DT_DYNINST; dynamic_ptr++);
558    if (dynamic_ptr->d_tag == DT_NULL) {
559       return NOT_REWRITTEN;
560    }
561
562    header = (struct trap_mapping_header *) (dynamic_ptr->d_un.d_val + l->l_addr);
563
564    if (header->signature != TRAP_HEADER_SIG)
565       return ERROR_INTERNAL;
566    if (header->pos != -1) {
567       set_bit(all_headers_current, header->pos, 1);
568       assert(all_headers[header->pos] == header);
569       return ALREADY_PARSED;
570    }
571
572    for (i = 0; i < header->num_entries; i++)
573    {
574       header->traps[i].source = (void *) (((unsigned long) header->traps[i].source) + l->l_addr);
575       header->traps[i].target = (void *) (((unsigned long) header->traps[i].target) + l->l_addr);
576       if (!header->low_entry || header->low_entry > (unsigned long) header->traps[i].source)
577          header->low_entry = (unsigned long) header->traps[i].source;
578       if (!header->high_entry || header->high_entry < (unsigned long) header->traps[i].source)
579          header->high_entry = (unsigned long) header->traps[i].source;
580    }
581
582    new_pos = get_next_free_bitmask(all_headers_last, -1);
583    assert(new_pos < NUM_LIBRARIES);
584    if (new_pos == NUM_LIBRARIES)
585       return ERROR_FULL;
586
587    header->pos = new_pos;
588    all_headers[new_pos] = header;
589    set_bit(all_headers_current, new_pos, 1);
590    set_bit(all_headers_last, new_pos, 1);
591
592    return PARSED;
593 }
594
595 static void clear_unloaded_libs()
596 {
597    unsigned i;
598    for (i = 0; i<NUM_LIBRARIES_BITMASK_SIZE; i++)
599    {
600       all_headers_last[i] = all_headers_current[i];
601    }
602 }
603
604 static void set_bit(unsigned *bit_mask, int bit, char value) {
605    assert(bit < NUM_LIBRARIES);
606    unsigned *word = bit_mask + bit / WORD_SIZE;
607    unsigned shift = bit % WORD_SIZE;
608    if (value) {
609       *word |= (1 << shift);
610    }
611    else {
612       *word &= ~(1 << shift);
613    }
614 }
615
616 //Wasn't actually needed
617 /*
618 static char get_bit(unsigned *bit_mask, int bit) {
619    assert(bit < NUM_LIBRARIES);
620    unsigned *word = bit_mask + bit / WORD_SIZE;
621    unsigned shift = bit % WORD_SIZE;
622    return (*word & (1 << shift)) ? 1 : 0;
623 }
624 */
625
626 static void clear_bitmask(unsigned *bit_mask) {
627    unsigned i;
628    for (i = 0; i < NUM_LIBRARIES_BITMASK_SIZE; i++) {
629       bit_mask[i] = 0;
630    }
631 }
632
633 static unsigned get_next_free_bitmask(unsigned *bit_mask, int last_pos) {
634    unsigned i, j;
635    j = last_pos+1;
636    i = j / WORD_SIZE;
637    for (; j < NUM_LIBRARIES; i++) {
638       if (bit_mask[i] == (unsigned) -1) {
639          j += WORD_SIZE;
640          continue;
641       }
642       for (;;) {
643          if (!((1 << (j % WORD_SIZE) & bit_mask[i]))) {
644             return j;
645          }
646          j++;
647          if (j % WORD_SIZE == 0) {
648             break;
649          }
650       }
651    }
652    return NUM_LIBRARIES;
653 }
654
655 static unsigned get_next_set_bitmask(unsigned *bit_mask, int last_pos) {
656    unsigned i, j;
657    j = last_pos+1;
658    i = j / WORD_SIZE;
659    for (; j < NUM_LIBRARIES; i++) {
660       if (bit_mask[i] == (unsigned) 0) {
661          j += WORD_SIZE;
662          continue;
663       }
664       for (;;) {
665          if ((1 << (j % WORD_SIZE) & bit_mask[i])) {
666             return j;
667          }
668          j++;
669          if (j % WORD_SIZE == 0) {
670             break;
671          }
672       }
673    }
674    return NUM_LIBRARIES;
675 }
676
677 #endif
678
679
680
681 #endif /* cap_mutatee_traps */
682
683 #if defined(cap_binary_rewriter) && !defined(DYNINST_RT_STATIC_LIB)
684 /* For a static binary, all global constructors are combined in an undefined
685  * order. Also, DYNINSTBaseInit must be run after all global constructors have
686  * been run. Since the order of global constructors is undefined, DYNINSTBaseInit
687  * cannot be run as a constructor in static binaries. Instead, it is run from a
688  * special constructor handler that processes all the global constructors in
689  * the binary. Leaving this code in would create a global constructor for the
690  * function runDYNINSTBaseInit(). See DYNINSTglobal_ctors_handler.
691  */
692 extern void r_debugCheck();
693 extern void DYNINSTBaseInit();
694 void runDYNINSTBaseInit() __attribute__((constructor));
695 void runDYNINSTBaseInit()
696 {
697     r_debugCheck();
698    DYNINSTBaseInit();
699 }
700 #endif
701
702
703 /*
704 //Small program for finding the correct values to fill in pos_in_pthreadt
705 // above
706 #include <pthread.h>
707 #include <stdio.h>
708 #include <sys/syscall.h>
709 #include <sys/types.h>
710 #include <unistd.h>
711
712 #define gettid() syscall(SYS_gettid)
713
714 pthread_attr_t attr;
715
716 void *foo(void *f) {
717   pid_t pid, tid;
718   unsigned stack_addr;
719   unsigned best_stack = 0xffffffff;
720   int best_stack_pos = 0;
721   void *start_func;
722   int *p;
723   int i = 0;
724   pid = getpid();
725   tid = gettid();
726   start_func = foo;
727   //x86 only.
728   asm("movl %%ebp,%0" : "=r" (stack_addr));
729   p = (int *) pthread_self();
730   while (i < 1000)
731   {
732     if (*p == (unsigned) pid)
733       printf("pid @ %d\n", i);
734     if (*p == (unsigned) tid)
735       printf("lwp @ %d\n", i);
736     if (*p > stack_addr && *p < best_stack)
737     {
738       best_stack = *p;
739       best_stack_pos = i;
740     }
741     if (*p == (unsigned) start_func)
742       printf("func @ %d\n", i);
743     i += sizeof(int);
744     p++;
745   }
746   printf("stack @ %d\n", best_stack_pos);
747   return NULL;
748 }
749
750 int main(int argc, char *argv[])
751 {
752   pthread_t t;
753   void *result;
754   pthread_attr_init(&attr);
755   pthread_create(&t, &attr, foo, NULL);
756   pthread_join(t, &result);
757   return 0;
758 }
759 */
760