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