]> git.saurik.com Git - apple/xnu.git/blob - SETUP/setsegname/setsegname.c
bd15b00256c2431d0be719b50e40cf1f2ce8f82e
[apple/xnu.git] / SETUP / setsegname / setsegname.c
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
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
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
108 usage(void)
109 {
110 fprintf(stderr, "Usage: %s [-s OLDSEGNAME] -n NEWSEGNAME input -o output\n", getprogname());
111 exit(1);
112 }
113
114 /*********************************************************************
115 *********************************************************************/
116 int
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 * 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 = &sects->segname;
214 flags = &sects->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 = &sects->segname;
224 flags = &sects->flags;
225 len = sizeof(*sects);
226 }
227
228 if (swap) {
229 nsects = OSSwapInt32(nsects);
230 }
231 while (nsects--) {
232 attr = *flags;
233 if (swap) {
234 attr = OSSwapInt32(attr);
235 }
236
237 if (!(S_ATTR_DEBUG & attr)) {
238 if (!oldseg_name ||
239 0 == strncmp(oldseg_name, (char *)names, sizeof(*names))) {
240 memset(names, 0x0, sizeof(*names));
241 strncpy((char *)names, newseg_name, sizeof(*names));
242 }
243 }
244
245 names = (typeof(names))(((uintptr_t) names) + len);
246 flags = (typeof(flags))(((uintptr_t) flags) + len);
247 }
248
249 len = cmds->cmdsize;
250 if (swap) {
251 len = OSSwapInt32(len);
252 }
253 cmds = (typeof(cmds))(((uintptr_t) cmds) + len);
254 }
255
256 int fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0755);
257 if (-1 == fd) {
258 error = -1;
259 } else {
260 error = writeFile(fd, (const void *) input, input_size);
261 close(fd);
262 }
263
264 if (error) {
265 fprintf(stderr, "couldn't write output: %s\n", strerror(errno));
266 exit(1);
267 }
268
269 exit(0);
270 return 0;
271 }