Implement token threading
[bpt/emacs.git] / src / unexaix.c
CommitLineData
0248680a 1/* Dump an executable image.
acaf905b 2 Copyright (C) 1985-1988, 1999, 2001-2012 Free Software Foundation, Inc.
4e3a36cd 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
3b7ad313
EN
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
4e3a36cd 18
9ec0b715 19/*
4e3a36cd
JB
20In other words, you are welcome to use, share and improve this program.
21You are forbidden to forbid anyone else to use, share and improve
22what you give them. Help stamp out software-hoarding! */
23
24
0248680a 25/* Originally based on the COFF unexec.c by Spencer W. Thomas.
4e3a36cd 26 *
0248680a
DL
27 * Subsequently hacked on by
28 * Bill Mann <Bill_Man@praxisint.com>
29 * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>
30 * Mike Sperber <sperber@informatik.uni-tuebingen.de>
4a438fc5 31 *
4e3a36cd 32 * Synopsis:
dd5ecd6b 33 * unexec (const char *new_name, const *old_name);
4e3a36cd
JB
34 *
35 * Takes a snapshot of the program and makes an a.out format file in the
36 * file named by the string argument new_name.
37 * If a_name is non-NULL, the symbol table will be taken from the given file.
38 * On some machines, an existing a_name file is required.
39 *
4e3a36cd
JB
40 */
41
18160b98 42#include <config.h>
ce701a33
PE
43#include "unexec.h"
44
4e3a36cd 45#define PERROR(file) report_error (file, new)
4e3a36cd
JB
46#include <a.out.h>
47/* Define getpagesize () if the system does not.
48 Note that this may depend on symbols defined in a.out.h
49 */
50#include "getpagesize.h"
76998edb 51
4e3a36cd 52#include <sys/types.h>
4e3a36cd
JB
53#include <stdio.h>
54#include <sys/stat.h>
55#include <errno.h>
0248680a
DL
56#include <unistd.h>
57#include <fcntl.h>
4e3a36cd 58
313d9eb2 59char *start_of_text (void); /* Start of text */
0248680a 60extern char *start_of_data (void); /* Start of initialized data */
4e3a36cd
JB
61
62extern int _data;
4e3a36cd 63extern int _text;
0248680a 64
4e3a36cd
JB
65#include <filehdr.h>
66#include <aouthdr.h>
67#include <scnhdr.h>
68#include <syms.h>
0248680a 69
4e3a36cd
JB
70static struct filehdr f_hdr; /* File header */
71static struct aouthdr f_ohdr; /* Optional file header (a.out) */
0248680a
DL
72static long bias; /* Bias to add for growth */
73static long lnnoptr; /* Pointer to line-number info within file */
4e3a36cd
JB
74
75static long text_scnptr;
76static long data_scnptr;
4a438fc5 77#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
4e3a36cd
JB
78static long load_scnptr;
79static long orig_load_scnptr;
80static long orig_data_scnptr;
dc44c39a 81static int unrelocate_symbols (int, int, const char *, const char *);
4e3a36cd
JB
82
83#ifndef MAX_SECTIONS
84#define MAX_SECTIONS 10
85#endif
86
dc44c39a 87static int adjust_lnnoptrs (int, int, const char *);
4e3a36cd
JB
88
89static int pagemask;
90
d7306fe6 91#include <setjmp.h>
8eca17c9 92#include "lisp.h"
4e3a36cd 93
0248680a 94static void
dc44c39a 95report_error (const char *file, int fd)
4e3a36cd
JB
96{
97 if (fd)
98 close (fd);
8eca17c9 99 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
4e3a36cd 100}
76998edb 101
4e3a36cd
JB
102#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
103#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
104#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
76998edb 105
0248680a 106static void
dc44c39a 107report_error_1 (int fd, const char *msg, int a1, int a2)
76998edb 108{
4e3a36cd 109 close (fd);
4e3a36cd 110 error (msg, a1, a2);
4e3a36cd
JB
111}
112
dc44c39a
PE
113static int make_hdr (int, int, const char *, const char *);
114static void mark_x (const char *);
0248680a 115static int copy_text_and_data (int);
dc44c39a 116static int copy_sym (int, int, const char *, const char *);
0248680a 117static void write_segment (int, char *, char *);
4e3a36cd
JB
118\f
119/* ****************************************************************
120 * unexec
121 *
122 * driving logic.
123 */
381259ef
PE
124void
125unexec (const char *new_name, const char *a_name)
76998edb 126{
0248680a 127 int new = -1, a_out = -1;
4e3a36cd 128
0248680a 129 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0)
4e3a36cd
JB
130 {
131 PERROR (a_name);
132 }
133 if ((new = creat (new_name, 0666)) < 0)
134 {
135 PERROR (new_name);
136 }
0248680a 137 if (make_hdr (new, a_out,
0248680a 138 a_name, new_name) < 0
4e3a36cd
JB
139 || copy_text_and_data (new) < 0
140 || copy_sym (new, a_out, a_name, new_name) < 0
4e3a36cd 141 || adjust_lnnoptrs (new, a_out, new_name) < 0
0248680a 142 || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
76998edb 143 {
4e3a36cd 144 close (new);
fffe2e14 145 return;
76998edb 146 }
76998edb 147
4e3a36cd
JB
148 close (new);
149 if (a_out >= 0)
150 close (a_out);
151 mark_x (new_name);
4e3a36cd
JB
152}
153
154/* ****************************************************************
155 * make_hdr
156 *
157 * Make the header in the new a.out from the header in core.
158 * Modify the text and data sizes.
159 */
160static int
0248680a 161make_hdr (int new, int a_out,
dc44c39a 162 const char *a_name, const char *new_name)
4e3a36cd 163{
0248680a 164 int scns;
dd5ecd6b
DN
165 unsigned int bss_start;
166 unsigned int data_start;
4e3a36cd
JB
167
168 struct scnhdr section[MAX_SECTIONS];
169 struct scnhdr * f_thdr; /* Text section header */
170 struct scnhdr * f_dhdr; /* Data section header */
171 struct scnhdr * f_bhdr; /* Bss section header */
172 struct scnhdr * f_lhdr; /* Loader section header */
173 struct scnhdr * f_tchdr; /* Typechk section header */
174 struct scnhdr * f_dbhdr; /* Debug section header */
175 struct scnhdr * f_xhdr; /* Except section header */
176
177 load_scnptr = orig_load_scnptr = lnnoptr = 0;
178 pagemask = getpagesize () - 1;
179
180 /* Adjust text/data boundary. */
4e3a36cd 181 data_start = (long) start_of_data ();
4e3a36cd
JB
182 data_start = ADDR_CORRECT (data_start);
183
4e3a36cd 184 data_start = data_start & ~pagemask; /* (Down) to page boundary. */
4e3a36cd 185
dd5ecd6b
DN
186 bss_start = ADDR_CORRECT (sbrk (0)) + pagemask;
187 bss_start &= ~ pagemask;
76998edb 188
4e3a36cd
JB
189 if (data_start > bss_start) /* Can't have negative data size. */
190 {
191 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
192 data_start, bss_start);
193 }
76998edb 194
4e3a36cd 195 /* Salvage as much info from the existing file as possible */
4e3a36cd
JB
196 f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
197 f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
198 if (a_out >= 0)
76998edb 199 {
4e3a36cd
JB
200 if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
201 {
202 PERROR (a_name);
203 }
4e3a36cd
JB
204 if (f_hdr.f_opthdr > 0)
205 {
206 if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
207 {
208 PERROR (a_name);
209 }
4e3a36cd
JB
210 }
211 if (f_hdr.f_nscns > MAX_SECTIONS)
212 {
213 ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
214 }
215 /* Loop through section headers */
216 for (scns = 0; scns < f_hdr.f_nscns; scns++) {
217 struct scnhdr *s = &section[scns];
218 if (read (a_out, s, sizeof (*s)) != sizeof (*s))
219 {
220 PERROR (a_name);
221 }
4e3a36cd
JB
222
223#define CHECK_SCNHDR(ptr, name, flags) \
5e617bc2 224 if (strcmp (s->s_name, name) == 0) { \
4e3a36cd 225 if (s->s_flags != flags) { \
5e617bc2
JB
226 fprintf (stderr, "unexec: %lx flags where %x expected in %s section.\n", \
227 (unsigned long)s->s_flags, flags, name); \
4e3a36cd
JB
228 } \
229 if (ptr) { \
5e617bc2
JB
230 fprintf (stderr, "unexec: duplicate section header for section %s.\n", \
231 name); \
4e3a36cd
JB
232 } \
233 ptr = s; \
234 }
5e617bc2
JB
235 CHECK_SCNHDR (f_thdr, _TEXT, STYP_TEXT);
236 CHECK_SCNHDR (f_dhdr, _DATA, STYP_DATA);
237 CHECK_SCNHDR (f_bhdr, _BSS, STYP_BSS);
238 CHECK_SCNHDR (f_lhdr, _LOADER, STYP_LOADER);
239 CHECK_SCNHDR (f_dbhdr, _DEBUG, STYP_DEBUG);
240 CHECK_SCNHDR (f_tchdr, _TYPCHK, STYP_TYPCHK);
241 CHECK_SCNHDR (f_xhdr, _EXCEPT, STYP_EXCEPT);
4e3a36cd
JB
242 }
243
244 if (f_thdr == 0)
245 {
0248680a 246 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _TEXT);
4e3a36cd
JB
247 }
248 if (f_dhdr == 0)
249 {
0248680a 250 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _DATA);
4e3a36cd
JB
251 }
252 if (f_bhdr == 0)
253 {
0248680a 254 ERROR1 ("unexec: couldn't find \"%s\" section", (int) _BSS);
4e3a36cd 255 }
76998edb 256 }
4e3a36cd 257 else
76998edb 258 {
4e3a36cd 259 ERROR0 ("can't build a COFF file from scratch yet");
76998edb 260 }
4e3a36cd
JB
261 orig_data_scnptr = f_dhdr->s_scnptr;
262 orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
263
264 /* Now we alter the contents of all the f_*hdr variables
265 to correspond to what we want to dump. */
4a438fc5
RS
266
267 /* Indicate that the reloc information is no longer valid for ld (bind);
268 we only update it enough to fake out the exec-time loader. */
269 f_hdr.f_flags |= (F_RELFLG | F_EXEC);
270
0248680a 271 f_ohdr.dsize = bss_start - f_ohdr.data_start;
dd5ecd6b 272 f_ohdr.bsize = 0;
4e3a36cd
JB
273
274 f_dhdr->s_size = f_ohdr.dsize;
275 f_bhdr->s_size = f_ohdr.bsize;
4a438fc5
RS
276 f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
277 f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
4e3a36cd
JB
278
279 /* fix scnptr's */
280 {
4a438fc5 281 ulong ptr = section[0].s_scnptr;
4e3a36cd 282
4a438fc5
RS
283 bias = -1;
284 for (scns = 0; scns < f_hdr.f_nscns; scns++)
285 {
286 struct scnhdr *s = &section[scns];
4e3a36cd 287
4a438fc5
RS
288 if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */
289 {
290 /*
291 * the text_start should probably be o_algntext but that doesn't
292 * seem to change
293 */
294 if (f_ohdr.text_start != 0) /* && scns != 0 */
295 {
296 s->s_size = 512 - (ptr % 512);
297 if (s->s_size == 512)
298 s->s_size = 0;
299 }
300 s->s_scnptr = ptr;
301 }
302 else if (s->s_flags & STYP_DATA)
4e3a36cd 303 s->s_scnptr = ptr;
4a438fc5
RS
304 else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
305 {
306 if (bias == -1) /* if first section after bss */
307 bias = ptr - s->s_scnptr;
4e3a36cd 308
4a438fc5
RS
309 s->s_scnptr += bias;
310 ptr = s->s_scnptr;
311 }
177c0ea7 312
4a438fc5
RS
313 ptr = ptr + s->s_size;
314 }
4e3a36cd
JB
315 }
316
317 /* fix other pointers */
4a438fc5
RS
318 for (scns = 0; scns < f_hdr.f_nscns; scns++)
319 {
320 struct scnhdr *s = &section[scns];
4e3a36cd 321
4a438fc5
RS
322 if (s->s_relptr != 0)
323 {
324 s->s_relptr += bias;
325 }
326 if (s->s_lnnoptr != 0)
327 {
328 if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
329 s->s_lnnoptr += bias;
330 }
331 }
4e3a36cd
JB
332
333 if (f_hdr.f_symptr > 0L)
76998edb 334 {
4e3a36cd 335 f_hdr.f_symptr += bias;
76998edb
JB
336 }
337
4e3a36cd
JB
338 text_scnptr = f_thdr->s_scnptr;
339 data_scnptr = f_dhdr->s_scnptr;
340 load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
76998edb 341
4e3a36cd
JB
342 if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
343 {
344 PERROR (new_name);
345 }
76998edb 346
4e3a36cd
JB
347 if (f_hdr.f_opthdr > 0)
348 {
349 if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
76998edb 350 {
4e3a36cd
JB
351 PERROR (new_name);
352 }
353 }
76998edb 354
4e3a36cd
JB
355 for (scns = 0; scns < f_hdr.f_nscns; scns++) {
356 struct scnhdr *s = &section[scns];
357 if (write (new, s, sizeof (*s)) != sizeof (*s))
358 {
359 PERROR (new_name);
360 }
361 }
76998edb 362
4e3a36cd 363 return (0);
4e3a36cd
JB
364}
365\f
366/* ****************************************************************
177c0ea7 367
4e3a36cd
JB
368 *
369 * Copy the text and data segments from memory to the new a.out
370 */
371static int
0248680a 372copy_text_and_data (int new)
4e3a36cd 373{
0248680a
DL
374 char *end;
375 char *ptr;
4e3a36cd 376
0248680a 377 lseek (new, (long) text_scnptr, SEEK_SET);
4e3a36cd
JB
378 ptr = start_of_text () + text_scnptr;
379 end = ptr + f_ohdr.tsize;
380 write_segment (new, ptr, end);
381
0248680a
DL
382 lseek (new, (long) data_scnptr, SEEK_SET);
383 ptr = (char *) f_ohdr.data_start;
4e3a36cd
JB
384 end = ptr + f_ohdr.dsize;
385 write_segment (new, ptr, end);
386
387 return 0;
388}
389
91b97ddb 390#define UnexBlockSz (1<<12) /* read/write block size */
0248680a
DL
391static void
392write_segment (int new, char *ptr, char *end)
4e3a36cd 393{
0248680a 394 int i, nwrite, ret;
4e3a36cd 395 char buf[80];
91b97ddb 396 char zeros[UnexBlockSz];
4e3a36cd
JB
397
398 for (i = 0; ptr < end;)
399 {
91b97ddb
RS
400 /* distance to next block. */
401 nwrite = (((int) ptr + UnexBlockSz) & -UnexBlockSz) - (int) ptr;
4e3a36cd
JB
402 /* But not beyond specified end. */
403 if (nwrite > end - ptr) nwrite = end - ptr;
404 ret = write (new, ptr, nwrite);
405 /* If write gets a page fault, it means we reached
406 a gap between the old text segment and the old data segment.
407 This gap has probably been remapped into part of the text segment.
408 So write zeros for it. */
409 if (ret == -1 && errno == EFAULT)
76998edb 410 {
0248680a 411 memset (zeros, 0, nwrite);
91b97ddb 412 write (new, zeros, nwrite);
76998edb 413 }
4e3a36cd 414 else if (nwrite != ret)
76998edb 415 {
4e3a36cd 416 sprintf (buf,
d63c1903
KH
417 "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d",
418 (unsigned long)ptr, new, nwrite, ret, errno);
4e3a36cd 419 PERROR (buf);
76998edb 420 }
4e3a36cd
JB
421 i += nwrite;
422 ptr += nwrite;
423 }
424}
425\f
426/* ****************************************************************
427 * copy_sym
428 *
429 * Copy the relocation information and symbol table from the a.out to the new
430 */
431static int
dc44c39a 432copy_sym (int new, int a_out, const char *a_name, const char *new_name)
4e3a36cd 433{
91b97ddb 434 char page[UnexBlockSz];
4e3a36cd 435 int n;
76998edb 436
4e3a36cd
JB
437 if (a_out < 0)
438 return 0;
76998edb 439
4a438fc5 440 if (orig_load_scnptr == 0L)
4e3a36cd 441 return 0;
76998edb 442
4a438fc5 443 if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */
0248680a 444 lseek (a_out, lnnoptr, SEEK_SET); /* start copying from there */
4e3a36cd 445 else
0248680a 446 lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */
4e3a36cd
JB
447
448 while ((n = read (a_out, page, sizeof page)) > 0)
449 {
450 if (write (new, page, n) != n)
76998edb 451 {
4e3a36cd 452 PERROR (new_name);
76998edb
JB
453 }
454 }
4e3a36cd
JB
455 if (n < 0)
456 {
457 PERROR (a_name);
458 }
459 return 0;
460}
461\f
462/* ****************************************************************
463 * mark_x
464 *
eb8c3be9 465 * After successfully building the new a.out, mark it executable
4e3a36cd
JB
466 */
467static void
dc44c39a 468mark_x (const char *name)
4e3a36cd
JB
469{
470 struct stat sbuf;
471 int um;
472 int new = 0; /* for PERROR */
76998edb 473
4e3a36cd
JB
474 um = umask (777);
475 umask (um);
476 if (stat (name, &sbuf) == -1)
477 {
478 PERROR (name);
479 }
480 sbuf.st_mode |= 0111 & ~um;
481 if (chmod (name, sbuf.st_mode) == -1)
482 PERROR (name);
483}
484\f
0248680a 485static int
dc44c39a 486adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
4e3a36cd 487{
0248680a
DL
488 int nsyms;
489 int naux;
490 int new;
4e3a36cd
JB
491 struct syment symentry;
492 union auxent auxentry;
4e3a36cd
JB
493
494 if (!lnnoptr || !f_hdr.f_symptr)
495 return 0;
496
0248680a 497 if ((new = open (new_name, O_RDWR)) < 0)
4e3a36cd
JB
498 {
499 PERROR (new_name);
500 return -1;
501 }
502
0248680a 503 lseek (new, f_hdr.f_symptr, SEEK_SET);
4e3a36cd
JB
504 for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
505 {
506 read (new, &symentry, SYMESZ);
91b97ddb
RS
507 if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL)
508 {
509 symentry.n_value += bias;
0248680a 510 lseek (new, -SYMESZ, SEEK_CUR);
91b97ddb
RS
511 write (new, &symentry, SYMESZ);
512 }
513
4a438fc5 514 for (naux = symentry.n_numaux; naux-- != 0; )
4e3a36cd
JB
515 {
516 read (new, &auxentry, AUXESZ);
517 nsyms++;
4a438fc5
RS
518 if (naux != 0 /* skip csect auxentry (last entry) */
519 && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
520 {
521 auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
0248680a 522 lseek (new, -AUXESZ, SEEK_CUR);
4a438fc5
RS
523 write (new, &auxentry, AUXESZ);
524 }
4e3a36cd
JB
525 }
526 }
527 close (new);
76998edb 528
0248680a
DL
529 return 0;
530}
4e3a36cd 531
0248680a 532static int
dc44c39a
PE
533unrelocate_symbols (int new, int a_out,
534 const char *a_name, const char *new_name)
76998edb 535{
0248680a 536 int i;
4e3a36cd 537 LDHDR ldhdr;
0248680a 538 LDREL ldrel;
4a438fc5 539 ulong t_reloc = (ulong) &_text - f_ohdr.text_start;
0248680a
DL
540#ifndef ALIGN_DATA_RELOC
541 ulong d_reloc = (ulong) &_data - f_ohdr.data_start;
542#else
177c0ea7 543 /* This worked (and was needed) before AIX 4.2.
0248680a 544 I have no idea why. -- Mike */
5e617bc2 545 ulong d_reloc = (ulong) &_data - ALIGN (f_ohdr.data_start, 2);
0248680a 546#endif
4e3a36cd 547 int * p;
4e3a36cd
JB
548
549 if (load_scnptr == 0)
550 return 0;
551
0248680a 552 lseek (a_out, orig_load_scnptr, SEEK_SET);
4e3a36cd
JB
553 if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
554 {
555 PERROR (new_name);
556 }
557
558#define SYMNDX_TEXT 0
559#define SYMNDX_DATA 1
560#define SYMNDX_BSS 2
4e3a36cd 561
0248680a
DL
562 for (i = 0; i < ldhdr.l_nreloc; i++)
563 {
564 lseek (a_out,
565 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
566 SEEK_SET);
4e3a36cd 567
0248680a
DL
568 if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ)
569 {
570 PERROR (a_name);
571 }
4e3a36cd
JB
572
573 /* move the BSS loader symbols to the DATA segment */
0248680a 574 if (ldrel.l_symndx == SYMNDX_BSS)
4e3a36cd 575 {
0248680a 576 ldrel.l_symndx = SYMNDX_DATA;
91b97ddb 577
4e3a36cd
JB
578 lseek (new,
579 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
0248680a 580 SEEK_SET);
4e3a36cd 581
0248680a 582 if (write (new, &ldrel, LDRELSZ) != LDRELSZ)
4e3a36cd
JB
583 {
584 PERROR (new_name);
585 }
586 }
587
0248680a 588 if (ldrel.l_rsecnm == f_ohdr.o_sndata)
4e3a36cd
JB
589 {
590 int orig_int;
591
4a438fc5 592 lseek (a_out,
0248680a
DL
593 orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
594 SEEK_SET);
4e3a36cd 595
0248680a
DL
596 if (read (a_out, (void *) &orig_int, sizeof (orig_int))
597 != sizeof (orig_int))
4e3a36cd
JB
598 {
599 PERROR (a_name);
600 }
601
0248680a 602 p = (int *) (ldrel.l_vaddr + d_reloc);
4a438fc5 603
0248680a 604 switch (ldrel.l_symndx) {
4e3a36cd 605 case SYMNDX_TEXT:
4a438fc5 606 orig_int = * p - t_reloc;
4e3a36cd
JB
607 break;
608
609 case SYMNDX_DATA:
610 case SYMNDX_BSS:
4a438fc5 611 orig_int = * p - d_reloc;
4e3a36cd
JB
612 break;
613 }
614
4a438fc5
RS
615 if (orig_int != * p)
616 {
617 lseek (new,
0248680a
DL
618 data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
619 SEEK_SET);
4a438fc5
RS
620 if (write (new, (void *) &orig_int, sizeof (orig_int))
621 != sizeof (orig_int))
622 {
623 PERROR (new_name);
624 }
625 }
4e3a36cd
JB
626 }
627 }
0248680a 628 return 0;
76998edb 629}
ab5796a9 630
313d9eb2
DN
631/*
632 * Return the address of the start of the text segment prior to
633 * doing an unexec. After unexec the return value is undefined.
634 * See crt0.c for further explanation and _start.
635 *
636 */
637
638char *
639start_of_text (void)
640{
641 return ((char *) 0x10000000);
642}