2 Note that the GNU project considers support for Xenix operation
3 a peripheral activity which should not be allowed to divert effort
4 from development of the GNU system. Changes in this code will be
5 installed when Xenix users send them in, but aside from that
6 we don't plan to think about it, or about whether other Emacs
7 maintenance might break it.
9 Copyright (C) 1988, 1994, 2001, 2002, 2003, 2004,
10 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
12 This file is part of GNU Emacs.
14 GNU Emacs is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 3, or (at your option)
19 GNU Emacs is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GNU Emacs; see the file COPYING. If not, write to
26 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 Boston, MA 02110-1301, USA. */
32 On 80386 Xenix, segmentation screws prevent us from modifying the text
33 segment at all. We basically just plug a new value for "data segment
34 size" into the countless headers and copy the other records straight
35 through. The data segment is ORG'ed at the xs_rbase value of the data
36 segment's xseg record (always @ 0x1880000, thanks to the "sophisticated
37 memory management hardware" of the chip) and extends to sbrk(0), exactly.
38 This code is afraid to malloc (should it be?), and alloca has to be the
39 wimpy, malloc-based version; consequently, data is usually copied in
46 #include <sys/types.h>
54 static void fatal_unexec ();
56 #define READ(_fd, _buffer, _size, _error_message, _error_arg) \
58 if (read(_fd, _buffer, _size) != _size) \
59 fatal_unexec(_error_message, _error_arg);
61 #define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
62 if (write(_fd, _buffer, _size) != _size) \
63 fatal_unexec(_error_message, _error_arg);
65 #define SEEK(_fd, _position, _error_message, _error_arg) \
67 if (lseek(_fd, _position, L_SET) != _position) \
68 fatal_unexec(_error_message, _error_arg);
71 extern char *strerror ();
78 /* Should check the magic number of the old executable;
86 unexec (new_name
, a_name
, data_start
, bss_start
, entry_address
)
87 char *new_name
, *a_name
;
88 unsigned data_start
, bss_start
, entry_address
;
90 char *sbrk (), *datalim
= sbrk (0), *data_org
;
91 long segpos
, textseen
, textpos
, textlen
, datapos
, datadiff
, datalen
;
93 struct xexec u_xexec
, /* a.out header */
95 struct xext u_xext
, /* extended header */
97 struct xseg u_xseg
, /* segment table entry */
99 int i
, nsegs
, isdata
= 0, infd
, outfd
;
101 infd
= open (a_name
, O_RDONLY
, 0);
102 if (infd
< 0) fatal_unexec ("opening %s", a_name
);
104 outfd
= creat (new_name
, 0666);
105 if (outfd
< 0) fatal_unexec ("creating %s", new_name
);
107 READ (infd
, u_xexecp
, sizeof (struct xexec
),
108 "error reading %s", a_name
);
109 check_exec (u_xexecp
);
110 READ (infd
, u_xextp
, sizeof (struct xext
),
111 "error reading %s", a_name
);
112 segpos
= u_xextp
->xe_segpos
;
113 nsegs
= u_xextp
->xe_segsize
/ sizeof (struct xseg
);
114 SEEK (infd
, segpos
, "seek error on %s", a_name
);
115 for (i
= 0; i
< nsegs
; i
++)
117 READ (infd
, u_xsegp
, sizeof (struct xseg
),
118 "error reading %s", a_name
);
119 switch (u_xsegp
->xs_type
)
125 textpos
= u_xsegp
->xs_filpos
;
126 textlen
= u_xsegp
->xs_psize
;
129 fatal_unexec ("invalid text segment in %s", a_name
);
135 datapos
= u_xsegp
->xs_filpos
;
136 datalen
= datalim
- (data_org
= (char *)(u_xsegp
->xs_rbase
));
137 datadiff
= datalen
- u_xsegp
->xs_psize
;
140 fatal_unexec ("invalid data segment in %s", a_name
);
145 fatal_unexec ("invalid segment record in %s", a_name
);
149 u_xexecp
->x_data
= datalen
;
151 WRITE (outfd
, u_xexecp
, sizeof (struct xexec
),
152 "error writing %s", new_name
);
153 WRITE (outfd
, u_xextp
, sizeof (struct xext
),
154 "error writing %s", new_name
);
155 SEEK (infd
, segpos
, "seek error on %s", a_name
);
156 SEEK (outfd
, segpos
, "seek error on %s", new_name
);
158 /* Copy the text segment record verbatim. */
160 copyrec (infd
, outfd
, sizeof (struct xseg
), a_name
, new_name
);
162 /* Read, modify, write the data segment record. */
164 READ (infd
, u_xsegp
, sizeof (struct xseg
),
165 "error reading %s", a_name
);
166 u_xsegp
->xs_psize
= u_xsegp
->xs_vsize
= datalen
;
167 u_xsegp
->xs_attr
&= (~XS_AITER
& ~XS_ABSS
);
168 WRITE (outfd
, u_xsegp
, sizeof (struct xseg
),
169 "error writing %s", new_name
);
171 /* Now copy any additional segment records, adjusting their
172 file position field */
174 for (i
= 2; i
< nsegs
; i
++)
176 READ (infd
, u_xsegp
, sizeof (struct xseg
),
177 "error reading %s", a_name
);
178 u_xsegp
->xs_filpos
+= datadiff
;
179 WRITE (outfd
, u_xsegp
, sizeof (struct xseg
),
180 "error writing %s", new_name
);
183 SEEK (infd
, textpos
, "seek error on %s", a_name
);
184 SEEK (outfd
, textpos
, "seek error on %s", new_name
);
185 copyrec (infd
, outfd
, textlen
, a_name
, new_name
);
187 SEEK (outfd
, datapos
, "seek error on %s", new_name
);
188 WRITE (outfd
, data_org
, datalen
,
189 "write error on %s", new_name
);
191 for (i
= 2, segpos
+= (2 * sizeof (struct xseg
));
193 i
++, segpos
+= sizeof (struct xseg
))
195 SEEK (infd
, segpos
, "seek error on %s", a_name
);
196 READ (infd
, u_xsegp
, sizeof (struct xseg
),
197 "read error on %s", a_name
);
198 SEEK (infd
, u_xsegp
->xs_filpos
, "seek error on %s", a_name
);
199 /* We should be at eof in the output file here, but we must seek
200 because the xs_filpos and xs_psize fields in symbol table
201 segments are inconsistent. */
202 SEEK (outfd
, u_xsegp
->xs_filpos
+ datadiff
, "seek error on %s", new_name
);
203 copyrec (infd
, outfd
, u_xsegp
->xs_psize
, a_name
, new_name
);
211 copyrec (infd
, outfd
, len
, in_name
, out_name
)
212 int infd
, outfd
, len
;
213 char *in_name
, *out_name
;
223 READ (infd
, buf
, chunk
, "error reading %s", in_name
);
224 WRITE (outfd
, buf
, chunk
, "error writing %s", out_name
);
232 * After successfully building the new a.out, mark it executable
239 int um
= umask (777);
241 if (stat (name
, &sbuf
) < 0)
242 fatal_unexec ("getting protection on %s", name
);
243 sbuf
.st_mode
|= 0111 & ~um
;
244 if (chmod (name
, sbuf
.st_mode
) < 0)
245 fatal_unexec ("setting protection on %s", name
);
249 fatal_unexec (s
, va_alist
)
254 fputs ("unexec: unexpected end of file, ", stderr
);
256 fprintf (stderr
, "unexec: %s, ", strerror (errno
));
258 _doprnt (s
, ap
, stderr
);
259 fputs (".\n", stderr
);
263 /* arch-tag: ce26be27-370a-438d-83b4-766059749a02
264 (do not change this comment) */