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) {
305            *stack_end = (vki_uint8_t *)(state->__esp ? state->__esp
306                                                      : VKI_USRSTACK);
307            vg_assert(VG_IS_PAGE_ALIGNED(*stack_end));
308            (*stack_end)--;
309         }
310         if (customstack) *customstack = state->__esp;
311         return 0;
312      }
313
314#elif defined(VGA_amd64)
315      if (flavor == x86_THREAD_STATE64 && count == x86_THREAD_STATE64_COUNT){
316         x86_thread_state64_t *state = (x86_thread_state64_t *)p;
317         if (entry) *entry = (vki_uint8_t *)state->__rip;
318         if (stack_end) {
319            *stack_end = (vki_uint8_t *)(state->__rsp ? state->__rsp
320                                                      : VKI_USRSTACK64);
321            vg_assert(VG_IS_PAGE_ALIGNED(*stack_end));
322            (*stack_end)--;
323         }
324         if (customstack) *customstack = state->__rsp;
325         return 0;
326      }
327
328#else
329# error unknown platform
330#endif
331      p += count;
332      left -= count;
333   }
334
335   print("bad executable (no arch-compatible thread state)\n");
336   return -1;
337}
338
339
340/* Returns the main stack size on this platform,
341   using getrlimit or a fixed size.
342   GrP fixme 64-bit? */
343static vki_size_t default_stack_size(void)
344{
345   struct vki_rlimit lim;
346   int err = VG_(getrlimit)(VKI_RLIMIT_STACK, &lim);
347   if (err) return 8*1024*1024; // 8 MB
348   else return lim.rlim_cur;
349}
350
351
352/*
353   Processes a LC_UNIXTHREAD command.
354   Returns 0 on success, -1 on any failure.
355   The stack is mapped in and returned in *out_stack.
356   The thread's entry point is returned in *out_entry.
357*/
358static int
359load_unixthread(vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
360                vki_uint8_t **out_entry, struct thread_command *threadcmd)
361{
362   int err;
363   vki_uint8_t *stack_end;
364   int customstack;
365
366   err = load_genericthread(&stack_end, &customstack, out_entry, threadcmd);
367   if (err) return -1;
368
369   if (!stack_end) {
370      print("bad executable (no thread stack)\n");
371      return -1;
372   }
373
374   if (!customstack) {
375      // Map the stack
376      vki_size_t stacksize = VG_PGROUNDUP(default_stack_size());
377      vm_address_t stackbase = VG_PGROUNDDN(stack_end+1-stacksize);
378      SysRes res;
379
380      res = VG_(am_mmap_anon_fixed_client)(stackbase, stacksize, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
381      check_mmap(res, stackbase, stacksize, "load_unixthread1");
382      if (out_stack_start) *out_stack_start = (vki_uint8_t *)stackbase;
383   } else {
384      // custom stack - mapped via __UNIXTHREAD segment
385   }
386
387   if (out_stack_end) *out_stack_end = stack_end;
388
389   return 0;
390}
391
392
393/* Allocates a stack mapping at a V-chosen address.  Pertains to
394   LC_MAIN commands, which seem to have appeared in OSX 10.8.
395
396   This is a really nasty hack -- allocates 64M+stack size, then
397   deallocates the 64M, to guarantee that the stack is at least 64M
398   above zero. */
399#if DARWIN_VERS >= DARWIN_10_8
400static int
401handle_lcmain ( vki_uint8_t **out_stack_start,
402                vki_uint8_t **out_stack_end,
403                vki_size_t requested_size )
404{
405   if (requested_size == 0) {
406      requested_size = default_stack_size();
407   }
408   requested_size = VG_PGROUNDUP(requested_size);
409
410   const vki_size_t HACK = 64 * 1024 * 1024;
411   requested_size += HACK;
412
413   SysRes res = VG_(am_mmap_anon_float_client)(requested_size,
414                   VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC);
415   check_mmap_float(res, requested_size, "handle_lcmain");
416   vg_assert(!sr_isError(res));
417   *out_stack_start = (vki_uint8_t*)sr_Res(res);
418   *out_stack_end   = *out_stack_start + requested_size - 1;
419
420   Bool need_discard = False;
421   res = VG_(am_munmap_client)(&need_discard, (Addr)*out_stack_start, HACK);
422   if (sr_isError(res)) return -1;
423   vg_assert(!need_discard); // True == wtf?
424
425   *out_stack_start += HACK;
426
427   return 0;
428}
429#endif /* DARWIN_VERS >= DARWIN_10_8 */
430
431
432
433/*
434   Processes an LC_LOAD_DYLINKER command.
435   Returns 0 on success, -1 on any error.
436   The linker itself is mapped into memory.
437   The linker's entry point is returned in *linker_entry.
438*/
439static int
440load_dylinker(vki_uint8_t **linker_entry, struct dylinker_command *dycmd)
441{
442   const HChar *name;
443
444   if (dycmd->name.offset >= dycmd->cmdsize) {
445      print("bad executable (invalid dylinker command)\n");
446      return -1;
447   }
448
449   name = dycmd->name.offset + (HChar *)dycmd;
450
451   // GrP fixme assumes name is terminated somewhere
452   return open_dylinker(name, linker_entry);
453}
454
455
456/*
457    Process an LC_THREAD command.
458    Returns 0 on success, -1 on any failure.
459    The thread's entry point is returned in *out_entry.
460*/
461static int
462load_thread(vki_uint8_t **out_entry, struct thread_command *threadcmd)
463{
464   int customstack;
465   int err;
466
467   err = load_genericthread(NULL, &customstack, out_entry, threadcmd);
468   if (err) return -1;
469   if (customstack) {
470      print("bad executable (stackless thread has stack)\n");
471      return -1;
472   }
473   return 0;
474}
475
476
477/*
478  Loads a Mach-O executable into memory, along with any threads,
479  stacks, and dylinker.
480  Returns 0 on success, -1 on any failure.
481  fd[offset..offset+size) is a Mach-O thin file.
482  filetype is MH_EXECUTE or MH_DYLINKER.
483  The mapped but empty stack is returned in *out_stack.
484  The executable's Mach headers are returned in *out_text.
485  The executable's entry point is returned in *out_entry.
486  The dylinker's entry point (if any) is returned in *out_linker_entry.
487  GrP fixme need to return whether dylinker was found - stack layout is different
488*/
489static int
490load_thin_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
491               const HChar *filename,
492               vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
493               vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
494{
495   VG_(debugLog)(1, "ume", "load_thin_file: begin:   %s\n", filename);
496   struct MACH_HEADER mh;
497   vki_uint8_t *headers;
498   vki_uint8_t *headers_end;
499   struct load_command *lc;
500   struct load_command *lcend;
501   struct SEGMENT_COMMAND *segcmd;
502   struct thread_command *threadcmd;
503   struct dylinker_command *dycmd;
504   int err;
505   SysRes res;
506   vki_size_t len;
507
508   vki_uint8_t *stack_start = NULL;   // allocated thread stack (hot end)
509   vki_uint8_t *stack_end = NULL;   // allocated thread stack (cold end)
510   vki_uint8_t *entry = NULL;   // static entry point
511   vki_uint8_t *text = NULL;    // start of text segment (i.e. the mach headers)
512   vki_uint8_t *linker_entry = NULL; // dylinker entry point
513
514   // Read Mach-O header
515   if (sizeof(mh) > size) {
516      print("bad executable (no Mach-O header)\n");
517   }
518   res = VG_(pread)(fd, &mh, sizeof(mh), offset);
519   if (sr_isError(res)  ||  sr_Res(res) != sizeof(mh)) {
520      print("bad executable (no Mach-O header)\n");
521      return -1;
522   }
523
524
525   // Sanity-check the header itself
526   if (mh.magic != MAGIC) {
527      print("bad executable (no Mach-O magic)\n");
528      return -1;
529   }
530
531   if (mh.filetype != filetype) {
532      // expecting MH_EXECUTE or MH_DYLINKER
533      print("bad executable (wrong file type)\n");
534      return -1;
535   }
536
537
538   // Map all headers into memory
539   len = sizeof(mh) + mh.sizeofcmds;
540   if (len > size) {
541      print("bad executable (missing load commands)\n");
542      return -1;
543   }
544
545   headers = VG_(malloc)("ume.macho.headers", len);
546   res = VG_(pread)(fd, headers, len, offset);
547   if (sr_isError(res)) {
548      print("couldn't read load commands from executable\n");
549      return -1;
550   }
551   headers_end = headers + len;
552
553
554   // Map some segments into client memory:
555   // LC_SEGMENT    (text, data, etc)
556   // UNIXSTACK     (stack)
557   // LOAD_DYLINKER (dyld)
558   lcend = (struct load_command *)(headers + mh.sizeofcmds + sizeof(mh));
559   for (lc = (struct load_command *)(headers + sizeof(mh));
560        lc < lcend;
561        lc = (struct load_command *)(lc->cmdsize + (vki_uint8_t *)lc))
562   {
563      if ((vki_uint8_t *)lc < headers  ||
564          lc->cmdsize+(vki_uint8_t *)lc > headers_end) {
565          print("bad executable (invalid load commands)\n");
566          return -1;
567      }
568
569      switch (lc->cmd) {
570
571#if   DARWIN_VERS >= DARWIN_10_8
572      case LC_MAIN: { /* New in 10.8 */
573         struct entry_point_command* epcmd
574            = (struct entry_point_command*)lc;
575         if (stack_start || stack_end) {
576            print("bad executable (multiple indications of stack)");
577            return -1;
578         }
579         err = handle_lcmain ( &stack_start, &stack_end, epcmd->stacksize );
580         if (err) return -1;
581         VG_(debugLog)(2, "ume", "lc_main: created stack %p-%p\n",
582	               stack_start, stack_end);
583         break;
584      }
585#     endif
586
587      case LC_SEGMENT_CMD:
588         if (lc->cmdsize < sizeof(struct SEGMENT_COMMAND)) {
589            print("bad executable (invalid load commands)\n");
590            return -1;
591         }
592         segcmd = (struct SEGMENT_COMMAND *)lc;
593         err = load_segment(fd, offset, size, &text, &stack_start,
594                            segcmd, filename);
595         if (err) return -1;
596
597         break;
598
599      case LC_UNIXTHREAD:
600         if (stack_end  ||  entry) {
601            print("bad executable (multiple thread commands)\n");
602            return -1;
603         }
604         if (lc->cmdsize < sizeof(struct thread_command)) {
605            print("bad executable (invalid load commands)\n");
606            return -1;
607         }
608         threadcmd = (struct thread_command *)lc;
609         err = load_unixthread(&stack_start, &stack_end, &entry, threadcmd);
610         if (err) return -1;
611         break;
612
613      case LC_LOAD_DYLINKER:
614         if (filetype == MH_DYLINKER) {
615            print("bad executable (dylinker needs a dylinker)\n");
616            return -1;
617         }
618         if (linker_entry) {
619            print("bad executable (multiple dylinker commands)\n");
620         }
621         if (lc->cmdsize < sizeof(struct dylinker_command)) {
622            print("bad executable (invalid load commands)\n");
623            return -1;
624         }
625         dycmd = (struct dylinker_command *)lc;
626         err = load_dylinker(&linker_entry, dycmd);
627         if (err) return -1;
628         break;
629
630      case LC_THREAD:
631         if (filetype == MH_EXECUTE) {
632            print("bad executable (stackless thread)\n");
633            return -1;
634         }
635         if (stack_end  ||  entry) {
636            print("bad executable (multiple thread commands)\n");
637            return -1;
638         }
639         if (lc->cmdsize < sizeof(struct thread_command)) {
640            print("bad executable (invalid load commands)\n");
641            return -1;
642         }
643         threadcmd = (struct thread_command *)lc;
644         err = load_thread(&entry, threadcmd);
645         if (err) return -1;
646         break;
647
648      default:
649         break;
650      }
651   }
652
653
654   // Done with the headers
655   VG_(free)(headers);
656
657   if (filetype == MH_EXECUTE) {
658      // Verify the necessary pieces for an executable:
659      // a stack
660      // a text segment
661      // an entry point (static or linker)
662      if (!stack_end || !stack_start) {
663         VG_(printf)("bad executable %s (no stack)\n", filename);
664         return -1;
665      }
666      if (!text) {
667         print("bad executable (no text segment)\n");
668         return -1;
669      }
670      if (!entry  &&  !linker_entry) {
671         print("bad executable (no entry point)\n");
672         return -1;
673      }
674   }
675   else if (filetype == MH_DYLINKER) {
676      // Verify the necessary pieces for a dylinker:
677      // an entry point
678      if (!entry) {
679         print("bad executable (no entry point)\n");
680         return -1;
681      }
682   }
683
684   if (out_stack_start) *out_stack_start = stack_start;
685   if (out_stack_end) *out_stack_end = stack_end;
686   if (out_text)  *out_text = text;
687   if (out_entry) *out_entry = entry;
688   if (out_linker_entry) *out_linker_entry = linker_entry;
689
690   VG_(debugLog)(1, "ume", "load_thin_file: success: %s\n", filename);
691   return 0;
692}
693
694
695/*
696 Load a fat Mach-O executable.
697*/
698static int
699load_fat_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
700             const HChar *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   struct fat_header fh;
705   vki_off_t arch_offset;
706   int i;
707   cpu_type_t good_arch;
708   SysRes res;
709
710#if defined(VGA_ppc32)
711   good_arch = CPU_TYPE_POWERPC;
712#elif defined(VGA_ppc64be)
713   good_arch = CPU_TYPE_POWERPC64BE;
714#elif defined(VGA_ppc64le)
715   good_arch = CPU_TYPE_POWERPC64LE;
716#elif defined(VGA_x86)
717   good_arch = CPU_TYPE_I386;
718#elif defined(VGA_amd64)
719   good_arch = CPU_TYPE_X86_64;
720#else
721# error unknown architecture
722#endif
723
724   // Read fat header
725   // All fat contents are BIG-ENDIAN
726   if (size < sizeof(fh)) {
727      print("bad executable (bad fat header)\n");
728      return -1;
729   }
730   res = VG_(pread)(fd, &fh, sizeof(fh), offset);
731   if (sr_isError(res)  ||  sr_Res(res) != sizeof(fh)) {
732      print("bad executable (bad fat header)\n");
733      return -1;
734   }
735
736   // Scan arch headers looking for a good one
737   arch_offset = offset + sizeof(fh);
738   fh.nfat_arch = VG_(ntohl)(fh.nfat_arch);
739   for (i = 0; i < fh.nfat_arch; i++) {
740      struct fat_arch arch;
741      if (arch_offset + sizeof(arch) > size) {
742          print("bad executable (corrupt fat archs)\n");
743          return -1;
744      }
745
746      res = VG_(pread)(fd, &arch, sizeof(arch), arch_offset);
747      arch_offset += sizeof(arch);
748      if (sr_isError(res)  ||  sr_Res(res) != sizeof(arch)) {
749         VG_(printf)("bad executable (corrupt fat arch) %x %llu\n",
750                     arch.cputype, (ULong)arch_offset);
751         return -1;
752      }
753
754      arch.cputype = VG_(ntohl)(arch.cputype);
755      arch.cpusubtype = VG_(ntohl)(arch.cpusubtype);
756      arch.offset = VG_(ntohl)(arch.offset);
757      arch.size = VG_(ntohl)(arch.size);
758      arch.align = VG_(ntohl)(arch.align);
759      if (arch.cputype == good_arch) {
760         // use this arch
761         if (arch.offset > size  ||  arch.offset + arch.size > size) {
762            print("bad executable (corrupt fat arch 2)\n");
763            return -1;
764         }
765         return load_mach_file(fd, offset+arch.offset, arch.size, filetype,
766                               filename, out_stack_start, out_stack_end,
767                               out_text, out_entry, out_linker_entry);
768      }
769   }
770
771   print("bad executable (can't run on this machine)\n");
772   return -1;
773}
774
775/*
776 Load a Mach-O executable or dylinker.
777 The file may be fat or thin.
778*/
779static int
780load_mach_file(int fd, vki_off_t offset, vki_off_t size, unsigned long filetype,
781              const HChar *filename,
782              vki_uint8_t **out_stack_start, vki_uint8_t **out_stack_end,
783              vki_uint8_t **out_text, vki_uint8_t **out_entry, vki_uint8_t **out_linker_entry)
784{
785   vki_uint32_t magic;
786   SysRes res;
787
788   if (size < sizeof(magic)) {
789      print("bad executable (no Mach-O magic)\n");
790      return -1;
791   }
792   res = VG_(pread)(fd, &magic, sizeof(magic), offset);
793   if (sr_isError(res)  ||  sr_Res(res) != sizeof(magic)) {
794      print("bad executable (no Mach-O magic)\n");
795      return -1;
796   }
797
798   if (magic == MAGIC) {
799      // thin
800      return load_thin_file(fd, offset, size, filetype, filename,
801                            out_stack_start, out_stack_end,
802                            out_text, out_entry, out_linker_entry);
803   } else if (magic == VG_(htonl)(FAT_MAGIC)) {
804      // fat
805      return load_fat_file(fd, offset, size, filetype, filename,
806                           out_stack_start, out_stack_end,
807                           out_text, out_entry, out_linker_entry);
808   } else {
809      // huh?
810      print("bad executable (bad Mach-O magic)\n");
811      return -1;
812   }
813}
814
815
816Bool VG_(match_macho)(const void *hdr, SizeT len)
817{
818   const vki_uint32_t *magic = hdr;
819
820   // GrP fixme check more carefully for matching fat arch?
821
822   return (len >= VKI_PAGE_SIZE  &&
823           (*magic == MAGIC  ||  *magic == VG_(ntohl)(FAT_MAGIC)))
824      ? True : False;
825}
826
827
828Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info)
829{
830   int err;
831   struct vg_stat sb;
832   vki_uint8_t *stack_start;
833   vki_uint8_t *stack_end;
834   vki_uint8_t *text;
835   vki_uint8_t *entry;
836   vki_uint8_t *linker_entry;
837
838   err = VG_(fstat)(fd, &sb);
839   if (err) {
840      print("couldn't stat executable\n");
841      return VKI_ENOEXEC;
842   }
843
844   err = load_mach_file(fd, 0, sb.size, MH_EXECUTE, name,
845                        &stack_start, &stack_end,
846                        &text, &entry, &linker_entry);
847   if (err) return VKI_ENOEXEC;
848
849   // GrP fixme exe_base
850   // GrP fixme exe_end
851   info->entry = (Addr)entry;
852   info->init_ip = (Addr)(linker_entry ? linker_entry : entry);
853   info->brkbase = 0xffffffff; // GrP fixme hack
854   info->init_toc = 0; // GrP fixme unused
855
856   info->stack_start = (Addr)stack_start;
857   info->stack_end = (Addr)stack_end;
858   info->text = (Addr)text;
859   info->dynamic = linker_entry ? True : False;
860
861   info->executable_path = VG_(strdup)("ume.macho.executable_path", name);
862
863   return 0;
864}
865
866#endif // defined(VGO_darwin)
867
868/*--------------------------------------------------------------------*/
869/*--- end                                                          ---*/
870/*--------------------------------------------------------------------*/
871
872