1/* 2 * Copyright (c) 2007 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <libc.h> 24#include <errno.h> 25 26#include <sys/stat.h> 27#include <sys/file.h> 28#include <sys/mman.h> 29 30#include <mach-o/swap.h> 31 32#include <stdbool.h> 33 34/********************************************************************* 35*********************************************************************/ 36static int 37writeFile(int fd, const void * data, size_t length) 38{ 39 int error = 0; 40 41 if (length != (size_t)write(fd, data, length)) { 42 error = -1; 43 } 44 45 if (error != 0) { 46 perror("couldn't write output"); 47 } 48 49 return error; 50} 51 52/********************************************************************* 53*********************************************************************/ 54static int 55readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize) 56{ 57 int error = -1; 58 int fd; 59 struct stat stat_buf; 60 61 *objAddr = 0; 62 *objSize = 0; 63 64 do { 65 if ((fd = open(path, O_RDONLY)) == -1) { 66 continue; 67 } 68 69 if (fstat(fd, &stat_buf) == -1) { 70 continue; 71 } 72 73 if (0 == (stat_buf.st_mode & S_IFREG)) { 74 continue; 75 } 76 77 if (0 == stat_buf.st_size) { 78 error = 0; 79 continue; 80 } 81 82 *objSize = stat_buf.st_size; 83 84 *objAddr = (vm_offset_t)mmap(NULL /* address */, *objSize, 85 PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE /* flags */, 86 fd, 0 /* offset */); 87 88 if ((void *)*objAddr == MAP_FAILED) { 89 *objAddr = 0; 90 *objSize = 0; 91 continue; 92 } 93 94 error = 0; 95 96 } while (false); 97 98 if (-1 != fd) { 99 close(fd); 100 } 101 if (error) { 102 fprintf(stderr, "couldn't read %s: %s\n", path, strerror(errno)); 103 } 104 105 return error; 106} 107 108static void 109usage(void) 110{ 111 fprintf(stderr, "Usage: %s [-s OLDSEGNAME] -n NEWSEGNAME input -o output\n", getprogname()); 112 exit(1); 113} 114 115/********************************************************************* 116*********************************************************************/ 117int main(int argc, char * argv[]) 118{ 119 int error; 120 const char * output_name = NULL; 121 const char * input_name = NULL; 122 const char * oldseg_name = NULL; 123 const char * newseg_name = NULL; 124 struct mach_header * hdr; 125 struct mach_header_64 * hdr64; 126 struct load_command * cmds; 127 boolean_t swap = false; 128 uint32_t ncmds, cmdtype; 129 uint32_t len; 130 vm_offset_t input; 131 vm_size_t input_size; 132 uint32_t nsects = 0; 133 uint32_t * flags = NULL; 134 uint32_t attr; 135 typedef char segname_t[16]; 136 segname_t * names = NULL; 137 int ch; 138 139 140 while ((ch = getopt(argc, argv, "s:n:o:")) != -1) { 141 switch (ch) { 142 case 's': 143 oldseg_name = optarg; 144 break; 145 case 'n': 146 newseg_name = optarg; 147 break; 148 case 'o': 149 output_name = optarg; 150 break; 151 case '?': 152 default: 153 usage(); 154 } 155 } 156 157 argc -= optind; 158 argv += optind; 159 160 if ((argc != 1) || !newseg_name || !output_name) { 161 usage(); 162 } 163 164 input_name = argv[0]; 165 166 error = readFile(input_name, &input, &input_size); 167 if (error) { 168 exit(1); 169 } 170 171 hdr = (typeof(hdr)) input; 172 switch (hdr->magic) { 173 case MH_CIGAM: 174 swap = true; 175 // fall thru 176 case MH_MAGIC: 177 ncmds = hdr->ncmds; 178 cmds = (typeof(cmds)) (hdr+1); 179 break; 180 181 case MH_CIGAM_64: 182 swap = true; 183 // fall thru 184 case MH_MAGIC_64: 185 hdr64 = (typeof(hdr64)) hdr; 186 ncmds = hdr64->ncmds; 187 cmds = (typeof(cmds)) (hdr64+1); 188 break; 189 190 default: 191 fprintf(stderr, "not macho input file\n"); 192 exit(1); 193 break; 194 } 195 196 if (swap) { 197 ncmds = OSSwapInt32(ncmds); 198 } 199 while (ncmds--) { 200 cmdtype = cmds->cmd; 201 if (swap) { 202 cmdtype = OSSwapInt32(cmdtype); 203 } 204 nsects = 0; 205 len = 0; 206 if (LC_SEGMENT == cmdtype) { 207 struct segment_command * segcmd; 208 struct section * sects; 209 210 segcmd = (typeof(segcmd)) cmds; 211 nsects = segcmd->nsects; 212 sects = (typeof(sects))(segcmd + 1); 213 names = §s->segname; 214 flags = §s->flags; 215 len = sizeof(*sects); 216 } else if (LC_SEGMENT_64 == cmdtype) { 217 struct segment_command_64 * segcmd; 218 struct section_64 * sects; 219 220 segcmd = (typeof(segcmd)) cmds; 221 nsects = segcmd->nsects; 222 sects = (typeof(sects))(segcmd + 1); 223 names = §s->segname; 224 flags = §s->flags; 225 len = sizeof(*sects); 226 } 227 228 if (swap) 229 nsects = OSSwapInt32(nsects); 230 while (nsects--) { 231 attr = *flags; 232 if (swap) { 233 attr = OSSwapInt32(attr); 234 } 235 236 if (!(S_ATTR_DEBUG & attr)) { 237 if (!oldseg_name || 238 0 == strncmp(oldseg_name, (char *)names, sizeof(*names))) { 239 memset(names, 0x0, sizeof(*names)); 240 strncpy((char *)names, newseg_name, sizeof(*names)); 241 } 242 } 243 244 names = (typeof(names))(((uintptr_t) names) + len); 245 flags = (typeof(flags))(((uintptr_t) flags) + len); 246 } 247 248 len = cmds->cmdsize; 249 if (swap) { 250 len = OSSwapInt32(len); 251 } 252 cmds = (typeof(cmds))(((uintptr_t) cmds) + len); 253 } 254 255 int fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755); 256 if (-1 == fd) { 257 error = -1; 258 } else { 259 error = writeFile(fd, (const void *) input, input_size); 260 close(fd); 261 } 262 263 if (error) { 264 fprintf(stderr, "couldn't write output: %s\n", strerror(errno)); 265 exit(1); 266 } 267 268 exit(0); 269 return 0; 270} 271