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 
print(const HChar * str)71 static void print(const HChar *str)
72 {
73    VG_(printf)("%s", str);
74 }
75 
check_mmap(SysRes res,Addr base,SizeT len,const HChar * who)76 static 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
check_mmap_float(SysRes res,SizeT len,const HChar * who)86 static 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 
96 static int
97 load_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 
102 static int
103 load_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 
108 static int
109 load_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  */
120 static int
open_dylinker(const HChar * filename,vki_uint8_t ** out_linker_entry)121 open_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 */
173 static int
load_segment(int fd,vki_off_t offset,vki_off_t size,vki_uint8_t ** text,vki_uint8_t ** stack_start,struct SEGMENT_COMMAND * segcmd,const HChar * filename)174 load_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 */
274 static int
load_genericthread(vki_uint8_t ** stack_end,int * customstack,vki_uint8_t ** entry,struct thread_command * threadcmd)275 load_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? */
default_stack_size(void)343 static 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 */
358 static int
load_unixthread(vki_uint8_t ** out_stack_start,vki_uint8_t ** out_stack_end,vki_uint8_t ** out_entry,struct thread_command * threadcmd)359 load_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
400 static int
handle_lcmain(vki_uint8_t ** out_stack_start,vki_uint8_t ** out_stack_end,vki_size_t requested_size)401 handle_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 */
439 static int
load_dylinker(vki_uint8_t ** linker_entry,struct dylinker_command * dycmd)440 load_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 */
461 static int
load_thread(vki_uint8_t ** out_entry,struct thread_command * threadcmd)462 load_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 */
489 static int
load_thin_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const HChar * filename,vki_uint8_t ** out_stack_start,vki_uint8_t ** out_stack_end,vki_uint8_t ** out_text,vki_uint8_t ** out_entry,vki_uint8_t ** out_linker_entry)490 load_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 */
698 static int
load_fat_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const HChar * filename,vki_uint8_t ** out_stack_start,vki_uint8_t ** out_stack_end,vki_uint8_t ** out_text,vki_uint8_t ** out_entry,vki_uint8_t ** out_linker_entry)699 load_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 */
779 static int
load_mach_file(int fd,vki_off_t offset,vki_off_t size,unsigned long filetype,const HChar * filename,vki_uint8_t ** out_stack_start,vki_uint8_t ** out_stack_end,vki_uint8_t ** out_text,vki_uint8_t ** out_entry,vki_uint8_t ** out_linker_entry)780 load_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 
VG_(match_macho)816 Bool 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 
VG_(load_macho)828 Int 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