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#ifndef __linux__ 24#include <libc.h> 25#else 26#include <stdio.h> 27#include <stdint.h> 28#include <stdarg.h> 29#include <stdlib.h> 30#include <string.h> 31#include <unistd.h> 32#endif 33 34#include <errno.h> 35 36#include <sys/stat.h> 37#include <sys/file.h> 38#include <sys/mman.h> 39 40#include <mach-o/swap.h> 41 42#ifdef __APPLE__ 43#include <IOKit/IOTypes.h> 44#else 45#undef OSSwapInt32 46#define OSSwapInt32 __builtin_bswap32 47#include <stdbool.h> 48#endif 49 50/********************************************************************* 51*********************************************************************/ 52static int 53writeFile(int fd, const void * data, size_t length) 54{ 55 int error = 0; 56 57 if (length != (size_t)write(fd, data, length)) { 58 error = -1; 59 } 60 61 if (error != 0) { 62 perror("couldn't write output"); 63 } 64 65 return error; 66} 67 68/********************************************************************* 69*********************************************************************/ 70static int 71readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize) 72{ 73 int error = -1; 74 int fd; 75 struct stat stat_buf; 76 77 *objAddr = 0; 78 *objSize = 0; 79 80 do { 81 if ((fd = open(path, O_RDONLY)) == -1) { 82 continue; 83 } 84 85 if (fstat(fd, &stat_buf) == -1) { 86 continue; 87 } 88 89 if (0 == (stat_buf.st_mode & S_IFREG)) { 90 continue; 91 } 92 93 if (0 == stat_buf.st_size) { 94 error = 0; 95 continue; 96 } 97 98 *objSize = stat_buf.st_size; 99 100 *objAddr = (vm_offset_t)mmap(NULL /* address */, *objSize, 101 PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE /* flags */, 102 fd, 0 /* offset */); 103 104 if ((void *)*objAddr == MAP_FAILED) { 105 *objAddr = 0; 106 *objSize = 0; 107 continue; 108 } 109 110 error = 0; 111 112 } while (false); 113 114 if (-1 != fd) { 115 close(fd); 116 } 117 if (error) { 118 fprintf(stderr, "couldn't read %s: %s\n", path, strerror(errno)); 119 } 120 121 return error; 122} 123 124/********************************************************************* 125*********************************************************************/ 126int main(int argc, char * argv[]) 127{ 128 int error; 129 const char * output_name = NULL; 130 const char * newseg_name = NULL; 131 struct mach_header * hdr; 132 struct mach_header_64 * hdr64; 133 struct load_command * cmds; 134 boolean_t swap = false; 135 uint32_t ncmds, cmdtype; 136 uint32_t len; 137 vm_offset_t input; 138 vm_size_t input_size; 139 uint32_t nsects = 0; 140 uint32_t * flags = NULL; 141 uint32_t attr; 142 typedef char segname_t[16]; 143 segname_t * names = NULL; 144 145 if ((argc != 5) || strcmp("-o", argv[3])) { 146 fprintf(stderr, "Usage: %s NEWSEGNAME input -o output\n", argv[0]); 147 exit(1); 148 } 149 150 output_name = argv[4]; 151 newseg_name = argv[1]; 152 153 error = readFile(argv[2], &input, &input_size); 154 if (error) { 155 exit(1); 156 } 157 158 hdr = (typeof(hdr)) input; 159 switch (hdr->magic) { 160 case MH_CIGAM: 161 swap = true; 162 // fall thru 163 case MH_MAGIC: 164 ncmds = hdr->ncmds; 165 cmds = (typeof(cmds)) (hdr+1); 166 break; 167 168 case MH_CIGAM_64: 169 swap = true; 170 // fall thru 171 case MH_MAGIC_64: 172 hdr64 = (typeof(hdr64)) hdr; 173 ncmds = hdr64->ncmds; 174 cmds = (typeof(cmds)) (hdr64+1); 175 break; 176 177 default: 178 fprintf(stderr, "not macho input file\n"); 179 exit(1); 180 break; 181 } 182 183 if (swap) { 184 ncmds = OSSwapInt32(ncmds); 185 } 186 while (ncmds--) { 187 cmdtype = cmds->cmd; 188 if (swap) { 189 cmdtype = OSSwapInt32(cmdtype); 190 } 191 nsects = 0; 192 len = 0; 193 if (LC_SEGMENT == cmdtype) { 194 struct segment_command * segcmd; 195 struct section * sects; 196 197 segcmd = (typeof(segcmd)) cmds; 198 nsects = segcmd->nsects; 199 sects = (typeof(sects))(segcmd + 1); 200 names = §s->segname; 201 flags = §s->flags; 202 len = sizeof(*sects); 203 } else if (LC_SEGMENT_64 == cmdtype) { 204 struct segment_command_64 * segcmd; 205 struct section_64 * sects; 206 207 segcmd = (typeof(segcmd)) cmds; 208 nsects = segcmd->nsects; 209 sects = (typeof(sects))(segcmd + 1); 210 names = §s->segname; 211 flags = §s->flags; 212 len = sizeof(*sects); 213 } 214 215 if (swap) 216 nsects = OSSwapInt32(nsects); 217 while (nsects--) { 218 attr = *flags; 219 if (swap) { 220 attr = OSSwapInt32(attr); 221 } 222 223 if (!(S_ATTR_DEBUG & attr)) { 224 strncpy((char *)names, newseg_name, sizeof(*names)); 225 } 226 227 names = (typeof(names))(((uintptr_t) names) + len); 228 flags = (typeof(flags))(((uintptr_t) flags) + len); 229 } 230 231 len = cmds->cmdsize; 232 if (swap) { 233 len = OSSwapInt32(len); 234 } 235 cmds = (typeof(cmds))(((uintptr_t) cmds) + len); 236 } 237 238 int fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755); 239 if (-1 == fd) { 240 error = -1; 241 } else { 242 error = writeFile(fd, (const void *) input, input_size); 243 close(fd); 244 } 245 246 if (error) { 247 fprintf(stderr, "couldn't write output: %s\n", strerror(errno)); 248 exit(1); 249 } 250 251 exit(0); 252 return 0; 253} 254