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-2013 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
71static void print(const HChar *str)
72{
73   VG_(printf)("%s", str);
74}
75
76static void check_mmap(SysRes res, Addr base, SizeT len, const HChar* who)
77{
78   if (sr_isError(res)) {
79      VG_(printf)("valgrind: mmap-FIXED(0x%llx, %lld) failed in UME (%s).\n",
80                  (ULong)base, (Long)len, who);
81      VG_(exit)(1);
82   }
83}
84
85#if DARWIN_VERS == DARWIN_10_8
86static void check_mmap_float(SysRes res, SizeT len, const HChar* who)
87{
88   if (sr_isError(res)) {
89      VG_(printf)("valgrind: mmap-FLOAT(size=%lld) failed in UME (%s).\n",
90                  (Long)len, who);
91      VG_(exit)(1);
92   }
93}
94#endif
95
96static int
97load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
98               const HChar *filename,
99               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
100               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
101
102static int
103load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
104              const HChar *filename,
105              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
106              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
107
108static int
109load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
110               const HChar *filename,
111               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
112               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry);
113
114
115/* Open and map a dylinker file.
116   Returns 0 on success, -1 on any failure.
117   filename must be an absolute path.
118   The dylinker's entry point is returned in *out_linker_entry.
119 */
120static int
121open_dylinker(const HChar *filename, vki_uint8_t **out_linker_entry)
122{
123   struct vg_stat sb;
124   vki_size_t filesize;
125   SysRes res;
126   int fd;
127   int err;
128
129   if (filename[0] != '/') {
130      print("bad executable (dylinker name is not an absolute path)\n");
131      return -1;
132   }
133
134   res = VG_(open)(filename, VKI_O_RDONLY, 0);
135   fd = sr_Res(res);
136   if (sr_isError(res)) {
137      print("couldn't open dylinker: ");
138      print(filename);
139      print("\n");
140      return -1;
141   }
142   err = VG_(fstat)(fd, &sb);
143   if (err) {
144      print("couldn't stat dylinker: ");
145      print(filename);
146      print("\n");
147      VG_(close)(fd);
148      return -1;
149   }
150   filesize = sb.size;
151
152   err = load_mach_file(fd, 0, filesize, MH_DYLINKER, filename,
153                        NULL, NULL, NULL, out_linker_entry, NULL);
154   if (err) {
155      print("...while loading dylinker: ");
156      print(filename);
157      print("\n");
158   }
159   VG_(close)(fd);
160   return err;
161}
162
163
164/*
165   Process an LC_SEGMENT command, mapping it into memory if appropriate.
166   fd[offset..size) is a Mach-O thin file.
167   Returns 0 on success, -1 on any failure.
168   If this segment contains the executable's Mach headers, their
169     loaded address is returned in *text.
170   If this segment is a __UNIXSTACK, its start address is returned in
171     *stack_start.
172*/
173static int
174load_segment(int fd, vki_off_t offset, vki_off_t size,
175             vki_uint8_t **text, vki_uint8_t **stack_start,
176             struct SEGMENT_COMMAND *segcmd, const HChar *filename)
177{
178   SysRes res;
179   Addr addr;
180   vki_size_t filesize; // page-aligned
181   vki_size_t vmsize;   // page-aligned
182   unsigned int prot;
183
184   // GrP fixme mark __UNIXSTACK as SF_STACK
185
186   // Don't honour the client's request to map PAGEZERO.  Why not?
187   // Because when the kernel loaded the valgrind tool executable,
188   // it will have mapped pagezero itself.  So further attempts
189   // to map it when loading the client are guaranteed to fail.
190#if VG_WORDSIZE == 4
191   if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
192      if (segcmd->vmsize != 0x1000) {
193         print("bad executable (__PAGEZERO is not 4 KB)\n");
194         return -1;
195      }
196      return 0;
197   }
198#endif
199#if VG_WORDSIZE == 8
200   if (segcmd->vmaddr == 0 && 0 == VG_(strcmp)(segcmd->segname, SEG_PAGEZERO)) {
201      if (segcmd->vmsize != 0x100000000) {
202         print("bad executable (__PAGEZERO is not 4 GB)\n");
203         return -1;
204      }
205      return 0;
206   }
207#endif
208
209   // Record the segment containing the Mach headers themselves
210   if (segcmd->fileoff == 0  &&  segcmd->filesize != 0) {
211      if (text) *text = (vki_uint8_t *)segcmd->vmaddr;
212   }
213
214   // Record the __UNIXSTACK start
215   if (0 == VG_(strcmp)(segcmd->segname, SEG_UNIXSTACK)) {
216      if (stack_start) *stack_start = (vki_uint8_t *)segcmd->vmaddr;
217   }
218
219   // Sanity-check the segment
220   if (segcmd->fileoff + segcmd->filesize > size) {
221      print("bad executable (invalid segment command)\n");
222      return -1;
223   }
224   if (segcmd->vmsize == 0) {
225      return 0;  // nothing to map - ok
226   }
227
228   // Get desired memory protection
229   // GrP fixme need maxprot too
230   prot = (((segcmd->initprot & VM_PROT_READ) ? VKI_PROT_READ : 0) |
231           ((segcmd->initprot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) |
232           ((segcmd->initprot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0));
233
234   // Map the segment
235   filesize = VG_PGROUNDUP(segcmd->filesize);
236   vmsize = VG_PGROUNDUP(segcmd->vmsize);
237   if (filesize > 0) {
238      addr = (Addr)segcmd->vmaddr;
239      VG_(debugLog)(2, "ume", "mmap fixed (file) (%#lx, %lu)\n", addr, filesize);
240      res = VG_(am_mmap_named_file_fixed_client)(addr, filesize, prot, fd,
241                                                 offset + segcmd->fileoff,
242                                                 filename);
243      check_mmap(res, addr, filesize, "load_segment1");
244   }
245
246   // Zero-fill the remainder of the segment, if any
247   if (segcmd->filesize != filesize) {
248      // non-page-aligned part
249      // GrP fixme kernel doesn't do this?
250      //bzero(segcmd->filesize+(vki_uint8_t *)addr, filesize-segcmd->filesize);
251   }
252   if (filesize != vmsize) {
253      // page-aligned part
254      SizeT length = vmsize - filesize;
255      addr = (Addr)(filesize + segcmd->vmaddr);
256      VG_(debugLog)(2, "ume", "mmap fixed (anon) (%#lx, %lu)\n", addr, length);
257      res = VG_(am_mmap_anon_fixed_client)(addr, length, prot);
258      check_mmap(res, addr, length, "load_segment2");
259   }
260
261   return 0;
262}
263
264
265/*
266   Parse a LC_THREAD or LC_UNIXTHREAD command.
267   Return 0 on success, -1 on any failure.
268   The stack address is returned in *stack. If the executable requested
269   a non-default stack address, *customstack is set to TRUE. The thread's
270   entry point is returned in *entry.
271   The stack itself (if any) is not mapped.
272   Other custom register settings are silently ignored (GrP fixme).
273*/
274static int
275load_genericthread(vki_uint8_t **stack_end,
276                   int *customstack, vki_uint8_t **entry,
277                   struct thread_command *threadcmd)
278{
279   unsigned int flavor;
280   unsigned int count;
281   unsigned int *p;
282   unsigned int left;
283
284   p = (unsigned int *)(threadcmd + 1);
285   left = (threadcmd->cmdsize - sizeof(struct thread_command)) / sizeof(*p);
286
287   while (left > 0) {
288      if (left < 2) {
289         print("bad executable (invalid thread command)\n");
290         return -1;
291      }
292      flavor = *p++; left--;
293      count = *p++; left--;
294
295      if (left < count) {
296         print("bad executable (invalid thread command 2)\n");
297         return -1;
298      }
299
300#if defined(VGA_x86)
301      if (flavor == i386_THREAD_STATE && count == i386_THREAD_STATE_COUNT) {
302         i386_thread_state_t *state = (i386_thread_state_t *)p;
303         if (entry) *entry = (vki_uint8_t *)state->__eip;
304         if (stack_end) *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp : VKI_USRSTACK);
305         if (customstack) *customstack = state->__esp;
306         return 0;
307      }
308
309#elif defined(VGA_amd64)
310      if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){
311         x86_thread_state64_t *state = (x86_thread_state64_t *)p;
312         if (entry) *entry = (vki_uint8_t *)state->__rip;
313         if (stack_end) *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp : VKI_USRSTACK64);
314         if (customstack) *customstack = state->__rsp;
315         return 0;
316      }
317
318#else
319# error unknown platform
320#endif
321      p += count;
322      left -= count;
323   }
324
325   print("bad executable (no arch-compatible thread state)\n");
326   return -1;
327}
328
329
330/* Returns the main stack size on this platform,
331   using getrlimit or a fixed size.
332   GrP fixme 64-bit? */
333static vki_size_t default_stack_size(void)
334{
335   struct vki_rlimit lim;
336   int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim);
337   if (err) return 8*1024*1024; // 8 MB
338   else return lim.rlim_cur;
339}
340
341
342/*
343   Processes a LC_UNIXTHREAD command.
344   Returns 0 on success, -1 on any failure.
345   The stack is mapped in and returned in *out_stack.
346   The thread's entry point is returned in *out_entry.
347*/
348static int
349load_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
350                vki_uint8_t **out_entry, struct thread_command *threadcmd)
351{
352   int err;
353   vki_uint8_t *stack_end;
354   int customstack;
355
356   err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd);
357   if (err) return -1;
358
359   if (!stack_end) {
360      print("bad executable (no thread stack)\n");
361      return -1;
362   }
363
364   if (!customstack) {
365      // Map the stack
366      vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
367      vm_address_t stackbase = VG_PGROUNDDN(stack_end-stacksize);
368      SysRes res;
369
370      res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
371      check_mmap(res, stackbase, stacksize, "load_unixthread1");
372      if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase;
373   } else {
374      // custom stack - mapped via __UNIXTHREAD segment
375   }
376
377   if (out_stack_end) *out_stack_end = stack_end;
378
379   return 0;
380}
381
382
383/* Allocates a stack mapping at a V-chosen address.  Pertains to
384   LC_MAIN commands, which seem to have appeared in OSX 10.8.
385
386   This is a really nasty hack -- allocates 64M+stack size, then
387   deallocates the 64M, to guarantee that the stack is at least 64M
388   above zero. */
389#if DARWIN_VERS == DARWIN_10_8
390static int
391handle_lcmain ( vki_uint8_t **out_stack_start,
392                vki_uint8_t **out_stack_end,
393                vki_size_t requested_size )
394{
395   if (requested_size == 0) {
396      requested_size = default_stack_size();
397   }
398   requested_size = VG_PGROUNDUP(requested_size);
399
400   const vki_size_t HACK = 64 * 1024 * 1024;
401   requested_size += HACK;
402
403   SysRes res = VG_(am_mmap_anon_float_client)(requested_size,
404                   VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
405   check_mmap_float(res, requested_size, "handle_lcmain");
406   vg_assert(!sr_isError(res));
407   *out_stack_start = (vki_uint8_t*)sr_Res(res);
408   *out_stack_end   = *out_stack_start + requested_size;
409
410   Bool need_discard = False;
411   res = VG_(am_munmap_client)(&need_discard, (Addr)*out_stack_start, HACK);
412   if (sr_isError(res)) return -1;
413   vg_assert(!need_discard); // True == wtf?
414
415   *out_stack_start += HACK;
416
417   return 0;
418}
419#endif /* DARWIN_VERS == DARWIN_10_8 */
420
421
422
423/*
424   Processes an LC_LOAD_DYLINKER command.
425   Returns 0 on success, -1 on any error.
426   The linker itself is mapped into memory.
427   The linker's entry point is returned in *linker_entry.
428*/
429static int
430load_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd)
431{
432   const HChar *name;
433
434   if (dycmd->name.offset >= dycmd->cmdsize) {
435      print("bad executable (invalid dylinker command)\n");
436      return -1;
437   }
438
439   name = dycmd->name.offset + (HChar *)dycmd;
440
441   // GrP fixme assumes name is terminated somewhere
442   return open_dylinker(name, linker_entry);
443}
444
445
446/*
447    Process an LC_THREAD command.
448    Returns 0 on success, -1 on any failure.
449    The thread's entry point is returned in *out_entry.
450*/
451static int
452load_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd)
453{
454   int customstack;
455   int err;
456
457   err = load_genericthread(NULL, &customstack, out_entry, threadcmd);
458   if (err) return -1;
459   if (customstack) {
460      print("bad executable (stackless thread has stack)\n");
461      return -1;
462   }
463   return 0;
464}
465
466
467/*
468  Loads a Mach-O executable into memory, along with any threads,
469  stacks, and dylinker.
470  Returns 0 on success, -1 on any failure.
471  fd[offset..offset+size) is a Mach-O thin file.
472  filetype is MH_EXECUTE or MH_DYLINKER.
473  The mapped but empty stack is returned in *out_stack.
474  The executable's Mach headers are returned in *out_text.
475  The executable's entry point is returned in *out_entry.
476  The dylinker's entry point (if any) is returned in *out_linker_entry.
477  GrP fixme need to return whether dylinker was found - stack layout is different
478*/
479static int
480load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
481               const HChar *filename,
482               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
483               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
484{
485   VG_(debugLog)(1, "ume", "load_thin_file: begin:   %s\n", filename);
486   struct MACH_HEADER mh;
487   vki_uint8_t *headers;
488   vki_uint8_t *headers_end;
489   struct load_command *lc;
490   struct load_command *lcend;
491   struct SEGMENT_COMMAND *segcmd;
492   struct thread_command *threadcmd;
493   struct dylinker_command *dycmd;
494   int err;
495   SysRes res;
496   vki_size_t len;
497
498   vki_uint8_t *stack_start = NULL;   // allocated thread stack (hot end)
499   vki_uint8_t *stack_end = NULL;   // allocated thread stack (cold end)
500   vki_uint8_t *entry = NULL;   // static entry point
501   vki_uint8_t *text = NULL;    // start of text segment (i.e. the mach headers)
502   vki_uint8_t *linker_entry = NULL; // dylinker entry point
503
504   // Read Mach-O header
505   if (sizeof(mh) > size) {
506      print("bad executable (no Mach-O header)\n");
507   }
508   res = VG_(pread)(fd, &mh, sizeof(mh), offset);
509   if (sr_isError(res)  ||  sr_Res(res) != sizeof(mh)) {
510      print("bad executable (no Mach-O header)\n");
511      return -1;
512   }
513
514
515   // Sanity-check the header itself
516   if (mh.magic != MAGIC) {
517      print("bad executable (no Mach-O magic)\n");
518      return -1;
519   }
520
521   if (mh.filetype != filetype) {
522      // expecting MH_EXECUTE or MH_DYLINKER
523      print("bad executable (wrong file type)\n");
524      return -1;
525   }
526
527
528   // Map all headers into memory
529   len = sizeof(mh) + mh.sizeofcmds;
530   if (len > size) {
531      print("bad executable (missing load commands)\n");
532      return -1;
533   }
534
535   headers = VG_(malloc)("ume.macho.headers", len);
536   res = VG_(pread)(fd, headers, len, offset);
537   if (sr_isError(res)) {
538      print("couldn't read load commands from executable\n");
539      return -1;
540   }
541   headers_end = headers + len;
542
543
544   // Map some segments into client memory:
545   // LC_SEGMENT    (text, data, etc)
546   // UNIXSTACK     (stack)
547   // LOAD_DYLINKER (dyld)
548   lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
549   for (lc = (struct load_command *)(headers + sizeof(mh));
550        lc < lcend;
551        lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
552   {
553      if ((vki_uint8_t *)lc < headers  ||
554          lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
555          print("bad executable (invalid load commands)\n");
556          return -1;
557      }
558
559      switch (lc->cmd) {
560
561#if   DARWIN_VERS == DARWIN_10_8
562      case LC_MAIN: { /* New in 10.8 */
563         struct entry_point_command* epcmd
564            = (struct entry_point_command*)lc;
565         if (stack_start || stack_end) {
566            print("bad executable (multiple indications of stack)");
567            return -1;
568         }
569         err = handle_lcmain ( &stack_start, &stack_end, epcmd->stacksize );
570         if (err) return -1;
571         VG_(debugLog)(2, "ume", "lc_main: created stack %p-%p\n",
572	               stack_start, stack_end);
573         break;
574      }
575#     endif
576
577      case LC_SEGMENT_CMD:
578         if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
579            print("bad executable (invalid load commands)\n");
580            return -1;
581         }
582         segcmd = (struct SEGMENT_COMMAND *)lc;
583         err = load_segment(fd, offset, size, &text, &stack_start,
584                            segcmd, filename);
585         if (err) return -1;
586
587         break;
588
589      case LC_UNIXTHREAD:
590         if (stack_end  ||  entry) {
591            print("bad executable (multiple thread commands)\n");
592            return -1;
593         }
594         if (lc->cmdsize < sizeof(struct thread_command)) {
595            print("bad executable (invalid load commands)\n");
596            return -1;
597         }
598         threadcmd = (struct thread_command *)lc;
599         err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd);
600         if (err) return -1;
601         break;
602
603      case LC_LOAD_DYLINKER:
604         if (filetype == MH_DYLINKER) {
605            print("bad executable (dylinker needs a dylinker)\n");
606            return -1;
607         }
608         if (linker_entry) {
609            print("bad executable (multiple dylinker commands)\n");
610         }
611         if (lc->cmdsize < sizeof(struct dylinker_command)) {
612            print("bad executable (invalid load commands)\n");
613            return -1;
614         }
615         dycmd = (struct dylinker_command *)lc;
616         err = load_dylinker(&linker_entry, dycmd);
617         if (err) return -1;
618         break;
619
620      case LC_THREAD:
621         if (filetype == MH_EXECUTE) {
622            print("bad executable (stackless thread)\n");
623            return -1;
624         }
625         if (stack_end  ||  entry) {
626            print("bad executable (multiple thread commands)\n");
627            return -1;
628         }
629         if (lc->cmdsize < sizeof(struct thread_command)) {
630            print("bad executable (invalid load commands)\n");
631            return -1;
632         }
633         threadcmd = (struct thread_command *)lc;
634         err = load_thread(&entry, threadcmd);
635         if (err) return -1;
636         break;
637
638      default:
639         break;
640      }
641   }
642
643
644   // Done with the headers
645   VG_(free)(headers);
646
647   if (filetype == MH_EXECUTE) {
648      // Verify the necessary pieces for an executable:
649      // a stack
650      // a text segment
651      // an entry point (static or linker)
652      if (!stack_end || !stack_start) {
653         VG_(printf)("bad executable %s (no stack)\n", filename);
654         return -1;
655      }
656      if (!text) {
657         print("bad executable (no text segment)\n");
658         return -1;
659      }
660      if (!entry  &&  !linker_entry) {
661         print("bad executable (no entry point)\n");
662         return -1;
663      }
664   }
665   else if (filetype == MH_DYLINKER) {
666      // Verify the necessary pieces for a dylinker:
667      // an entry point
668      if (!entry) {
669         print("bad executable (no entry point)\n");
670         return -1;
671      }
672   }
673
674   if (out_stack_start) *out_stack_start = stack_start;
675   if (out_stack_end) *out_stack_end = stack_end;
676   if (out_text)  *out_text = text;
677   if (out_entry) *out_entry = entry;
678   if (out_linker_entry) *out_linker_entry = linker_entry;
679
680   VG_(debugLog)(1, "ume", "load_thin_file: success: %s\n", filename);
681   return 0;
682}
683
684
685/*
686 Load a fat Mach-O executable.
687*/
688static int
689load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
690             const HChar *filename,
691             vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
692             vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
693{
694   struct fat_header fh;
695   vki_off_t arch_offset;
696   int i;
697   cpu_type_t good_arch;
698   SysRes res;
699
700#if defined(VGA_ppc32)
701   good_arch = CPU_TYPE_POWERPC;
702#elif defined(VGA_ppc64)
703   good_arch = CPU_TYPE_POWERPC64;
704#elif defined(VGA_x86)
705   good_arch = CPU_TYPE_I386;
706#elif defined(VGA_amd64)
707   good_arch = CPU_TYPE_X86_64;
708#else
709# error unknown architecture
710#endif
711
712   // Read fat header
713   // All fat contents are BIG-ENDIAN
714   if (size < sizeof(fh)) {
715      print("bad executable (bad fat header)\n");
716      return -1;
717   }
718   res = VG_(pread)(fd, &fh, sizeof(fh), offset);
719   if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
720      print("bad executable (bad fat header)\n");
721      return -1;
722   }
723
724   // Scan arch headers looking for a good one
725   arch_offset = offset + sizeof(fh);
726   fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
727   for (i = 0; i < fh.nfat_arch; i++) {
728      struct fat_arch arch;
729      if (arch_offset + sizeof(arch) > size) {
730          print("bad executable (corrupt fat archs)\n");
731          return -1;
732      }
733
734      res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
735      arch_offset += sizeof(arch);
736      if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
737         VG_(printf)("bad executable (corrupt fat arch) %x %llu\n",
738                     arch.cputype, (ULong)arch_offset);
739         return -1;
740      }
741
742      arch.cputype = VG_(ntohl)(arch.cputype);
743      arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
744      arch.offset = VG_(ntohl)(arch.offset);
745      arch.size = VG_(ntohl)(arch.size);
746      arch.align = VG_(ntohl)(arch.align);
747      if (arch.cputype == good_arch) {
748         // use this arch
749         if (arch.offset > size  ||  arch.offset + arch.size > size) {
750            print("bad executable (corrupt fat arch 2)\n");
751            return -1;
752         }
753         return load_mach_file(fd, offset+arch.offset, arch.size, filetype,
754                               filename, out_stack_start, out_stack_end,
755                               out_text, out_entry, out_linker_entry);
756      }
757   }
758
759   print("bad executable (can't run on this machine)\n");
760   return -1;
761}
762
763/*
764 Load a Mach-O executable or dylinker.
765 The file may be fat or thin.
766*/
767static int
768load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
769              const HChar *filename,
770              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
771              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
772{
773   vki_uint32_t magic;
774   SysRes res;
775
776   if (size < sizeof(magic)) {
777      print("bad executable (no Mach-O magic)\n");
778      return -1;
779   }
780   res = VG_(pread)(fd, &magic, sizeof(magic), offset);
781   if (sr_isError(res)  ||  sr_Res(res) != sizeof(magic)) {
782      print("bad executable (no Mach-O magic)\n");
783      return -1;
784   }
785
786   if (magic == MAGIC) {
787      // thin
788      return load_thin_file(fd, offset, size, filetype, filename,
789                            out_stack_start, out_stack_end,
790                            out_text, out_entry, out_linker_entry);
791   } else if (magic == VG_(htonl)(FAT_MAGIC)) {
792      // fat
793      return load_fat_file(fd, offset, size, filetype, filename,
794                           out_stack_start, out_stack_end,
795                           out_text, out_entry, out_linker_entry);
796   } else {
797      // huh?
798      print("bad executable (bad Mach-O magic)\n");
799      return -1;
800   }
801}
802
803
804Bool VG_(match_macho)(const void *hdr, Int len)
805{
806   const vki_uint32_t *magic = hdr;
807
808   // GrP fixme check more carefully for matching fat arch?
809
810   return (len >= VKI_PAGE_SIZE  &&
811           (*magic == MAGIC  ||  *magic == VG_(ntohl)(FAT_MAGIC)))
812      ? True : False;
813}
814
815
816Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
817{
818   int err;
819   struct vg_stat sb;
820   vki_uint8_t *stack_start;
821   vki_uint8_t *stack_end;
822   vki_uint8_t *text;
823   vki_uint8_t *entry;
824   vki_uint8_t *linker_entry;
825
826   err = VG_(fstat)(fd, &sb);
827   if (err) {
828      print("couldn't stat executable\n");
829      return VKI_ENOEXEC;
830   }
831
832   err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name,
833                        &stack_start, &stack_end,
834                        &text, &entry, &linker_entry);
835   if (err) return VKI_ENOEXEC;
836
837   // GrP fixme exe_base
838   // GrP fixme exe_end
839   info->entry = (Addr)entry;
840   info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
841   info->brkbase = 0xffffffff; // GrP fixme hack
842   info->init_toc = 0; // GrP fixme unused
843
844   info->stack_start = (Addr)stack_start;
845   info->stack_end = (Addr)stack_end;
846   info->text = (Addr)text;
847   info->dynamic = linker_entry ? True : False;
848
849   info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
850
851   return 0;
852}
853
854#endif // defined(VGO_darwin)
855
856/*--------------------------------------------------------------------*/
857/*--- end                                                          ---*/
858/*--------------------------------------------------------------------*/
859
860