#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>
+#include <unistd.h>
+/* Instead of unistd.h, this used to include libc.h.
+ "Nelson H. F. Beebe" <beebe@math.utah.edu> says that doesn't work
+ in system version 3.3. */
int malloc_cookie;
* pages it vm_allocated and write only those out into the data segment.
*
* This kludge may break when we stop using fixed virtual address
- * shared libraries. Actually, emacs will probably continue working, but be
+ * shared libraries. Actually, emacs will probably continue working, but be
* much larger on disk than it needs to be (because non-malloced data will
* be in the file).
*/
*the_commands = malloc(sizeof(*the_commands));
} else {
(*the_commands_len)++;
- *the_commands = realloc(*the_commands,
+ *the_commands = realloc(*the_commands,
(*the_commands_len *
sizeof(**the_commands)));
}
return (0);
}
for (i = 0; i < the_header->ncmds; i++) {
- if (read(fd, &command, sizeof(struct load_command)) !=
+ if (read(fd, &command, sizeof(struct load_command)) !=
sizeof(struct load_command)) {
fatal_unexec("cannot read macho load command header");
return (0);
buf = malloc(command.cmdsize);
buf->cmd = command.cmd;
buf->cmdsize = command.cmdsize;
- if (read(fd, ((char *)buf +
- sizeof(struct load_command)),
+ if (read(fd, ((char *)buf +
+ sizeof(struct load_command)),
size) != size) {
fatal_unexec("cannot read load command data");
return (0);
region.address = 0;
*address = 0;
for (;;) {
- ret = vm_region(task_self(),
- ®ion.address,
- ®ion.size,
- ®ion.protection,
- ®ion.max_protection,
+ ret = vm_region(task_self(),
+ ®ion.address,
+ ®ion.size,
+ ®ion.protection,
+ ®ion.max_protection,
®ion.inheritance,
- ®ion.shared,
- ®ion.object_name,
+ ®ion.shared,
+ ®ion.object_name,
®ion.offset);
if (ret != KERN_SUCCESS || region.address >= VM_HIGHDATA) {
break;
}
if (*address != 0) {
if (region.address > *address + *size) {
- if (!filldatagap(*address, size,
+ if (!filldatagap(*address, size,
region.address)) {
return (0);
}
- }
+ }
*size += region.size;
} else {
if (region.address == sect->addr) {
*address = region.address;
*size = region.size;
- }
+ }
}
region.address += region.size;
}
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;
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);
}
if (strcmp(segment->segname, SEG_DATA) == 0) {
fdatastart = segment->fileoff;
fdatasize = segment->filesize;
- fgrowth = (data_size -
+ fgrowth = (data_size -
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 *)
((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;
}
}
-
+
/*
* Write header
*/
- if (write(outfd, &the_header,
+ if (write(outfd, &the_header,
sizeof(the_header)) != sizeof(the_header)) {
fatal_unexec("cannot write output file");
return (0);
}
-
+
/*
* Write commands
*/
for (i = 0; i < the_commands_len; i++) {
- if (write(outfd, the_commands[i],
- the_commands[i]->cmdsize) !=
+ if (write(outfd, the_commands[i],
+ the_commands[i]->cmdsize) !=
the_commands[i]->cmdsize) {
fatal_unexec("cannot write output file");
return (0);
}
}
-
+
/*
* Write original text
*/
- if (lseek(infd, the_header.sizeofcmds + sizeof(the_header),
+ if (lseek(infd, the_header.sizeofcmds + sizeof(the_header),
L_SET) < 0) {
fatal_unexec("cannot seek input file");
return (0);
}
- size = fdatastart - (sizeof(the_header) +
+ size = fdatastart - (sizeof(the_header) +
the_header.sizeofcmds);
buf = my_malloc(size);
if (read(infd, buf, size) != size) {
return (0);
}
my_free(buf, size);
-
-
+
+
/*
* Write new data
*/
- if (write(outfd, (char *)data_address,
+ if (write(outfd, (char *)data_address,
data_size) != data_size) {
fatal_unexec("cannot write output file");
return (0);
}
-
+
}
/*
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);
}
fatal_unexec("cannot open input file `%s'", infile);
exit(1);
}
-
+
tmpnam(tmpbuf);
tmpfile = rindex(tmpbuf, '/');
if (tmpfile == NULL) {
exit(1);
}
}
+
+/* arch-tag: 9796bdc3-c050-417a-b2f5-4cfd31032634
+ (do not change this comment) */