Mercurial > emacs
annotate src/unexsunos4.c @ 4413:5a00cec8e9b0
(fill-region-as-paragraph): When we take one word
after the fill column, don't stop at period with just one space.
When checking whether at beginning of line, if no fill prefix,
ignore intervening whitespace.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 02 Aug 1993 05:55:56 +0000 |
parents | 507f64624555 |
children | 1fc792473491 |
rev | line source |
---|---|
685 | 1 /* Contributed by Viktor Dukhovni. */ |
486 | 2 /* |
3 * Unexec for Berkeley a.out format + SUNOS shared libraries | |
4 * The unexeced executable contains the __DYNAMIC area from the | |
5 * original text file, and then the rest of data + bss + malloced area of | |
6 * the current process. (The __DYNAMIC area is at the top of the process | |
7 * data segment, we use "data_start" defined externally to mark the start | |
8 * of the "real" data segment.) | |
9 * | |
10 * For programs that want to remap some of the data segment read only | |
11 * a run_time_remap is provided. This attempts to remap largest area starting | |
12 * and ending on page boundaries between "data_start" and "bndry" | |
13 * For this it to figure out where the text file is located. A path search | |
14 * is attempted after trying argv[0] and if all fails we simply do not remap | |
15 * | |
16 * One feature of run_time_remap () is mandatory: reseting the break. | |
17 * | |
18 * Note that we can no longer map data into the text segment, as this causes | |
19 * the __DYNAMIC struct to become read only, breaking the runtime loader. | |
20 * Thus we no longer need to mess with a private crt0.c, the standard one | |
21 * will do just fine, since environ can live in the writable area between | |
22 * __DYNAMIC and data_start, just make sure that pre-crt0.o (the name | |
23 * is somewhat abused here) is loaded first! | |
24 * | |
25 */ | |
26 #ifdef emacs | |
27 #include "config.h" | |
28 #endif | |
29 | |
30 #include <sys/param.h> | |
31 #include <sys/mman.h> | |
32 #include <sys/file.h> | |
33 #include <sys/stat.h> | |
34 #include <string.h> | |
35 #include <stdio.h> | |
36 #include <a.out.h> | |
37 | |
38 /* | |
39 * for programs other than emacs | |
40 * define data_start + initialized here, and make sure | |
41 * this object is loaded first! | |
42 * emacs will define these elsewhere, and load the object containing | |
43 * data_start (pre-crt0.o or firstfile.o?) first! | |
44 * The custom crt0.o *must not* be loaded! | |
45 */ | |
46 #ifndef emacs | |
47 static int data_start = 0; | |
48 static int initialized = 0; | |
49 #else | |
50 extern int initialized; | |
51 extern unsigned data_start; | |
52 extern int pureptr; | |
53 #endif | |
54 | |
55 extern char *getenv (); | |
56 static unsigned Brk; | |
57 static struct exec nhdr; | |
58 static int rd_only_len; | |
59 static long cookie; | |
60 | |
61 | |
62 unexec (new_name, a_name, bndry, bss_start, entry) | |
63 char *new_name, *a_name; | |
64 unsigned bndry, bss_start, entry; | |
65 { | |
66 char buf[PAGSIZ]; | |
67 int fd, new; | |
68 char *old; | |
69 struct exec ohdr; /* Allocate on the stack, not needed in the next life */ | |
70 struct stat stat; | |
71 | |
72 #ifdef emacs | |
73 fprintf (stderr, "Used %d bytes of Pure Storage\n", pureptr); | |
74 #endif | |
75 | |
76 if ((fd = open (a_name, O_RDONLY)) < 0) | |
77 { | |
78 fprintf (stderr, "%s: open: ", a_name); | |
79 perror (a_name); | |
80 exit (1); | |
81 } | |
82 if ((new = open (new_name, O_WRONLY | O_CREAT, 0666)) == -1) | |
83 { | |
84 fprintf (stderr, "%s: open: ", a_name); | |
85 perror (new_name); | |
86 exit (1); | |
87 } | |
88 | |
89 if ((fstat (fd, &stat) == -1)) | |
90 { | |
91 fprintf (stderr, "%s: ", a_name); | |
92 perror ("fstat"); | |
93 exit (1); | |
94 } | |
95 | |
96 old = (char *)mmap (0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); | |
97 if (old == (char *)-1) | |
98 { | |
99 fprintf (stderr, "%s: ", a_name); | |
100 perror ("mmap"); | |
101 exit (1); | |
102 } | |
103 close (fd); | |
104 | |
105 nhdr = ohdr = (*(struct exec *)old); | |
106 | |
107 | |
108 /* | |
3591
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
971
diff
changeset
|
109 * Remember a magic cookie so we know we've got the right binary |
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
971
diff
changeset
|
110 * when remapping. |
486 | 111 */ |
112 cookie = time (0); | |
113 | |
114 Brk = sbrk (0); /* Save the break, it is reset to &_end (by ld.so?) */ | |
115 | |
116 /* | |
117 * Round up data start to a page boundary (Lose if not a 2 power!) | |
118 */ | |
119 data_start = ((((int)&data_start) - 1) & ~(N_PAGSIZ (nhdr) - 1)) + N_PAGSIZ (nhdr); | |
120 | |
121 /* | |
122 * Round down read only pages to a multiple of the page size | |
123 */ | |
124 if (bndry) | |
125 rd_only_len = ((int)bndry & ~(N_PAGSIZ (nhdr) - 1)) - data_start; | |
126 | |
127 #ifndef emacs | |
128 /* Have to do this some time before dumping the data */ | |
129 initialized = 1; | |
130 #endif | |
131 | |
132 /* | |
133 * Handle new data and bss sizes and optional new entry point. | |
134 * No one actually uses bss_start and entry, but tradition compels | |
135 * one to support them. | |
136 * Could complain if bss_start > Brk, but the caller is *supposed* to know | |
137 * what she is doing. | |
138 */ | |
139 nhdr.a_data = (bss_start ? bss_start : Brk) - N_DATADDR (nhdr); | |
140 nhdr.a_bss = bss_start ? Brk - bss_start : 0; | |
141 if (entry) | |
142 nhdr.a_entry = entry; | |
143 | |
144 /* | |
145 * Write out the text segment with new header | |
146 * Dynamic executables are ZMAGIC with N_TXTOFF==0 and the header | |
147 * part of the text segment, but no need to rely on this. | |
148 * So write the TEXT first, then go back replace the header. | |
149 * Doing it in the other order is less general! | |
150 */ | |
151 lseek (new, N_TXTOFF (nhdr), L_SET); | |
152 write (new, old + N_TXTOFF (ohdr), N_TXTOFF (ohdr) + ohdr.a_text); | |
153 lseek (new, 0L, L_SET); | |
154 write (new, &nhdr, sizeof (nhdr)); | |
155 | |
156 /* | |
157 * Write out the head of the old data segment from the file not | |
158 * from core, this has the unresolved __DYNAMIC relocation data | |
159 * we need to reload | |
160 */ | |
161 lseek (new, N_DATOFF (nhdr), L_SET); | |
162 write (new, old + N_DATOFF (ohdr), (int)&data_start - N_DATADDR (ohdr)); | |
163 | |
164 /* | |
165 * Copy the rest of the data from core | |
166 */ | |
167 write (new, &data_start, N_BSSADDR (nhdr) - (int)&data_start); | |
168 | |
169 /* | |
170 * Copy the symbol table and line numbers | |
171 */ | |
172 lseek (new, N_TRELOFF (nhdr), L_SET); | |
173 write (new, old + N_TRELOFF (ohdr), stat.st_size - N_TRELOFF (ohdr)); | |
174 | |
175 fchmod (new, 0755); | |
176 } | |
177 | |
178 void | |
179 run_time_remap (progname) | |
180 char *progname; | |
181 { | |
182 char aout[MAXPATHLEN]; | |
183 register char *path, *p; | |
184 | |
185 /* Just in case */ | |
186 if (!initialized) | |
187 return; | |
188 | |
189 /* Restore the break */ | |
190 brk (Brk); | |
191 | |
192 /* If nothing to remap: we are done! */ | |
193 if (rd_only_len == 0) | |
194 return; | |
195 | |
196 /* | |
197 * Attempt to find the executable | |
198 * First try argv[0], will almost always succeed as shells tend to give | |
199 * the full path from the hash list rather than using execvp () | |
200 */ | |
201 if (is_it (progname)) | |
202 return; | |
203 | |
204 /* | |
205 * If argv[0] is a full path and does not exist, not much sense in | |
206 * searching further | |
207 */ | |
208 if (strchr (progname, '/')) | |
209 return; | |
210 | |
211 /* | |
212 * Try to search for argv[0] on the PATH | |
213 */ | |
214 path = getenv ("PATH"); | |
215 if (path == NULL) | |
216 return; | |
217 | |
218 while (*path) | |
219 { | |
220 /* copy through ':' or end */ | |
221 for (p = aout; *p = *path; ++p, ++path) | |
222 if (*p == ':') | |
223 { | |
224 ++path; /* move past ':' */ | |
225 break; | |
226 } | |
227 *p++ = '/'; | |
228 strcpy (p, progname); | |
229 /* | |
230 * aout is a candidate full path name | |
231 */ | |
232 if (is_it (aout)) | |
233 return; | |
234 } | |
235 } | |
236 | |
237 is_it (path) | |
238 char *path; | |
239 { | |
240 int fd; | |
241 long paths_cookie; | |
242 struct exec hdr; | |
243 | |
244 /* | |
245 * Open an executable and check for a valid header! | |
246 * Can't bcmp() the header with what we had, it may have been stripped! | |
247 * so we may save looking at non executables with the same name, mostly | |
248 * directories. | |
249 */ | |
250 fd = open (path, O_RDONLY); | |
251 if (fd != -1) | |
252 { | |
253 if (read (fd, &hdr, sizeof (hdr)) == sizeof (hdr) | |
254 && !N_BADMAG (hdr) && N_DATOFF (hdr) == N_DATOFF (nhdr) | |
255 && N_TRELOFF (hdr) == N_TRELOFF (nhdr)) | |
256 { | |
257 /* compare cookies */ | |
258 lseek (fd, N_DATOFF (hdr) + (int)&cookie - N_DATADDR (hdr), L_SET); | |
259 read (fd, &paths_cookie, sizeof (paths_cookie)); | |
260 if (paths_cookie == cookie) | |
261 { /* Eureka */ | |
262 | |
263 /* | |
264 * Do the mapping | |
265 * The PROT_EXEC may not be needed, but it is safer this way. | |
266 * should the shared library decide to indirect through | |
267 * addresses in the data segment not part of __DYNAMIC | |
268 */ | |
269 mmap (data_start, rd_only_len, PROT_READ | PROT_EXEC, | |
270 MAP_SHARED | MAP_FIXED, fd, | |
271 N_DATOFF (hdr) + data_start - N_DATADDR (hdr)); | |
272 close (fd); | |
273 return 1; | |
274 } | |
275 } | |
276 close (fd); | |
277 } | |
278 return 0; | |
279 } |