]> git.saurik.com Git - apple/bootx.git/blame - macho-to-xcoff.tproj/macho-to-xcoff.c
BootX-81.tar.gz
[apple/bootx.git] / macho-to-xcoff.tproj / macho-to-xcoff.c
CommitLineData
04fee52e
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
8be739c0
A
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.
04fee52e 11 *
8be739c0
A
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
04fee52e
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
8be739c0
A
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.
04fee52e
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * macho-to-xcoff.c - Converts a Mach-O file an XCOFF.
24 *
366defd1 25 * Copyright (c) 1998-2002 Apple Computer, Inc.
04fee52e
A
26 *
27 * DRI: Josh de Cesare
28 */
29
873b6fa6 30#define __srr0 srr0 // works with or without conformance
04fee52e
A
31#include <stdio.h>
32#include <stdlib.h>
366defd1 33#include <strings.h>
04fee52e
A
34#include <mach-o/loader.h>
35#include <mach/thread_status.h>
36#include <mach/ppc/thread_status.h>
37
38
39char *progname;
40static FILE *machoF;
41static FILE *xcoffF;
42
43static struct mach_header mhead;
44
45typedef unsigned char UInt8;
46typedef unsigned short UInt16;
47typedef 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
74typedef 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
95typedef 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
108enum SectionNumbers {
109 kTextSN = 1,
110 kDataSN,
111 kBSSSN
112};
113
114#define kTextName ".text"
115#define kDataName ".data"
116#define kBSSName ".bss"
117
118static 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
163static UInt32 textFileOffset;
164static UInt32 textSize;
165static UInt32 dataFileOffset;
166static UInt32 dataSize;
167static UInt32 bssSize;
168
169
170static 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
178static 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
366defd1 201int main (int argc, char **argv)
04fee52e
A
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
366defd1 231 printf("Mach-o file has magic=0x%08lX, %ld commands\n", SWAPL(mhead.magic), SWAPL(mhead.ncmds));
04fee52e
A
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:
366defd1 237 printf ("segment: %s: 0x%08lX of 0x%08lX bytes\n",
04fee52e
A
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);
366defd1 243 printf ("__TEXT size = 0x%08lX\n", textSize);
04fee52e
A
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);
366defd1 250 printf ("__DATA size = 0x%08lX\n", dataSize);
04fee52e 251 bssSize = SWAPL(SCP->vmsize) - SWAPL(SCP->filesize);
366defd1 252 printf ("__BSS size = 0x%08lX\n", bssSize);
04fee52e
A
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 {
366defd1 258 printf ("ignoring mach-o section \"%s\"\n", SCP->segname);
04fee52e
A
259 }
260 break;
261
262 case LC_THREAD:
263 case LC_UNIXTHREAD:
873b6fa6 264 xHead.opt.entryPoint = ((ppc_thread_state_t *)
04fee52e
A
265 (cp + sizeof(struct thread_command)
266 + 2 * sizeof(unsigned long)) )->srr0;
366defd1 267 printf("Entry point %lx\n\n", SWAPL(xHead.opt.entryPoint));
04fee52e
A
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;
366defd1 286 if (argc == 4) sscanf(argv[3],"%lx",&xHead.opt.entryPoint);
04fee52e
A
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);
366defd1
A
296
297 return 0;
04fee52e 298}