Mercurial > hg > xemacs-beta
comparison src/unexelf.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | 501cfd01ee6d |
children | 11054d720c21 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
16 You should have received a copy of the GNU General Public License | 16 You should have received a copy of the GNU General Public License |
17 along with XEmacs; see the file COPYING. If not, write to | 17 along with XEmacs; see the file COPYING. If not, write to |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 Boston, MA 02111-1307, USA. */ | 19 Boston, MA 02111-1307, USA. */ |
20 | 20 |
21 /* Synched up with: FSF 20.4. */ | 21 /* Synched up with: FSF 20.2. */ |
22 | 22 |
23 /* | 23 /* |
24 * unexec.c - Convert a running program into an a.out file. | 24 * unexec.c - Convert a running program into an a.out file. |
25 * | 25 * |
26 * Author: Spencer W. Thomas | 26 * Author: Spencer W. Thomas |
411 | 411 |
412 #ifndef emacs | 412 #ifndef emacs |
413 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) | 413 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) |
414 #else | 414 #else |
415 #include <config.h> | 415 #include <config.h> |
416 extern void fatal (const char *, ...); | 416 extern void fatal (CONST char *, ...); |
417 #endif | 417 #endif |
418 | 418 |
419 #include <sys/types.h> | 419 #include <sys/types.h> |
420 #include <stdio.h> | 420 #include <stdio.h> |
421 #include <sys/stat.h> | 421 #include <sys/stat.h> |
422 #include <memory.h> | 422 #include <memory.h> |
423 #include <string.h> | 423 #include <string.h> |
424 #include <errno.h> | 424 #include <errno.h> |
425 #include <unistd.h> | 425 #include <unistd.h> |
426 #include <fcntl.h> | 426 #include <fcntl.h> |
427 #if !defined (__NetBSD__) && !defined (__OpenBSD__) | |
428 #include <elf.h> | 427 #include <elf.h> |
429 #endif | |
430 #include <sys/mman.h> | 428 #include <sys/mman.h> |
431 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) | 429 |
432 #include <sys/elf_mips.h> | 430 #if __GLIBC__ - 0 >= 2 |
433 #include <sym.h> | |
434 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
435 #ifdef __sgi | |
436 #include <sym.h> /* for HDRR declaration */ | |
437 #endif /* __sgi */ | |
438 | |
439 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__) | |
440 /* Declare COFF debugging symbol table. This used to be in | |
441 /usr/include/sym.h, but this file is no longer included in Red Hat | |
442 5.0 and presumably in any other glibc 2.x based distribution. */ | |
443 typedef struct { | |
444 short magic; | |
445 short vstamp; | |
446 int ilineMax; | |
447 int idnMax; | |
448 int ipdMax; | |
449 int isymMax; | |
450 int ioptMax; | |
451 int iauxMax; | |
452 int issMax; | |
453 int issExtMax; | |
454 int ifdMax; | |
455 int crfd; | |
456 int iextMax; | |
457 long cbLine; | |
458 long cbLineOffset; | |
459 long cbDnOffset; | |
460 long cbPdOffset; | |
461 long cbSymOffset; | |
462 long cbOptOffset; | |
463 long cbAuxOffset; | |
464 long cbSsOffset; | |
465 long cbSsExtOffset; | |
466 long cbFdOffset; | |
467 long cbRfdOffset; | |
468 long cbExtOffset; | |
469 } HDRR, *pHDRR; | |
470 #define cbHDRR sizeof(HDRR) | |
471 #define hdrNil ((pHDRR)0) | |
472 #endif | |
473 | |
474 #ifdef __NetBSD__ | |
475 /* | |
476 * NetBSD does not have normal-looking user-land ELF support. | |
477 */ | |
478 # ifdef __alpha__ | |
479 # define ELFSIZE 64 | |
480 # else | |
481 # define ELFSIZE 32 | |
482 # endif | |
483 # include <sys/exec_elf.h> | |
484 | |
485 # define PT_LOAD Elf_pt_load | |
486 # define SHT_SYMTAB Elf_sht_symtab | |
487 # define SHT_DYNSYM Elf_sht_dynsym | |
488 # define SHT_NULL Elf_sht_null | |
489 # define SHT_NOBITS Elf_sht_nobits | |
490 # define SHT_REL Elf_sht_rel | |
491 # define SHT_RELA Elf_sht_rela | |
492 | |
493 # define SHN_UNDEF Elf_eshn_undefined | |
494 # define SHN_ABS Elf_eshn_absolute | |
495 # define SHN_COMMON Elf_eshn_common | |
496 | |
497 # ifdef __alpha__ | |
498 # include <sys/exec_ecoff.h> | |
499 # define HDRR struct ecoff_symhdr | |
500 # define pHDRR HDRR * | |
501 # endif | |
502 #endif /* __NetBSD__ */ | |
503 | |
504 #ifdef __OpenBSD__ | |
505 # include <sys/exec_elf.h> | |
506 #endif | |
507 | |
508 #if __GNU_LIBRARY__ - 0 >= 6 | |
509 # include <link.h> /* get ElfW etc */ | 431 # include <link.h> /* get ElfW etc */ |
510 #endif | 432 #endif |
511 | 433 |
512 #ifndef ElfW | 434 #ifndef ElfW |
513 # ifdef __STDC__ | 435 # ifdef __STDC__ |
563 (n)++; } while (0) | 485 (n)++; } while (0) |
564 typedef unsigned char byte; | 486 typedef unsigned char byte; |
565 | 487 |
566 /* Round X up to a multiple of Y. */ | 488 /* Round X up to a multiple of Y. */ |
567 | 489 |
568 static ElfW(Addr) | 490 static int |
569 round_up (ElfW(Addr) x, ElfW(Addr) y) | 491 round_up (int x, int y) |
570 { | 492 { |
571 int rem = x % y; | 493 int rem = x % y; |
572 if (rem == 0) | 494 if (rem == 0) |
573 return x; | 495 return x; |
574 return x - rem + y; | 496 return x - rem + y; |
607 ElfW(Addr) old_bss_addr, new_bss_addr; | 529 ElfW(Addr) old_bss_addr, new_bss_addr; |
608 ElfW(Word) old_bss_size, new_data2_size; | 530 ElfW(Word) old_bss_size, new_data2_size; |
609 ElfW(Off) new_data2_offset; | 531 ElfW(Off) new_data2_offset; |
610 ElfW(Addr) new_data2_addr; | 532 ElfW(Addr) new_data2_addr; |
611 | 533 |
612 int n, nn, old_bss_index, old_data_index, new_data2_index; | 534 int n, nn, old_bss_index, old_data_index; |
613 int old_sbss_index, old_mdebug_index; | |
614 struct stat stat_buf; | 535 struct stat stat_buf; |
615 | 536 |
616 /* Open the old file & map it into the address space. */ | 537 /* Open the old file & map it into the address space. */ |
617 | 538 |
618 old_file = open (old_name, O_RDONLY); | 539 old_file = open (old_name, O_RDONLY); |
621 fatal ("Can't open %s for reading: errno %d\n", old_name, errno); | 542 fatal ("Can't open %s for reading: errno %d\n", old_name, errno); |
622 | 543 |
623 if (fstat (old_file, &stat_buf) == -1) | 544 if (fstat (old_file, &stat_buf) == -1) |
624 fatal ("Can't fstat (%s): errno %d\n", old_name, errno); | 545 fatal ("Can't fstat (%s): errno %d\n", old_name, errno); |
625 | 546 |
626 old_base = (caddr_t) mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); | 547 old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); |
627 | 548 |
628 if (old_base == (caddr_t) -1) | 549 if (old_base == (caddr_t) -1) |
629 fatal ("Can't mmap (%s): errno %d\n", old_name, errno); | 550 fatal ("Can't mmap (%s): errno %d\n", old_name, errno); |
630 | 551 |
631 #ifdef DEBUG | 552 #ifdef DEBUG |
657 break; | 578 break; |
658 } | 579 } |
659 if (old_bss_index == old_file_h->e_shnum) | 580 if (old_bss_index == old_file_h->e_shnum) |
660 fatal ("Can't find .bss in %s.\n", old_name, 0); | 581 fatal ("Can't find .bss in %s.\n", old_name, 0); |
661 | 582 |
662 for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum; | 583 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
663 old_sbss_index++) | 584 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
664 { | |
665 #ifdef DEBUG | |
666 fprintf (stderr, "Looking for .sbss - found %s\n", | |
667 old_section_names + OLD_SECTION_H (old_sbss_index).sh_name); | |
668 #endif | |
669 if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name, | |
670 ".sbss")) | |
671 break; | |
672 } | |
673 if (old_sbss_index == old_file_h->e_shnum) | |
674 { | |
675 old_sbss_index = -1; | |
676 old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr; | |
677 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size; | |
678 new_data2_index = old_bss_index; | |
679 } | |
680 else | |
681 { | |
682 old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr; | |
683 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size | |
684 + OLD_SECTION_H(old_sbss_index).sh_size; | |
685 new_data2_index = old_sbss_index; | |
686 } | |
687 | |
688 for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum; | |
689 old_mdebug_index++) | |
690 { | |
691 #ifdef DEBUG | |
692 fprintf (stderr, "Looking for .mdebug - found %s\n", | |
693 old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name); | |
694 #endif | |
695 if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name, | |
696 ".mdebug")) | |
697 break; | |
698 } | |
699 if (old_mdebug_index == old_file_h->e_shnum) | |
700 old_mdebug_index = 0; | |
701 | |
702 for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum; | |
703 old_data_index++) | |
704 { | |
705 #ifdef DEBUG | |
706 fprintf (stderr, "Looking for .data - found %s\n", | |
707 old_section_names + OLD_SECTION_H (old_data_index).sh_name); | |
708 #endif | |
709 if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name, | |
710 ".data")) | |
711 break; | |
712 } | |
713 if (old_data_index == old_file_h->e_shnum) | |
714 old_data_index = 0; | |
715 | |
716 #if defined (emacs) || !defined (DEBUG) | 585 #if defined (emacs) || !defined (DEBUG) |
717 new_bss_addr = (ElfW(Addr)) sbrk (0); | 586 new_bss_addr = (ElfW(Addr)) sbrk (0); |
718 #else | 587 #else |
719 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 588 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
720 #endif | 589 #endif |
721 new_data2_addr = old_bss_addr; | 590 new_data2_addr = old_bss_addr; |
722 new_data2_size = new_bss_addr - old_bss_addr; | 591 new_data2_size = new_bss_addr - old_bss_addr; |
723 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + | 592 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; |
724 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | |
725 | 593 |
726 #ifdef DEBUG | 594 #ifdef DEBUG |
727 fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 595 fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
728 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 596 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
729 fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 597 fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
748 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; | 616 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; |
749 | 617 |
750 if (ftruncate (new_file, new_file_size)) | 618 if (ftruncate (new_file, new_file_size)) |
751 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); | 619 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); |
752 | 620 |
753 new_base = (caddr_t) mmap (0, new_file_size, PROT_READ | PROT_WRITE, | |
754 #ifdef UNEXEC_USE_MAP_PRIVATE | 621 #ifdef UNEXEC_USE_MAP_PRIVATE |
755 MAP_PRIVATE, | 622 new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, |
623 new_file, 0); | |
756 #else | 624 #else |
757 MAP_SHARED, | 625 new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, |
758 #endif | 626 new_file, 0); |
759 new_file, 0); | 627 #endif |
760 | 628 |
761 if (new_base == (caddr_t) -1) | 629 if (new_base == (caddr_t) -1) |
762 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | 630 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); |
763 | 631 |
764 new_file_h = (ElfW(Ehdr) *) new_base; | 632 new_file_h = (ElfW(Ehdr) *) new_base; |
804 /* Compute maximum of all requirements for alignment of section. */ | 672 /* Compute maximum of all requirements for alignment of section. */ |
805 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; | 673 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; |
806 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 674 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
807 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 675 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
808 | 676 |
809 #ifdef __mips | 677 #ifndef __mips /* ifndef added by jwz at suggestion of |
810 /* According to r02kar@x4u2.desy.de (Karsten Kuenne) | 678 r02kar@x4u2.desy.de (Karsten Kuenne) to avoid |
811 and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we | 679 "Program segment above .bss" when dumping. |
812 always get "Program segment above .bss" when dumping | 680 */ |
813 when the executable doesn't have an sbss section. */ | 681 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) |
814 if (old_sbss_index != -1) | 682 fatal ("Program segment above .bss in %s\n", old_name, 0); |
815 #endif /* __mips */ | 683 #endif /* __mips */ |
816 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz | |
817 > (old_sbss_index == -1 | |
818 ? old_bss_addr | |
819 : round_up (old_bss_addr, alignment))) | |
820 fatal ("Program segment above .bss in %s\n", old_name, 0); | |
821 | 684 |
822 if (NEW_PROGRAM_H (n).p_type == PT_LOAD | 685 if (NEW_PROGRAM_H (n).p_type == PT_LOAD |
823 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | 686 && (round_up ((int) ((NEW_PROGRAM_H (n)).p_vaddr |
824 + (NEW_PROGRAM_H (n)).p_filesz, | 687 + (NEW_PROGRAM_H (n)).p_filesz), |
825 alignment) | 688 alignment) |
826 == round_up (old_bss_addr, alignment))) | 689 == round_up ((int) old_bss_addr, alignment))) |
827 break; | 690 break; |
828 } | 691 } |
829 if (n < 0) | 692 if (n < 0) |
830 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | 693 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); |
831 | 694 |
832 /* Make sure that the size includes any padding before the old .bss | |
833 section. */ | |
834 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; | 695 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; |
835 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | 696 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; |
836 | 697 |
837 #if 0 /* Maybe allow section after data2 - does this ever happen? */ | 698 #if 0 /* Maybe allow section after data2 - does this ever happen? */ |
838 for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 699 for (n = new_file_h->e_phnum - 1; n >= 0; n--) |
863 /* Walk through all section headers, insert the new data2 section right | 724 /* Walk through all section headers, insert the new data2 section right |
864 before the new bss section. */ | 725 before the new bss section. */ |
865 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) | 726 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) |
866 { | 727 { |
867 caddr_t src; | 728 caddr_t src; |
868 /* If it is (s)bss section, insert the new data2 section before it. */ | 729 /* If it is bss section, insert the new data2 section before it. */ |
869 /* new_data2_index is the index of either old_sbss or old_bss, that was | 730 if (n == old_bss_index) |
870 chosen as a section for new_data2. */ | |
871 if (n == new_data2_index) | |
872 { | 731 { |
873 /* Steal the data section header for this data2 section. */ | 732 /* Steal the data section header for this data2 section. */ |
874 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), | 733 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), |
875 new_file_h->e_shentsize); | 734 new_file_h->e_shentsize); |
876 | 735 |
883 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; | 742 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; |
884 | 743 |
885 /* Now copy over what we have in the memory now. */ | 744 /* Now copy over what we have in the memory now. */ |
886 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, | 745 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, |
887 (caddr_t) OLD_SECTION_H (n).sh_addr, | 746 (caddr_t) OLD_SECTION_H (n).sh_addr, |
747 /* #### mrb: should be old_bss_size instead? */ | |
888 new_data2_size); | 748 new_data2_size); |
889 nn++; | 749 nn++; |
890 } | 750 } |
891 | 751 |
892 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | 752 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), |
893 old_file_h->e_shentsize); | 753 old_file_h->e_shentsize); |
894 | 754 |
895 if (n == old_bss_index | 755 /* The new bss section's size is zero, and its file offset and virtual |
896 /* The new bss and sbss section's size is zero, and its file offset | 756 address should be off by NEW_DATA2_SIZE. */ |
897 and virtual address should be off by NEW_DATA2_SIZE. */ | 757 if (n == old_bss_index) |
898 || n == old_sbss_index | |
899 ) | |
900 { | 758 { |
901 /* NN should be `old_s?bss_index + 1' at this point. */ | 759 /* NN should be `old_bss_index + 1' at this point. */ |
902 NEW_SECTION_H (nn).sh_offset = | 760 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
903 NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size; | 761 NEW_SECTION_H (nn).sh_addr += new_data2_size; |
904 NEW_SECTION_H (nn).sh_addr = | |
905 NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size; | |
906 /* Let the new bss section address alignment be the same as the | 762 /* Let the new bss section address alignment be the same as the |
907 section address alignment followed the old bss section, so | 763 section address alignment followed the old bss section, so |
908 this section will be placed in exactly the same place. */ | 764 this section will be placed in exactly the same place. */ |
909 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; | 765 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; |
910 NEW_SECTION_H (nn).sh_size = 0; | 766 NEW_SECTION_H (nn).sh_size = 0; |
924 Erik Deumens, deumens@qtp.ufl.edu. */ | 780 Erik Deumens, deumens@qtp.ufl.edu. */ |
925 if (NEW_SECTION_H (nn).sh_offset | 781 if (NEW_SECTION_H (nn).sh_offset |
926 >= OLD_SECTION_H (old_bss_index-1).sh_offset) | 782 >= OLD_SECTION_H (old_bss_index-1).sh_offset) |
927 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 783 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
928 #else | 784 #else |
929 if (round_up (NEW_SECTION_H (nn).sh_offset, | 785 if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) |
930 OLD_SECTION_H (old_bss_index).sh_addralign) | |
931 >= new_data2_offset) | |
932 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 786 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
933 #endif | 787 #endif |
934 /* Any section that was originally placed after the section | 788 /* Any section that was originally placed after the section |
935 header table should now be off by the size of one section | 789 header table should now be off by the size of one section |
936 header table entry. */ | 790 header table entry. */ |
955 continue; | 809 continue; |
956 | 810 |
957 /* Write out the sections. .data and .data1 (and data2, called | 811 /* Write out the sections. .data and .data1 (and data2, called |
958 ".data" in the strings table) get copied from the current process | 812 ".data" in the strings table) get copied from the current process |
959 instead of the old file. */ | 813 instead of the old file. */ |
814 #ifdef __powerpc__ | |
815 /* The PowerPC has additional 'data' segments which need to be saved */ | |
816 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || | |
817 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || | |
818 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || | |
819 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) | |
820 #else | |
960 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | 821 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") |
961 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | 822 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), |
962 ".sdata") | |
963 /* Taking these sections from the current process, breaks | |
964 Linux in a subtle way. Binaries only run on the | |
965 architecture (e.g. i586 vs i686) of the dumping machine */ | |
966 #ifdef __sgi | |
967 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
968 ".lit4") | |
969 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
970 ".lit8") | |
971 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
972 ".got") | |
973 #endif | |
974 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
975 ".sdata1") | |
976 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
977 ".data1")) | 823 ".data1")) |
824 #endif | |
978 src = (caddr_t) OLD_SECTION_H (n).sh_addr; | 825 src = (caddr_t) OLD_SECTION_H (n).sh_addr; |
979 else | 826 else |
980 src = old_base + OLD_SECTION_H (n).sh_offset; | 827 src = old_base + OLD_SECTION_H (n).sh_offset; |
981 | 828 |
982 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 829 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
983 NEW_SECTION_H (nn).sh_size); | 830 NEW_SECTION_H (nn).sh_size); |
984 | |
985 #ifdef __alpha__ | |
986 /* Update Alpha COFF symbol table: */ | |
987 if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") | |
988 == 0) | |
989 { | |
990 pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); | |
991 | |
992 symhdr->cbLineOffset += new_data2_size; | |
993 symhdr->cbDnOffset += new_data2_size; | |
994 symhdr->cbPdOffset += new_data2_size; | |
995 symhdr->cbSymOffset += new_data2_size; | |
996 symhdr->cbOptOffset += new_data2_size; | |
997 symhdr->cbAuxOffset += new_data2_size; | |
998 symhdr->cbSsOffset += new_data2_size; | |
999 symhdr->cbSsExtOffset += new_data2_size; | |
1000 symhdr->cbFdOffset += new_data2_size; | |
1001 symhdr->cbRfdOffset += new_data2_size; | |
1002 symhdr->cbExtOffset += new_data2_size; | |
1003 } | |
1004 #endif /* __alpha__ */ | |
1005 | |
1006 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) | |
1007 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) | |
1008 { | |
1009 int diff = NEW_SECTION_H(nn).sh_offset | |
1010 - OLD_SECTION_H(old_mdebug_index).sh_offset; | |
1011 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); | |
1012 | |
1013 if (diff) | |
1014 { | |
1015 phdr->cbLineOffset += diff; | |
1016 phdr->cbDnOffset += diff; | |
1017 phdr->cbPdOffset += diff; | |
1018 phdr->cbSymOffset += diff; | |
1019 phdr->cbOptOffset += diff; | |
1020 phdr->cbAuxOffset += diff; | |
1021 phdr->cbSsOffset += diff; | |
1022 phdr->cbSsExtOffset += diff; | |
1023 phdr->cbFdOffset += diff; | |
1024 phdr->cbRfdOffset += diff; | |
1025 phdr->cbExtOffset += diff; | |
1026 } | |
1027 } | |
1028 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
1029 | |
1030 #ifdef __sgi | |
1031 /* Adjust the HDRR offsets in .mdebug and copy the | |
1032 line data if it's in its usual 'hole' in the object. | |
1033 Makes the new file debuggable with dbx. | |
1034 patches up two problems: the absolute file offsets | |
1035 in the HDRR record of .mdebug (see /usr/include/syms.h), and | |
1036 the ld bug that gets the line table in a hole in the | |
1037 elf file rather than in the .mdebug section proper. | |
1038 David Anderson. davea@sgi.com Jan 16,1994. */ | |
1039 if (n == old_mdebug_index) | |
1040 { | |
1041 #define MDEBUGADJUST(__ct,__fileaddr) \ | |
1042 if (n_phdrr->__ct > 0) \ | |
1043 { \ | |
1044 n_phdrr->__fileaddr += movement; \ | |
1045 } | |
1046 | |
1047 HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); | |
1048 HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); | |
1049 unsigned movement = new_data2_size; | |
1050 | |
1051 MDEBUGADJUST (idnMax, cbDnOffset); | |
1052 MDEBUGADJUST (ipdMax, cbPdOffset); | |
1053 MDEBUGADJUST (isymMax, cbSymOffset); | |
1054 MDEBUGADJUST (ioptMax, cbOptOffset); | |
1055 MDEBUGADJUST (iauxMax, cbAuxOffset); | |
1056 MDEBUGADJUST (issMax, cbSsOffset); | |
1057 MDEBUGADJUST (issExtMax, cbSsExtOffset); | |
1058 MDEBUGADJUST (ifdMax, cbFdOffset); | |
1059 MDEBUGADJUST (crfd, cbRfdOffset); | |
1060 MDEBUGADJUST (iextMax, cbExtOffset); | |
1061 /* The Line Section, being possible off in a hole of the object, | |
1062 requires special handling. */ | |
1063 if (n_phdrr->cbLine > 0) | |
1064 { | |
1065 if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset | |
1066 + OLD_SECTION_H (n).sh_size)) | |
1067 { | |
1068 /* line data is in a hole in elf. do special copy and adjust | |
1069 for this ld mistake. | |
1070 */ | |
1071 n_phdrr->cbLineOffset += movement; | |
1072 | |
1073 memcpy (n_phdrr->cbLineOffset + new_base, | |
1074 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); | |
1075 } | |
1076 else | |
1077 { | |
1078 /* somehow line data is in .mdebug as it is supposed to be. */ | |
1079 MDEBUGADJUST (cbLine, cbLineOffset); | |
1080 } | |
1081 } | |
1082 } | |
1083 #endif /* __sgi */ | |
1084 | 831 |
1085 /* If it is the symbol table, its st_shndx field needs to be patched. */ | 832 /* If it is the symbol table, its st_shndx field needs to be patched. */ |
1086 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 833 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
1087 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 834 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
1088 { | 835 { |
1137 case SHT_RELA: | 884 case SHT_RELA: |
1138 /* This code handles two different size structs, but there should | 885 /* This code handles two different size structs, but there should |
1139 be no harm in that provided that r_offset is always the first | 886 be no harm in that provided that r_offset is always the first |
1140 member. */ | 887 member. */ |
1141 nn = section.sh_info; | 888 nn = section.sh_info; |
889 #ifdef __powerpc__ | |
890 /* The PowerPC has additional 'data' segments which need to be saved */ | |
891 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || | |
892 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || | |
893 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || | |
894 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) | |
895 #else | |
1142 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | 896 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") |
1143 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | 897 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), |
1144 ".sdata") | |
1145 #ifdef __sgi | |
1146 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1147 ".lit4") | |
1148 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1149 ".lit8") | |
1150 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1151 ".got") | |
1152 #endif | |
1153 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1154 ".sdata1") | |
1155 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1156 ".data1")) | 898 ".data1")) |
899 #endif | |
1157 { | 900 { |
1158 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - | 901 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - |
1159 NEW_SECTION_H (nn).sh_offset; | 902 NEW_SECTION_H (nn).sh_offset; |
1160 caddr_t reloc = old_base + section.sh_offset, end; | 903 caddr_t reloc = old_base + section.sh_offset, end; |
1161 for (end = reloc + section.sh_size; reloc < end; | 904 for (end = reloc + section.sh_size; reloc < end; |
1162 reloc += section.sh_entsize) | 905 reloc += section.sh_entsize) |
1163 { | 906 { |
1164 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; | 907 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; |
1165 #ifdef __alpha__ | |
1166 /* The Alpha ELF binutils currently have a bug that | |
1167 sometimes results in relocs that contain all | |
1168 zeroes. Work around this for now... */ | |
1169 if (((ElfW(Rel) *) reloc)->r_offset == 0) | |
1170 continue; | |
1171 #endif | |
1172 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); | 908 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); |
1173 } | 909 } |
1174 } | 910 } |
1175 break; | 911 break; |
1176 } | 912 } |