/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.1 (the "License"). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* test of standalone rld * usage: rldtest * */ #include #include #include extern int errno; typedef unsigned int entry_t; struct mach_header head; #define zalloc(a) malloc(a) #define zfree(a) free(a) #define xread read #define min(a,b) ((a) < (b) ? (a) : (b)) extern void *malloc(int size); loadmacho( struct mach_header *head, int dev, int io, entry_t *rentry, char **raddr, int *rsize, int file_offset ) { int ncmds; unsigned cmds, cp; struct xxx_thread_command { unsigned long cmd; unsigned long cmdsize; unsigned long flavor; unsigned long count; i386_thread_state_t state; } *th; unsigned int entry; int size, vmsize = 0; unsigned int vmaddr = ~0; // XXX should check cputype cmds = (unsigned int) zalloc(head->sizeofcmds); b_lseek(io, sizeof (struct mach_header) + file_offset, 0); if (read(io, cmds, head->sizeofcmds) != head->sizeofcmds) {printf("error reading commands\n"); goto shread;} for (ncmds = head->ncmds, cp = cmds; ncmds > 0; ncmds--) { unsigned int addr; // putchar('.'); #define lcp ((struct load_command *)cp) switch (lcp->cmd) { case LC_SEGMENT: #define scp ((struct segment_command *)cp) addr = (scp->vmaddr & 0x3fffffff) + (int)*raddr; if (scp->filesize) { // Is this an OK assumption? // if the filesize is zero, it doesn't // take up any virtual space... // (Hopefully this only excludes PAGEZERO.) // Also, ignore linkedit segment when // computing size, because we will erase // the linkedit segment later. if(strncmp(scp->segname, SEG_LINKEDIT, sizeof(scp->segname)) != 0) vmsize += scp->vmsize; vmaddr = min(vmaddr, addr); // Zero any space at the end of the segment. bzero((char *)(addr + scp->filesize), scp->vmsize - scp->filesize); // FIXME: check to see if we overflow // the available space (should be passed in // as the size argument). b_lseek(io, scp->fileoff + file_offset, 0); if (xread(io, (char *)addr, scp->filesize) != scp->filesize) { printf("Error loading section\n"); printf("File size =%x; fileoff_set=%x; addr=%x\n", scp->filesize, scp->fileoff, addr); goto shread; } } break; case LC_THREAD: case LC_UNIXTHREAD: th = (struct xxx_thread_command *)cp; entry = th->state.eip; break; } cp += lcp->cmdsize; } // kernBootStruct->rootdev = (dev & 0xffffff00) | devMajor[Dev(dev)]; zfree((char *)cmds); *rentry = (entry_t)( (int) entry & 0x3fffffff ); *rsize = vmsize; *raddr = (char *)vmaddr; return 0; shread: zfree((char *)cmds); printf("Read error\n"); return -1; } loadprog( int dev, int fd, entry_t *entry, // entry point char **addr, // load address int *size // size of loaded program ) { /* get file header */ read(fd, &head, sizeof(head)); if (head.magic == MH_MAGIC) { return loadmacho((struct mach_header *) &head, dev, fd, entry, addr, size,0); } else if (head.magic == 0xbebafeca) { printf("no fat binary support yet\n"); return -1; } printf("unrecognized binary format\n"); return -1; } #define DRIVER "/usr/Devices/EtherExpress16.config/EtherExpress16_reloc" void usage(void) { fprintf(stderr,"usage: rldtest \n"); exit(1); } main(int argc, char **argv) { int fd; char *mem, *workmem, *ebuf; char *laddr, *kaddr, *daddr; NXStream *str; struct mach_header *mh; int ret, size, ksize, dsize, count; entry_t entry; int (*fn)(); struct section *sp; char *kernel, *sarld, *driver; if (argc != 4) usage(); sarld = argv[1]; kernel = argv[2]; driver = argv[3]; mem = malloc(1024 * 1024 * 16); printf("mem = %x\n",mem); laddr = (char *)0x0; fd = open(sarld,0); if (fd < 0) { fprintf(stderr, "couldn't open sarld %s, error %d\n",sarld,errno); exit(1); } printf("fd = %d\n",fd); loadprog(0, fd, &entry, &laddr, &size); close(fd); printf("entry = %x, laddr = %x, size = %d\n",entry, laddr, size); fn = (int (*)())entry; fd = open(kernel,0); if (fd < 0) { fprintf(stderr, "couldn't open kernel %s, error %d\n",kernel,errno); exit(1); } kaddr = 0; loadprog(0, fd, &entry, &kaddr, &ksize); printf("entry = %x, kaddr = %x, ksize = %d\n",entry, kaddr, ksize); close(fd); daddr = (char *)0x70000; fd = open(driver,0); if (fd < 0) { fprintf(stderr, "couldn't open driver %s, error %d\n",driver,errno); exit(1); } size = 0; do { count = read(fd, daddr, 65536); daddr += count; size += count; } while (count > 0); daddr = (char *)0x70000; printf("entry = %x, daddr = %x, size = %d\n",entry, daddr, size); close(fd); workmem = malloc(300 * 1024); ebuf = malloc(64 * 1024); ebuf[0] = 0; dsize = 16 * 1024 * 1024 - (int)kaddr - (int)ksize; printf("about to call %x\n",fn); ret = (*fn)( "mach_kernel", kaddr, "driver", daddr, size, kaddr + ksize, &dsize, ebuf, 64 * 1024, workmem, 300 * 1024 ); printf("rld return: %d '%s'\n",ret, ebuf); #define SEG_OBJC "__OBJC" sp = getsectbyname ("__TEXT", "__text"); printf("text section: %s\n",sp->sectname); sp = getsectbynamefromheader (kaddr+ksize, "__OBJC", "__module_info"); printf("objc section: %s\n",sp->sectname); sp = getsectdatafromheader (kaddr+ksize, SEG_OBJC, "__module_info", &size); printf("objc section: %s\n",sp->sectname); printf("getsectdata ret = %d\n",sp); free(mem); }