/* * Copyright (c) 2007 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * 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 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef __linux__ #include #else #include #include #include #include #include #include #endif #include #include #include #include #include #ifdef __APPLE__ #include #else #undef OSSwapInt32 #define OSSwapInt32 __builtin_bswap32 #include #endif /********************************************************************* *********************************************************************/ static int writeFile(int fd, const void * data, size_t length) { int error = 0; if (length != (size_t)write(fd, data, length)) { error = -1; } if (error != 0) { perror("couldn't write output"); } return error; } /********************************************************************* *********************************************************************/ static int readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize) { int error = -1; int fd; struct stat stat_buf; *objAddr = 0; *objSize = 0; do { if ((fd = open(path, O_RDONLY)) == -1) { continue; } if (fstat(fd, &stat_buf) == -1) { continue; } if (0 == (stat_buf.st_mode & S_IFREG)) { continue; } if (0 == stat_buf.st_size) { error = 0; continue; } *objSize = stat_buf.st_size; *objAddr = (vm_offset_t)mmap(NULL /* address */, *objSize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE /* flags */, fd, 0 /* offset */); if ((void *)*objAddr == MAP_FAILED) { *objAddr = 0; *objSize = 0; continue; } error = 0; } while (false); if (-1 != fd) { close(fd); } if (error) { fprintf(stderr, "couldn't read %s: %s\n", path, strerror(errno)); } return error; } /********************************************************************* *********************************************************************/ int main(int argc, char * argv[]) { int error; const char * output_name = NULL; const char * newseg_name = NULL; struct mach_header * hdr; struct mach_header_64 * hdr64; struct load_command * cmds; boolean_t swap = false; uint32_t ncmds, cmdtype; uint32_t len; vm_offset_t input; vm_size_t input_size; uint32_t nsects = 0; uint32_t * flags = NULL; uint32_t attr; typedef char segname_t[16]; segname_t * names = NULL; if ((argc != 5) || strcmp("-o", argv[3])) { fprintf(stderr, "Usage: %s NEWSEGNAME input -o output\n", argv[0]); exit(1); } output_name = argv[4]; newseg_name = argv[1]; error = readFile(argv[2], &input, &input_size); if (error) { exit(1); } hdr = (typeof(hdr)) input; switch (hdr->magic) { case MH_CIGAM: swap = true; // fall thru case MH_MAGIC: ncmds = hdr->ncmds; cmds = (typeof(cmds)) (hdr+1); break; case MH_CIGAM_64: swap = true; // fall thru case MH_MAGIC_64: hdr64 = (typeof(hdr64)) hdr; ncmds = hdr64->ncmds; cmds = (typeof(cmds)) (hdr64+1); break; default: fprintf(stderr, "not macho input file\n"); exit(1); break; } if (swap) { ncmds = OSSwapInt32(ncmds); } while (ncmds--) { cmdtype = cmds->cmd; if (swap) { cmdtype = OSSwapInt32(cmdtype); } nsects = 0; len = 0; if (LC_SEGMENT == cmdtype) { struct segment_command * segcmd; struct section * sects; segcmd = (typeof(segcmd)) cmds; nsects = segcmd->nsects; sects = (typeof(sects))(segcmd + 1); names = §s->segname; flags = §s->flags; len = sizeof(*sects); } else if (LC_SEGMENT_64 == cmdtype) { struct segment_command_64 * segcmd; struct section_64 * sects; segcmd = (typeof(segcmd)) cmds; nsects = segcmd->nsects; sects = (typeof(sects))(segcmd + 1); names = §s->segname; flags = §s->flags; len = sizeof(*sects); } if (swap) nsects = OSSwapInt32(nsects); while (nsects--) { attr = *flags; if (swap) { attr = OSSwapInt32(attr); } if (!(S_ATTR_DEBUG & attr)) { strncpy((char *)names, newseg_name, sizeof(*names)); } names = (typeof(names))(((uintptr_t) names) + len); flags = (typeof(flags))(((uintptr_t) flags) + len); } len = cmds->cmdsize; if (swap) { len = OSSwapInt32(len); } cmds = (typeof(cmds))(((uintptr_t) cmds) + len); } int fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755); if (-1 == fd) { error = -1; } else { error = writeFile(fd, (const void *) input, input_size); close(fd); } if (error) { fprintf(stderr, "couldn't write output: %s\n", strerror(errno)); exit(1); } exit(0); return 0; }