]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_ume/macho.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_ume / macho.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- User-mode execve() for Mach-O executables      m_ume_macho.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2005-2010 Apple Inc.
11       Greg Parker  gparker@apple.com
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26    02111-1307, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29 */
30
31 #if defined(VGO_darwin)
32
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35
36 #include "pub_core_aspacemgr.h"     // various mapping fns
37 #include "pub_core_debuglog.h"
38 #include "pub_core_libcassert.h"    // VG_(exit), vg_assert
39 #include "pub_core_libcbase.h"      // VG_(memcmp), etc
40 #include "pub_core_libcfile.h"      // VG_(open) et al
41 #include "pub_core_libcprint.h"
42 #include "pub_core_libcproc.h"
43 #include "pub_core_machine.h"       // VG_ELF_CLASS (XXX: which should be moved)
44 #include "pub_core_mallocfree.h"    // VG_(malloc), VG_(free)
45 #include "pub_core_syscall.h"       // VG_(strerror)
46 #include "pub_core_ume.h"           // self
47
48 #include "priv_ume.h"
49
50 #include <mach/mach.h>
51
52 #include <mach-o/dyld.h>
53 #include <mach-o/fat.h>
54 #include <mach-o/loader.h>
55
56 #if VG_WORDSIZE == 4
57 #define MAGIC MH_MAGIC
58 #define MACH_HEADER mach_header
59 #define LC_SEGMENT_CMD LC_SEGMENT
60 #define SEGMENT_COMMAND segment_command
61 #define SECTION section
62 #else
63 #define MAGIC MH_MAGIC_64
64 #define MACH_HEADER mach_header_64
65 #define LC_SEGMENT_CMD LC_SEGMENT_64
66 #define SEGMENT_COMMAND segment_command_64
67 #define SECTION section_64
68 #endif
69
70
71 static void print(const char *str)
72 {
73    VG_(printf)("%s", str);
74 }
75
76 static void check_mmap(SysRes res, Addr base, SizeT len, HChar* who)
77 {
78    if (sr_isError(res)) {
79       VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME (%s).\n", 
80                   (ULong)base, (Long)len, who);
81       VG_(exit)(1);
82    }
83 }
84
85
86 static int 
87 load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
88                const char *filename, 
89                vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
90                vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
91
92 static int 
93 load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
94               const char *filename, 
95               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
96               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
97
98 static int 
99 load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
100                const char *filename, 
101                vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
102                vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
103
104
105 /* Open and map a dylinker file.
106    Returns 0 on success, -1 on any failure.
107    filename must be an absolute path.
108    The dylinker's entry point is returned in *out_linker_entry.
109  */
110 static int 
111 open_dylinker(const char *filename, vki_uint8_t **out_linker_entry)
112 {
113    struct vg_stat sb;
114    vki_size_t filesize;
115    SysRes res;
116    int fd;
117    int err;
118
119    if (filename[0] != '/') {
120       print("bad executable (dylinker name is not an absolute path)\n");
121       return -1;
122    }
123
124    res = VG_(open)(filename, VKI_O_RDONLY, 0);
125    fd = sr_Res(res);
126    if (sr_isError(res)) {
127       print("couldn't open dylinker: ");
128       print(filename);
129       print("\n");
130       return -1;
131    }
132    err = VG_(fstat)(fd, &sb);
133    if (err) {
134       print("couldn't stat dylinker: ");
135       print(filename);
136       print("\n");
137       VG_(close)(fd);
138       return -1;
139    }
140    filesize = sb.size;
141
142    err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename, 
143                         NULL, NULL, NULL, out_linker_entry, NULL);
144    if (err) {
145       print("...while loading dylinker: ");
146       print(filename);
147       print("\n");
148    }
149    VG_(close)(fd);
150    return err;
151 }
152
153
154 /* 
155    Process an LC_SEGMENT command, mapping it into memory if appropriate.
156    fd[offset..size) is a Mach-O thin file. 
157    Returns 0 on success, -1 on any failure.
158    If this segment contains the executable's Mach headers, their 
159      loaded address is returned in *text.
160    If this segment is a __UNIXSTACK, its start address is returned in 
161      *stack_start.
162 */
163 static int
164 load_segment(int fd, vki_off_t offset, vki_off_t size, 
165              vki_uint8_t **text, vki_uint8_t **stack_start, 
166              struct SEGMENT_COMMAND *segcmd, const HChar *filename)
167 {
168    SysRes res;
169    Addr addr;
170    vki_size_t filesize; // page-aligned 
171    vki_size_t vmsize;   // page-aligned
172    unsigned int prot;
173
174    // GrP fixme mark __UNIXSTACK as SF_STACK
175     
176    // Don't honour the client's request to map PAGEZERO.  Why not?
177    // Because when the kernel loaded the valgrind tool executable,
178    // it will have mapped pagezero itself.  So further attempts
179    // to map it when loading the client are guaranteed to fail.
180 #if VG_WORDSIZE == 4
181    if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
182       if (segcmd->vmsize != 0x1000) {
183          print("bad executable (__PAGEZERO is not 4 KB)\n");
184          return -1;
185       }
186       return 0;
187    }
188 #endif
189 #if VG_WORDSIZE == 8
190    if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
191       if (segcmd->vmsize != 0x100000000) {
192          print("bad executable (__PAGEZERO is not 4 GB)\n");
193          return -1;
194       }
195       return 0;
196    }
197 #endif
198
199    // Record the segment containing the Mach headers themselves
200    if (segcmd->fileoff == 0  &&  segcmd->filesize != 0) {
201       if (text) *text = (vki_uint8_t *)segcmd->vmaddr;
202    }
203
204    // Record the __UNIXSTACK start
205    if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) {
206       if (stack_start) *stack_start = (vki_uint8_t *)segcmd->vmaddr;
207    }
208
209    // Sanity-check the segment
210    if (segcmd->fileoff + segcmd->filesize > size) {
211       print("bad executable (invalid segment command)\n");
212       return -1;
213    }
214    if (segcmd->vmsize == 0) {
215       return 0;  // nothing to map - ok
216    }
217
218    // Get desired memory protection
219    // GrP fixme need maxprot too
220    prot = (((segcmd->initprot & VM_PROT_READ) ? VKI_PROT_READ : 0) |
221            ((segcmd->initprot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) |
222            ((segcmd->initprot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0));
223
224    // Map the segment    
225    filesize = VG_PGROUNDUP(segcmd->filesize);
226    vmsize = VG_PGROUNDUP(segcmd->vmsize);
227    if (filesize > 0) {
228       addr = (Addr)segcmd->vmaddr;
229       VG_(debugLog)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr, filesize);
230       res = VG_(am_mmap_named_file_fixed_client)(addr, filesize, prot, fd, 
231                                                  offset + segcmd->fileoff, 
232                                                  filename);
233       check_mmap(res, addr, filesize, "load_segment1");
234    }
235
236    // Zero-fill the remainder of the segment, if any
237    if (segcmd->filesize != filesize) {
238       // non-page-aligned part
239       // GrP fixme kernel doesn't do this?
240       //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
241    }
242    if (filesize != vmsize) {
243       // page-aligned part
244       SizeT length = vmsize - filesize;
245       addr = (Addr)(filesize + segcmd->vmaddr);
246       VG_(debugLog)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr, length);
247       res = VG_(am_mmap_anon_fixed_client)(addr, length, prot);
248       check_mmap(res, addr, length, "load_segment2");
249    }
250
251    return 0;
252 }
253
254
255 /* 
256    Parse a LC_THREAD or LC_UNIXTHREAD command. 
257    Return 0 on success, -1 on any failure.
258    The stack address is returned in *stack. If the executable requested 
259    a non-default stack address, *customstack is set to TRUE. The thread's 
260    entry point is returned in *entry.
261    The stack itself (if any) is not mapped.
262    Other custom register settings are silently ignored (GrP fixme).
263 */
264 static int 
265 load_genericthread(vki_uint8_t **stack_end, 
266                    int *customstack, vki_uint8_t **entry, 
267                    struct thread_command *threadcmd)
268 {
269    unsigned int flavor;
270    unsigned int count;
271    unsigned int *p;
272    unsigned int left; 
273
274    p = (unsigned int *)(threadcmd + 1);
275    left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p);
276
277    while (left > 0) {
278       if (left < 2) {
279          print("bad executable (invalid thread command)\n");
280          return -1;
281       }
282       flavor = *p++; left--;
283       count = *p++; left--;
284       
285       if (left < count) {
286          print("bad executable (invalid thread command 2)\n");
287          return -1;
288       }
289
290 #if defined(VGA_x86)
291       if (flavor == i386_THREAD_STATE && count == i386_THREAD_STATE_COUNT) {
292          i386_thread_state_t *state = (i386_thread_state_t *)p;
293          if (entry) *entry = (vki_uint8_t *)state->__eip;
294          if (stack_end) *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp : VKI_USRSTACK);
295          if (customstack) *customstack = state->__esp;
296          return 0;
297       }
298
299 #elif defined(VGA_amd64)
300       if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){
301          x86_thread_state64_t *state = (x86_thread_state64_t *)p;
302          if (entry) *entry = (vki_uint8_t *)state->__rip;
303          if (stack_end) *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp : VKI_USRSTACK64);
304          if (customstack) *customstack = state->__rsp;
305          return 0;
306       }
307
308 #else
309 # error unknown platform
310 #endif
311       p += count;
312       left -= count;
313    }
314
315    print("bad executable (no arch-compatible thread state)\n");
316    return -1;
317 }
318
319
320 /* Returns the main stack size on this platform, 
321    using getrlimit or a fixed size.
322    GrP fixme 64-bit? */
323 static vki_size_t default_stack_size(void)
324 {
325    struct vki_rlimit lim;
326    int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim);
327    if (err) return 8*1024*1024; // 8 MB
328    else return lim.rlim_cur;
329 }
330
331
332 /* 
333    Processes a LC_UNIXTHREAD command.
334    Returns 0 on success, -1 on any failure.
335    The stack is mapped in and returned in *out_stack. 
336    The thread's entry point is returned in *out_entry.
337 */
338 static int 
339 load_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
340                 vki_uint8_t **out_entry, struct thread_command *threadcmd)
341 {
342    int err;
343    vki_uint8_t *stack_end;
344    int customstack;
345
346    err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd);
347    if (err) return -1;
348
349    if (!stack_end) {
350       print("bad executable (no thread stack)\n");
351       return -1;
352    }
353
354    if (!customstack) {
355       // Map the stack
356       vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
357       vm_address_t stackbase = VG_PGROUNDDN(stack_end-stacksize);
358       SysRes res;
359         
360       res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
361       check_mmap(res, stackbase, stacksize, "load_unixthread1");
362       if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase;
363    } else {
364       // custom stack - mapped via __UNIXTHREAD segment
365    }
366
367    if (out_stack_end) *out_stack_end = stack_end;
368
369    return 0;
370 }
371
372
373 /* 
374    Processes an LC_LOAD_DYLINKER command. 
375    Returns 0 on success, -1 on any error.
376    The linker itself is mapped into memory.
377    The linker's entry point is returned in *linker_entry.
378 */
379 static int 
380 load_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd)
381 {
382    const char *name;
383
384    if (dycmd->name.offset >= dycmd->cmdsize) {
385       print("bad executable (invalid dylinker command)\n");
386       return -1;
387    }
388
389    name = dycmd->name.offset + (char *)dycmd;
390     
391    // GrP fixme assumes name is terminated somewhere
392    return open_dylinker(name, linker_entry);
393 }
394
395
396 /* 
397     Process an LC_THREAD command. 
398     Returns 0 on success, -1 on any failure.
399     The thread's entry point is returned in *out_entry.
400 */
401 static int 
402 load_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd)
403 {
404    int customstack;
405    int err;
406
407    err = load_genericthread(NULL, &customstack, out_entry, threadcmd);
408    if (err) return -1;
409    if (customstack) {
410       print("bad executable (stackless thread has stack)\n");
411       return -1;
412    }
413    return 0;
414 }
415
416
417 /*
418   Loads a Mach-O executable into memory, along with any threads, 
419   stacks, and dylinker.
420   Returns 0 on success, -1 on any failure.
421   fd[offset..offset+size) is a Mach-O thin file.
422   filetype is MH_EXECUTE or MH_DYLINKER.
423   The mapped but empty stack is returned in *out_stack.
424   The executable's Mach headers are returned in *out_text.
425   The executable's entry point is returned in *out_entry.
426   The dylinker's entry point (if any) is returned in *out_linker_entry.
427   GrP fixme need to return whether dylinker was found - stack layout is different
428 */
429 static int 
430 load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
431                const char *filename, 
432                vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
433                vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
434 {
435    struct MACH_HEADER mh;
436    vki_uint8_t *headers;
437    vki_uint8_t *headers_end;
438    struct load_command *lc;
439    struct load_command *lcend;
440    struct SEGMENT_COMMAND *segcmd;
441    struct thread_command *threadcmd;
442    struct dylinker_command *dycmd;
443    int err;
444    SysRes res;
445    vki_size_t len;
446
447    vki_uint8_t *stack_start = NULL;   // allocated thread stack (hot end)
448    vki_uint8_t *stack_end = NULL;   // allocated thread stack (cold end)
449    vki_uint8_t *entry = NULL;   // static entry point
450    vki_uint8_t *text = NULL;    // start of text segment (i.e. the mach headers)
451    vki_uint8_t *linker_entry = NULL; // dylinker entry point
452
453    // Read Mach-O header
454    if (sizeof(mh) > size) {
455       print("bad executable (no Mach-O header)\n");
456    }
457    res = VG_(pread)(fd, &mh, sizeof(mh), offset);
458    if (sr_isError(res)  ||  sr_Res(res) != sizeof(mh)) {
459       print("bad executable (no Mach-O header)\n");
460       return -1;
461    }
462    
463
464    // Sanity-check the header itself
465    if (mh.magic != MAGIC) {
466       print("bad executable (no Mach-O magic)\n");
467       return -1;
468    }
469
470    if (mh.filetype != filetype) {
471       // expecting MH_EXECUTE or MH_DYLINKER
472       print("bad executable (wrong file type)\n");
473       return -1;
474    }
475
476
477    // Map all headers into memory
478    len = sizeof(mh) + mh.sizeofcmds;
479    if (len > size) {
480       print("bad executable (missing load commands)\n");
481       return -1;
482    }
483
484    headers = VG_(malloc)("ume.macho.headers", len);
485    res = VG_(pread)(fd, headers, len, offset);
486    if (sr_isError(res)) {
487       print("couldn't read load commands from executable\n");
488       return -1;
489    }
490    headers_end = headers + size;
491
492    
493    // Map some segments into client memory:
494    // LC_SEGMENT    (text, data, etc)
495    // UNIXSTACK     (stack)
496    // LOAD_DYLINKER (dyld)
497    lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
498    for (lc = (struct load_command *)(headers + sizeof(mh)); 
499         lc < lcend; 
500         lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
501    {
502       if ((vki_uint8_t *)lc < headers  ||  
503           lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
504           print("bad executable (invalid load commands)\n");
505           return -1;
506       }
507
508       switch (lc->cmd) {
509       case LC_SEGMENT_CMD:
510          if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
511             print("bad executable (invalid load commands)\n");
512             return -1;
513          }
514          segcmd = (struct SEGMENT_COMMAND *)lc;
515          err = load_segment(fd, offset, size, &text, &stack_start, 
516                             segcmd, filename);
517          if (err) return -1;
518           
519          break;
520
521       case LC_UNIXTHREAD:
522          if (stack_end  ||  entry) {
523             print("bad executable (multiple thread commands)\n");
524             return -1;
525          }
526          if (lc->cmdsize < sizeof(struct thread_command)) {
527             print("bad executable (invalid load commands)\n");
528             return -1;
529          }
530          threadcmd = (struct thread_command *)lc;
531          err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd);
532          if (err) return -1;
533          break;
534
535       case LC_LOAD_DYLINKER:
536          if (filetype == MH_DYLINKER) {
537             print("bad executable (dylinker needs a dylinker)\n");
538             return -1;
539          }
540          if (linker_entry) {
541             print("bad executable (multiple dylinker commands)\n");
542          }
543          if (lc->cmdsize < sizeof(struct dylinker_command)) {
544             print("bad executable (invalid load commands)\n");
545             return -1;
546          }
547          dycmd = (struct dylinker_command *)lc;
548          err = load_dylinker(&linker_entry, dycmd);
549          if (err) return -1;
550          break;
551
552       case LC_THREAD:
553          if (filetype == MH_EXECUTE) {
554             print("bad executable (stackless thread)\n");
555             return -1;
556          }
557          if (stack_end  ||  entry) {
558             print("bad executable (multiple thread commands)\n");
559             return -1;
560          }
561          if (lc->cmdsize < sizeof(struct thread_command)) {
562             print("bad executable (invalid load commands)\n");
563             return -1;
564          }
565          threadcmd = (struct thread_command *)lc;
566          err = load_thread(&entry, threadcmd);
567          if (err) return -1;
568          break;
569
570       default:
571          break;
572       }
573    }
574
575
576    // Done with the headers
577    VG_(free)(headers);
578
579    if (filetype == MH_EXECUTE) {
580       // Verify the necessary pieces for an executable:
581       // a stack
582       // a text segment
583       // an entry point (static or linker)
584       if (!stack_end || !stack_start) {
585          print("bad executable (no stack)\n");
586          return -1;
587       }
588       if (!text) {
589          print("bad executable (no text segment)\n");
590          return -1;
591       }
592       if (!entry  &&  !linker_entry) {
593          print("bad executable (no entry point)\n");
594          return -1;
595       }
596    }
597    else if (filetype == MH_DYLINKER) {
598       // Verify the necessary pieces for a dylinker:
599       // an entry point
600       if (!entry) {
601          print("bad executable (no entry point)\n");
602          return -1;
603       }
604    }
605
606    if (out_stack_start) *out_stack_start = stack_start;
607    if (out_stack_end) *out_stack_end = stack_end;
608    if (out_text)  *out_text = text;
609    if (out_entry) *out_entry = entry;
610    if (out_linker_entry) *out_linker_entry = linker_entry;
611    
612    return 0;
613 }
614
615
616 /*
617  Load a fat Mach-O executable.
618 */
619 static int 
620 load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
621              const char *filename, 
622              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
623              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
624 {
625    struct fat_header fh;
626    vki_off_t arch_offset;
627    int i;
628    cpu_type_t good_arch;
629    SysRes res;
630
631 #if defined(VGA_ppc32)
632    good_arch = CPU_TYPE_POWERPC;
633 #elif defined(VGA_ppc64)
634    good_arch = CPU_TYPE_POWERPC64;
635 #elif defined(VGA_x86)
636    good_arch = CPU_TYPE_I386;
637 #elif defined(VGA_amd64)
638    good_arch = CPU_TYPE_X86_64;
639 #else
640 # error unknown architecture
641 #endif
642
643    // Read fat header
644    // All fat contents are BIG-ENDIAN
645    if (size < sizeof(fh)) {
646       print("bad executable (bad fat header)\n");
647       return -1;
648    }
649    res = VG_(pread)(fd, &fh, sizeof(fh), offset);
650    if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
651       print("bad executable (bad fat header)\n");
652       return -1;
653    }
654    
655    // Scan arch headers looking for a good one
656    arch_offset = offset + sizeof(fh);
657    fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
658    for (i = 0; i < fh.nfat_arch; i++) {
659       struct fat_arch arch;
660       if (arch_offset + sizeof(arch) > size) {
661           print("bad executable (corrupt fat archs)\n");
662           return -1;
663       }
664
665       res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
666       arch_offset += sizeof(arch);
667       if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
668          VG_(printf)("bad executable (corrupt fat arch) %x %llu\n", 
669                      arch.cputype, (ULong)arch_offset);
670          return -1;
671       }
672
673       arch.cputype = VG_(ntohl)(arch.cputype);
674       arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
675       arch.offset = VG_(ntohl)(arch.offset);
676       arch.size = VG_(ntohl)(arch.size);
677       arch.align = VG_(ntohl)(arch.align);
678       if (arch.cputype == good_arch) {
679          // use this arch
680          if (arch.offset > size  ||  arch.offset + arch.size > size) {
681             print("bad executable (corrupt fat arch 2)\n");
682             return -1;
683          }
684          return load_mach_file(fd, offset+arch.offset, arch.size, filetype, 
685                                filename, out_stack_start, out_stack_end, 
686                                out_text, out_entry, out_linker_entry);
687       }
688    }
689
690    print("bad executable (can't run on this machine)\n");
691    return -1;
692 }
693
694 /*
695  Load a Mach-O executable or dylinker.
696  The file may be fat or thin.
697 */
698 static int 
699 load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype, 
700               const char *filename, 
701               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end, 
702               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
703 {
704    vki_uint32_t magic;
705    SysRes res;
706
707    if (size < sizeof(magic)) {
708       print("bad executable (no Mach-O magic)\n");
709       return -1;
710    }
711    res = VG_(pread)(fd, &magic, sizeof(magic), offset);
712    if (sr_isError(res)  ||  sr_Res(res) != sizeof(magic)) {
713       print("bad executable (no Mach-O magic)\n");
714       return -1;
715    }
716    
717    if (magic == MAGIC) {
718       // thin
719       return load_thin_file(fd, offset, size, filetype, filename, 
720                             out_stack_start, out_stack_end, 
721                             out_text, out_entry, out_linker_entry);
722    } else if (magic == VG_(htonl)(FAT_MAGIC)) {
723       // fat
724       return load_fat_file(fd, offset, size, filetype, filename, 
725                            out_stack_start, out_stack_end, 
726                            out_text, out_entry, out_linker_entry);
727    } else {
728       // huh?
729       print("bad executable (bad Mach-O magic)\n");
730       return -1;
731    }
732 }
733
734
735 Bool VG_(match_macho)(Char *hdr, Int len)
736 {
737    vki_uint32_t *magic = (vki_uint32_t *)hdr;
738
739    // GrP fixme check more carefully for matching fat arch?
740
741    return (len >= VKI_PAGE_SIZE  &&  
742            (*magic == MAGIC  ||  *magic == VG_(ntohl)(FAT_MAGIC))) 
743       ? True : False;
744 }
745
746
747 Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
748 {
749    int err;
750    struct vg_stat sb;
751    vki_uint8_t *stack_start;
752    vki_uint8_t *stack_end;
753    vki_uint8_t *text;
754    vki_uint8_t *entry;
755    vki_uint8_t *linker_entry;
756
757    err = VG_(fstat)(fd, &sb);
758    if (err) {
759       print("couldn't stat executable\n");
760       return VKI_ENOEXEC;
761    }
762    
763    err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name, 
764                         &stack_start, &stack_end, 
765                         &text, &entry, &linker_entry);
766    if (err) return VKI_ENOEXEC;
767
768    // GrP fixme exe_base
769    // GrP fixme exe_end
770    info->entry = (Addr)entry;
771    info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
772    info->brkbase = 0xffffffff; // GrP fixme hack
773    info->init_toc = 0; // GrP fixme unused
774
775    info->stack_start = (Addr)stack_start;
776    info->stack_end = (Addr)stack_end;
777    info->text = (Addr)text;
778    info->dynamic = linker_entry ? True : False;
779
780    info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
781
782    return 0;
783 }
784
785 #endif // defined(VGO_darwin)
786
787 /*--------------------------------------------------------------------*/
788 /*--- end                                                          ---*/
789 /*--------------------------------------------------------------------*/
790