2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
26 * macho-to-xcoff.c - Converts a Mach-O file an XCOFF.
28 * Copyright (c) 1998-2002 Apple Computer, Inc.
36 #include <mach-o/loader.h>
37 #include <mach/thread_status.h>
38 #include <mach/ppc/thread_status.h>
45 static struct mach_header mhead
;
47 typedef unsigned char UInt8
;
48 typedef unsigned short UInt16
;
49 typedef unsigned long UInt32
;
52 #define SWAPL(value) ( (((value) >> 24) & 0xff) | \
53 (((value) >> 8) & 0xff00) | \
54 (((value) << 8) & 0xff0000) | \
55 (((value) << 24) & 0xff000000) )
57 #define SWAPS(value) ( (((value) >> 8) & 0xff) | \
58 (((value) << 8) & 0xff00) )
67 #define kFileMagic 0x1DF
79 #define kOptHeaderMagic 0x10B
102 UInt32 sectionFileOffset
;
103 UInt32 relocationsFileOffset
;
104 UInt32 lineNumbersFileOffset
;
110 enum SectionNumbers
{
116 #define kTextName ".text"
117 #define kDataName ".data"
118 #define kBSSName ".bss"
128 SWAPS(kFileMagic
), /* magic */
129 SWAPS(3), /* nSections */
133 SWAPS(sizeof (XOptHeader
)), /* optHeaderSize */
137 SWAPS(kOptHeaderMagic
), /* magic */
146 SWAPS(kTextSN
), /* snEntry */
147 SWAPS(kTextSN
), /* snText */
148 SWAPS(kDataSN
), /* snData */
149 SWAPS(0), /* snTOC */
150 SWAPS(0), /* snLoader */
151 SWAPS(kBSSSN
), /* snBSS */
165 static UInt32 textFileOffset
;
166 static UInt32 textSize
;
167 static UInt32 dataFileOffset
;
168 static UInt32 dataSize
;
169 static UInt32 bssSize
;
172 static void usage (char *msg
)
174 printf ("Usage: %s mach-o-file-name xcoff-file-name\n\n%s\n",
180 static void copyMachOSectionToXCOFF (UInt32 machoOffset
, UInt32 sectionSize
)
182 static char buf
[65536];
184 fseek (machoF
, machoOffset
, SEEK_SET
);
186 while (sectionSize
) {
187 long readSize
= sectionSize
> sizeof (buf
) ? sizeof (buf
) : sectionSize
;
191 actualSize
= fread (buf
, 1, readSize
, machoF
);
192 if (actualSize
< 0) perror ("read error for section");
194 writeSize
= actualSize
;
195 actualSize
= fwrite (buf
, 1, writeSize
, xcoffF
);
196 if (actualSize
< 0) perror ("write error for section");
198 sectionSize
-= actualSize
;
203 int main (int argc
, char **argv
)
208 #define LCP ((struct load_command *) cp)
209 #define SCP ((struct segment_command *) cp)
213 if (argc
< 3) usage ("wrong number of parameters");
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");
220 n
= fread (&mhead
, sizeof (mhead
), 1, machoF
);
221 if (n
!= 1) perror ("error reading mach-o file header");
223 if (SWAPL(mhead
.magic
) != MH_MAGIC
224 || SWAPL(mhead
.filetype
) != MH_EXECUTE
)
225 usage ("bad mach-o file header");
227 cmdsP
= malloc (SWAPL(mhead
.sizeofcmds
));
228 if (cmdsP
== 0) usage ("cmdsP allocation failed");
230 n
= fread (cmdsP
, SWAPL(mhead
.sizeofcmds
), 1, machoF
);
231 if (n
!= 1) perror ("error reading mach-o commands");
233 printf("Mach-o file has magic=0x%08lX, %ld commands\n", SWAPL(mhead
.magic
), SWAPL(mhead
.ncmds
));
235 for (n
= 0, cp
= cmdsP
; n
< SWAPL(mhead
.ncmds
); ++n
, cp
+= SWAPL(LCP
->cmdsize
)) {
237 switch (SWAPL(LCP
->cmd
)) {
239 printf ("segment: %s: 0x%08lX of 0x%08lX bytes\n",
240 SCP
->segname
, SWAPL(SCP
->vmaddr
), SWAPL(SCP
->vmsize
));
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
;
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
;
257 /* Use just FILE part -- rest is BSS */
258 xHead
.data
.size
= SCP
->filesize
;
260 printf ("ignoring mach-o section \"%s\"\n", SCP
->segname
);
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
));
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
);
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
));
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
);
290 /* Write out the XCOFF file, copying the relevant mach-o file sections */
291 fwrite (&xHead
, sizeof (xHead
), 1, xcoffF
);
293 copyMachOSectionToXCOFF (textFileOffset
, textSize
);
294 copyMachOSectionToXCOFF (dataFileOffset
, dataSize
);