]> git.saurik.com Git - apple/xnu.git/blob - SETUP/setsegname/setsegname.c
9afd6bc5de03e9aca4d984b1decd3fa575ffd638
[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 <IOKit/IOTypes.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
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
108 /*********************************************************************
109 *********************************************************************/
110 int main(int argc, char * argv[])
111 {
112 int error;
113 const char * output_name = NULL;
114 const char * newseg_name = NULL;
115 struct mach_header * hdr;
116 struct mach_header_64 * hdr64;
117 struct load_command * cmds;
118 boolean_t swap = false;
119 uint32_t ncmds, cmdtype;
120 uint32_t len;
121 vm_offset_t input;
122 vm_size_t input_size;
123 uint32_t nsects = 0;
124 uint32_t * flags = NULL;
125 uint32_t attr;
126 typedef char segname_t[16];
127 segname_t * names = NULL;
128
129 if ((argc != 5) || strcmp("-o", argv[3])) {
130 fprintf(stderr, "Usage: %s NEWSEGNAME input -o output\n", argv[0]);
131 exit(1);
132 }
133
134 output_name = argv[4];
135 newseg_name = argv[1];
136
137 error = readFile(argv[2], &input, &input_size);
138 if (error) {
139 exit(1);
140 }
141
142 hdr = (typeof(hdr)) input;
143 switch (hdr->magic) {
144 case MH_CIGAM:
145 swap = true;
146 // fall thru
147 case MH_MAGIC:
148 ncmds = hdr->ncmds;
149 cmds = (typeof(cmds)) (hdr+1);
150 break;
151
152 case MH_CIGAM_64:
153 swap = true;
154 // fall thru
155 case MH_MAGIC_64:
156 hdr64 = (typeof(hdr64)) hdr;
157 ncmds = hdr64->ncmds;
158 cmds = (typeof(cmds)) (hdr64+1);
159 break;
160
161 default:
162 fprintf(stderr, "not macho input file\n");
163 exit(1);
164 break;
165 }
166
167 if (swap) {
168 ncmds = OSSwapInt32(ncmds);
169 }
170 while (ncmds--) {
171 cmdtype = cmds->cmd;
172 if (swap) {
173 cmdtype = OSSwapInt32(cmdtype);
174 }
175 nsects = 0;
176 len = 0;
177 if (LC_SEGMENT == cmdtype) {
178 struct segment_command * segcmd;
179 struct section * sects;
180
181 segcmd = (typeof(segcmd)) cmds;
182 nsects = segcmd->nsects;
183 sects = (typeof(sects))(segcmd + 1);
184 names = &sects->segname;
185 flags = &sects->flags;
186 len = sizeof(*sects);
187 } else if (LC_SEGMENT_64 == cmdtype) {
188 struct segment_command_64 * segcmd;
189 struct section_64 * sects;
190
191 segcmd = (typeof(segcmd)) cmds;
192 nsects = segcmd->nsects;
193 sects = (typeof(sects))(segcmd + 1);
194 names = &sects->segname;
195 flags = &sects->flags;
196 len = sizeof(*sects);
197 }
198
199 if (swap)
200 nsects = OSSwapInt32(nsects);
201 while (nsects--) {
202 attr = *flags;
203 if (swap) {
204 attr = OSSwapInt32(attr);
205 }
206
207 if (!(S_ATTR_DEBUG & attr)) {
208 strncpy((char *)names, newseg_name, sizeof(*names));
209 }
210
211 names = (typeof(names))(((uintptr_t) names) + len);
212 flags = (typeof(flags))(((uintptr_t) flags) + len);
213 }
214
215 len = cmds->cmdsize;
216 if (swap) {
217 len = OSSwapInt32(len);
218 }
219 cmds = (typeof(cmds))(((uintptr_t) cmds) + len);
220 }
221
222 int fd = open(output_name, O_WRONLY|O_CREAT|O_TRUNC, 0755);
223 if (-1 == fd) {
224 error = -1;
225 } else {
226 error = writeFile(fd, (const void *) input, input_size);
227 close(fd);
228 }
229
230 if (error) {
231 fprintf(stderr, "couldn't write output: %s\n", strerror(errno));
232 exit(1);
233 }
234
235 exit(0);
236 return 0;
237 }