Index: trunk/i386/util/machOconv.c =================================================================== --- trunk/i386/util/machOconv.c (revision 2072) +++ trunk/i386/util/machOconv.c (revision 2073) @@ -38,14 +38,10 @@ static bool swap_ends; -static unsigned long swap( - unsigned long x -) +static unsigned long swap(unsigned long x) { - if (swap_ends) - return OSSwapInt32(x); - else - return x; + if (swap_ends) return OSSwapInt32(x); + else return x; } int @@ -56,102 +52,158 @@ int nc, ncmds; char * cp; - if (argc == 2) { - infile = open(argv[1], O_RDONLY); - if (infile < 0) - goto usage; - outfile = fileno(stdout); + if (argc == 2) + { + infile = open(argv[1], O_RDONLY); + if (infile < 0) goto usage; + outfile = fileno(stdout); } - else if (argc == 3) { + else if (argc == 3) + { infile = open(argv[1], O_RDONLY); - if (infile < 0) - goto usage; - outfile = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (outfile < 0) - goto usage; + if (infile < 0) goto usage; + outfile = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (outfile < 0) goto usage; } - else { -usage: + else + { + usage: fprintf(stderr, "usage: machOconv inputfile [outputfile]\n"); - exit(1); + exit(1); } nc = read(infile, &mh, sizeof (mh)); - if (nc < 0) { - perror("read mach header"); - exit(1); + if (nc < 0) + { + perror("read mach header"); + exit(1); } - if (nc < (int)sizeof (mh)) { - fprintf(stderr, "read mach header: premature EOF %d\n", nc); - exit(1); + if (nc < (int)sizeof (mh)) + { + fprintf(stderr, "read mach header: premature EOF %d\n", nc); + exit(1); } - if (mh.magic == MH_MAGIC) - swap_ends = false; - else if (mh.magic == MH_CIGAM) - swap_ends = true; - else { + if (mh.magic == MH_MAGIC) swap_ends = false; + else if (mh.magic == MH_CIGAM) swap_ends = true; + else + { fprintf(stderr, "bad magic number %lx\n", (unsigned long)mh.magic); - exit(1); + exit(1); } - + cmds = calloc(swap(mh.sizeofcmds), sizeof (char)); - if (cmds == 0) { - fprintf(stderr, "alloc load commands: no memory\n"); - exit(1); + if (cmds == 0) + { + fprintf(stderr, "alloc load commands: no memory\n"); + exit(1); } nc = read(infile, cmds, swap(mh.sizeofcmds)); - if (nc < 0) { - perror("read load commands"); - exit(1); + if (nc < 0) + { + perror("read load commands"); + exit(1); } - if (nc < (int)swap(mh.sizeofcmds)) { - fprintf(stderr, "read load commands: premature EOF %d\n", nc); - exit(1); + if (nc < (int)swap(mh.sizeofcmds)) + { + fprintf(stderr, "read load commands: premature EOF %d\n", nc); + exit(1); } - for ( ncmds = swap(mh.ncmds), cp = cmds; - ncmds > 0; ncmds--) { + unsigned long vmstart = (unsigned long)-1; + + // First pass: determine actual load address + for (ncmds = swap(mh.ncmds), cp = cmds; + ncmds > 0; ncmds--) + { +#define lcp ((struct load_command *)cp) +#define scp ((struct segment_command *)cp) + bool isDATA; unsigned vmsize; + unsigned vmaddr; + + switch(swap(lcp->cmd)) + { + case LC_SEGMENT: + isDATA = (strcmp(scp->segname, "__DATA") == 0); + if (isDATA) + { + vmaddr = swap(scp->vmaddr); + vmsize = swap(scp->filesize); + } + else + { + vmaddr = swap(scp->vmaddr); + vmsize = swap(scp->vmsize); + } + if(vmstart > swap(scp->vmaddr)) + { + vmstart = swap(scp->vmaddr); + } + } + cp += swap(lcp->cmdsize); + + } + + // Second pass: output to file. + for (ncmds = swap(mh.ncmds), cp = cmds; + ncmds > 0; ncmds--) + { #define lcp ((struct load_command *)cp) - switch(swap(lcp->cmd)) { - - case LC_SEGMENT: #define scp ((struct segment_command *)cp) - isDATA = (strcmp(scp->segname, "__DATA") == 0); - if (isDATA) - vmsize = swap(scp->filesize); - else - vmsize = swap(scp->vmsize); - result = vm_allocate(mach_task_self(), &data, vmsize, true); - if (result != KERN_SUCCESS) { - mach_error("vm_allocate segment data", result); - exit(1); - } - lseek(infile, swap(scp->fileoff), L_SET); - nc = read(infile, (void *)data, swap(scp->filesize)); - if (nc < 0) { - perror("read segment data"); - exit(1); - } - if (nc < (int)swap(scp->filesize)) { - fprintf(stderr, "read segment data: premature EOF %d\n", nc); - exit(1); - } + bool isDATA; + unsigned vmsize; + unsigned vmaddr; + + switch(swap(lcp->cmd)) + { + case LC_SEGMENT: + isDATA = (strcmp(scp->segname, "__DATA") == 0); + if (isDATA) + { + vmaddr = swap(scp->vmaddr); + vmsize = swap(scp->filesize); + } + else + { + vmaddr = swap(scp->vmaddr); + vmsize = swap(scp->vmsize); + } + + result = vm_allocate(mach_task_self(), &data, vmsize, true); + if (result != KERN_SUCCESS) { + mach_error("vm_allocate segment data", result); + exit(1); + } + + lseek(infile, swap(scp->fileoff), L_SET); + nc = read(infile, (void *)data, swap(scp->filesize)); + if (nc < 0) { + perror("read segment data"); + exit(1); + } + if (nc < (int)swap(scp->filesize)) { + fprintf(stderr, "read segment data: premature EOF %d\n", nc); + exit(1); + } + + // seeking output file + printf("Seek Load Address: 0x%0.8lx\n", swap(scp->vmaddr) - vmstart); - nc = write(outfile, (void *)data, vmsize); - if (nc < (int)vmsize) { - perror("write segment data"); - exit(1); - } - - vm_deallocate(mach_task_self(), data, vmsize); - break; - } - - cp += swap(lcp->cmdsize); + lseek(outfile, swap(scp->vmaddr) - vmstart, L_SET); + nc = write(outfile, (void *)data, vmsize); + if (nc < (int)vmsize) { + perror("write segment data"); + exit(1); + } + + vm_deallocate(mach_task_self(), data, vmsize); + break; + } + + cp += swap(lcp->cmdsize); } exit(0);