Changed to fork for paradyndPVM since client calls pvmendtask which writes
[dyninst.git] / dyninstAPI / src / process.C
1 /*
2  *  Copyright 1993 Jeff Hollingsworth.  All rights reserved.
3  *
4  */
5
6 #ifndef lint
7 static char Copyright[] = "@(#) Copyright (c) 1993 Jeff Hollingsowrth\
8     All rights reserved.";
9
10 static char rcsid[] = "@(#) $Header: /home/jaw/CVSROOT_20081103/CVSROOT/core/dyninstAPI/src/process.C,v 1.5 1994/03/31 02:00:35 markc Exp $";
11 #endif
12
13 /*
14  * process.C - Code to control a process.
15  *
16  * $Log: process.C,v $
17  * Revision 1.5  1994/03/31 02:00:35  markc
18  * Changed to fork for paradyndPVM since client calls pvmendtask which writes
19  * to the address space.
20  *
21  * Revision 1.4  1994/03/22  21:03:15  hollings
22  * Made it possible to add new processes (& paradynd's) via addExecutable.
23  *
24  * Revision 1.3  1994/03/20  01:53:11  markc
25  * Added a buffer to each process structure to allow for multiple writers on the
26  * traceStream.  Replaced old inst-pvm.C.  Changed addProcess to return type
27  * int.
28  *
29  * Revision 1.2  1994/02/05  23:09:56  hollings
30  * Added extern for sys_errlist[] (g++ version 2.5.7).
31  *
32  * Revision 1.1  1994/01/27  20:31:38  hollings
33  * Iinital version of paradynd speaking dynRPC igend protocol.
34  *
35  * Revision 1.8  1993/10/04  21:38:41  hollings
36  * round inferrior mallocs to cache line size.
37  *
38  * Revision 1.7  1993/08/23  23:15:25  hollings
39  * added code to third parameter to findInternalAddress calls.
40  *
41  * Revision 1.6  1993/08/11  01:47:09  hollings
42  * added copyInferrior heap for UNIX fork.
43  *
44  * Revision 1.5  1993/07/13  18:29:38  hollings
45  * new include file syntax.
46  *
47  * Revision 1.4  1993/06/28  23:13:18  hollings
48  * fixed process stopping.
49  *
50  * Revision 1.3  1993/06/22  19:00:01  hollings
51  * global inst state.
52  *
53  * Revision 1.2  1993/06/08  20:14:34  hollings
54  * state prior to bc net ptrace replacement.
55  *
56  * Revision 1.1  1993/03/19  22:45:45  hollings
57  * Initial revision
58  *
59  *
60  */
61
62 #include <assert.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <unistd.h>
66 #include <sys/socket.h>
67 #include <sys/param.h>
68 #include <sys/ptrace.h>
69 #include <errno.h>
70
71 #include "rtinst/h/rtinst.h"
72 #include "rtinst/h/trace.h"
73 #include "dyninst.h"
74 #include "symtab.h"
75 #include "process.h"
76 #include "util.h"
77
78 List<process*> processList;
79
80 extern char *sys_errlist[];
81
82 /* root of process resource list */
83 resource processResource;
84
85 extern "C" ptrace();
86
87 #define INFERRIOR_HEAP_BASE     "DYNINSTdata"
88 #define GLOBAL_HEAP_BASE        "DYNINSTglobalData"
89
90 void initInferiorHeap(process *proc, Boolean globalHeap)
91 {
92     assert(proc->symbols);
93
94     proc->heap = (freeListEntry*) xcalloc(sizeof(freeListEntry), 1);
95     if (globalHeap) {
96         proc->heap->addr = 
97             findInternalAddress(proc->symbols, GLOBAL_HEAP_BASE, True);
98     } else {
99         proc->heap->addr = 
100             findInternalAddress(proc->symbols, INFERRIOR_HEAP_BASE, True);
101     }
102     proc->heap->length = SYN_INST_BUF_SIZE;
103     proc->heap->next = NULL;
104     proc->status = HEAPfree;
105 }
106
107 void copyInferriorHeap(process *from, process *to)
108 {
109     freeListEntry *curr;
110     freeListEntry *newEntry;
111
112     assert(from->symbols);
113     assert(to->symbols);
114
115     to->heap = NULL;
116     /* copy individual elements */
117     for (curr=from->heap; curr; curr=curr->next) {
118         newEntry = (freeListEntry*) xcalloc(sizeof(freeListEntry), 1);
119         *newEntry = *curr;
120
121         /* setup next pointers */
122         newEntry->next = to->heap;
123         to->heap = newEntry;
124     }
125     to->status = HEAPfree;
126 }
127
128 int inferriorMalloc(process *proc, int size)
129 {
130     freeListEntry *newEntry;
131     freeListEntry *curr;
132
133     /* round to next cache line size */
134     /* 32 bytes on a SPARC */
135     size = (size + 0x1f) & ~0x1f; 
136     for (curr=proc->heap; curr; curr=curr->next) {
137         if ((curr->status == HEAPfree) && (curr->length >= size)) break;
138     }
139
140     if (!curr) {
141         printf("Inferrior heap overflow\n");
142         abort();
143     }
144
145     if (curr->length != size) {
146         newEntry = (freeListEntry *) xcalloc(sizeof(freeListEntry), 1);
147         newEntry->length = curr->length - size;
148         newEntry->addr = curr->addr + size;
149         newEntry->next = curr->next;
150         newEntry->status = HEAPfree;
151
152         /* now split curr */
153         curr->status = HEAPallocated;
154         curr->length = size;
155         curr->next = newEntry;
156     }
157     return(curr->addr);
158 }
159
160 void inferriorFree(process *proc, int pointer)
161 {
162 #ifdef notdef
163     freeListEntry *curr;
164
165     /* free is currently disabled because we can't handle the case of an
166      *  inst function being deleted while active.  Not freeing the memory means
167      *  it stil contains the tramp and will get itself out safely.
168      */
169
170     for (curr=proc->heap; curr; curr=curr->next) {
171         if (curr->addr == pointer) break;
172     }
173
174     if (!curr) {
175         printf("unable to find heap entry %x\n", pointer);
176         abort();
177     }
178
179     if (curr->status != HEAPallocated) {
180         printf("attempt to free already free heap entry %x\n", pointer);
181         abort();
182     }
183     curr->status = HEAPfree;
184 #endif
185 }
186
187 process *allocateProcess(int pid, char *name)
188 {
189     process *ret;
190
191     ret = (process *) xcalloc(sizeof(process), 1);
192     processList.add(ret, (void *) pid);
193
194     ret->pid = pid;
195     if (!processResource) {
196         processResource = newResource(rootResource, NULL, "Process", 0.0);
197     }
198     ret->rid = newResource(processResource, ret, name, 0.0);
199
200     ret->bufEnd = 0;
201     return(ret);
202 }
203
204 /*
205  * Create a new instance of the named process.  Read the symbols and start
206  *   the program
207  */
208 process *createProcess(char *file, char *argv[], int nenv, char *envp[])
209 {
210     int pid;
211     int r;
212     image *i;
213     process *ret;
214     char name[20];
215     int tracePipe[2];
216
217     r = socketpair(AF_UNIX, SOCK_STREAM, (int) NULL, tracePipe);
218     if (r) {
219         perror("socketpair");
220         return(NULL);
221     }
222     //
223     // WARNING This code assumes that vfork is used, and a failed exec will
224     //   corectly change failed in the parent process.
225     //
226     errno = 0;
227 #ifdef PARADYND_PVM
228 // must use fork, since pvmendtask will do some writing in the address space
229     pid = fork();
230 #else
231     pid = vfork();
232 #endif
233     if (pid > 0) {
234         if (errno) {
235             printf("Unable to start %s: %s\n", file, sys_errlist[errno]);
236             return(NULL);
237         }
238
239         i = parseImage(file, 0);
240         if (!i) return(NULL);
241
242         /* parent */
243         sprintf(name, "%s", i->name);
244         ret = allocateProcess(pid, name);
245         ret->symbols = i;
246         initInferiorHeap(ret, False);
247
248         ret->status = neonatal;
249         ret->traceLink = tracePipe[0];
250         close(tracePipe[1]);
251         return(ret);
252     } else if (pid == 0) {
253 #ifdef PARADYND_PVM
254         pvmendtask(); 
255 #endif   
256         close(tracePipe[0]);
257         if (dup2(tracePipe[1], 3) != 3)
258           {
259             fprintf (stderr, "dup2 failed\n");
260             abort();
261           }
262
263         /* close if higher */
264         if (tracePipe[1] > 3) close(tracePipe[1]);
265
266         /* indicate our desire to be trace */
267         errno = 0;
268         ptrace(0, 0, 0, 0);
269         if (errno != 0) {
270           perror("ptrace error\n");
271           _exit(-1);
272         }
273 #ifdef PARADYND_PVM
274         while (nenv-- > 0)
275                 pvmputenv(envp[nenv]);
276 #endif
277         execv(file, argv);
278         perror("exev");
279         _exit(-1);
280     } else {
281         perror("vfork");
282         free(ret);
283         return(NULL);
284     }
285 }
286
287 process *findProcess(int pid)
288 {
289    return(processList.find((void *) pid));
290    return(NULL);
291 }