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