diff options
| author | Richard M. Stallman | 1996-03-07 20:17:45 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-03-07 20:17:45 +0000 |
| commit | 4a438fc5174459a044df208373a43e737c2c714b (patch) | |
| tree | 7ef759b7ff2407cba5a20947134a697a3b109d2a /src | |
| parent | e024a2f4ab5c253fe040d3fd2edf7be902e21823 (diff) | |
| download | emacs-4a438fc5174459a044df208373a43e737c2c714b.tar.gz emacs-4a438fc5174459a044df208373a43e737c2c714b.zip | |
Handle both AIX 3.2 and 4.1 bind output.
(make_hdr): Handle data_start being non-zero for 4.1. Padding
sections are omitted in 4.1, but padding bytes can still be
present. Calculate bias directly from first real section following bss.
(copy_text_and_data): Correct data section starting point for 4.1.
(adjust_lnnoptrs): Adjust line number pointers correctly for both
3.2 and 4.1, based on published IBM documentation.
(unrelocate_symbols): Compute and subtract relocation offsets for
text and data sections. Handle data_start being non-zero for 4.1.
Skip unnecessary writes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexaix.c | 191 |
1 files changed, 95 insertions, 96 deletions
diff --git a/src/unexaix.c b/src/unexaix.c index 69b19d2dc54..445f01886dd 100644 --- a/src/unexaix.c +++ b/src/unexaix.c | |||
| @@ -33,6 +33,14 @@ what you give them. Help stamp out software-hoarding! */ | |||
| 33 | * Date: Tue Mar 2 1982 | 33 | * Date: Tue Mar 2 1982 |
| 34 | * Modified heavily since then. | 34 | * Modified heavily since then. |
| 35 | * | 35 | * |
| 36 | * Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996 | ||
| 37 | * As of AIX 4.1, text, data, and bss are pre-relocated by the binder in | ||
| 38 | * such a way that the file can be mapped with code in one segment and | ||
| 39 | * data/bss in another segment, without reading or copying the file, by | ||
| 40 | * the AIX exec loader. Padding sections are omitted, nevertheless | ||
| 41 | * small amounts of 'padding' still occurs between sections in the file. | ||
| 42 | * As modified, this code handles both 3.2 and 4.1 conventions. | ||
| 43 | * | ||
| 36 | * Synopsis: | 44 | * Synopsis: |
| 37 | * unexec (new_name, a_name, data_start, bss_start, entry_address) | 45 | * unexec (new_name, a_name, data_start, bss_start, entry_address) |
| 38 | * char *new_name, *a_name; | 46 | * char *new_name, *a_name; |
| @@ -203,21 +211,20 @@ extern int _end; | |||
| 203 | #endif /* not UMAX */ | 211 | #endif /* not UMAX */ |
| 204 | #endif /* Not STRIDE */ | 212 | #endif /* Not STRIDE */ |
| 205 | #endif /* not USG */ | 213 | #endif /* not USG */ |
| 206 | static long block_copy_start; /* Old executable start point */ | ||
| 207 | static struct filehdr f_hdr; /* File header */ | 214 | static struct filehdr f_hdr; /* File header */ |
| 208 | static struct aouthdr f_ohdr; /* Optional file header (a.out) */ | 215 | static struct aouthdr f_ohdr; /* Optional file header (a.out) */ |
| 209 | long bias; /* Bias to add for growth */ | 216 | long bias; /* Bias to add for growth */ |
| 210 | long lnnoptr; /* Pointer to line-number info within file */ | 217 | long lnnoptr; /* Pointer to line-number info within file */ |
| 211 | #define SYMS_START block_copy_start | ||
| 212 | 218 | ||
| 213 | static long text_scnptr; | 219 | static long text_scnptr; |
| 214 | static long data_scnptr; | 220 | static long data_scnptr; |
| 215 | #ifdef XCOFF | 221 | #ifdef XCOFF |
| 222 | #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) | ||
| 216 | static long load_scnptr; | 223 | static long load_scnptr; |
| 217 | static long orig_load_scnptr; | 224 | static long orig_load_scnptr; |
| 218 | static long orig_data_scnptr; | 225 | static long orig_data_scnptr; |
| 219 | #endif | 226 | #endif |
| 220 | static long data_st; | 227 | static ulong data_st; /* start of data area written out */ |
| 221 | 228 | ||
| 222 | #ifndef MAX_SECTIONS | 229 | #ifndef MAX_SECTIONS |
| 223 | #define MAX_SECTIONS 10 | 230 | #define MAX_SECTIONS 10 |
| @@ -381,7 +388,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | |||
| 381 | 388 | ||
| 382 | #ifdef COFF | 389 | #ifdef COFF |
| 383 | /* Salvage as much info from the existing file as possible */ | 390 | /* Salvage as much info from the existing file as possible */ |
| 384 | block_copy_start = 0; | ||
| 385 | f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL; | 391 | f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL; |
| 386 | f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL; | 392 | f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL; |
| 387 | if (a_out >= 0) | 393 | if (a_out >= 0) |
| @@ -390,14 +396,12 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | |||
| 390 | { | 396 | { |
| 391 | PERROR (a_name); | 397 | PERROR (a_name); |
| 392 | } | 398 | } |
| 393 | block_copy_start += sizeof (f_hdr); | ||
| 394 | if (f_hdr.f_opthdr > 0) | 399 | if (f_hdr.f_opthdr > 0) |
| 395 | { | 400 | { |
| 396 | if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) | 401 | if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr)) |
| 397 | { | 402 | { |
| 398 | PERROR (a_name); | 403 | PERROR (a_name); |
| 399 | } | 404 | } |
| 400 | block_copy_start += sizeof (f_ohdr); | ||
| 401 | } | 405 | } |
| 402 | if (f_hdr.f_nscns > MAX_SECTIONS) | 406 | if (f_hdr.f_nscns > MAX_SECTIONS) |
| 403 | { | 407 | { |
| @@ -410,11 +414,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | |||
| 410 | { | 414 | { |
| 411 | PERROR (a_name); | 415 | PERROR (a_name); |
| 412 | } | 416 | } |
| 413 | if (s->s_scnptr > 0L) | ||
| 414 | { | ||
| 415 | if (block_copy_start < s->s_scnptr + s->s_size) | ||
| 416 | block_copy_start = s->s_scnptr + s->s_size; | ||
| 417 | } | ||
| 418 | 417 | ||
| 419 | #define CHECK_SCNHDR(ptr, name, flags) \ | 418 | #define CHECK_SCNHDR(ptr, name, flags) \ |
| 420 | if (strcmp(s->s_name, name) == 0) { \ | 419 | if (strcmp(s->s_name, name) == 0) { \ |
| @@ -459,7 +458,11 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | |||
| 459 | 458 | ||
| 460 | /* Now we alter the contents of all the f_*hdr variables | 459 | /* Now we alter the contents of all the f_*hdr variables |
| 461 | to correspond to what we want to dump. */ | 460 | to correspond to what we want to dump. */ |
| 462 | f_hdr.f_flags |= (F_RELFLG | F_EXEC); /* Why? */ | 461 | |
| 462 | /* Indicate that the reloc information is no longer valid for ld (bind); | ||
| 463 | we only update it enough to fake out the exec-time loader. */ | ||
| 464 | f_hdr.f_flags |= (F_RELFLG | F_EXEC); | ||
| 465 | |||
| 463 | #ifdef EXEC_MAGIC | 466 | #ifdef EXEC_MAGIC |
| 464 | f_ohdr.magic = EXEC_MAGIC; | 467 | f_ohdr.magic = EXEC_MAGIC; |
| 465 | #endif | 468 | #endif |
| @@ -467,73 +470,77 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) | |||
| 467 | f_ohdr.tsize = data_start - f_ohdr.text_start; | 470 | f_ohdr.tsize = data_start - f_ohdr.text_start; |
| 468 | f_ohdr.text_start = (long) start_of_text (); | 471 | f_ohdr.text_start = (long) start_of_text (); |
| 469 | #endif | 472 | #endif |
| 470 | f_ohdr.dsize = bss_start - ((unsigned) &_data); | 473 | data_st = f_ohdr.data_start ? f_ohdr.data_start : (ulong) &_data; |
| 474 | f_ohdr.dsize = bss_start - data_st; | ||
| 471 | f_ohdr.bsize = bss_end - bss_start; | 475 | f_ohdr.bsize = bss_end - bss_start; |
| 472 | 476 | ||
| 473 | f_dhdr->s_size = f_ohdr.dsize; | 477 | f_dhdr->s_size = f_ohdr.dsize; |
| 474 | f_bhdr->s_size = f_ohdr.bsize; | 478 | f_bhdr->s_size = f_ohdr.bsize; |
| 475 | f_bhdr->s_paddr = f_ohdr.dsize; | 479 | f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize; |
| 476 | f_bhdr->s_vaddr = f_ohdr.dsize; | 480 | f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize; |
| 477 | 481 | ||
| 478 | /* fix scnptr's */ | 482 | /* fix scnptr's */ |
| 479 | { | 483 | { |
| 480 | long ptr; | 484 | ulong ptr = section[0].s_scnptr; |
| 481 | 485 | ||
| 482 | for (scns = 0; scns < f_hdr.f_nscns; scns++) { | 486 | bias = -1; |
| 483 | struct scnhdr *s = §ion[scns]; | 487 | for (scns = 0; scns < f_hdr.f_nscns; scns++) |
| 484 | if (scns == 0) | 488 | { |
| 485 | ptr = s->s_scnptr; | 489 | struct scnhdr *s = §ion[scns]; |
| 486 | 490 | ||
| 487 | if (s->s_scnptr != 0) | 491 | if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */ |
| 488 | { | 492 | { |
| 493 | /* | ||
| 494 | * the text_start should probably be o_algntext but that doesn't | ||
| 495 | * seem to change | ||
| 496 | */ | ||
| 497 | if (f_ohdr.text_start != 0) /* && scns != 0 */ | ||
| 498 | { | ||
| 499 | s->s_size = 512 - (ptr % 512); | ||
| 500 | if (s->s_size == 512) | ||
| 501 | s->s_size = 0; | ||
| 502 | } | ||
| 503 | s->s_scnptr = ptr; | ||
| 504 | } | ||
| 505 | else if (s->s_flags & STYP_DATA) | ||
| 489 | s->s_scnptr = ptr; | 506 | s->s_scnptr = ptr; |
| 490 | } | 507 | else if (!(s->s_flags & (STYP_TEXT | STYP_BSS))) |
| 491 | 508 | { | |
| 492 | if ((s->s_flags & 0xffff) == STYP_PAD) | 509 | if (bias == -1) /* if first section after bss */ |
| 493 | { | 510 | bias = ptr - s->s_scnptr; |
| 494 | /* | ||
| 495 | * the text_start should probably be o_algntext but that doesn't | ||
| 496 | * seem to change | ||
| 497 | */ | ||
| 498 | if (f_ohdr.text_start != 0) /* && scns != 0 */ | ||
| 499 | { | ||
| 500 | s->s_size = 512 - (s->s_scnptr % 512); | ||
| 501 | if (s->s_size == 512) | ||
| 502 | s->s_size = 0; | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | ptr = ptr + s->s_size; | ||
| 507 | } | ||
| 508 | 511 | ||
| 509 | bias = ptr - block_copy_start; | 512 | s->s_scnptr += bias; |
| 513 | ptr = s->s_scnptr; | ||
| 514 | } | ||
| 515 | |||
| 516 | ptr = ptr + s->s_size; | ||
| 517 | } | ||
| 510 | } | 518 | } |
| 511 | 519 | ||
| 512 | /* fix other pointers */ | 520 | /* fix other pointers */ |
| 513 | for (scns = 0; scns < f_hdr.f_nscns; scns++) { | 521 | for (scns = 0; scns < f_hdr.f_nscns; scns++) |
| 514 | struct scnhdr *s = §ion[scns]; | 522 | { |
| 523 | struct scnhdr *s = §ion[scns]; | ||
| 515 | 524 | ||
| 516 | if (s->s_relptr != 0) | 525 | if (s->s_relptr != 0) |
| 517 | { | 526 | { |
| 518 | s->s_relptr += bias; | 527 | s->s_relptr += bias; |
| 519 | } | 528 | } |
| 520 | if (s->s_lnnoptr != 0) | 529 | if (s->s_lnnoptr != 0) |
| 521 | { | 530 | { |
| 522 | if (lnnoptr == 0) lnnoptr = s->s_lnnoptr; | 531 | if (lnnoptr == 0) lnnoptr = s->s_lnnoptr; |
| 523 | s->s_lnnoptr += bias; | 532 | s->s_lnnoptr += bias; |
| 524 | } | 533 | } |
| 525 | } | 534 | } |
| 526 | 535 | ||
| 527 | if (f_hdr.f_symptr > 0L) | 536 | if (f_hdr.f_symptr > 0L) |
| 528 | { | 537 | { |
| 529 | f_hdr.f_symptr += bias; | 538 | f_hdr.f_symptr += bias; |
| 530 | } | 539 | } |
| 531 | 540 | ||
| 532 | data_st = data_start; | ||
| 533 | text_scnptr = f_thdr->s_scnptr; | 541 | text_scnptr = f_thdr->s_scnptr; |
| 534 | data_scnptr = f_dhdr->s_scnptr; | 542 | data_scnptr = f_dhdr->s_scnptr; |
| 535 | load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; | 543 | load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; |
| 536 | block_copy_start = orig_load_scnptr; | ||
| 537 | 544 | ||
| 538 | #ifdef ADJUST_EXEC_HEADER | 545 | #ifdef ADJUST_EXEC_HEADER |
| 539 | ADJUST_EXEC_HEADER | 546 | ADJUST_EXEC_HEADER |
| @@ -583,7 +590,7 @@ copy_text_and_data (new) | |||
| 583 | write_segment (new, ptr, end); | 590 | write_segment (new, ptr, end); |
| 584 | 591 | ||
| 585 | lseek (new, (long) data_scnptr, 0); | 592 | lseek (new, (long) data_scnptr, 0); |
| 586 | ptr = (char *) &_data; | 593 | ptr = (char *) data_st; |
| 587 | end = ptr + f_ohdr.dsize; | 594 | end = ptr + f_ohdr.dsize; |
| 588 | write_segment (new, ptr, end); | 595 | write_segment (new, ptr, end); |
| 589 | 596 | ||
| @@ -644,13 +651,13 @@ copy_sym (new, a_out, a_name, new_name) | |||
| 644 | if (a_out < 0) | 651 | if (a_out < 0) |
| 645 | return 0; | 652 | return 0; |
| 646 | 653 | ||
| 647 | if (SYMS_START == 0L) | 654 | if (orig_load_scnptr == 0L) |
| 648 | return 0; | 655 | return 0; |
| 649 | 656 | ||
| 650 | if (lnnoptr && lnnoptr < SYMS_START) /* if there is line number info */ | 657 | if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */ |
| 651 | lseek (a_out, lnnoptr, 0); /* start copying from there */ | 658 | lseek (a_out, lnnoptr, 0); /* start copying from there */ |
| 652 | else | 659 | else |
| 653 | lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */ | 660 | lseek (a_out, orig_load_scnptr, 0); /* Position a.out to symtab. */ |
| 654 | 661 | ||
| 655 | while ((n = read (a_out, page, sizeof page)) > 0) | 662 | while ((n = read (a_out, page, sizeof page)) > 0) |
| 656 | { | 663 | { |
| @@ -703,6 +710,8 @@ mark_x (name) | |||
| 703 | * the auxiliary entries that need adjustment, this routine will | 710 | * the auxiliary entries that need adjustment, this routine will |
| 704 | * be fixed. As it is now, all such entries are wrong and sdb | 711 | * be fixed. As it is now, all such entries are wrong and sdb |
| 705 | * will complain. Fred Fish, UniSoft Systems Inc. | 712 | * will complain. Fred Fish, UniSoft Systems Inc. |
| 713 | * | ||
| 714 | * I believe this is now fixed correctly. Bill Mann | ||
| 706 | */ | 715 | */ |
| 707 | 716 | ||
| 708 | #ifdef COFF | 717 | #ifdef COFF |
| @@ -743,15 +752,17 @@ adjust_lnnoptrs (writedesc, readdesc, new_name) | |||
| 743 | for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) | 752 | for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) |
| 744 | { | 753 | { |
| 745 | read (new, &symentry, SYMESZ); | 754 | read (new, &symentry, SYMESZ); |
| 746 | for (naux = 0; naux < symentry.n_numaux; naux++) | 755 | for (naux = symentry.n_numaux; naux-- != 0; ) |
| 747 | { | 756 | { |
| 748 | read (new, &auxentry, AUXESZ); | 757 | read (new, &auxentry, AUXESZ); |
| 749 | nsyms++; | 758 | nsyms++; |
| 750 | if (ISFCN (symentry.n_type)) { | 759 | if (naux != 0 /* skip csect auxentry (last entry) */ |
| 751 | auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; | 760 | && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT)) |
| 752 | lseek (new, -AUXESZ, 1); | 761 | { |
| 753 | write (new, &auxentry, AUXESZ); | 762 | auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; |
| 754 | } | 763 | lseek (new, -AUXESZ, 1); |
| 764 | write (new, &auxentry, AUXESZ); | ||
| 765 | } | ||
| 755 | } | 766 | } |
| 756 | } | 767 | } |
| 757 | close (new); | 768 | close (new); |
| @@ -774,8 +785,8 @@ unrelocate_symbols (new, a_out, a_name, new_name) | |||
| 774 | register LDREL *ldrel; | 785 | register LDREL *ldrel; |
| 775 | LDHDR ldhdr; | 786 | LDHDR ldhdr; |
| 776 | LDREL ldrel_buf [20]; | 787 | LDREL ldrel_buf [20]; |
| 777 | ulong t_start = (ulong) &_text; | 788 | ulong t_reloc = (ulong) &_text - f_ohdr.text_start; |
| 778 | ulong d_start = (ulong) &_data; | 789 | ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2); |
| 779 | int * p; | 790 | int * p; |
| 780 | int dirty; | 791 | int dirty; |
| 781 | 792 | ||
| @@ -837,49 +848,37 @@ unrelocate_symbols (new, a_out, a_name, new_name) | |||
| 837 | { | 848 | { |
| 838 | int orig_int; | 849 | int orig_int; |
| 839 | 850 | ||
| 840 | #ifdef AIX4_1 | 851 | lseek (a_out, |
| 841 | lseek (a_out, orig_data_scnptr + (ldrel->l_vaddr - d_start), 0); | 852 | orig_data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0); |
| 842 | #else | ||
| 843 | lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0); | ||
| 844 | #endif | ||
| 845 | 853 | ||
| 846 | if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int)) | 854 | if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int)) |
| 847 | { | 855 | { |
| 848 | PERROR (a_name); | 856 | PERROR (a_name); |
| 849 | } | 857 | } |
| 850 | 858 | ||
| 859 | p = (int *) (ldrel->l_vaddr + d_reloc); | ||
| 860 | |||
| 851 | switch (ldrel->l_symndx) { | 861 | switch (ldrel->l_symndx) { |
| 852 | case SYMNDX_TEXT: | 862 | case SYMNDX_TEXT: |
| 853 | #ifdef AIX4_1 | 863 | orig_int = * p - t_reloc; |
| 854 | p = (int *) (ldrel->l_vaddr); | ||
| 855 | orig_int = * p; | ||
| 856 | #else | ||
| 857 | p = (int *) (d_start + ldrel->l_vaddr); | ||
| 858 | orig_int = * p - (t_start - f_ohdr.text_start); | ||
| 859 | #endif | ||
| 860 | break; | 864 | break; |
| 861 | 865 | ||
| 862 | case SYMNDX_DATA: | 866 | case SYMNDX_DATA: |
| 863 | case SYMNDX_BSS: | 867 | case SYMNDX_BSS: |
| 864 | #ifdef AIX4_1 | 868 | orig_int = * p - d_reloc; |
| 865 | p = (int *) (ldrel->l_vaddr); | ||
| 866 | orig_int = * p; | ||
| 867 | #else | ||
| 868 | p = (int *) (d_start + ldrel->l_vaddr); | ||
| 869 | orig_int = * p - (d_start - f_ohdr.data_start); | ||
| 870 | #endif | ||
| 871 | break; | 869 | break; |
| 872 | } | 870 | } |
| 873 | 871 | ||
| 874 | #ifdef AIX4_1 | 872 | if (orig_int != * p) |
| 875 | lseek (new, data_scnptr + (ldrel->l_vaddr - d_start), 0); | 873 | { |
| 876 | #else | 874 | lseek (new, |
| 877 | lseek (new, data_scnptr + ldrel->l_vaddr, 0); | 875 | data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0); |
| 878 | #endif | 876 | if (write (new, (void *) &orig_int, sizeof (orig_int)) |
| 879 | if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int)) | 877 | != sizeof (orig_int)) |
| 880 | { | 878 | { |
| 881 | PERROR (new_name); | 879 | PERROR (new_name); |
| 882 | } | 880 | } |
| 881 | } | ||
| 883 | } | 882 | } |
| 884 | } | 883 | } |
| 885 | } | 884 | } |