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.4 by asvitkine, 2007-01-21T17:10:49Z vs.
Revision 1.7 by asvitkine, 2011-12-27T19:50:38Z

# Line 29 | Line 29
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   * Under Mach there is very little assumed about the memory map of object
# Line 55 | Line 128 | main(int argc, const char *argv[])
128   {
129          int fd;
130          char *addr;
131 +        off_t file_size;
132          struct mach_header *machhead;
133 <        struct segment_command *sc_cmd;
133 > #if defined(MH_MAGIC_64)
134 >        struct mach_header_64 *machhead64;
135 > #endif
136 >        struct fat_header *fathead;
137  
138          if (argc != 2) {
139                  (void)fprintf(stderr, "Usage: %s executable\n", progname);
140                  exit(1);
141          }
142  
143 <        fd = open(argv[1], O_RDWR, 0);
143 >        filename = argv[1];
144 >
145 >        fd = open(filename, O_RDWR, 0);
146          if (fd == -1) {
147                  (void)fprintf(stderr, "%s: could not open %s: %s\n",
148 <                        progname, argv[1], strerror(errno));
148 >                        progname, filename, strerror(errno));
149 >                exit(1);
150 >        }
151 >
152 >        file_size = lseek(fd, 0, SEEK_END);
153 >        if (file_size == -1) {
154 >                // for some mysterious reason, this sometimes fails...
155 >                file_size = 0x1000;
156 > #if 0
157 >                (void)fprintf(stderr, "%s: could not get size of %s: %s\n",
158 >                      progname, filename, strerror(errno));
159                  exit(1);
160 + #endif
161          }
162  
163          /*
164           * Size does not really matter, it will be rounded-up to a multiple
165           * of the page size automatically.
166           */
167 <        addr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
167 >        addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
168              MAP_FILE | MAP_SHARED, fd, 0);
169          if (addr == NULL) {
170                  (void)fprintf(stderr, "%s: could not mmap %s: %s\n",
171 <                                progname, argv[1], strerror(errno));
171 >                                progname, filename, strerror(errno));
172                  exit(1);
173          }
174  
175          /*
176           * Check to see if the Mach-O magic bytes are in the header.
87         * If we cared about cross compiling we would also check against
88         * MH_CIGAM and then change the endianness with every access, but
89         * we do not care about that.
177           */
178          machhead = (void *)addr;
179 <        if (machhead->magic != MH_MAGIC) {
179 > #if defined(MH_MAGIC_64)
180 >        machhead64 = (void *)addr;
181 > #endif
182 >        fathead = (void *)addr;
183 >
184 > #if defined(MH_MAGIC_64)
185 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM || machhead64->magic == MH_CIGAM_64;
186 > #else
187 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM;
188 > #endif
189 >
190 >        if (target_uint32(machhead->magic) == MH_MAGIC) {
191 >                pagezero_32(machhead);
192 > #if defined(MH_MAGIC_64)
193 >        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
194 >                pagezero_64(machhead64);
195 > #endif
196 >        } else if (target_uint32(fathead->magic) == FAT_MAGIC) {
197 >                struct fat_arch *arch = (void *)&fathead[1];
198 >                int saved_swap = do_swap;
199 >                int i;
200 >                for (i = 0; i < target_uint32(fathead->nfat_arch); ++i, ++arch) {
201 >                        machhead   = (void *)(addr + target_uint32(arch->offset));
202 > #if defined(MH_MAGIC_64)
203 >                        machhead64 = (void *)(addr + target_uint32(arch->offset));
204 > #endif
205 > #if defined(MH_MAGIC_64)
206 >                        do_swap = machhead->magic == MH_CIGAM || machhead64->magic == MH_CIGAM_64;
207 > #else
208 >                        do_swap = machhead->magic == MH_CIGAM;
209 > #endif
210 >                        if (target_uint32(machhead->magic) == MH_MAGIC) {
211 >                                pagezero_32(machhead);
212 > #if defined(MH_MAGIC_64)
213 >                        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
214 >                                pagezero_64(machhead64);
215 > #endif
216 >                        } else {
217 >                                (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
218 >                                                progname, filename);
219 >                                exit(1);
220 >                        }
221 >                        do_swap = saved_swap;
222 >                }
223 >        } else {
224                  (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
225 <                                progname, argv[1]);
95 <                exit(1);
96 <        }
97 <
98 <        if (machhead->filetype != MH_EXECUTE) {
99 <                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
100 <                                progname, argv[1]);
225 >                                progname, filename);
226                  exit(1);
227          }
228  
104        if (machhead->ncmds == 0) {
105                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
106                                progname, argv[1]);
107                exit(1);
108        }
109
110        sc_cmd = (void *)&machhead[1];
111        if (sc_cmd->cmd != LC_SEGMENT){
112                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
113                                progname, argv[1]);
114                exit(1);
115        }
116
117        if (strncmp(sc_cmd->segname, "__PAGEZERO",
118                         sizeof (*sc_cmd->segname))) {
119                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
120                                progname, argv[1]);
121                exit(1);
122        }
123
124        /* change the permissions */
125        sc_cmd->maxprot = VM_PROT_ALL;
126        sc_cmd->initprot = VM_PROT_ALL;
127
229          /*
230           * We do not make __PAGEZERO 8K in this program because then
231           * all of the offsets would be wrong in the object file after
232           * this segment. Instead we use the -pagezero_size option
233           * to link the executable.
234           */
235 <        if (msync(addr, 0x1000, MS_SYNC) == -1) {
235 >        if (msync(addr, file_size, MS_SYNC) == -1) {
236                  (void)fprintf(stderr, "%s: could not sync %s: %s\n",
237 <                                progname, argv[1], strerror(errno));
237 >                                progname, filename, strerror(errno));
238                  exit(1);
239          }
240  
241 <        if (munmap(addr, 0x1000) == -1) {
241 >        if (munmap(addr, file_size) == -1) {
242                  (void)fprintf(stderr, "%s: could not unmap %s: %s\n",
243 <                                progname, argv[1], strerror(errno));
243 >                                progname, filename, strerror(errno));
244                  exit(1);
245          }
246  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines