Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/util/machOconv.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdbool.h>
28#include <mach/mach.h>
29#include <mach/mach_error.h>
30#include <sys/file.h>
31#include <mach-o/loader.h>
32#include <libkern/OSByteOrder.h>
33#include <unistd.h>
34
35intinfile, outfile;
36
37void *cmds;
38
39struct mach_headermh;
40
41static boolswap_ends;
42
43//==============================================================================
44
45static unsigned long swap(unsigned long x)
46{
47if (swap_ends)
48{
49return OSSwapInt32(x);
50}
51else
52{
53return x;
54}
55}
56
57
58//==============================================================================
59
60int main(int argc, char *argv[])
61{
62kern_return_tresult;
63vm_address_tdata;
64intnc, ncmds;
65char *cp;
66
67if (argc == 2)
68{
69infile = open(argv[1], O_RDONLY);
70
71if (infile < 0)
72{
73goto filenotfound;
74}
75
76outfile = fileno(stdout);
77}
78else if (argc == 3)
79{
80infile = open(argv[1], O_RDONLY);
81
82if (infile < 0)
83{
84goto filenotfound;
85}
86
87outfile = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
88
89if (outfile < 0)
90{
91goto openerror;
92}
93}
94else
95{
96fprintf(stderr, "Usage: machOconv inputfile [outputfile]\n");
97exit(1);
98
99filenotfound:
100fprintf(stderr, "Error: File Not Found\n");
101exit(1);
102
103openerror:
104fprintf(stderr, "Error: Open Failed\n");
105exit(1);
106}
107
108nc = read(infile, &mh, sizeof (mh));
109
110if (nc < 0)
111{
112perror("read mach header");
113exit(1);
114}
115
116if (nc < (int)sizeof (mh))
117{
118fprintf(stderr, "Error: read mach header: premature EOF %d\n", nc);
119exit(1);
120}
121
122if (mh.magic == MH_MAGIC)
123{
124swap_ends = false;
125}
126else if (mh.magic == MH_CIGAM)
127{
128swap_ends = true;
129}
130else
131{
132fprintf(stderr, "Error: bad magic number %lx\n", (unsigned long)mh.magic);
133exit(1);
134}
135
136cmds = calloc(swap(mh.sizeofcmds), sizeof (char));
137
138if (cmds == 0)
139{
140fprintf(stderr, "Error: alloc load commands: no memory\n");
141exit(1);
142}
143
144nc = read(infile, cmds, swap(mh.sizeofcmds));
145
146if (nc < 0)
147{
148perror("read load commands");
149exit(1);
150}
151
152if (nc < (int)swap(mh.sizeofcmds))
153{
154fprintf(stderr, "Error: read load commands: premature EOF %d\n", nc);
155exit(1);
156}
157
158unsigned long vmstart = (unsigned long) -1;
159
160// First pass: determine actual load address
161for (ncmds = swap(mh.ncmds), cp = cmds; ncmds > 0; ncmds--)
162{
163#define lcp((struct load_command *)cp)
164#define scp((struct segment_command *)cp)
165
166switch(swap(lcp->cmd))
167{
168case LC_SEGMENT:
169if (vmstart > swap(scp->vmaddr))
170{
171vmstart = swap(scp->vmaddr);
172}
173}
174cp += swap(lcp->cmdsize);
175
176}
177
178// Second pass: output to file.
179for (ncmds = swap(mh.ncmds), cp = cmds; ncmds > 0; ncmds--)
180{
181#define lcp((struct load_command *)cp)
182#define scp((struct segment_command *)cp)
183
184boolisDATA;
185unsignedvmsize;
186
187switch(swap(lcp->cmd))
188{
189case LC_SEGMENT:
190isDATA = (strncmp(scp->segname, "__DATA", sizeof("__DATA")) == 0);
191
192if (isDATA)
193{
194vmsize = swap(scp->filesize);
195}
196else
197{
198vmsize = swap(scp->vmsize);
199}
200
201result = vm_allocate(mach_task_self(), &data, vmsize, true);
202
203if (result != KERN_SUCCESS)
204{
205mach_error("vm_allocate segment data", result);
206exit(1);
207}
208
209lseek(infile, swap(scp->fileoff), L_SET);
210nc = read(infile, (void *)data, swap(scp->filesize));
211
212if (nc < 0)
213{
214perror("read segment data");
215exit(1);
216}
217
218if (nc < (int)swap(scp->filesize))
219{
220fprintf(stderr, "read segment data: premature EOF %d\n", nc);
221exit(1);
222}
223
224lseek(outfile, swap(scp->vmaddr) - vmstart, L_SET);
225nc = write(outfile, (void *)data, vmsize);
226
227if (nc < (int)vmsize)
228{
229perror("write segment data");
230exit(1);
231}
232
233vm_deallocate(mach_task_self(), data, vmsize);
234break;
235}
236
237cp += swap(lcp->cmdsize);
238}
239
240exit(0);
241}
242

Archive Download this file

Revision: 2635