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