2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * macho-to-xcoff.c - Converts a Mach-O file an XCOFF.
25 * Copyright (c) 1998-2002 Apple Computer, Inc.
33 #include <mach-o/loader.h>
34 #include <mach/thread_status.h>
35 #include <mach/ppc/thread_status.h>
42 static struct mach_header mhead
;
44 typedef unsigned char UInt8
;
45 typedef unsigned short UInt16
;
46 typedef unsigned long UInt32
;
49 #define SWAPL(value) ( (((value) >> 24) & 0xff) | \
50 (((value) >> 8) & 0xff00) | \
51 (((value) << 8) & 0xff0000) | \
52 (((value) << 24) & 0xff000000) )
54 #define SWAPS(value) ( (((value) >> 8) & 0xff) | \
55 (((value) << 8) & 0xff00) )
64 #define kFileMagic 0x1DF
76 #define kOptHeaderMagic 0x10B
99 UInt32 sectionFileOffset
;
100 UInt32 relocationsFileOffset
;
101 UInt32 lineNumbersFileOffset
;
107 enum SectionNumbers
{
113 #define kTextName ".text"
114 #define kDataName ".data"
115 #define kBSSName ".bss"
125 SWAPS(kFileMagic
), /* magic */
126 SWAPS(3), /* nSections */
130 SWAPS(sizeof (XOptHeader
)), /* optHeaderSize */
134 SWAPS(kOptHeaderMagic
), /* magic */
143 SWAPS(kTextSN
), /* snEntry */
144 SWAPS(kTextSN
), /* snText */
145 SWAPS(kDataSN
), /* snData */
146 SWAPS(0), /* snTOC */
147 SWAPS(0), /* snLoader */
148 SWAPS(kBSSSN
), /* snBSS */
162 static UInt32 textFileOffset
;
163 static UInt32 textSize
;
164 static UInt32 dataFileOffset
;
165 static UInt32 dataSize
;
166 static UInt32 bssSize
;
169 static void usage (char *msg
)
171 printf ("Usage: %s mach-o-file-name xcoff-file-name\n\n%s\n",
177 static void copyMachOSectionToXCOFF (UInt32 machoOffset
, UInt32 sectionSize
)
179 static char buf
[65536];
181 fseek (machoF
, machoOffset
, SEEK_SET
);
183 while (sectionSize
) {
184 long readSize
= sectionSize
> sizeof (buf
) ? sizeof (buf
) : sectionSize
;
188 actualSize
= fread (buf
, 1, readSize
, machoF
);
189 if (actualSize
< 0) perror ("read error for section");
191 writeSize
= actualSize
;
192 actualSize
= fwrite (buf
, 1, writeSize
, xcoffF
);
193 if (actualSize
< 0) perror ("write error for section");
195 sectionSize
-= actualSize
;
200 int main (int argc
, char **argv
)
205 #define LCP ((struct load_command *) cp)
206 #define SCP ((struct segment_command *) cp)
210 if (argc
< 3) usage ("wrong number of parameters");
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");
217 n
= fread (&mhead
, sizeof (mhead
), 1, machoF
);
218 if (n
!= 1) perror ("error reading mach-o file header");
220 if (SWAPL(mhead
.magic
) != MH_MAGIC
221 || SWAPL(mhead
.filetype
) != MH_EXECUTE
)
222 usage ("bad mach-o file header");
224 cmdsP
= malloc (SWAPL(mhead
.sizeofcmds
));
225 if (cmdsP
== 0) usage ("cmdsP allocation failed");
227 n
= fread (cmdsP
, SWAPL(mhead
.sizeofcmds
), 1, machoF
);
228 if (n
!= 1) perror ("error reading mach-o commands");
230 printf("Mach-o file has magic=0x%08lX, %ld commands\n", SWAPL(mhead
.magic
), SWAPL(mhead
.ncmds
));
232 for (n
= 0, cp
= cmdsP
; n
< SWAPL(mhead
.ncmds
); ++n
, cp
+= SWAPL(LCP
->cmdsize
)) {
234 switch (SWAPL(LCP
->cmd
)) {
236 printf ("segment: %s: 0x%08lX of 0x%08lX bytes\n",
237 SCP
->segname
, SWAPL(SCP
->vmaddr
), SWAPL(SCP
->vmsize
));
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
;
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
;
254 /* Use just FILE part -- rest is BSS */
255 xHead
.data
.size
= SCP
->filesize
;
257 printf ("ignoring mach-o section \"%s\"\n", SCP
->segname
);
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
));
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
);
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
));
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
);
287 /* Write out the XCOFF file, copying the relevant mach-o file sections */
288 fwrite (&xHead
, sizeof (xHead
), 1, xcoffF
);
290 copyMachOSectionToXCOFF (textFileOffset
, textSize
);
291 copyMachOSectionToXCOFF (dataFileOffset
, dataSize
);