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