]>
Commit | Line | Data |
---|---|---|
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 | ||
39 | char *progname; | |
40 | static FILE *machoF; | |
41 | static FILE *xcoffF; | |
42 | ||
43 | static struct mach_header mhead; | |
44 | ||
45 | typedef unsigned char UInt8; | |
46 | typedef unsigned short UInt16; | |
47 | typedef 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 | ||
74 | typedef 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 | ||
95 | typedef 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 | ||
108 | enum SectionNumbers { | |
109 | kTextSN = 1, | |
110 | kDataSN, | |
111 | kBSSSN | |
112 | }; | |
113 | ||
114 | #define kTextName ".text" | |
115 | #define kDataName ".data" | |
116 | #define kBSSName ".bss" | |
117 | ||
118 | static 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 | ||
163 | static UInt32 textFileOffset; | |
164 | static UInt32 textSize; | |
165 | static UInt32 dataFileOffset; | |
166 | static UInt32 dataSize; | |
167 | static UInt32 bssSize; | |
168 | ||
169 | ||
170 | static 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 | ||
178 | static 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 | 201 | int 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 | } |