]> git.saurik.com Git - apple/xnu.git/blame - SETUP/setsegname/setsegname.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / SETUP / setsegname / setsegname.c
CommitLineData
6d2010ae
A
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
39236c6e 32#include <stdbool.h>
6d2010ae
A
33
34/*********************************************************************
35*********************************************************************/
36static int
37writeFile(int fd, const void * data, size_t length)
38{
0a7de745 39 int error = 0;
6d2010ae 40
0a7de745
A
41 if (length != (size_t)write(fd, data, length)) {
42 error = -1;
43 }
6d2010ae 44
0a7de745
A
45 if (error != 0) {
46 perror("couldn't write output");
47 }
6d2010ae 48
0a7de745 49 return error;
6d2010ae
A
50}
51
52/*********************************************************************
53*********************************************************************/
54static int
55readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize)
56{
0a7de745
A
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;
6d2010ae
A
105}
106
39236c6e
A
107static void
108usage(void)
109{
c3c9b80d 110 fprintf(stderr, "Usage: %s [-s OLDSEGNAME] [-i IGNORESEGNAME] -n NEWSEGNAME input -o output\n", getprogname());
0a7de745 111 exit(1);
39236c6e
A
112}
113
6d2010ae
A
114/*********************************************************************
115*********************************************************************/
0a7de745
A
116int
117main(int argc, char * argv[])
6d2010ae 118{
0a7de745
A
119 int error;
120 const char * output_name = NULL;
121 const char * input_name = NULL;
122 const char * oldseg_name = NULL;
c3c9b80d 123 const char * ignoreseg_name = NULL;
0a7de745
A
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
c3c9b80d 141 while ((ch = getopt(argc, argv, "s:i:n:o:")) != -1) {
0a7de745
A
142 switch (ch) {
143 case 's':
144 oldseg_name = optarg;
145 break;
c3c9b80d
A
146 case 'i':
147 ignoreseg_name = optarg;
148 break;
0a7de745
A
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;
39236c6e
A
163
164 if ((argc != 1) || !newseg_name || !output_name) {
0a7de745
A
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
c3c9b80d
A
241 if (!(S_ATTR_DEBUG & attr) && (!ignoreseg_name ||
242 0 != strncmp(ignoreseg_name, (char *)names, sizeof(*names)))) {
0a7de745
A
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;
6d2010ae 276}