Home | History | Annotate | Download | only in m_ume
      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 (at) 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 
     80 static void print(const HChar *str)
     81 {
     82    VG_(printf)("%s", str);
     83 }
     84 
     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
     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
    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
    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
    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? */
    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
    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
    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
    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
    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
    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
    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
    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 
    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 
    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