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