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