summaryrefslogtreecommitdiff
path: root/src/unexnext.c
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1997-01-10 02:53:35 +0000
committerRichard M. Stallman <rms@gnu.org>1997-01-10 02:53:35 +0000
commitacacb2920929152a02f5836d39189b04cea08202 (patch)
treeac3c27a848aece275d542c9e1d675570ec46ab63 /src/unexnext.c
parent1c626aaf749003439929908143e519befd64eb53 (diff)
downloademacs-acacb2920929152a02f5836d39189b04cea08202.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.c80
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);
}