1 | /*␊ |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
7 | * Reserved. This file contains Original Code and/or Modifications of␊ |
8 | * Original Code as defined in and that are subject to the Apple Public␊ |
9 | * Source License Version 2.0 (the "License"). You may not use this file␊ |
10 | * except in compliance with the License. Please obtain a copy of the␊ |
11 | * License at http://www.apple.com/publicsource and read it before using␊ |
12 | * this file.␊ |
13 | * ␊ |
14 | * The Original Code and all software distributed under the License are␊ |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the␊ |
19 | * License for the specific language governing rights and limitations␊ |
20 | * under the License.␊ |
21 | * ␊ |
22 | * @APPLE_LICENSE_HEADER_END@␊ |
23 | */␊ |
24 | #include <stdio.h>␊ |
25 | #include <stdlib.h>␊ |
26 | #include <mach/mach.h>␊ |
27 | #include <mach/mach_error.h>␊ |
28 | #include <sys/file.h>␊ |
29 | #include <mach-o/loader.h>␊ |
30 | #include <libkern/OSByteOrder.h>␊ |
31 | #include <unistd.h>␊ |
32 | ␊ |
33 | int␉infile, outfile;␊ |
34 | ␊ |
35 | struct mach_header␉mh;␊ |
36 | void *␉␉cmds;␊ |
37 | ␊ |
38 | boolean_t␉␉swap_ends;␊ |
39 | ␊ |
40 | static unsigned long swap(␊ |
41 | unsigned long x␊ |
42 | )␊ |
43 | {␊ |
44 | if (swap_ends)␊ |
45 | ␉return OSSwapInt32(x);␊ |
46 | else␊ |
47 | ␉return x;␊ |
48 | }␊ |
49 | ␊ |
50 | int␊ |
51 | main(int argc, char *argv[])␊ |
52 | {␊ |
53 | kern_return_t␉result;␊ |
54 | vm_address_t␉data;␊ |
55 | int␉␉␉nc, ncmds;␊ |
56 | char *␉␉cp;␊ |
57 | ␊ |
58 | if (argc == 2) {␊ |
59 | ␉infile = open(argv[1], O_RDONLY);␊ |
60 | ␉if (infile < 0)␊ |
61 | ␉ goto usage;␊ |
62 | ␉outfile = fileno(stdout);␊ |
63 | }␊ |
64 | else if (argc == 3) {␊ |
65 | ␉infile = open(argv[1], O_RDONLY);␊ |
66 | ␉if (infile < 0)␊ |
67 | ␉ goto usage;␊ |
68 | ␉outfile = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644);␊ |
69 | ␉if (outfile < 0)␊ |
70 | ␉ goto usage;␊ |
71 | }␊ |
72 | else {␊ |
73 | usage:␊ |
74 | ␉fprintf(stderr, "usage: machOconv inputfile [outputfile]\n");␊ |
75 | ␉exit(1);␊ |
76 | }␊ |
77 | ␊ |
78 | nc = read(infile, &mh, sizeof (mh));␊ |
79 | if (nc < 0) {␊ |
80 | ␉perror("read mach header");␊ |
81 | ␉exit(1);␊ |
82 | }␊ |
83 | if (nc < (int)sizeof (mh)) {␊ |
84 | ␉fprintf(stderr, "read mach header: premature EOF %d\n", nc);␊ |
85 | ␉exit(1);␊ |
86 | }␊ |
87 | if (mh.magic == MH_MAGIC)␊ |
88 | ␉swap_ends = FALSE;␊ |
89 | else if (mh.magic == MH_CIGAM)␊ |
90 | ␉swap_ends = TRUE;␊ |
91 | else {␊ |
92 | ␉fprintf(stderr, "bad magic number %lx\n", (unsigned long)mh.magic);␊ |
93 | ␉exit(1);␊ |
94 | }␊ |
95 | ␊ |
96 | cmds = calloc(swap(mh.sizeofcmds), sizeof (char));␊ |
97 | if (cmds == 0) {␊ |
98 | ␉fprintf(stderr, "alloc load commands: no memory\n");␊ |
99 | ␉exit(1);␊ |
100 | }␊ |
101 | nc = read(infile, cmds, swap(mh.sizeofcmds));␊ |
102 | if (nc < 0) {␊ |
103 | ␉perror("read load commands");␊ |
104 | ␉exit(1);␊ |
105 | }␊ |
106 | if (nc < (int)swap(mh.sizeofcmds)) {␊ |
107 | ␉fprintf(stderr, "read load commands: premature EOF %d\n", nc);␊ |
108 | ␉exit(1);␊ |
109 | }␊ |
110 | ␊ |
111 | for (␉ncmds = swap(mh.ncmds), cp = cmds;␊ |
112 | ␉␉ncmds > 0; ncmds--) {␊ |
113 | ␉ boolean_t␉isDATA;␊ |
114 | ␉ unsigned␉vmsize;␊ |
115 | ␊ |
116 | #define lcp␉((struct load_command *)cp) ␊ |
117 | ␉switch(swap(lcp->cmd)) {␊ |
118 | ␊ |
119 | ␉case LC_SEGMENT:␊ |
120 | #define scp␉((struct segment_command *)cp)␊ |
121 | ␉ isDATA = (strcmp(scp->segname, "__DATA") == 0);␊ |
122 | ␉ if (isDATA)␊ |
123 | ␉ ␉vmsize = swap(scp->filesize);␊ |
124 | ␉ else␊ |
125 | ␉ ␉vmsize = swap(scp->vmsize);␊ |
126 | ␉ result = vm_allocate(mach_task_self(), &data, vmsize, TRUE);␊ |
127 | ␉ if (result != KERN_SUCCESS) {␊ |
128 | ␉␉mach_error("vm_allocate segment data", result);␊ |
129 | ␉␉exit(1);␊ |
130 | ␉ }␊ |
131 | ␊ |
132 | ␉ lseek(infile, swap(scp->fileoff), L_SET);␊ |
133 | ␉ nc = read(infile, (void *)data, swap(scp->filesize));␊ |
134 | ␉ if (nc < 0) {␊ |
135 | ␉␉perror("read segment data");␊ |
136 | ␉␉exit(1);␊ |
137 | ␉ }␊ |
138 | ␉ if (nc < (int)swap(scp->filesize)) {␊ |
139 | ␉␉fprintf(stderr, "read segment data: premature EOF %d\n", nc);␊ |
140 | ␉␉exit(1);␊ |
141 | ␉ }␊ |
142 | ␊ |
143 | ␉ nc = write(outfile, (void *)data, vmsize);␊ |
144 | ␉ if (nc < (int)vmsize) {␊ |
145 | ␉␉perror("write segment data");␊ |
146 | ␉␉exit(1);␊ |
147 | ␉ }␊ |
148 | ␉ ␊ |
149 | ␉ vm_deallocate(mach_task_self(), data, vmsize);␊ |
150 | ␉ break;␊ |
151 | ␉}␊ |
152 | ␊ |
153 | ␉cp += swap(lcp->cmdsize);␊ |
154 | }␊ |
155 | ␉␊ |
156 | exit(0);␊ |
157 | }␊ |
158 | |