Mercurial > hg > xemacs-beta
comparison src/unexelf.c @ 353:3b3709405255 r21-1-6
Import from CVS: tag r21-1-6
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:55:33 +0200 |
parents | afd57c14dfc8 |
children | 4711e16a8e49 |
comparison
equal
deleted
inserted
replaced
352:e7288c5461ae | 353:3b3709405255 |
---|---|
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.2. */ | 21 /* Synched up with: FSF 20.4. */ |
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 |
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__) | |
427 #include <elf.h> | 428 #include <elf.h> |
429 #endif | |
428 #include <sys/mman.h> | 430 #include <sys/mman.h> |
429 | 431 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) |
430 #if __GLIBC__ - 0 >= 2 | 432 #include <sys/elf_mips.h> |
433 #include <sym.h> | |
434 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
435 #if __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 /* | |
498 * The magic of picking the right size types is handled by the ELFSIZE | |
499 * definition above. | |
500 */ | |
501 # ifdef __STDC__ | |
502 # define ElfW(type) Elf_##type | |
503 # else | |
504 # define ElfW(type) Elf_/**/type | |
505 # endif | |
506 | |
507 # ifdef __alpha__ | |
508 # include <sys/exec_ecoff.h> | |
509 # define HDRR struct ecoff_symhdr | |
510 # define pHDRR HDRR * | |
511 # endif | |
512 #endif /* __NetBSD__ */ | |
513 | |
514 #ifdef __OpenBSD__ | |
515 # include <sys/exec_elf.h> | |
516 #endif | |
517 | |
518 #if __GNU_LIBRARY__ - 0 >= 6 | |
431 # include <link.h> /* get ElfW etc */ | 519 # include <link.h> /* get ElfW etc */ |
432 #endif | 520 #endif |
433 | 521 |
434 #ifndef ElfW | 522 #ifndef ElfW |
435 # ifdef __STDC__ | 523 # ifdef __STDC__ |
485 (n)++; } while (0) | 573 (n)++; } while (0) |
486 typedef unsigned char byte; | 574 typedef unsigned char byte; |
487 | 575 |
488 /* Round X up to a multiple of Y. */ | 576 /* Round X up to a multiple of Y. */ |
489 | 577 |
490 static int | 578 static ElfW(Addr) |
491 round_up (int x, int y) | 579 round_up (ElfW(Addr) x, ElfW(Addr) y) |
492 { | 580 { |
493 int rem = x % y; | 581 int rem = x % y; |
494 if (rem == 0) | 582 if (rem == 0) |
495 return x; | 583 return x; |
496 return x - rem + y; | 584 return x - rem + y; |
529 ElfW(Addr) old_bss_addr, new_bss_addr; | 617 ElfW(Addr) old_bss_addr, new_bss_addr; |
530 ElfW(Word) old_bss_size, new_data2_size; | 618 ElfW(Word) old_bss_size, new_data2_size; |
531 ElfW(Off) new_data2_offset; | 619 ElfW(Off) new_data2_offset; |
532 ElfW(Addr) new_data2_addr; | 620 ElfW(Addr) new_data2_addr; |
533 | 621 |
534 int n, nn, old_bss_index, old_data_index; | 622 int n, nn, old_bss_index, old_data_index, new_data2_index; |
623 int old_sbss_index, old_mdebug_index; | |
535 struct stat stat_buf; | 624 struct stat stat_buf; |
536 | 625 |
537 /* Open the old file & map it into the address space. */ | 626 /* Open the old file & map it into the address space. */ |
538 | 627 |
539 old_file = open (old_name, O_RDONLY); | 628 old_file = open (old_name, O_RDONLY); |
578 break; | 667 break; |
579 } | 668 } |
580 if (old_bss_index == old_file_h->e_shnum) | 669 if (old_bss_index == old_file_h->e_shnum) |
581 fatal ("Can't find .bss in %s.\n", old_name, 0); | 670 fatal ("Can't find .bss in %s.\n", old_name, 0); |
582 | 671 |
583 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 672 for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum; |
584 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 673 old_sbss_index++) |
674 { | |
675 #ifdef DEBUG | |
676 fprintf (stderr, "Looking for .sbss - found %s\n", | |
677 old_section_names + OLD_SECTION_H (old_sbss_index).sh_name); | |
678 #endif | |
679 if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name, | |
680 ".sbss")) | |
681 break; | |
682 } | |
683 if (old_sbss_index == old_file_h->e_shnum) | |
684 { | |
685 old_sbss_index = -1; | |
686 old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr; | |
687 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size; | |
688 new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset; | |
689 new_data2_index = old_bss_index; | |
690 } | |
691 else | |
692 { | |
693 old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr; | |
694 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size | |
695 + OLD_SECTION_H(old_sbss_index).sh_size; | |
696 new_data2_offset = OLD_SECTION_H(old_sbss_index).sh_offset; | |
697 new_data2_index = old_sbss_index; | |
698 } | |
699 | |
700 for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum; | |
701 old_mdebug_index++) | |
702 { | |
703 #ifdef DEBUG | |
704 fprintf (stderr, "Looking for .mdebug - found %s\n", | |
705 old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name); | |
706 #endif | |
707 if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name, | |
708 ".mdebug")) | |
709 break; | |
710 } | |
711 if (old_mdebug_index == old_file_h->e_shnum) | |
712 old_mdebug_index = 0; | |
713 | |
585 #if defined (emacs) || !defined (DEBUG) | 714 #if defined (emacs) || !defined (DEBUG) |
586 new_bss_addr = (ElfW(Addr)) sbrk (0); | 715 new_bss_addr = (ElfW(Addr)) sbrk (0); |
587 #else | 716 #else |
588 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 717 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
589 #endif | 718 #endif |
590 new_data2_addr = old_bss_addr; | 719 new_data2_addr = old_bss_addr; |
591 new_data2_size = new_bss_addr - old_bss_addr; | 720 new_data2_size = new_bss_addr - old_bss_addr; |
592 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; | |
593 | 721 |
594 #ifdef DEBUG | 722 #ifdef DEBUG |
595 fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 723 fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
596 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 724 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
597 fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 725 fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
672 /* Compute maximum of all requirements for alignment of section. */ | 800 /* Compute maximum of all requirements for alignment of section. */ |
673 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; | 801 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; |
674 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 802 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
675 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 803 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
676 | 804 |
677 #ifndef __mips /* ifndef added by jwz at suggestion of | 805 #ifdef __mips |
678 r02kar@x4u2.desy.de (Karsten Kuenne) to avoid | 806 /* According to r02kar@x4u2.desy.de (Karsten Kuenne) |
679 "Program segment above .bss" when dumping. | 807 and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we |
680 */ | 808 always get "Program segment above .bss" when dumping |
681 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) | 809 when the executable doesn't have an sbss section. */ |
682 fatal ("Program segment above .bss in %s\n", old_name, 0); | 810 if (old_sbss_index != -1) |
683 #endif /* __mips */ | 811 #endif /* __mips */ |
812 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz | |
813 > (old_sbss_index == -1 | |
814 ? old_bss_addr | |
815 : round_up (old_bss_addr, alignment))) | |
816 fatal ("Program segment above .bss in %s\n", old_name, 0); | |
684 | 817 |
685 if (NEW_PROGRAM_H (n).p_type == PT_LOAD | 818 if (NEW_PROGRAM_H (n).p_type == PT_LOAD |
686 && (round_up ((int) ((NEW_PROGRAM_H (n)).p_vaddr | 819 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr |
687 + (NEW_PROGRAM_H (n)).p_filesz), | 820 + (NEW_PROGRAM_H (n)).p_filesz, |
688 alignment) | 821 alignment) |
689 == round_up ((int) old_bss_addr, alignment))) | 822 == round_up (old_bss_addr, alignment))) |
690 break; | 823 break; |
691 } | 824 } |
692 if (n < 0) | 825 if (n < 0) |
693 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | 826 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); |
694 | 827 |
828 /* Make sure that the size includes any padding before the old .bss | |
829 section. */ | |
695 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; | 830 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; |
696 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | 831 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; |
697 | 832 |
698 #if 0 /* Maybe allow section after data2 - does this ever happen? */ | 833 #if 0 /* Maybe allow section after data2 - does this ever happen? */ |
699 for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 834 for (n = new_file_h->e_phnum - 1; n >= 0; n--) |
724 /* Walk through all section headers, insert the new data2 section right | 859 /* Walk through all section headers, insert the new data2 section right |
725 before the new bss section. */ | 860 before the new bss section. */ |
726 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) | 861 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) |
727 { | 862 { |
728 caddr_t src; | 863 caddr_t src; |
729 /* If it is bss section, insert the new data2 section before it. */ | 864 /* If it is (s)bss section, insert the new data2 section before it. */ |
730 if (n == old_bss_index) | 865 /* new_data2_index is the index of either old_sbss or old_bss, that was |
866 chosen as a section for new_data2. */ | |
867 if (n == new_data2_index) | |
731 { | 868 { |
732 /* Steal the data section header for this data2 section. */ | 869 /* Steal the data section header for this data2 section. */ |
733 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), | 870 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), |
734 new_file_h->e_shentsize); | 871 new_file_h->e_shentsize); |
735 | 872 |
742 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; | 879 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; |
743 | 880 |
744 /* Now copy over what we have in the memory now. */ | 881 /* Now copy over what we have in the memory now. */ |
745 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, | 882 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, |
746 (caddr_t) OLD_SECTION_H (n).sh_addr, | 883 (caddr_t) OLD_SECTION_H (n).sh_addr, |
747 /* #### mrb: should be old_bss_size instead? */ | |
748 new_data2_size); | 884 new_data2_size); |
749 nn++; | 885 nn++; |
750 } | 886 } |
751 | 887 |
752 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | 888 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), |
753 old_file_h->e_shentsize); | 889 old_file_h->e_shentsize); |
754 | 890 |
755 /* The new bss section's size is zero, and its file offset and virtual | 891 if (n == old_bss_index |
756 address should be off by NEW_DATA2_SIZE. */ | 892 /* The new bss and sbss section's size is zero, and its file offset |
757 if (n == old_bss_index) | 893 and virtual address should be off by NEW_DATA2_SIZE. */ |
894 || n == old_sbss_index | |
895 ) | |
758 { | 896 { |
759 /* NN should be `old_bss_index + 1' at this point. */ | 897 /* NN should be `old_s?bss_index + 1' at this point. */ |
760 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 898 NEW_SECTION_H (nn).sh_offset = |
761 NEW_SECTION_H (nn).sh_addr += new_data2_size; | 899 NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size; |
900 NEW_SECTION_H (nn).sh_addr = | |
901 NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size; | |
762 /* Let the new bss section address alignment be the same as the | 902 /* Let the new bss section address alignment be the same as the |
763 section address alignment followed the old bss section, so | 903 section address alignment followed the old bss section, so |
764 this section will be placed in exactly the same place. */ | 904 this section will be placed in exactly the same place. */ |
765 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; | 905 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; |
766 NEW_SECTION_H (nn).sh_size = 0; | 906 NEW_SECTION_H (nn).sh_size = 0; |
780 Erik Deumens, deumens@qtp.ufl.edu. */ | 920 Erik Deumens, deumens@qtp.ufl.edu. */ |
781 if (NEW_SECTION_H (nn).sh_offset | 921 if (NEW_SECTION_H (nn).sh_offset |
782 >= OLD_SECTION_H (old_bss_index-1).sh_offset) | 922 >= OLD_SECTION_H (old_bss_index-1).sh_offset) |
783 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 923 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
784 #else | 924 #else |
785 if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) | 925 if (round_up (NEW_SECTION_H (nn).sh_offset, |
926 OLD_SECTION_H (old_bss_index).sh_addralign) | |
927 >= new_data2_offset) | |
786 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 928 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
787 #endif | 929 #endif |
788 /* Any section that was originally placed after the section | 930 /* Any section that was originally placed after the section |
789 header table should now be off by the size of one section | 931 header table should now be off by the size of one section |
790 header table entry. */ | 932 header table entry. */ |
809 continue; | 951 continue; |
810 | 952 |
811 /* Write out the sections. .data and .data1 (and data2, called | 953 /* Write out the sections. .data and .data1 (and data2, called |
812 ".data" in the strings table) get copied from the current process | 954 ".data" in the strings table) get copied from the current process |
813 instead of the old file. */ | 955 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 | |
821 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | 956 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") |
822 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | 957 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), |
958 ".sdata") | |
959 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
960 ".lit4") | |
961 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
962 ".lit8") | |
963 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
964 ".got") | |
965 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
966 ".sdata1") | |
967 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
823 ".data1")) | 968 ".data1")) |
824 #endif | |
825 src = (caddr_t) OLD_SECTION_H (n).sh_addr; | 969 src = (caddr_t) OLD_SECTION_H (n).sh_addr; |
826 else | 970 else |
827 src = old_base + OLD_SECTION_H (n).sh_offset; | 971 src = old_base + OLD_SECTION_H (n).sh_offset; |
828 | 972 |
829 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 973 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
830 NEW_SECTION_H (nn).sh_size); | 974 NEW_SECTION_H (nn).sh_size); |
975 | |
976 #ifdef __alpha__ | |
977 /* Update Alpha COFF symbol table: */ | |
978 if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") | |
979 == 0) | |
980 { | |
981 pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); | |
982 | |
983 symhdr->cbLineOffset += new_data2_size; | |
984 symhdr->cbDnOffset += new_data2_size; | |
985 symhdr->cbPdOffset += new_data2_size; | |
986 symhdr->cbSymOffset += new_data2_size; | |
987 symhdr->cbOptOffset += new_data2_size; | |
988 symhdr->cbAuxOffset += new_data2_size; | |
989 symhdr->cbSsOffset += new_data2_size; | |
990 symhdr->cbSsExtOffset += new_data2_size; | |
991 symhdr->cbFdOffset += new_data2_size; | |
992 symhdr->cbRfdOffset += new_data2_size; | |
993 symhdr->cbExtOffset += new_data2_size; | |
994 } | |
995 #endif /* __alpha__ */ | |
996 | |
997 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) | |
998 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) | |
999 { | |
1000 int diff = NEW_SECTION_H(nn).sh_offset | |
1001 - OLD_SECTION_H(old_mdebug_index).sh_offset; | |
1002 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); | |
1003 | |
1004 if (diff) | |
1005 { | |
1006 phdr->cbLineOffset += diff; | |
1007 phdr->cbDnOffset += diff; | |
1008 phdr->cbPdOffset += diff; | |
1009 phdr->cbSymOffset += diff; | |
1010 phdr->cbOptOffset += diff; | |
1011 phdr->cbAuxOffset += diff; | |
1012 phdr->cbSsOffset += diff; | |
1013 phdr->cbSsExtOffset += diff; | |
1014 phdr->cbFdOffset += diff; | |
1015 phdr->cbRfdOffset += diff; | |
1016 phdr->cbExtOffset += diff; | |
1017 } | |
1018 } | |
1019 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
1020 | |
1021 #if __sgi | |
1022 /* Adjust the HDRR offsets in .mdebug and copy the | |
1023 line data if it's in its usual 'hole' in the object. | |
1024 Makes the new file debuggable with dbx. | |
1025 patches up two problems: the absolute file offsets | |
1026 in the HDRR record of .mdebug (see /usr/include/syms.h), and | |
1027 the ld bug that gets the line table in a hole in the | |
1028 elf file rather than in the .mdebug section proper. | |
1029 David Anderson. davea@sgi.com Jan 16,1994. */ | |
1030 if (n == old_mdebug_index) | |
1031 { | |
1032 #define MDEBUGADJUST(__ct,__fileaddr) \ | |
1033 if (n_phdrr->__ct > 0) \ | |
1034 { \ | |
1035 n_phdrr->__fileaddr += movement; \ | |
1036 } | |
1037 | |
1038 HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); | |
1039 HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); | |
1040 unsigned movement = new_data2_size; | |
1041 | |
1042 MDEBUGADJUST (idnMax, cbDnOffset); | |
1043 MDEBUGADJUST (ipdMax, cbPdOffset); | |
1044 MDEBUGADJUST (isymMax, cbSymOffset); | |
1045 MDEBUGADJUST (ioptMax, cbOptOffset); | |
1046 MDEBUGADJUST (iauxMax, cbAuxOffset); | |
1047 MDEBUGADJUST (issMax, cbSsOffset); | |
1048 MDEBUGADJUST (issExtMax, cbSsExtOffset); | |
1049 MDEBUGADJUST (ifdMax, cbFdOffset); | |
1050 MDEBUGADJUST (crfd, cbRfdOffset); | |
1051 MDEBUGADJUST (iextMax, cbExtOffset); | |
1052 /* The Line Section, being possible off in a hole of the object, | |
1053 requires special handling. */ | |
1054 if (n_phdrr->cbLine > 0) | |
1055 { | |
1056 if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset | |
1057 + OLD_SECTION_H (n).sh_size)) | |
1058 { | |
1059 /* line data is in a hole in elf. do special copy and adjust | |
1060 for this ld mistake. | |
1061 */ | |
1062 n_phdrr->cbLineOffset += movement; | |
1063 | |
1064 memcpy (n_phdrr->cbLineOffset + new_base, | |
1065 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); | |
1066 } | |
1067 else | |
1068 { | |
1069 /* somehow line data is in .mdebug as it is supposed to be. */ | |
1070 MDEBUGADJUST (cbLine, cbLineOffset); | |
1071 } | |
1072 } | |
1073 } | |
1074 #endif /* __sgi */ | |
831 | 1075 |
832 /* If it is the symbol table, its st_shndx field needs to be patched. */ | 1076 /* If it is the symbol table, its st_shndx field needs to be patched. */ |
833 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 1077 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
834 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 1078 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
835 { | 1079 { |
884 case SHT_RELA: | 1128 case SHT_RELA: |
885 /* This code handles two different size structs, but there should | 1129 /* This code handles two different size structs, but there should |
886 be no harm in that provided that r_offset is always the first | 1130 be no harm in that provided that r_offset is always the first |
887 member. */ | 1131 member. */ |
888 nn = section.sh_info; | 1132 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 | |
896 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | 1133 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") |
897 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | 1134 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), |
1135 ".sdata") | |
1136 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1137 ".lit4") | |
1138 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1139 ".lit8") | |
1140 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1141 ".got") | |
1142 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1143 ".sdata1") | |
1144 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
898 ".data1")) | 1145 ".data1")) |
899 #endif | |
900 { | 1146 { |
901 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - | 1147 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - |
902 NEW_SECTION_H (nn).sh_offset; | 1148 NEW_SECTION_H (nn).sh_offset; |
903 caddr_t reloc = old_base + section.sh_offset, end; | 1149 caddr_t reloc = old_base + section.sh_offset, end; |
904 for (end = reloc + section.sh_size; reloc < end; | 1150 for (end = reloc + section.sh_size; reloc < end; |
905 reloc += section.sh_entsize) | 1151 reloc += section.sh_entsize) |
906 { | 1152 { |
907 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; | 1153 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; |
1154 #ifdef __alpha__ | |
1155 /* The Alpha ELF binutils currently have a bug that | |
1156 sometimes results in relocs that contain all | |
1157 zeroes. Work around this for now... */ | |
1158 if (((ElfW(Rel) *) reloc)->r_offset == 0) | |
1159 continue; | |
1160 #endif | |
908 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); | 1161 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); |
909 } | 1162 } |
910 } | 1163 } |
911 break; | 1164 break; |
912 } | 1165 } |