diff options
| author | YAMAMOTO Mitsuharu | 2007-11-27 08:30:34 +0000 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2007-11-27 08:30:34 +0000 |
| commit | 7aee2da7256acbe6ad1965ff08b60743ac819482 (patch) | |
| tree | 58b3eff2fa09beff6853057848feaa0907e93ba9 /src | |
| parent | 0a7a6051a9c0b50cd59285e9d174d3362e913ebd (diff) | |
| download | emacs-7aee2da7256acbe6ad1965ff08b60743ac819482.tar.gz emacs-7aee2da7256acbe6ad1965ff08b60743ac819482.zip | |
(unrelocate): New argument BASE. Use it instead of
reloc_base.
(copy_dysymtab): Compute relocation base here.
(rebase_reloc_address) [__ppc64__]: New function.
(copy_dysymtab) [__ppc64__]: Use it if relocation base needs to be
changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/unexmacosx.c | 104 |
2 files changed, 95 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 13edfa07e90..7c7fb76378a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2007-11-27 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | ||
| 2 | |||
| 3 | * unexmacosx.c (unrelocate): New argument BASE. Use it instead of | ||
| 4 | reloc_base. | ||
| 5 | (copy_dysymtab): Compute relocation base here. | ||
| 6 | (rebase_reloc_address) [__ppc64__]: New function. | ||
| 7 | (copy_dysymtab) [__ppc64__]: Use it if relocation base needs to be | ||
| 8 | changed. | ||
| 9 | |||
| 1 | 2007-11-26 Jason Rumney <jasonr@gnu.org> | 10 | 2007-11-26 Jason Rumney <jasonr@gnu.org> |
| 2 | 11 | ||
| 3 | * w32proc.c (sys_spawnve): Quote args with wildcards. | 12 | * w32proc.c (sys_spawnve): Quote args with wildcards. |
diff --git a/src/unexmacosx.c b/src/unexmacosx.c index eceffc4af4b..dadc19d52e3 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c | |||
| @@ -900,26 +900,13 @@ copy_symtab (struct load_command *lc, long delta) | |||
| 900 | 900 | ||
| 901 | /* Fix up relocation entries. */ | 901 | /* Fix up relocation entries. */ |
| 902 | static void | 902 | static void |
| 903 | unrelocate (const char *name, off_t reloff, int nrel) | 903 | unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base) |
| 904 | { | 904 | { |
| 905 | int i, unreloc_count; | 905 | int i, unreloc_count; |
| 906 | struct relocation_info reloc_info; | 906 | struct relocation_info reloc_info; |
| 907 | struct scattered_relocation_info *sc_reloc_info | 907 | struct scattered_relocation_info *sc_reloc_info |
| 908 | = (struct scattered_relocation_info *) &reloc_info; | 908 | = (struct scattered_relocation_info *) &reloc_info; |
| 909 | vm_address_t reloc_base, location; | 909 | vm_address_t location; |
| 910 | |||
| 911 | #ifdef _LP64 | ||
| 912 | #if __ppc64__ | ||
| 913 | reloc_base = (data_segment_scp->vmaddr >= 0x100000000 | ||
| 914 | ? data_segment_scp->vmaddr : 0); | ||
| 915 | #else | ||
| 916 | /* First writable segment address. */ | ||
| 917 | reloc_base = data_segment_scp->vmaddr; | ||
| 918 | #endif | ||
| 919 | #else | ||
| 920 | /* First segment address in the file (unless MH_SPLIT_SEGS set). */ | ||
| 921 | reloc_base = 0; | ||
| 922 | #endif | ||
| 923 | 910 | ||
| 924 | for (unreloc_count = 0, i = 0; i < nrel; i++) | 911 | for (unreloc_count = 0, i = 0; i < nrel; i++) |
| 925 | { | 912 | { |
| @@ -933,7 +920,7 @@ unrelocate (const char *name, off_t reloff, int nrel) | |||
| 933 | switch (reloc_info.r_type) | 920 | switch (reloc_info.r_type) |
| 934 | { | 921 | { |
| 935 | case GENERIC_RELOC_VANILLA: | 922 | case GENERIC_RELOC_VANILLA: |
| 936 | location = reloc_base + reloc_info.r_address; | 923 | location = base + reloc_info.r_address; |
| 937 | if (location >= data_segment_scp->vmaddr | 924 | if (location >= data_segment_scp->vmaddr |
| 938 | && location < (data_segment_scp->vmaddr | 925 | && location < (data_segment_scp->vmaddr |
| 939 | + data_segment_scp->vmsize)) | 926 | + data_segment_scp->vmsize)) |
| @@ -972,15 +959,73 @@ unrelocate (const char *name, off_t reloff, int nrel) | |||
| 972 | unreloc_count, nrel, name); | 959 | unreloc_count, nrel, name); |
| 973 | } | 960 | } |
| 974 | 961 | ||
| 962 | #if __ppc64__ | ||
| 963 | /* Rebase r_address in the relocation table. */ | ||
| 964 | static void | ||
| 965 | rebase_reloc_address (off_t reloff, int nrel, long linkedit_delta, long diff) | ||
| 966 | { | ||
| 967 | int i; | ||
| 968 | struct relocation_info reloc_info; | ||
| 969 | struct scattered_relocation_info *sc_reloc_info | ||
| 970 | = (struct scattered_relocation_info *) &reloc_info; | ||
| 971 | |||
| 972 | for (i = 0; i < nrel; i++, reloff += sizeof (reloc_info)) | ||
| 973 | { | ||
| 974 | if (lseek (infd, reloff - linkedit_delta, L_SET) | ||
| 975 | != reloff - linkedit_delta) | ||
| 976 | unexec_error ("rebase_reloc_table: cannot seek to reloc_info"); | ||
| 977 | if (!unexec_read (&reloc_info, sizeof (reloc_info))) | ||
| 978 | unexec_error ("rebase_reloc_table: cannot read reloc_info"); | ||
| 979 | |||
| 980 | if (sc_reloc_info->r_scattered == 0 | ||
| 981 | && reloc_info.r_type == GENERIC_RELOC_VANILLA) | ||
| 982 | { | ||
| 983 | reloc_info.r_address -= diff; | ||
| 984 | if (!unexec_write (reloff, &reloc_info, sizeof (reloc_info))) | ||
| 985 | unexec_error ("rebase_reloc_table: cannot write reloc_info"); | ||
| 986 | } | ||
| 987 | } | ||
| 988 | } | ||
| 989 | #endif | ||
| 990 | |||
| 975 | /* Copy a LC_DYSYMTAB load command from the input file to the output | 991 | /* Copy a LC_DYSYMTAB load command from the input file to the output |
| 976 | file, adjusting the file offset fields. */ | 992 | file, adjusting the file offset fields. */ |
| 977 | static void | 993 | static void |
| 978 | copy_dysymtab (struct load_command *lc, long delta) | 994 | copy_dysymtab (struct load_command *lc, long delta) |
| 979 | { | 995 | { |
| 980 | struct dysymtab_command *dstp = (struct dysymtab_command *) lc; | 996 | struct dysymtab_command *dstp = (struct dysymtab_command *) lc; |
| 997 | vm_address_t base; | ||
| 981 | 998 | ||
| 982 | unrelocate ("local", dstp->locreloff, dstp->nlocrel); | 999 | #ifdef _LP64 |
| 983 | unrelocate ("external", dstp->extreloff, dstp->nextrel); | 1000 | #if __ppc64__ |
| 1001 | { | ||
| 1002 | int i; | ||
| 1003 | |||
| 1004 | base = 0; | ||
| 1005 | for (i = 0; i < nlc; i++) | ||
| 1006 | if (lca[i]->cmd == LC_SEGMENT) | ||
| 1007 | { | ||
| 1008 | struct segment_command *scp = (struct segment_command *) lca[i]; | ||
| 1009 | |||
| 1010 | if (scp->vmaddr + scp->vmsize > 0x100000000 | ||
| 1011 | && (scp->initprot & VM_PROT_WRITE) != 0) | ||
| 1012 | { | ||
| 1013 | base = data_segment_scp->vmaddr; | ||
| 1014 | break; | ||
| 1015 | } | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | #else | ||
| 1019 | /* First writable segment address. */ | ||
| 1020 | base = data_segment_scp->vmaddr; | ||
| 1021 | #endif | ||
| 1022 | #else | ||
| 1023 | /* First segment address in the file (unless MH_SPLIT_SEGS set). */ | ||
| 1024 | base = 0; | ||
| 1025 | #endif | ||
| 1026 | |||
| 1027 | unrelocate ("local", dstp->locreloff, dstp->nlocrel, base); | ||
| 1028 | unrelocate ("external", dstp->extreloff, dstp->nextrel, base); | ||
| 984 | 1029 | ||
| 985 | if (dstp->nextrel > 0) { | 1030 | if (dstp->nextrel > 0) { |
| 986 | dstp->extreloff += delta; | 1031 | dstp->extreloff += delta; |
| @@ -999,6 +1044,29 @@ copy_dysymtab (struct load_command *lc, long delta) | |||
| 999 | unexec_error ("cannot write symtab command to header"); | 1044 | unexec_error ("cannot write symtab command to header"); |
| 1000 | 1045 | ||
| 1001 | curr_header_offset += lc->cmdsize; | 1046 | curr_header_offset += lc->cmdsize; |
| 1047 | |||
| 1048 | #if __ppc64__ | ||
| 1049 | /* Check if the relocation base needs to be changed. */ | ||
| 1050 | if (base == 0) | ||
| 1051 | { | ||
| 1052 | vm_address_t newbase = 0; | ||
| 1053 | int i; | ||
| 1054 | |||
| 1055 | for (i = 0; i < num_unexec_regions; i++) | ||
| 1056 | if (unexec_regions[i].range.address + unexec_regions[i].range.size | ||
| 1057 | > 0x100000000) | ||
| 1058 | { | ||
| 1059 | newbase = data_segment_scp->vmaddr; | ||
| 1060 | break; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | if (newbase) | ||
| 1064 | { | ||
| 1065 | rebase_reloc_address (dstp->locreloff, dstp->nlocrel, delta, newbase); | ||
| 1066 | rebase_reloc_address (dstp->extreloff, dstp->nextrel, delta, newbase); | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | #endif | ||
| 1002 | } | 1070 | } |
| 1003 | 1071 | ||
| 1004 | /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output | 1072 | /* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output |