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