xref: /xnu-11215.41.3/SETUP/setsegname/setsegname.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 *********************************************************************/
36 static int
writeFile(int fd,const void * data,size_t length)37 writeFile(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 *********************************************************************/
54 static int
readFile(const char * path,vm_offset_t * objAddr,vm_size_t * objSize)55 readFile(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 	} while (false);
96 
97 	if (-1 != fd) {
98 		close(fd);
99 	}
100 	if (error) {
101 		fprintf(stderr, "couldn't read %s: %s\n", path, strerror(errno));
102 	}
103 
104 	return error;
105 }
106 
107 static void
usage(void)108 usage(void)
109 {
110 	fprintf(stderr, "Usage: %s [-s OLDSEGNAME] [-i IGNORESEGNAME] -n NEWSEGNAME input -o output\n", getprogname());
111 	exit(1);
112 }
113 
114 /*********************************************************************
115 *********************************************************************/
116 int
main(int argc,char * argv[])117 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            * ignoreseg_name = NULL;
124 	const char            * newseg_name = NULL;
125 	struct mach_header    * hdr;
126 	struct mach_header_64 * hdr64;
127 	struct load_command   * cmds;
128 	boolean_t                   swap = false;
129 	uint32_t                    ncmds, cmdtype;
130 	uint32_t                    len;
131 	vm_offset_t                 input;
132 	vm_size_t                   input_size;
133 	uint32_t                    nsects = 0;
134 	uint32_t                * flags = NULL;
135 	uint32_t                    attr;
136 	typedef char            segname_t[16];
137 	segname_t             * names = NULL;
138 	int                     ch;
139 
140 
141 	while ((ch = getopt(argc, argv, "s:i:n:o:")) != -1) {
142 		switch (ch) {
143 		case 's':
144 			oldseg_name = optarg;
145 			break;
146 		case 'i':
147 			ignoreseg_name = optarg;
148 			break;
149 		case 'n':
150 			newseg_name = optarg;
151 			break;
152 		case 'o':
153 			output_name = optarg;
154 			break;
155 		case '?':
156 		default:
157 			usage();
158 		}
159 	}
160 
161 	argc -= optind;
162 	argv += optind;
163 
164 	if ((argc != 1) || !newseg_name || !output_name) {
165 		usage();
166 	}
167 
168 	input_name = argv[0];
169 
170 	error = readFile(input_name, &input, &input_size);
171 	if (error) {
172 		exit(1);
173 	}
174 
175 	hdr = (typeof(hdr))input;
176 	switch (hdr->magic) {
177 	case MH_CIGAM:
178 		swap = true;
179 	// fall thru
180 	case MH_MAGIC:
181 		ncmds = hdr->ncmds;
182 		cmds  = (typeof(cmds))(hdr + 1);
183 		break;
184 
185 	case MH_CIGAM_64:
186 		swap = true;
187 	// fall thru
188 	case MH_MAGIC_64:
189 		hdr64 = (typeof(hdr64))hdr;
190 		ncmds = hdr64->ncmds;
191 		cmds  = (typeof(cmds))(hdr64 + 1);
192 		break;
193 
194 	default:
195 		fprintf(stderr, "not macho input file\n");
196 		exit(1);
197 		break;
198 	}
199 
200 	if (swap) {
201 		ncmds = OSSwapInt32(ncmds);
202 	}
203 	while (ncmds--) {
204 		cmdtype = cmds->cmd;
205 		if (swap) {
206 			cmdtype = OSSwapInt32(cmdtype);
207 		}
208 		nsects = 0;
209 		len    = 0;
210 		if (LC_SEGMENT == cmdtype) {
211 			struct segment_command * segcmd;
212 			struct section         * sects;
213 
214 			segcmd = (typeof(segcmd))cmds;
215 			nsects = segcmd->nsects;
216 			sects  = (typeof(sects))(segcmd + 1);
217 			names  = &sects->segname;
218 			flags  = &sects->flags;
219 			len    = sizeof(*sects);
220 		} else if (LC_SEGMENT_64 == cmdtype) {
221 			struct segment_command_64 * segcmd;
222 			struct section_64         * sects;
223 
224 			segcmd = (typeof(segcmd))cmds;
225 			nsects = segcmd->nsects;
226 			sects  = (typeof(sects))(segcmd + 1);
227 			names  = &sects->segname;
228 			flags  = &sects->flags;
229 			len    = sizeof(*sects);
230 		}
231 
232 		if (swap) {
233 			nsects = OSSwapInt32(nsects);
234 		}
235 		while (nsects--) {
236 			attr = *flags;
237 			if (swap) {
238 				attr = OSSwapInt32(attr);
239 			}
240 
241 			if (!(S_ATTR_DEBUG & attr) && (!ignoreseg_name ||
242 			    0 != strncmp(ignoreseg_name, (char *)names, sizeof(*names)))) {
243 				if (!oldseg_name ||
244 				    0 == strncmp(oldseg_name, (char *)names, sizeof(*names))) {
245 					memset(names, 0x0, sizeof(*names));
246 					strncpy((char *)names, newseg_name, sizeof(*names));
247 				}
248 			}
249 
250 			names = (typeof(names))(((uintptr_t) names) + len);
251 			flags = (typeof(flags))(((uintptr_t) flags) + len);
252 		}
253 
254 		len = cmds->cmdsize;
255 		if (swap) {
256 			len = OSSwapInt32(len);
257 		}
258 		cmds = (typeof(cmds))(((uintptr_t) cmds) + len);
259 	}
260 
261 	int fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0755);
262 	if (-1 == fd) {
263 		error = -1;
264 	} else {
265 		error = writeFile(fd, (const void *) input, input_size);
266 		close(fd);
267 	}
268 
269 	if (error) {
270 		fprintf(stderr, "couldn't write output: %s\n", strerror(errno));
271 		exit(1);
272 	}
273 
274 	exit(0);
275 	return 0;
276 }
277