ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Darwin/lowmem.c
(Generate patch)

Comparing BasiliskII/src/Unix/Darwin/lowmem.c (file contents):
Revision 1.3 by gbeauche, 2005-01-30T21:42:14Z vs.
Revision 1.6 by asvitkine, 2009-11-13T01:57:48Z

# Line 25 | Line 25
25   #include <fcntl.h>
26   #include <errno.h>
27   #include <stdio.h>
28 + #include <stdlib.h>
29   #include <string.h>
30   #include <mach/vm_prot.h>
31   #include <mach-o/loader.h>
32 + #include <mach-o/fat.h>
33  
34   static const char progname[] = "lowmem";
35 + static const char *filename;
36 +
37 + static int do_swap = 0;
38 +
39 + static uint32_t target_uint32(uint32_t value)
40 + {
41 +        if (do_swap)
42 +                value = OSSwapInt32(value);
43 +        return value;
44 + }
45 +
46 + void pagezero_32(struct mach_header *machhead)
47 + {
48 +        struct segment_command *sc_cmd;
49 +
50 +        if (target_uint32(machhead->filetype) != MH_EXECUTE) {
51 +                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
52 +                                progname, filename);
53 +                exit(1);
54 +        }
55 +        if (machhead->ncmds == 0) {
56 +                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
57 +                                progname, filename);
58 +                exit(1);
59 +        }
60 +        sc_cmd = (void *)&machhead[1];
61 +        if (target_uint32(sc_cmd->cmd) != LC_SEGMENT){
62 +                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
63 +                                progname, filename);
64 +                exit(1);
65 +        }
66 +        if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof (*sc_cmd->segname))) {
67 +                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
68 +                                progname, filename);
69 +                exit(1);
70 +        }
71 +        /* change the permissions */
72 +        sc_cmd->maxprot = target_uint32(VM_PROT_ALL);
73 +        sc_cmd->initprot = target_uint32(VM_PROT_ALL);
74 + }
75 +
76 + #if defined(MH_MAGIC_64)
77 + void pagezero_64(struct mach_header_64 *machhead)
78 + {
79 +        struct segment_command_64 *sc_cmd;
80 +
81 +        if (target_uint32(machhead->filetype) != MH_EXECUTE) {
82 +                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
83 +                                progname, filename);
84 +                exit(1);
85 +        }
86 +        if (machhead->ncmds == 0) {
87 +                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
88 +                                progname, filename);
89 +                exit(1);
90 +        }
91 +        sc_cmd = (void *)&machhead[1];
92 +        if (target_uint32(sc_cmd->cmd) != LC_SEGMENT_64) {
93 +                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
94 +                                progname, filename);
95 +                exit(1);
96 +        }
97 +        if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof(*sc_cmd->segname))) {
98 +                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
99 +                                progname, filename);
100 +                exit(1);
101 +        }
102 +        /* change the permissions */
103 +        sc_cmd->maxprot = target_uint32(VM_PROT_ALL);
104 +        sc_cmd->initprot = target_uint32(VM_PROT_ALL);
105 + }
106 + #endif
107  
108   /*
109 + /*
110   * Under Mach there is very little assumed about the memory map of object
111   * files. It is the job of the loader to create the initial memory map of an
112   * executable. In a Mach-O executable there will be numerous loader commands
# Line 54 | Line 129 | main(int argc, const char *argv[])
129   {
130          int fd;
131          char *addr;
132 +        off_t file_size;
133          struct mach_header *machhead;
134 <        struct segment_command *sc_cmd;
134 > #if defined(MH_MAGIC_64)
135 >        struct mach_header_64 *machhead64;
136 > #endif
137 >        struct fat_header *fathead;
138  
139          if (argc != 2) {
140                  (void)fprintf(stderr, "Usage: %s executable\n", progname);
141                  exit(1);
142          }
143  
144 <        fd = open(argv[1], O_RDWR, 0);
144 >        filename = argv[1];
145 >
146 >        fd = open(filename, O_RDWR, 0);
147          if (fd == -1) {
148                  (void)fprintf(stderr, "%s: could not open %s: %s\n",
149 <                        progname, argv[1], strerror(errno));
149 >                        progname, filename, strerror(errno));
150 >                exit(1);
151 >        }
152 >
153 >        file_size = lseek(fd, 0, SEEK_END);
154 >        if (file_size == -1) {
155 >                // for some mysterious reason, this sometimes fails...
156 >                file_size = 0x1000;
157 > #if 0
158 >                (void)fprintf(stderr, "%s: could not get size of %s: %s\n",
159 >                      progname, filename, strerror(errno));
160                  exit(1);
161 + #endif
162          }
163  
164          /*
165           * Size does not really matter, it will be rounded-up to a multiple
166           * of the page size automatically.
167           */
168 <        addr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
168 >        addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
169              MAP_FILE | MAP_SHARED, fd, 0);
170          if (addr == NULL) {
171                  (void)fprintf(stderr, "%s: could not mmap %s: %s\n",
172 <                                progname, argv[1], strerror(errno));
172 >                                progname, filename, strerror(errno));
173                  exit(1);
174          }
175  
176          /*
177           * Check to see if the Mach-O magic bytes are in the header.
86         * If we cared about cross compiling we would also check against
87         * MH_CIGAM and then change the endianness with every access, but
88         * we do not care about that.
178           */
179          machhead = (void *)addr;
180 <        if (machhead->magic != MH_MAGIC) {
180 > #if defined(MH_MAGIC_64)
181 >        machhead64 = (void *)addr;
182 > #endif
183 >        fathead = (void *)addr;
184 >
185 > #if defined(MH_MAGIC_64)
186 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM || machhead64->magic == MH_CIGAM_64;
187 > #else
188 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM;
189 > #endif
190 >
191 >        if (target_uint32(machhead->magic) == MH_MAGIC) {
192 >                pagezero_32(machhead);
193 > #if defined(MH_MAGIC_64)
194 >        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
195 >                pagezero_64(machhead64);
196 > #endif
197 >        } else if (target_uint32(fathead->magic) == FAT_MAGIC) {
198 >                struct fat_arch *arch = (void *)&fathead[1];
199 >                int saved_swap = do_swap;
200 >                int i;
201 >                for (i = 0; i < target_uint32(fathead->nfat_arch); ++i, ++arch) {
202 >                        machhead   = (void *)(addr + target_uint32(arch->offset));
203 > #if defined(MH_MAGIC_64)
204 >                        machhead64 = (void *)(addr + target_uint32(arch->offset));
205 > #endif
206 > #if defined(MH_MAGIC_64)
207 >                        do_swap = machhead->magic == MH_CIGAM || machhead64->magic == MH_CIGAM_64;
208 > #else
209 >                        do_swap = machhead->magic == MH_CIGAM;
210 > #endif
211 >                        if (target_uint32(machhead->magic) == MH_MAGIC) {
212 >                                pagezero_32(machhead);
213 > #if defined(MH_MAGIC_64)
214 >                        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
215 >                                pagezero_64(machhead64);
216 > #endif
217 >                        } else {
218 >                                (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
219 >                                                progname, filename);
220 >                                exit(1);
221 >                        }
222 >                        do_swap = saved_swap;
223 >                }
224 >        } else {
225                  (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
226 <                                progname, argv[1]);
94 <                exit(1);
95 <        }
96 <
97 <        if (machhead->filetype != MH_EXECUTE) {
98 <                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
99 <                                progname, argv[1]);
226 >                                progname, filename);
227                  exit(1);
228          }
229  
103        if (machhead->ncmds == 0) {
104                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
105                                progname, argv[1]);
106                exit(1);
107        }
108
109        sc_cmd = (void *)&machhead[1];
110        if (sc_cmd->cmd != LC_SEGMENT){
111                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
112                                progname, argv[1]);
113                exit(1);
114        }
115
116        if (strncmp(sc_cmd->segname, "__PAGEZERO",
117                         sizeof (*sc_cmd->segname))) {
118                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
119                                progname, argv[1]);
120                exit(1);
121        }
122
123        /* change the permissions */
124        sc_cmd->maxprot = VM_PROT_ALL;
125        sc_cmd->initprot = VM_PROT_ALL;
126
230          /*
231           * We do not make __PAGEZERO 8K in this program because then
232           * all of the offsets would be wrong in the object file after
233           * this segment. Instead we use the -pagezero_size option
234           * to link the executable.
235           */
236 <        if (msync(addr, 0x1000, MS_SYNC) == -1) {
236 >        if (msync(addr, file_size, MS_SYNC) == -1) {
237                  (void)fprintf(stderr, "%s: could not sync %s: %s\n",
238 <                                progname, argv[1], strerror(errno));
238 >                                progname, filename, strerror(errno));
239                  exit(1);
240          }
241  
242 <        if (munmap(addr, 0x1000) == -1) {
242 >        if (munmap(addr, file_size) == -1) {
243                  (void)fprintf(stderr, "%s: could not unmap %s: %s\n",
244 <                                progname, argv[1], strerror(errno));
244 >                                progname, filename, strerror(errno));
245                  exit(1);
246          }
247  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines