aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2007-11-27 08:30:34 +0000
committerYAMAMOTO Mitsuharu2007-11-27 08:30:34 +0000
commit7aee2da7256acbe6ad1965ff08b60743ac819482 (patch)
tree58b3eff2fa09beff6853057848feaa0907e93ba9 /src
parent0a7a6051a9c0b50cd59285e9d174d3362e913ebd (diff)
downloademacs-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/ChangeLog9
-rw-r--r--src/unexmacosx.c104
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 @@
12007-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
12007-11-26 Jason Rumney <jasonr@gnu.org> 102007-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. */
902static void 902static void
903unrelocate (const char *name, off_t reloff, int nrel) 903unrelocate (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. */
964static void
965rebase_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. */
977static void 993static void
978copy_dysymtab (struct load_command *lc, long delta) 994copy_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