95 |
#include <unistd.h> |
#include <unistd.h> |
96 |
#include <mach/mach.h> |
#include <mach/mach.h> |
97 |
#include <mach-o/loader.h> |
#include <mach-o/loader.h> |
98 |
|
#include <mach-o/reloc.h> |
99 |
|
#if defined (__ppc__) |
100 |
|
#include <mach-o/ppc/reloc.h> |
101 |
|
#endif |
102 |
#include <objc/malloc.h> |
#include <objc/malloc.h> |
103 |
|
|
104 |
#define VERBOSE 1 |
#define VERBOSE 1 |
162 |
|
|
163 |
malloc_zone_t *emacs_zone; |
malloc_zone_t *emacs_zone; |
164 |
|
|
165 |
|
/* file offset of input file's data segment */ |
166 |
|
off_t data_segment_old_fileoff; |
167 |
|
|
168 |
|
struct segment_command *data_segment_scp; |
169 |
|
|
170 |
/* Read n bytes from infd into memory starting at address dest. |
/* Read n bytes from infd into memory starting at address dest. |
171 |
Return true if successful, false otherwise. */ |
Return true if successful, false otherwise. */ |
172 |
static int |
static int |
772 |
curr_header_offset += lc->cmdsize; |
curr_header_offset += lc->cmdsize; |
773 |
} |
} |
774 |
|
|
775 |
|
/* Fix up relocation entries. */ |
776 |
|
static void |
777 |
|
unrelocate (const char *name, off_t reloff, int nrel) |
778 |
|
{ |
779 |
|
int i, unreloc_count; |
780 |
|
struct relocation_info reloc_info; |
781 |
|
struct scattered_relocation_info *sc_reloc_info |
782 |
|
= (struct scattered_relocation_info *) &reloc_info; |
783 |
|
|
784 |
|
for (unreloc_count = 0, i = 0; i < nrel; i++) |
785 |
|
{ |
786 |
|
if (lseek (infd, reloff, L_SET) != reloff) |
787 |
|
unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i); |
788 |
|
if (!unexec_read (&reloc_info, sizeof (reloc_info))) |
789 |
|
unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i); |
790 |
|
reloff += sizeof (reloc_info); |
791 |
|
|
792 |
|
if (sc_reloc_info->r_scattered == 0) |
793 |
|
switch (reloc_info.r_type) |
794 |
|
{ |
795 |
|
case GENERIC_RELOC_VANILLA: |
796 |
|
if (reloc_info.r_address >= data_segment_scp->vmaddr |
797 |
|
&& reloc_info.r_address < (data_segment_scp->vmaddr |
798 |
|
+ data_segment_scp->vmsize)) |
799 |
|
{ |
800 |
|
off_t src_off = data_segment_old_fileoff |
801 |
|
+ reloc_info.r_address - data_segment_scp->vmaddr; |
802 |
|
off_t dst_off = data_segment_scp->fileoff |
803 |
|
+ reloc_info.r_address - data_segment_scp->vmaddr; |
804 |
|
|
805 |
|
if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length)) |
806 |
|
unexec_error ("unrelocate: %s:%d cannot copy original value", |
807 |
|
name, i); |
808 |
|
unreloc_count++; |
809 |
|
} |
810 |
|
break; |
811 |
|
default: |
812 |
|
unexec_error ("unrelocate: %s:%d cannot handle type = %d", |
813 |
|
name, i, reloc_info.r_type); |
814 |
|
} |
815 |
|
else |
816 |
|
switch (sc_reloc_info->r_type) |
817 |
|
{ |
818 |
|
#if defined (__ppc__) |
819 |
|
case PPC_RELOC_PB_LA_PTR: |
820 |
|
/* nothing to do for prebound lazy pointer */ |
821 |
|
break; |
822 |
|
#endif |
823 |
|
default: |
824 |
|
unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d", |
825 |
|
name, i, sc_reloc_info->r_type); |
826 |
|
} |
827 |
|
} |
828 |
|
|
829 |
|
if (nrel > 0) |
830 |
|
printf ("Fixed up %d/%d %s relocation entries in data segment.\n", |
831 |
|
unreloc_count, nrel, name); |
832 |
|
} |
833 |
|
|
834 |
/* Copy a LC_DYSYMTAB load command from the input file to the output |
/* Copy a LC_DYSYMTAB load command from the input file to the output |
835 |
file, adjusting the file offset fields. */ |
file, adjusting the file offset fields. */ |
836 |
static void |
static void |
838 |
{ |
{ |
839 |
struct dysymtab_command *dstp = (struct dysymtab_command *) lc; |
struct dysymtab_command *dstp = (struct dysymtab_command *) lc; |
840 |
|
|
841 |
/* If Mach-O executable is not prebound, relocation entries need |
unrelocate ("local", dstp->locreloff, dstp->nlocrel); |
842 |
fixing up. This is not supported currently. */ |
unrelocate ("external", dstp->extreloff, dstp->nextrel); |
|
if (!(mh.flags & MH_PREBOUND) && (dstp->nextrel != 0 || dstp->nlocrel != 0)) |
|
|
unexec_error ("cannot handle LC_DYSYMTAB with relocation entries"); |
|
843 |
|
|
844 |
if (dstp->nextrel > 0) { |
if (dstp->nextrel > 0) { |
845 |
dstp->extreloff += delta; |
dstp->extreloff += delta; |
911 |
struct segment_command *scp = (struct segment_command *) lca[i]; |
struct segment_command *scp = (struct segment_command *) lca[i]; |
912 |
if (strncmp (scp->segname, SEG_DATA, 16) == 0) |
if (strncmp (scp->segname, SEG_DATA, 16) == 0) |
913 |
{ |
{ |
914 |
|
/* save data segment file offset and segment_command for |
915 |
|
unrelocate */ |
916 |
|
data_segment_old_fileoff = scp->fileoff; |
917 |
|
data_segment_scp = scp; |
918 |
|
|
919 |
copy_data_segment (lca[i]); |
copy_data_segment (lca[i]); |
920 |
} |
} |
921 |
else |
else |