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.6 by asvitkine, 2009-11-13T01:57:48Z

# 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 + /*
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 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  
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.
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.
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]);
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]);
226 >                                progname, filename);
227                  exit(1);
228          }
229  
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
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