diff options
author | Richard M. Stallman <rms@gnu.org> | 1997-01-10 02:53:35 +0000 |
---|---|---|
committer | Richard M. Stallman <rms@gnu.org> | 1997-01-10 02:53:35 +0000 |
commit | e6df688b398a55b25474b94d60f50671432b3b4d (patch) | |
tree | 6a3e0321411d1219f2bf9f892ab5a8946154b5b3 /src/unexnext.c | |
parent | 07628d5dfcf0d118bdc27dc1ab5fddb4f9b769f8 (diff) | |
download | emacs-e6df688b398a55b25474b94d60f50671432b3b4d.tar.gz |
Include <mach-o/reloc.h>.
(fgrowth): Initialize to zero.
(vmaddr_growth, dataseg_vmaddr, dataseg_vmend): New variables.
[NS_TARGET] (extreloff, nextrel, dysymtab, reloc_info): New variables.
(unexec_doit): Adjust file offsets of segments that follow the
enlarged data segment. Adjust vmaddr of the SEG_LINKEDIT segment that
follows the data segment.
[NS_TARGET] (unexec_doit): Adjust file offsets in the LC_DYSYMTAB load
command that follows the data segment. Zero out relocation entries
that fall within the data segment.
Diffstat (limited to 'src/unexnext.c')
-rw-r--r-- | src/unexnext.c | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/src/unexnext.c b/src/unexnext.c index 66f52fa0352..1cf41ca05a1 100644 --- a/src/unexnext.c +++ b/src/unexnext.c @@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ #include <stdarg.h> #include <mach/mach.h> #include <mach-o/loader.h> +#include <mach-o/reloc.h> #include <sys/file.h> #include <sys/stat.h> #include <libc.h> @@ -243,7 +244,7 @@ unexec_doit( struct load_command **the_commands = NULL; unsigned the_commands_len; struct mach_header the_header; - int fgrowth; + int fgrowth = 0; int fdatastart; int fdatasize; int size; @@ -251,9 +252,18 @@ unexec_doit( char *buf; vm_address_t data_address; vm_size_t data_size; + vm_size_t vmaddr_growth = 0; + vm_size_t dataseg_vmaddr, dataseg_vmend; struct segment_command *segment; +#ifdef NS_TARGET + unsigned long extreloff = 0; + unsigned long nextrel = 0; + struct dysymtab_command *dysymtab; + struct relocation_info reloc_info; +#endif + if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) { return (0); } @@ -284,7 +294,17 @@ unexec_doit( segment->filesize); segment->vmsize = data_size; segment->filesize = data_size; + dataseg_vmaddr = segment->vmaddr; + dataseg_vmend = segment->vmaddr + segment->vmsize; + vmaddr_growth = segment->vmaddr + segment->vmsize; + } else { + ((struct segment_command *)the_commands[i])->fileoff += fgrowth; + } + + if( strcmp( segment->segname, SEG_LINKEDIT ) == 0 ) { + segment->vmaddr = vmaddr_growth; } + break; case LC_SYMTAB: ((struct symtab_command *) @@ -296,6 +316,15 @@ unexec_doit( ((struct symseg_command *) the_commands[i])->offset += fgrowth; break; +#ifdef NS_TARGET + case LC_DYSYMTAB: + dysymtab = ((struct dysymtab_command *)the_commands[i]); + extreloff = dysymtab->extreloff; + nextrel = dysymtab->nextrel; + dysymtab->indirectsymoff += fgrowth; + dysymtab->extreloff += fgrowth; + break; +#endif default: break; } @@ -382,6 +411,55 @@ unexec_doit( return (0); } free(buf); + +#ifdef NS_TARGET + /* + * Fix up relocation entries in the data segment. + */ + + if (lseek(infd, extreloff, L_SET) < 0) { + fatal_unexec("cannot seek input file"); + return (0); + } + + for (i = 0; i < nextrel; i++) + { + long zeroval = 0; + + if (read(infd, &reloc_info, sizeof (reloc_info)) != sizeof (reloc_info)) { + fatal_unexec("cannot read input file"); + return (0); + } + if (reloc_info.r_address >= dataseg_vmaddr && reloc_info.r_address < dataseg_vmend) + { + if (lseek (outfd, fdatastart + reloc_info.r_address - dataseg_vmaddr, L_SET) < 0 ) { + fatal_unexec("cannot seek input file"); + return (0); + } + switch (reloc_info.r_length) { + case 0: + if (write(outfd, &zeroval, 1) != 1) { + fatal_unexec("cannot write output file"); + return (0); + } + break; + case 1: + if (write(outfd, &zeroval, 2) != 2) { + fatal_unexec("cannot write output file"); + return (0); + } + break; + case 2: + if (write(outfd, &zeroval, 4) != 4) { + fatal_unexec("cannot write output file"); + return (0); + } + break; + } + } + } +#endif + return (1); } |