- Changed to call PTRACE_TRACEME in DYNINSTos_init
[dyninst.git] / dyninstAPI_RT / src / RTlinux.c
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
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.
10  * 
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.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
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.
29  * 
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.
40  */
41
42 /************************************************************************
43  * RTlinux.c: mutatee-side library function specific to Linux
44 ************************************************************************/
45
46 #include <signal.h>
47 #include <assert.h>
48 #include <stdio.h>
49 #include <dlfcn.h>
50
51 #include <sys/ptrace.h>
52
53 #include "dyninstAPI_RT/h/rtinst.h"
54
55 /************************************************************************
56  * void DYNINSTos_init(void)
57  *
58  * os initialization function
59 ************************************************************************/
60
61 void DYNINSTtrapHandler(int sig, struct sigcontext uap );
62
63 void
64 DYNINSTos_init(int calledByFork, int calledByAttach)
65 {
66     /*
67        Install trap handler.
68        This is currently being used only on the x86 platform.
69     */
70     
71     struct sigaction act;
72     act.sa_handler = (void(*)(int))DYNINSTtrapHandler;
73     act.sa_flags = 0;
74     sigfillset(&act.sa_mask);
75     if (sigaction(SIGTRAP, &act, 0) != 0) {
76         perror("sigaction(SIGTRAP)");
77         assert(0);
78         abort();
79     }
80     
81     ptrace( PTRACE_TRACEME, 0, 0, 0 );
82 }
83
84
85 \f
86
87
88 /****************************************************************************
89    The trap handler. Currently being used only on x86 platform.
90
91    Traps are used when we can't insert a jump at a point. The trap
92    handler looks up the address of the base tramp for the point that
93    uses the trap, and set the pc to this base tramp.
94    The paradynd is responsible for updating the tramp table when it
95    inserts instrumentation.
96 *****************************************************************************/
97
98 trampTableEntry DYNINSTtrampTable[TRAMPTABLESZ];
99 unsigned DYNINSTtotalTraps = 0;
100
101 static unsigned lookup(unsigned key) {
102     unsigned u;
103     unsigned k;
104     for (u = HASH1(key); 1; u = (u + HASH2(key)) % TRAMPTABLESZ) {
105       k = DYNINSTtrampTable[u].key;
106       if (k == 0)
107         return 0;
108       else if (k == key)
109         return DYNINSTtrampTable[u].val;
110     }
111     /* not reached */
112     assert(0);
113     abort();
114 }
115
116 void DYNINSTtrapHandler(int sig, struct sigcontext uap ) {
117     unsigned pc = uap.eip;
118     unsigned nextpc = lookup(pc);
119
120     if (!nextpc) {
121       /* kludge: maybe the PC was not automatically adjusted after the trap */
122       /* this happens for a forked process */
123       pc--;
124       nextpc = lookup(pc);
125     }
126
127     if (nextpc) {
128                 /* WARNING -- Remove before using in real use, it could KILL anything
129                    that instruments libc */
130                 /*fprintf( stderr, "DYNINST trap %#.8x -> %#.8x\n", pc, nextpc );*/
131       uap.eip = nextpc;
132     } else {
133       assert(0);
134       abort();
135     }
136     DYNINSTtotalTraps++;
137 }
138
139 int DYNINSTloadLibrary(char *libname)
140 {
141     if (dlopen(libname, RTLD_NOW | RTLD_GLOBAL) != NULL)
142         return 1;
143     else 
144         return 0;
145 }