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.9 by asvitkine, 2011-12-27T21:01:32Z

# 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 + #include <sys/stat.h>
34  
35   static const char progname[] = "lowmem";
36 + static const char *filename;
37 +
38 + static int do_swap = 0;
39 +
40 + static uint32_t target_uint32(uint32_t value)
41 + {
42 +        if (do_swap)
43 +                value = OSSwapInt32(value);
44 +        return value;
45 + }
46 +
47 + void pagezero_32(struct mach_header *machhead)
48 + {
49 +        struct segment_command *sc_cmd;
50 +
51 +        if (target_uint32(machhead->filetype) != MH_EXECUTE) {
52 +                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
53 +                                progname, filename);
54 +                exit(1);
55 +        }
56 +        if (machhead->ncmds == 0) {
57 +                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
58 +                                progname, filename);
59 +                exit(1);
60 +        }
61 +        sc_cmd = (void *)&machhead[1];
62 +        if (target_uint32(sc_cmd->cmd) != LC_SEGMENT){
63 +                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
64 +                                progname, filename);
65 +                exit(1);
66 +        }
67 +        if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof (*sc_cmd->segname))) {
68 +                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
69 +                                progname, filename);
70 +                exit(1);
71 +        }
72 +        /* change the permissions */
73 +        sc_cmd->maxprot = target_uint32(VM_PROT_ALL);
74 +        sc_cmd->initprot = target_uint32(VM_PROT_ALL);
75 + }
76 +
77 + #if defined(MH_MAGIC_64)
78 + void pagezero_64(struct mach_header_64 *machhead)
79 + {
80 +        struct segment_command_64 *sc_cmd;
81 +
82 +        if (target_uint32(machhead->filetype) != MH_EXECUTE) {
83 +                (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n",
84 +                                progname, filename);
85 +                exit(1);
86 +        }
87 +        if (machhead->ncmds == 0) {
88 +                (void)fprintf(stderr, "%s: %s does not contain any load commands\n",
89 +                                progname, filename);
90 +                exit(1);
91 +        }
92 +        sc_cmd = (void *)&machhead[1];
93 +        if (target_uint32(sc_cmd->cmd) != LC_SEGMENT_64) {
94 +                (void)fprintf(stderr, "%s: load segment not first command in %s\n",
95 +                                progname, filename);
96 +                exit(1);
97 +        }
98 +        if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof(*sc_cmd->segname))) {
99 +                (void)fprintf(stderr, "%s: zero page not first segment in %s\n",
100 +                                progname, filename);
101 +                exit(1);
102 +        }
103 +        /* change the permissions */
104 +        sc_cmd->maxprot = target_uint32(VM_PROT_ALL);
105 +        sc_cmd->initprot = target_uint32(VM_PROT_ALL);
106 + }
107 + #endif
108  
109   /*
110   * Under Mach there is very little assumed about the memory map of object
# Line 55 | 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 >        struct stat f;
139  
140          if (argc != 2) {
141                  (void)fprintf(stderr, "Usage: %s executable\n", progname);
142                  exit(1);
143          }
144  
145 <        fd = open(argv[1], O_RDWR, 0);
145 >        filename = argv[1];
146 >
147 >        if (stat(filename, &f)) {
148 >                (void)fprintf(stderr, "%s: could not stat %s: %s\n",
149 >                        progname, filename, strerror(errno));
150 >                exit(1);
151 >        }
152 >        file_size = f.st_size;
153 >
154 >        fd = open(filename, O_RDWR, 0);
155          if (fd == -1) {
156                  (void)fprintf(stderr, "%s: could not open %s: %s\n",
157 <                        progname, argv[1], strerror(errno));
157 >                        progname, filename, strerror(errno));
158                  exit(1);
159          }
160  
# Line 74 | Line 162 | main(int argc, const char *argv[])
162           * Size does not really matter, it will be rounded-up to a multiple
163           * of the page size automatically.
164           */
165 <        addr = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
165 >        addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
166              MAP_FILE | MAP_SHARED, fd, 0);
167 <        if (addr == NULL) {
167 >        if (addr == NULL || addr == MAP_FAILED) {
168                  (void)fprintf(stderr, "%s: could not mmap %s: %s\n",
169 <                                progname, argv[1], strerror(errno));
169 >                                progname, filename, strerror(errno));
170                  exit(1);
171          }
172  
173          /*
174           * 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.
175           */
176          machhead = (void *)addr;
177 <        if (machhead->magic != MH_MAGIC) {
177 > #if defined(MH_MAGIC_64)
178 >        machhead64 = (void *)addr;
179 > #endif
180 >        fathead = (void *)addr;
181 >
182 > #if defined(MH_MAGIC_64)
183 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM || machhead64->magic == MH_CIGAM_64;
184 > #else
185 >        do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM;
186 > #endif
187 >
188 >        if (target_uint32(machhead->magic) == MH_MAGIC) {
189 >                pagezero_32(machhead);
190 > #if defined(MH_MAGIC_64)
191 >        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
192 >                pagezero_64(machhead64);
193 > #endif
194 >        } else if (target_uint32(fathead->magic) == FAT_MAGIC) {
195 >                struct fat_arch *arch = (void *)&fathead[1];
196 >                int saved_swap = do_swap;
197 >                int i;
198 >                for (i = 0; i < target_uint32(fathead->nfat_arch); ++i, ++arch) {
199 >                        machhead   = (void *)(addr + target_uint32(arch->offset));
200 > #if defined(MH_MAGIC_64)
201 >                        machhead64 = (void *)(addr + target_uint32(arch->offset));
202 > #endif
203 > #if defined(MH_MAGIC_64)
204 >                        do_swap = machhead->magic == MH_CIGAM || machhead64->magic == MH_CIGAM_64;
205 > #else
206 >                        do_swap = machhead->magic == MH_CIGAM;
207 > #endif
208 >                        if (target_uint32(machhead->magic) == MH_MAGIC) {
209 >                                pagezero_32(machhead);
210 > #if defined(MH_MAGIC_64)
211 >                        } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) {
212 >                                pagezero_64(machhead64);
213 > #endif
214 >                        } else {
215 >                                (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
216 >                                                progname, filename);
217 >                                exit(1);
218 >                        }
219 >                        do_swap = saved_swap;
220 >                }
221 >        } else {
222                  (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n",
223 <                                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]);
223 >                                progname, filename);
224                  exit(1);
225          }
226  
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
227          /*
228           * We do not make __PAGEZERO 8K in this program because then
229           * all of the offsets would be wrong in the object file after
230           * this segment. Instead we use the -pagezero_size option
231           * to link the executable.
232           */
233 <        if (msync(addr, 0x1000, MS_SYNC) == -1) {
233 >        if (msync(addr, file_size, MS_SYNC) == -1) {
234                  (void)fprintf(stderr, "%s: could not sync %s: %s\n",
235 <                                progname, argv[1], strerror(errno));
235 >                                progname, filename, strerror(errno));
236                  exit(1);
237          }
238  
239 <        if (munmap(addr, 0x1000) == -1) {
239 >        if (munmap(addr, file_size) == -1) {
240                  (void)fprintf(stderr, "%s: could not unmap %s: %s\n",
241 <                                progname, argv[1], strerror(errno));
241 >                                progname, filename, strerror(errno));
242                  exit(1);
243          }
244  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines