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