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