]> git.saurik.com Git - apple/bootx.git/blob - macho-to-xcoff.tproj/macho-to-xcoff.c
9d0586fe2e0781e0d369034684a06814d68b57e9
[apple/bootx.git] / macho-to-xcoff.tproj / macho-to-xcoff.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * macho-to-xcoff.c - Converts a Mach-O file an XCOFF.
27 *
28 * Copyright (c) 1998-2002 Apple Computer, Inc.
29 *
30 * DRI: Josh de Cesare
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <strings.h>
36 #include <mach-o/loader.h>
37 #include <mach/thread_status.h>
38 #include <mach/ppc/thread_status.h>
39
40
41 char *progname;
42 static FILE *machoF;
43 static FILE *xcoffF;
44
45 static struct mach_header mhead;
46
47 typedef unsigned char UInt8;
48 typedef unsigned short UInt16;
49 typedef unsigned long UInt32;
50
51 #ifdef __i386__
52 #define SWAPL(value) ( (((value) >> 24) & 0xff) | \
53 (((value) >> 8) & 0xff00) | \
54 (((value) << 8) & 0xff0000) | \
55 (((value) << 24) & 0xff000000) )
56
57 #define SWAPS(value) ( (((value) >> 8) & 0xff) | \
58 (((value) << 8) & 0xff00) )
59 #else
60 #define SWAPS(W) (W)
61 #define SWAPL(L) (L)
62 #endif
63
64 typedef struct {
65 /* File header */
66 UInt16 magic;
67 #define kFileMagic 0x1DF
68 UInt16 nSections;
69 UInt32 timeAndDate;
70 UInt32 symPtr;
71 UInt32 nSyms;
72 UInt16 optHeaderSize;
73 UInt16 flags;
74 } XFileHeader;
75
76 typedef struct {
77 /* Optional header */
78 UInt16 magic;
79 #define kOptHeaderMagic 0x10B
80 UInt16 version;
81 UInt32 textSize;
82 UInt32 dataSize;
83 UInt32 BSSSize;
84 UInt32 entryPoint;
85 UInt32 textStart;
86 UInt32 dataStart;
87 UInt32 toc;
88 UInt16 snEntry;
89 UInt16 snText;
90 UInt16 snData;
91 UInt16 snTOC;
92 UInt16 snLoader;
93 UInt16 snBSS;
94 UInt8 filler[28];
95 } XOptHeader;
96
97 typedef struct {
98 char name[8];
99 UInt32 pAddr;
100 UInt32 vAddr;
101 UInt32 size;
102 UInt32 sectionFileOffset;
103 UInt32 relocationsFileOffset;
104 UInt32 lineNumbersFileOffset;
105 UInt16 nRelocations;
106 UInt16 nLineNumbers;
107 UInt32 flags;
108 } XSection;
109
110 enum SectionNumbers {
111 kTextSN = 1,
112 kDataSN,
113 kBSSSN
114 };
115
116 #define kTextName ".text"
117 #define kDataName ".data"
118 #define kBSSName ".bss"
119
120 static struct {
121 XFileHeader file;
122 XOptHeader opt;
123 XSection text;
124 XSection data;
125 XSection BSS;
126 } xHead = {
127 { /* file */
128 SWAPS(kFileMagic), /* magic */
129 SWAPS(3), /* nSections */
130 0, /* timeAndDate */
131 0, /* symPtr */
132 0, /* nSyms */
133 SWAPS(sizeof (XOptHeader)), /* optHeaderSize */
134 0
135 },
136 { /* opt */
137 SWAPS(kOptHeaderMagic), /* magic */
138 0, /* version */
139 0, /* textSize */
140 0, /* dataSize */
141 0, /* BSSSize */
142 0, /* entryPoint */
143 0, /* textStart */
144 0, /* dataStart */
145 0, /* toc */
146 SWAPS(kTextSN), /* snEntry */
147 SWAPS(kTextSN), /* snText */
148 SWAPS(kDataSN), /* snData */
149 SWAPS(0), /* snTOC */
150 SWAPS(0), /* snLoader */
151 SWAPS(kBSSSN), /* snBSS */
152 },
153 { /* text section */
154 kTextName
155 },
156 { /* data section */
157 kDataName
158 },
159 { /* BSS section */
160 kBSSName
161 }
162 };
163
164
165 static UInt32 textFileOffset;
166 static UInt32 textSize;
167 static UInt32 dataFileOffset;
168 static UInt32 dataSize;
169 static UInt32 bssSize;
170
171
172 static void usage (char *msg)
173 {
174 printf ("Usage: %s mach-o-file-name xcoff-file-name\n\n%s\n",
175 progname, msg);
176 exit (1);
177 }
178
179
180 static void copyMachOSectionToXCOFF (UInt32 machoOffset, UInt32 sectionSize)
181 {
182 static char buf[65536];
183
184 fseek (machoF, machoOffset, SEEK_SET);
185
186 while (sectionSize) {
187 long readSize = sectionSize > sizeof (buf) ? sizeof (buf) : sectionSize;
188 long writeSize;
189 long actualSize;
190
191 actualSize = fread (buf, 1, readSize, machoF);
192 if (actualSize < 0) perror ("read error for section");
193
194 writeSize = actualSize;
195 actualSize = fwrite (buf, 1, writeSize, xcoffF);
196 if (actualSize < 0) perror ("write error for section");
197
198 sectionSize -= actualSize;
199 }
200 }
201
202
203 int main (int argc, char **argv)
204 {
205 int n;
206 char *cmdsP, *cp;
207
208 #define LCP ((struct load_command *) cp)
209 #define SCP ((struct segment_command *) cp)
210
211 progname = argv[0];
212
213 if (argc < 3) usage ("wrong number of parameters");
214
215 machoF = fopen (argv[1], "rb");
216 if (machoF == 0) perror ("Can't open mach-o file");
217 xcoffF = fopen (argv[2], "wb");
218 if (xcoffF == 0) perror ("Can't create and/or open XCOFF file");
219
220 n = fread (&mhead, sizeof (mhead), 1, machoF);
221 if (n != 1) perror ("error reading mach-o file header");
222
223 if (SWAPL(mhead.magic) != MH_MAGIC
224 || SWAPL(mhead.filetype) != MH_EXECUTE)
225 usage ("bad mach-o file header");
226
227 cmdsP = malloc (SWAPL(mhead.sizeofcmds));
228 if (cmdsP == 0) usage ("cmdsP allocation failed");
229
230 n = fread (cmdsP, SWAPL(mhead.sizeofcmds), 1, machoF);
231 if (n != 1) perror ("error reading mach-o commands");
232
233 printf("Mach-o file has magic=0x%08lX, %ld commands\n", SWAPL(mhead.magic), SWAPL(mhead.ncmds));
234
235 for (n = 0, cp = cmdsP; n < SWAPL(mhead.ncmds); ++n, cp += SWAPL(LCP->cmdsize)) {
236
237 switch (SWAPL(LCP->cmd)) {
238 case LC_SEGMENT:
239 printf ("segment: %s: 0x%08lX of 0x%08lX bytes\n",
240 SCP->segname, SWAPL(SCP->vmaddr), SWAPL(SCP->vmsize));
241
242 if (strncmp (SCP->segname, SEG_TEXT, sizeof (SCP->segname)) == 0) {
243 textFileOffset = SWAPL(SCP->fileoff);
244 textSize = SWAPL(SCP->filesize);
245 printf ("__TEXT size = 0x%08lX\n", textSize);
246 xHead.text.pAddr = xHead.text.vAddr = SCP->vmaddr;
247 xHead.text.size = SCP->vmsize;
248 } else
249 if (strncmp (SCP->segname, SEG_DATA, sizeof (SCP->segname)) == 0) {
250 dataFileOffset = SWAPL(SCP->fileoff);
251 dataSize = SWAPL(SCP->filesize);
252 printf ("__DATA size = 0x%08lX\n", dataSize);
253 bssSize = SWAPL(SCP->vmsize) - SWAPL(SCP->filesize);
254 printf ("__BSS size = 0x%08lX\n", bssSize);
255 xHead.data.pAddr = xHead.data.vAddr = SCP->vmaddr;
256
257 /* Use just FILE part -- rest is BSS */
258 xHead.data.size = SCP->filesize;
259 } else {
260 printf ("ignoring mach-o section \"%s\"\n", SCP->segname);
261 }
262 break;
263
264 case LC_THREAD:
265 case LC_UNIXTHREAD:
266 xHead.opt.entryPoint = ((ppc_saved_state_t *)
267 (cp + sizeof(struct thread_command)
268 + 2 * sizeof(unsigned long)) )->srr0;
269 printf("Entry point %lx\n\n", SWAPL(xHead.opt.entryPoint));
270 break;
271 }
272 }
273
274 /* Construct BSS out of thin air: the part of the data section
275 that is NOT file mapped */
276 xHead.BSS.pAddr = xHead.BSS.vAddr = SWAPL(SWAPL(xHead.data.pAddr) + SWAPL(xHead.data.size));
277 xHead.BSS.size = SWAPL(bssSize);
278
279 /* Calculate the section file offsets in the resulting XCOFF file */
280 xHead.text.sectionFileOffset = SWAPL(sizeof (xHead.file) + sizeof (xHead.opt)
281 + sizeof (xHead.text) + sizeof (xHead.data) + sizeof (xHead.BSS));
282 xHead.data.sectionFileOffset = SWAPL(SWAPL(xHead.text.sectionFileOffset) + SWAPL(xHead.text.size));
283
284 /* MT - write opt header */
285 xHead.opt.textSize = xHead.text.size;
286 xHead.opt.dataSize = xHead.data.size;
287 xHead.opt.BSSSize = xHead.BSS.size;
288 if (argc == 4) sscanf(argv[3],"%lx",&xHead.opt.entryPoint);
289
290 /* Write out the XCOFF file, copying the relevant mach-o file sections */
291 fwrite (&xHead, sizeof (xHead), 1, xcoffF);
292
293 copyMachOSectionToXCOFF (textFileOffset, textSize);
294 copyMachOSectionToXCOFF (dataFileOffset, dataSize);
295
296 fclose (machoF);
297 fclose (xcoffF);
298
299 return 0;
300 }