Home | History | Annotate | Download | only in m_debuginfo
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Reading of syms & debug info from Mach-O files.              ---*/
      4 /*---                                                  readmacho.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2005-2012 Apple Inc.
     12       Greg Parker gparker (at) apple.com
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     27    02111-1307, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     32 #if defined(VGO_darwin)
     33 
     34 #include "pub_core_basics.h"
     35 #include "pub_core_vki.h"
     36 #include "pub_core_libcbase.h"
     37 #include "pub_core_libcprint.h"
     38 #include "pub_core_libcassert.h"
     39 #include "pub_core_libcfile.h"
     40 #include "pub_core_libcproc.h"
     41 #include "pub_core_aspacemgr.h"    /* for mmaping debuginfo files */
     42 #include "pub_core_machine.h"      /* VG_ELF_CLASS */
     43 #include "pub_core_options.h"
     44 #include "pub_core_oset.h"
     45 #include "pub_core_tooliface.h"    /* VG_(needs) */
     46 #include "pub_core_xarray.h"
     47 #include "pub_core_clientstate.h"
     48 #include "pub_core_debuginfo.h"
     49 
     50 #include "priv_d3basics.h"
     51 #include "priv_misc.h"
     52 #include "priv_tytypes.h"
     53 #include "priv_storage.h"
     54 #include "priv_readmacho.h"
     55 #include "priv_readdwarf.h"
     56 #include "priv_readdwarf3.h"
     57 #include "priv_readstabs.h"
     58 
     59 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
     60 #include <mach-o/loader.h>
     61 #include <mach-o/nlist.h>
     62 #include <mach-o/fat.h>
     63 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
     64 
     65 #if VG_WORDSIZE == 4
     66 # define MAGIC MH_MAGIC
     67 # define MACH_HEADER mach_header
     68 # define LC_SEGMENT_CMD LC_SEGMENT
     69 # define SEGMENT_COMMAND segment_command
     70 # define SECTION section
     71 # define NLIST nlist
     72 #else
     73 # define MAGIC MH_MAGIC_64
     74 # define MACH_HEADER mach_header_64
     75 # define LC_SEGMENT_CMD LC_SEGMENT_64
     76 # define SEGMENT_COMMAND segment_command_64
     77 # define SECTION section_64
     78 # define NLIST nlist_64
     79 #endif
     80 
     81 
     82 /*------------------------------------------------------------*/
     83 /*---                                                      ---*/
     84 /*--- Mach-O file mapping/unmapping helpers                ---*/
     85 /*---                                                      ---*/
     86 /*------------------------------------------------------------*/
     87 
     88 typedef
     89    struct {
     90       /* These two describe the entire mapped-in ("primary") image,
     91          fat headers, kitchen sink, whatnot: the entire file.  The
     92          image is mapped into img[0 .. img_szB-1]. */
     93       UChar* img;
     94       SizeT  img_szB;
     95       /* These two describe the Mach-O object of interest, which is
     96          presumably somewhere inside the primary image.
     97          map_image_aboard() below, which generates this info, will
     98          carefully check that the macho_ fields denote a section of
     99          memory that falls entirely inside img[0 .. img_szB-1]. */
    100       UChar* macho_img;
    101       SizeT  macho_img_szB;
    102    }
    103    ImageInfo;
    104 
    105 
    106 Bool ML_(is_macho_object_file)( const void* buf, SizeT szB )
    107 {
    108    /* (JRS: the Mach-O headers might not be in this mapped data,
    109       because we only mapped a page for this initial check,
    110       or at least not very much, and what's at the start of the file
    111       is in general a so-called fat header.  The Mach-O object we're
    112       interested in could be arbitrarily far along the image, and so
    113       we can't assume its header will fall within this page.) */
    114 
    115    /* But we can say that either it's a fat object, in which case it
    116       begins with a fat header, or it's unadorned Mach-O, in which
    117       case it starts with a normal header.  At least do what checks we
    118       can to establish whether or not we're looking at something
    119       sane. */
    120 
    121    const struct fat_header*  fh_be = buf;
    122    const struct MACH_HEADER* mh    = buf;
    123 
    124    vg_assert(buf);
    125    if (szB < sizeof(struct fat_header))
    126       return False;
    127    if (VG_(ntohl)(fh_be->magic) == FAT_MAGIC)
    128       return True;
    129 
    130    if (szB < sizeof(struct MACH_HEADER))
    131       return False;
    132    if (mh->magic == MAGIC)
    133       return True;
    134 
    135    return False;
    136 }
    137 
    138 
    139 /* Unmap an image mapped in by map_image_aboard. */
    140 static void unmap_image ( /*MOD*/ImageInfo* ii )
    141 {
    142    SysRes sres;
    143    vg_assert(ii->img);
    144    vg_assert(ii->img_szB > 0);
    145    sres = VG_(am_munmap_valgrind)( (Addr)ii->img, ii->img_szB );
    146    /* Do we care if this fails?  I suppose so; it would indicate
    147       some fairly serious snafu with the mapping of the file. */
    148    vg_assert( !sr_isError(sres) );
    149    VG_(memset)(ii, 0, sizeof(*ii));
    150 }
    151 
    152 
    153 /* Map a given fat or thin object aboard, find the thin part if
    154    necessary, do some checks, and write details of both the fat and
    155    thin parts into *ii.  Returns False (and leaves the file unmapped)
    156    on failure.  Guarantees to return pointers to a valid(ish) Mach-O
    157    image if it succeeds. */
    158 static Bool map_image_aboard ( DebugInfo* di, /* only for err msgs */
    159                                /*OUT*/ImageInfo* ii, UChar* filename )
    160 {
    161    VG_(memset)(ii, 0, sizeof(*ii));
    162 
    163    /* First off, try to map the thing in. */
    164    { SizeT  size;
    165      SysRes fd, sres;
    166      struct vg_stat stat_buf;
    167 
    168      fd = VG_(stat)(filename, &stat_buf);
    169      if (sr_isError(fd)) {
    170         ML_(symerr)(di, True, "Can't stat image (to determine its size)?!");
    171         return False;
    172      }
    173      size = stat_buf.size;
    174 
    175      fd = VG_(open)(filename, VKI_O_RDONLY, 0);
    176      if (sr_isError(fd)) {
    177        ML_(symerr)(di, True, "Can't open image to read symbols?!");
    178         return False;
    179      }
    180 
    181      sres = VG_(am_mmap_file_float_valgrind)
    182                ( size, VKI_PROT_READ, sr_Res(fd), 0 );
    183      if (sr_isError(sres)) {
    184         ML_(symerr)(di, True, "Can't mmap image to read symbols?!");
    185         return False;
    186      }
    187 
    188      VG_(close)(sr_Res(fd));
    189 
    190      ii->img     = (UChar*)sr_Res(sres);
    191      ii->img_szB = size;
    192    }
    193 
    194    /* Now it's mapped in and we have .img and .img_szB set.  Look for
    195       the embedded Mach-O object.  If not findable, unmap and fail. */
    196    { struct fat_header*  fh_be;
    197      struct fat_header   fh;
    198      struct MACH_HEADER* mh;
    199 
    200      // Assume initially that we have a thin image, and update
    201      // these if it turns out to be fat.
    202      ii->macho_img     = ii->img;
    203      ii->macho_img_szB = ii->img_szB;
    204 
    205      // Check for fat header.
    206      if (ii->img_szB < sizeof(struct fat_header)) {
    207         ML_(symerr)(di, True, "Invalid Mach-O file (0 too small).");
    208         goto unmap_and_fail;
    209      }
    210 
    211      // Fat header is always BIG-ENDIAN
    212      fh_be = (struct fat_header *)ii->img;
    213      fh.magic = VG_(ntohl)(fh_be->magic);
    214      fh.nfat_arch = VG_(ntohl)(fh_be->nfat_arch);
    215      if (fh.magic == FAT_MAGIC) {
    216         // Look for a good architecture.
    217         struct fat_arch *arch_be;
    218         struct fat_arch arch;
    219         Int f;
    220         if (ii->img_szB < sizeof(struct fat_header)
    221                           + fh.nfat_arch * sizeof(struct fat_arch)) {
    222            ML_(symerr)(di, True, "Invalid Mach-O file (1 too small).");
    223            goto unmap_and_fail;
    224         }
    225         for (f = 0, arch_be = (struct fat_arch *)(fh_be+1);
    226              f < fh.nfat_arch;
    227              f++, arch_be++) {
    228            Int cputype;
    229 #          if defined(VGA_ppc)
    230            cputype = CPU_TYPE_POWERPC;
    231 #          elif defined(VGA_ppc64)
    232            cputype = CPU_TYPE_POWERPC64;
    233 #          elif defined(VGA_x86)
    234            cputype = CPU_TYPE_X86;
    235 #          elif defined(VGA_amd64)
    236            cputype = CPU_TYPE_X86_64;
    237 #          else
    238 #            error "unknown architecture"
    239 #          endif
    240            arch.cputype    = VG_(ntohl)(arch_be->cputype);
    241            arch.cpusubtype = VG_(ntohl)(arch_be->cpusubtype);
    242            arch.offset     = VG_(ntohl)(arch_be->offset);
    243            arch.size       = VG_(ntohl)(arch_be->size);
    244            if (arch.cputype == cputype) {
    245               if (ii->img_szB < arch.offset + arch.size) {
    246                  ML_(symerr)(di, True, "Invalid Mach-O file (2 too small).");
    247                  goto unmap_and_fail;
    248               }
    249               ii->macho_img     = ii->img + arch.offset;
    250               ii->macho_img_szB = arch.size;
    251               break;
    252            }
    253         }
    254         if (f == fh.nfat_arch) {
    255            ML_(symerr)(di, True,
    256                        "No acceptable architecture found in fat file.");
    257            goto unmap_and_fail;
    258         }
    259      }
    260 
    261      /* Sanity check what we found. */
    262 
    263      /* assured by logic above */
    264      vg_assert(ii->img_szB >= sizeof(struct fat_header));
    265 
    266      if (ii->macho_img_szB < sizeof(struct MACH_HEADER)) {
    267         ML_(symerr)(di, True, "Invalid Mach-O file (3 too small).");
    268         goto unmap_and_fail;
    269      }
    270 
    271      if (ii->macho_img_szB > ii->img_szB) {
    272         ML_(symerr)(di, True, "Invalid Mach-O file (thin bigger than fat).");
    273         goto unmap_and_fail;
    274      }
    275 
    276      if (ii->macho_img >= ii->img
    277          && ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB) {
    278         /* thin entirely within fat, as expected */
    279      } else {
    280         ML_(symerr)(di, True, "Invalid Mach-O file (thin not inside fat).");
    281         goto unmap_and_fail;
    282      }
    283 
    284      mh = (struct MACH_HEADER *)ii->macho_img;
    285      if (mh->magic != MAGIC) {
    286         ML_(symerr)(di, True, "Invalid Mach-O file (bad magic).");
    287         goto unmap_and_fail;
    288      }
    289 
    290      if (ii->macho_img_szB < sizeof(struct MACH_HEADER) + mh->sizeofcmds) {
    291         ML_(symerr)(di, True, "Invalid Mach-O file (4 too small).");
    292         goto unmap_and_fail;
    293      }
    294    }
    295 
    296    vg_assert(ii->img);
    297    vg_assert(ii->macho_img);
    298    vg_assert(ii->img_szB > 0);
    299    vg_assert(ii->macho_img_szB > 0);
    300    vg_assert(ii->macho_img >= ii->img);
    301    vg_assert(ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB);
    302    return True;  /* success */
    303    /*NOTREACHED*/
    304 
    305   unmap_and_fail:
    306    unmap_image(ii);
    307    return False; /* bah! */
    308 }
    309 
    310 
    311 /*------------------------------------------------------------*/
    312 /*---                                                      ---*/
    313 /*--- Mach-O symbol table reading                          ---*/
    314 /*---                                                      ---*/
    315 /*------------------------------------------------------------*/
    316 
    317 /* Read a symbol table (nlist).  Add the resulting candidate symbols
    318    to 'syms'; the caller will post-process them and hand them off to
    319    ML_(addSym) itself. */
    320 static
    321 void read_symtab( /*OUT*/XArray* /* DiSym */ syms,
    322                   struct _DebugInfo* di,
    323                   struct NLIST* o_symtab, UInt o_symtab_count,
    324                   UChar*     o_strtab, UInt o_strtab_sz )
    325 {
    326    Int    i;
    327    Addr   sym_addr;
    328    DiSym  disym;
    329    UChar* name;
    330 
    331    static UChar* s_a_t_v = NULL; /* do not make non-static */
    332 
    333    for (i = 0; i < o_symtab_count; i++) {
    334       struct NLIST *nl = o_symtab+i;
    335       if ((nl->n_type & N_TYPE) == N_SECT) {
    336          sym_addr = di->text_bias + nl->n_value;
    337     /*} else if ((nl->n_type & N_TYPE) == N_ABS) {
    338          GrP fixme don't ignore absolute symbols?
    339          sym_addr = nl->n_value; */
    340       } else {
    341          continue;
    342       }
    343 
    344       if (di->trace_symtab)
    345          VG_(printf)("nlist raw: avma %010lx  %s\n",
    346                      sym_addr, o_strtab + nl->n_un.n_strx );
    347 
    348       /* If no part of the symbol falls within the mapped range,
    349          ignore it. */
    350       if (sym_addr <= di->text_avma
    351           || sym_addr >= di->text_avma+di->text_size) {
    352          continue;
    353       }
    354 
    355       /* skip names which point outside the string table;
    356          following these risks segfaulting Valgrind */
    357       name = o_strtab + nl->n_un.n_strx;
    358       if (name < o_strtab || name >= o_strtab + o_strtab_sz)
    359          continue;
    360 
    361       /* skip nameless symbols; these appear to be common, but
    362          useless */
    363       if (*name == 0)
    364          continue;
    365 
    366       disym.addr      = sym_addr;
    367       disym.tocptr    = 0;
    368       disym.pri_name  = ML_(addStr)(di, name, -1);
    369       disym.sec_names = NULL;
    370       disym.size      = // let canonicalize fix it
    371                         di->text_avma+di->text_size - sym_addr;
    372       disym.isText    = True;
    373       disym.isIFunc   = False;
    374       // Lots of user function names get prepended with an underscore.  Eg. the
    375       // function 'f' becomes the symbol '_f'.  And the "below main"
    376       // function is called "start".  So we skip the leading underscore, and
    377       // if we see 'start' and --show-below-main=no, we rename it as
    378       // "start_according_to_valgrind", which makes it easy to spot later
    379       // and display as "(below main)".
    380       if (disym.pri_name[0] == '_') {
    381          disym.pri_name++;
    382       }
    383       else if (!VG_(clo_show_below_main) && VG_STREQ(disym.pri_name, "start")) {
    384          if (s_a_t_v == NULL)
    385             s_a_t_v = ML_(addStr)(di, "start_according_to_valgrind", -1);
    386          vg_assert(s_a_t_v);
    387          disym.pri_name = s_a_t_v;
    388       }
    389 
    390       vg_assert(disym.pri_name);
    391       VG_(addToXA)( syms, &disym );
    392    }
    393 }
    394 
    395 
    396 /* Compare DiSyms by their start address, and for equal addresses, use
    397    the primary name as a secondary sort key. */
    398 static Int cmp_DiSym_by_start_then_name ( void* v1, void* v2 )
    399 {
    400    DiSym* s1 = (DiSym*)v1;
    401    DiSym* s2 = (DiSym*)v2;
    402    if (s1->addr < s2->addr) return -1;
    403    if (s1->addr > s2->addr) return 1;
    404    return VG_(strcmp)(s1->pri_name, s2->pri_name);
    405 }
    406 
    407 /* 'cand' is a bunch of candidate symbols obtained by reading
    408    nlist-style symbol table entries.  Their ends may overlap, so sort
    409    them and truncate them accordingly.  The code in this routine is
    410    copied almost verbatim from read_symbol_table() in readxcoff.c. */
    411 static void tidy_up_cand_syms ( /*MOD*/XArray* /* of DiSym */ syms,
    412                                 Bool trace_symtab )
    413 {
    414    Word nsyms, i, j, k, m;
    415 
    416    nsyms = VG_(sizeXA)(syms);
    417 
    418    VG_(setCmpFnXA)(syms, cmp_DiSym_by_start_then_name);
    419    VG_(sortXA)(syms);
    420 
    421    /* We only know for sure the start addresses (actual VMAs) of
    422       symbols, and an overestimation of their end addresses.  So sort
    423       by start address, then clip each symbol so that its end address
    424       does not overlap with the next one along.
    425 
    426       There is a small refinement: if a group of symbols have the same
    427       address, treat them as a group: find the next symbol along that
    428       has a higher start address, and clip all of the group
    429       accordingly.  This clips the group as a whole so as not to
    430       overlap following symbols.  This leaves prefersym() in
    431       storage.c, which is not nlist-specific, to later decide which of
    432       the symbols in the group to keep.
    433 
    434       Another refinement is that we need to get rid of symbols which,
    435       after clipping, have identical starts, ends, and names.  So the
    436       sorting uses the name as a secondary key.
    437    */
    438 
    439    for (i = 0; i < nsyms; i++) {
    440       for (k = i+1;
    441            k < nsyms
    442              && ((DiSym*)VG_(indexXA)(syms,i))->addr
    443                  == ((DiSym*)VG_(indexXA)(syms,k))->addr;
    444            k++)
    445          ;
    446       /* So now [i .. k-1] is a group all with the same start address.
    447          Clip their ending addresses so they don't overlap [k].  In
    448          the normal case (no overlaps), k == i+1. */
    449       if (k < nsyms) {
    450          DiSym* next = (DiSym*)VG_(indexXA)(syms,k);
    451          for (m = i; m < k; m++) {
    452             DiSym* here = (DiSym*)VG_(indexXA)(syms,m);
    453             vg_assert(here->addr < next->addr);
    454             if (here->addr + here->size > next->addr)
    455                here->size = next->addr - here->addr;
    456          }
    457       }
    458       i = k-1;
    459       vg_assert(i <= nsyms);
    460    }
    461 
    462    j = 0;
    463    if (nsyms > 0) {
    464       j = 1;
    465       for (i = 1; i < nsyms; i++) {
    466          DiSym *s_j1, *s_j, *s_i;
    467          vg_assert(j <= i);
    468          s_j1 = (DiSym*)VG_(indexXA)(syms, j-1);
    469          s_j  = (DiSym*)VG_(indexXA)(syms, j);
    470          s_i  = (DiSym*)VG_(indexXA)(syms, i);
    471          if (s_i->addr != s_j1->addr
    472              || s_i->size != s_j1->size
    473              || 0 != VG_(strcmp)(s_i->pri_name, s_j1->pri_name)) {
    474             *s_j = *s_i;
    475             j++;
    476          } else {
    477             if (trace_symtab)
    478                VG_(printf)("nlist cleanup: dump duplicate avma %010lx  %s\n",
    479                            s_i->addr, s_i->pri_name );
    480          }
    481       }
    482    }
    483    vg_assert(j >= 0 && j <= nsyms);
    484    VG_(dropTailXA)(syms, nsyms - j);
    485 }
    486 
    487 
    488 /*------------------------------------------------------------*/
    489 /*---                                                      ---*/
    490 /*--- Mach-O top-level processing                          ---*/
    491 /*---                                                      ---*/
    492 /*------------------------------------------------------------*/
    493 
    494 #if !defined(APPLE_DSYM_EXT_AND_SUBDIRECTORY)
    495 #define APPLE_DSYM_EXT_AND_SUBDIRECTORY ".dSYM/Contents/Resources/DWARF/"
    496 #endif
    497 
    498 
    499 static Bool file_exists_p(const Char *path)
    500 {
    501    struct vg_stat sbuf;
    502    SysRes res = VG_(stat)(path, &sbuf);
    503    return sr_isError(res) ? False : True;
    504 }
    505 
    506 
    507 /* Search for an existing dSYM file as a possible separate debug file.
    508    Adapted from gdb. */
    509 static Char *
    510 find_separate_debug_file (const Char *executable_name)
    511 {
    512    Char *basename_str;
    513    Char *dot_ptr;
    514    Char *slash_ptr;
    515    Char *dsymfile;
    516 
    517    /* Make sure the object file name itself doesn't contain ".dSYM" in it or we
    518       will end up with an infinite loop where after we add a dSYM symbol file,
    519       it will then enter this function asking if there is a debug file for the
    520       dSYM file itself.  */
    521    if (VG_(strcasestr) (executable_name, ".dSYM") == NULL)
    522    {
    523       /* Check for the existence of a .dSYM file for a given executable.  */
    524       basename_str = VG_(basename) (executable_name);
    525       dsymfile = ML_(dinfo_zalloc)("di.readmacho.dsymfile",
    526                     VG_(strlen) (executable_name)
    527                     + VG_(strlen) (APPLE_DSYM_EXT_AND_SUBDIRECTORY)
    528                     + VG_(strlen) (basename_str)
    529                     + 1
    530                  );
    531 
    532       /* First try for the dSYM in the same directory as the original file.  */
    533       VG_(strcpy) (dsymfile, executable_name);
    534       VG_(strcat) (dsymfile, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
    535       VG_(strcat) (dsymfile, basename_str);
    536 
    537       if (file_exists_p (dsymfile))
    538          return dsymfile;
    539 
    540       /* Now search for any parent directory that has a '.' in it so we can find
    541          Mac OS X applications, bundles, plugins, and any other kinds of files.
    542          Mac OS X application bundles wil have their program in
    543          "/some/path/MyApp.app/Contents/MacOS/MyApp" (or replace ".app" with
    544          ".bundle" or ".plugin" for other types of bundles).  So we look for any
    545          prior '.' character and try appending the apple dSYM extension and
    546          subdirectory and see if we find an existing dSYM file (in the above
    547          MyApp example the dSYM would be at either:
    548          "/some/path/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp" or
    549          "/some/path/MyApp.dSYM/Contents/Resources/DWARF/MyApp".  */
    550       VG_(strcpy) (dsymfile, VG_(dirname) (executable_name));
    551       while ((dot_ptr = VG_(strrchr) (dsymfile, '.')))
    552       {
    553          /* Find the directory delimiter that follows the '.' character since
    554             we now look for a .dSYM that follows any bundle extension.  */
    555          slash_ptr = VG_(strchr) (dot_ptr, '/');
    556          if (slash_ptr)
    557          {
    558              /* NULL terminate the string at the '/' character and append
    559                 the path down to the dSYM file.  */
    560             *slash_ptr = '\0';
    561             VG_(strcat) (slash_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
    562             VG_(strcat) (slash_ptr, basename_str);
    563             if (file_exists_p (dsymfile))
    564                return dsymfile;
    565          }
    566 
    567          /* NULL terminate the string at the '.' character and append
    568             the path down to the dSYM file.  */
    569          *dot_ptr = '\0';
    570          VG_(strcat) (dot_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
    571          VG_(strcat) (dot_ptr, basename_str);
    572          if (file_exists_p (dsymfile))
    573             return dsymfile;
    574 
    575          /* NULL terminate the string at the '.' locatated by the strrchr()
    576             function again.  */
    577          *dot_ptr = '\0';
    578 
    579          /* We found a previous extension '.' character and did not find a
    580             dSYM file so now find previous directory delimiter so we don't
    581             try multiple times on a file name that may have a version number
    582             in it such as "/some/path/MyApp.6.0.4.app".  */
    583          slash_ptr = VG_(strrchr) (dsymfile, '/');
    584          if (!slash_ptr)
    585             break;
    586          /* NULL terminate the string at the previous directory character
    587             and search again.  */
    588          *slash_ptr = '\0';
    589       }
    590    }
    591 
    592    return NULL;
    593 }
    594 
    595 
    596 static UChar *getsectdata(UChar* base, SizeT size,
    597                           Char *segname, Char *sectname,
    598                           /*OUT*/Word *sect_size)
    599 {
    600    struct MACH_HEADER *mh = (struct MACH_HEADER *)base;
    601    struct load_command *cmd;
    602    Int c;
    603 
    604    for (c = 0, cmd = (struct load_command *)(mh+1);
    605         c < mh->ncmds;
    606         c++, cmd = (struct load_command *)(cmd->cmdsize + (Addr)cmd))
    607    {
    608       if (cmd->cmd == LC_SEGMENT_CMD) {
    609          struct SEGMENT_COMMAND *seg = (struct SEGMENT_COMMAND *)cmd;
    610          if (0 == VG_(strncmp(seg->segname, segname, sizeof(seg->segname)))) {
    611             struct SECTION *sects = (struct SECTION *)(seg+1);
    612             Int s;
    613             for (s = 0; s < seg->nsects; s++) {
    614                if (0 == VG_(strncmp(sects[s].sectname, sectname,
    615                                     sizeof(sects[s].sectname))))
    616                {
    617                   if (sect_size) *sect_size = sects[s].size;
    618                   return (UChar *)(base + sects[s].offset);
    619                }
    620             }
    621          }
    622       }
    623    }
    624 
    625    if (sect_size) *sect_size = 0;
    626    return 0;
    627 }
    628 
    629 
    630 /* Brute force just simply search for uuid[0..15] in img[0..n_img-1] */
    631 static Bool check_uuid_matches ( Addr imgA, Word n_img, UChar* uuid )
    632 {
    633    Word   i;
    634    UChar* img = (UChar*)imgA;
    635    UChar  first = uuid[0];
    636    if (n_img < 16)
    637       return False;
    638    for (i = 0; i < n_img-16; i++) {
    639       if (img[i] != first)
    640          continue;
    641       if (0 == VG_(memcmp)( &img[i], &uuid[0], 16 ))
    642          return True;
    643    }
    644    return False;
    645 }
    646 
    647 
    648 /* Heuristic kludge: return True if this looks like an installed
    649    standard library; hence we shouldn't consider automagically running
    650    dsymutil on it. */
    651 static Bool is_systemish_library_name ( UChar* name )
    652 {
    653    vg_assert(name);
    654    if (0 == VG_(strncasecmp)(name, "/usr/", 5)
    655        || 0 == VG_(strncasecmp)(name, "/bin/", 5)
    656        || 0 == VG_(strncasecmp)(name, "/sbin/", 6)
    657        || 0 == VG_(strncasecmp)(name, "/opt/", 5)
    658        || 0 == VG_(strncasecmp)(name, "/sw/", 4)
    659        || 0 == VG_(strncasecmp)(name, "/System/", 8)
    660        || 0 == VG_(strncasecmp)(name, "/Library/", 9)
    661        || 0 == VG_(strncasecmp)(name, "/Applications/", 14)) {
    662       return True;
    663    } else {
    664       return False;
    665    }
    666 }
    667 
    668 
    669 Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
    670 {
    671    struct symtab_command *symcmd = NULL;
    672    struct dysymtab_command *dysymcmd = NULL;
    673    HChar* dsymfilename = NULL;
    674    Bool have_uuid = False;
    675    UChar uuid[16];
    676    ImageInfo ii;  /* main file */
    677    ImageInfo iid; /* auxiliary .dSYM file */
    678    Bool ok;
    679    Word i;
    680    struct _DebugInfoMapping* rx_map = NULL;
    681    struct _DebugInfoMapping* rw_map = NULL;
    682 
    683    /* mmap the object file to look for di->soname and di->text_bias
    684       and uuid and nlist and STABS */
    685 
    686    /* This should be ensured by our caller (that we're in the accept
    687       state). */
    688    vg_assert(di->fsm.have_rx_map);
    689    vg_assert(di->fsm.have_rw_map);
    690 
    691    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
    692       struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
    693       if (map->rx && !rx_map)
    694          rx_map = map;
    695       if (map->rw && !rw_map)
    696          rw_map = map;
    697       if (rx_map && rw_map)
    698          break;
    699    }
    700    vg_assert(rx_map);
    701    vg_assert(rw_map);
    702 
    703    if (VG_(clo_verbosity) > 1)
    704       VG_(message)(Vg_DebugMsg,
    705                    "%s (rx at %#lx, rw at %#lx)\n", di->fsm.filename,
    706                    rx_map->avma, rw_map->avma );
    707 
    708    VG_(memset)(&ii,   0, sizeof(ii));
    709    VG_(memset)(&iid,  0, sizeof(iid));
    710    VG_(memset)(&uuid, 0, sizeof(uuid));
    711 
    712    ok = map_image_aboard( di, &ii, di->fsm.filename );
    713    if (!ok) goto fail;
    714 
    715    vg_assert(ii.macho_img != NULL && ii.macho_img_szB > 0);
    716 
    717    /* Poke around in the Mach-O header, to find some important
    718       stuff. */
    719    // Find LC_SYMTAB and LC_DYSYMTAB, if present.
    720    // Read di->soname from LC_ID_DYLIB if present,
    721    //    or from LC_ID_DYLINKER if present,
    722    //    or use "NONE".
    723    // Get di->text_bias (aka slide) based on the corresponding LC_SEGMENT
    724    // Get uuid for later dsym search
    725 
    726    di->text_bias = 0;
    727 
    728    { struct MACH_HEADER *mh = (struct MACH_HEADER *)ii.macho_img;
    729       struct load_command *cmd;
    730       Int c;
    731 
    732       for (c = 0, cmd = (struct load_command *)(mh+1);
    733            c < mh->ncmds;
    734            c++, cmd = (struct load_command *)(cmd->cmdsize
    735                                               + (unsigned long)cmd)) {
    736          if (cmd->cmd == LC_SYMTAB) {
    737             symcmd = (struct symtab_command *)cmd;
    738          }
    739          else if (cmd->cmd == LC_DYSYMTAB) {
    740             dysymcmd = (struct dysymtab_command *)cmd;
    741          }
    742          else if (cmd->cmd == LC_ID_DYLIB && mh->filetype == MH_DYLIB) {
    743             // GrP fixme bundle?
    744             struct dylib_command *dcmd = (struct dylib_command *)cmd;
    745             UChar *dylibname = dcmd->dylib.name.offset + (UChar *)dcmd;
    746             UChar *soname = VG_(strrchr)(dylibname, '/');
    747             if (!soname) soname = dylibname;
    748             else soname++;
    749             di->soname = ML_(dinfo_strdup)("di.readmacho.dylibname",
    750                                            soname);
    751          }
    752          else if (cmd->cmd==LC_ID_DYLINKER  &&  mh->filetype==MH_DYLINKER) {
    753             struct dylinker_command *dcmd = (struct dylinker_command *)cmd;
    754             UChar *dylinkername = dcmd->name.offset + (UChar *)dcmd;
    755             UChar *soname = VG_(strrchr)(dylinkername, '/');
    756             if (!soname) soname = dylinkername;
    757             else soname++;
    758             di->soname = ML_(dinfo_strdup)("di.readmacho.dylinkername",
    759                                            soname);
    760          }
    761 
    762          // A comment from Julian about why varinfo[35] fail:
    763          //
    764          // My impression is, from comparing the output of otool -l for these
    765          // executables with the logic in ML_(read_macho_debug_info),
    766          // specifically the part that begins "else if (cmd->cmd ==
    767          // LC_SEGMENT_CMD) {", that it's a complete hack which just happens
    768          // to work ok for text symbols.  In particular, it appears to assume
    769          // that in a "struct load_command" of type LC_SEGMENT_CMD, the first
    770          // "struct SEGMENT_COMMAND" inside it is going to contain the info we
    771          // need.  However, otool -l shows, and also the Apple docs state,
    772          // that a struct load_command may contain an arbitrary number of
    773          // struct SEGMENT_COMMANDs, so I'm not sure why it's OK to merely
    774          // snarf the first.  But I'm not sure about this.
    775          //
    776          // The "Try for __DATA" block below simply adds acquisition of data
    777          // svma/bias values using the same assumption.  It also needs
    778          // (probably) to deal with bss sections, but I don't understand how
    779          // this all ties together really, so it requires further study.
    780          //
    781          // If you can get your head around the relationship between MachO
    782          // segments, sections and load commands, this might be relatively
    783          // easy to fix properly.
    784          //
    785          // Basically we need to come up with plausible numbers for di->
    786          // {text,data,bss}_{avma,svma}, from which the _bias numbers are
    787          // then trivially derived.  Then I think the debuginfo reader should
    788          // work pretty well.
    789          else if (cmd->cmd == LC_SEGMENT_CMD) {
    790             struct SEGMENT_COMMAND *seg = (struct SEGMENT_COMMAND *)cmd;
    791             /* Try for __TEXT */
    792             if (!di->text_present
    793                 && 0 == VG_(strcmp)(seg->segname, "__TEXT")
    794                 /* DDD: is the  next line a kludge? -- JRS */
    795                 && seg->fileoff == 0 && seg->filesize != 0) {
    796                di->text_present = True;
    797                di->text_svma = (Addr)seg->vmaddr;
    798                di->text_avma = rx_map->avma;
    799                di->text_size = seg->vmsize;
    800                di->text_bias = di->text_avma - di->text_svma;
    801                /* Make the _debug_ values be the same as the
    802                   svma/bias for the primary object, since there is
    803                   no secondary (debuginfo) object, but nevertheless
    804                   downstream biasing of Dwarf3 relies on the
    805                   _debug_ values. */
    806                di->text_debug_svma = di->text_svma;
    807                di->text_debug_bias = di->text_bias;
    808             }
    809             /* Try for __DATA */
    810             if (!di->data_present
    811                 && 0 == VG_(strcmp)(seg->segname, "__DATA")
    812                 /* && DDD:seg->fileoff == 0 */ && seg->filesize != 0) {
    813                di->data_present = True;
    814                di->data_svma = (Addr)seg->vmaddr;
    815                di->data_avma = rw_map->avma;
    816                di->data_size = seg->vmsize;
    817                di->data_bias = di->data_avma - di->data_svma;
    818                di->data_debug_svma = di->data_svma;
    819                di->data_debug_bias = di->data_bias;
    820             }
    821          }
    822          else if (cmd->cmd == LC_UUID) {
    823              struct uuid_command *uuid_cmd = (struct uuid_command *)cmd;
    824              VG_(memcpy)(uuid, uuid_cmd->uuid, sizeof(uuid));
    825              have_uuid = True;
    826          }
    827       }
    828    }
    829 
    830    if (!di->soname) {
    831       di->soname = ML_(dinfo_strdup)("di.readmacho.noname", "NONE");
    832    }
    833 
    834    if (di->trace_symtab) {
    835       VG_(printf)("\n");
    836       VG_(printf)("SONAME = %s\n", di->soname);
    837       VG_(printf)("\n");
    838    }
    839 
    840    /* Now we have the base object to hand.  Read symbols from it. */
    841 
    842    if (ii.macho_img && ii.macho_img_szB > 0 && symcmd && dysymcmd) {
    843 
    844       /* Read nlist symbol table */
    845       struct NLIST *syms;
    846       UChar *strs;
    847       XArray* /* DiSym */ candSyms = NULL;
    848       Word nCandSyms;
    849 
    850       if (ii.macho_img_szB < symcmd->stroff + symcmd->strsize
    851           || ii.macho_img_szB < symcmd->symoff + symcmd->nsyms
    852                                                  * sizeof(struct NLIST)) {
    853          ML_(symerr)(di, False, "Invalid Mach-O file (5 too small).");
    854          goto fail;
    855       }
    856       if (dysymcmd->ilocalsym + dysymcmd->nlocalsym > symcmd->nsyms
    857           || dysymcmd->iextdefsym + dysymcmd->nextdefsym > symcmd->nsyms) {
    858          ML_(symerr)(di, False, "Invalid Mach-O file (bad symbol table).");
    859          goto fail;
    860       }
    861 
    862       syms = (struct NLIST *)(ii.macho_img + symcmd->symoff);
    863       strs = (UChar *)(ii.macho_img + symcmd->stroff);
    864 
    865       if (VG_(clo_verbosity) > 1)
    866          VG_(message)(Vg_DebugMsg,
    867             "   reading syms   from primary file (%d %d)\n",
    868             dysymcmd->nextdefsym, dysymcmd->nlocalsym );
    869 
    870       /* Read candidate symbols into 'candSyms', so we can truncate
    871          overlapping ends and generally tidy up, before presenting
    872          them to ML_(addSym). */
    873       candSyms = VG_(newXA)(
    874                     ML_(dinfo_zalloc), "di.readmacho.candsyms.1",
    875                     ML_(dinfo_free), sizeof(DiSym)
    876                  );
    877       vg_assert(candSyms);
    878 
    879       // extern symbols
    880       read_symtab(candSyms,
    881                   di,
    882                   syms + dysymcmd->iextdefsym, dysymcmd->nextdefsym,
    883                   strs, symcmd->strsize);
    884       // static and private_extern symbols
    885       read_symtab(candSyms,
    886                   di,
    887                   syms + dysymcmd->ilocalsym, dysymcmd->nlocalsym,
    888                   strs, symcmd->strsize);
    889 
    890       /* tidy up the cand syms -- trim overlapping ends.  May resize
    891          candSyms. */
    892       tidy_up_cand_syms( candSyms, di->trace_symtab );
    893 
    894       /* and finally present them to ML_(addSym) */
    895       nCandSyms = VG_(sizeXA)( candSyms );
    896       for (i = 0; i < nCandSyms; i++) {
    897          DiSym* cand = (DiSym*) VG_(indexXA)( candSyms, i );
    898          vg_assert(cand->pri_name != NULL);
    899          vg_assert(cand->sec_names == NULL);
    900          if (di->trace_symtab)
    901             VG_(printf)("nlist final: acquire  avma %010lx-%010lx  %s\n",
    902                         cand->addr, cand->addr + cand->size - 1,
    903                         cand->pri_name );
    904          ML_(addSym)( di, cand );
    905       }
    906       VG_(deleteXA)( candSyms );
    907    }
    908 
    909    /* If there's no UUID in the primary, don't even bother to try and
    910       read any DWARF, since we won't be able to verify it matches.
    911       Our policy is not to load debug info unless we can verify that
    912       it matches the primary.  Just declare success at this point.
    913       And don't complain to the user, since that would cause us to
    914       complain on objects compiled without -g.  (Some versions of
    915       XCode are observed to omit a UUID entry for object linked(?)
    916       without -g.  Others don't appear to omit it.) */
    917    if (!have_uuid)
    918       goto success;
    919 
    920    /* mmap the dSYM file to look for DWARF debug info.  If successful,
    921       use the .macho_img and .macho_img_szB in iid. */
    922 
    923    dsymfilename = find_separate_debug_file( di->fsm.filename );
    924 
    925    /* Try to load it. */
    926    if (dsymfilename) {
    927       Bool valid;
    928 
    929       if (VG_(clo_verbosity) > 1)
    930          VG_(message)(Vg_DebugMsg, "   dSYM= %s\n", dsymfilename);
    931 
    932       ok = map_image_aboard( di, &iid, dsymfilename );
    933       if (!ok) goto fail;
    934 
    935       /* check it has the right uuid. */
    936       vg_assert(have_uuid);
    937       valid = iid.macho_img && iid.macho_img_szB > 0
    938               && check_uuid_matches( (Addr)iid.macho_img,
    939                                      iid.macho_img_szB, uuid );
    940       if (valid)
    941          goto read_the_dwarf;
    942 
    943       if (VG_(clo_verbosity) > 1)
    944          VG_(message)(Vg_DebugMsg, "   dSYM does not have "
    945                                    "correct UUID (out of date?)\n");
    946    }
    947 
    948    /* There was no dsym file, or it doesn't match.  We'll have to try
    949       regenerating it, unless --dsymutil=no, in which case just complain
    950       instead. */
    951 
    952    /* If this looks like a lib that we shouldn't run dsymutil on, just
    953       give up.  (possible reasons: is system lib, or in /usr etc, or
    954       the dsym dir would not be writable by the user, or we're running
    955       as root) */
    956    vg_assert(di->fsm.filename);
    957    if (is_systemish_library_name(di->fsm.filename))
    958       goto success;
    959 
    960    if (!VG_(clo_dsymutil)) {
    961       if (VG_(clo_verbosity) == 1) {
    962          VG_(message)(Vg_DebugMsg, "%s:\n", di->fsm.filename);
    963       }
    964       if (VG_(clo_verbosity) > 0)
    965          VG_(message)(Vg_DebugMsg, "%sdSYM directory %s; consider using "
    966                       "--dsymutil=yes\n",
    967                       VG_(clo_verbosity) > 1 ? "   " : "",
    968                       dsymfilename ? "has wrong UUID" : "is missing");
    969       goto success;
    970    }
    971 
    972    /* Run dsymutil */
    973 
    974    { Int r;
    975      HChar* dsymutil = "/usr/bin/dsymutil ";
    976      HChar* cmd = ML_(dinfo_zalloc)( "di.readmacho.tmp1",
    977                                      VG_(strlen)(dsymutil)
    978                                      + VG_(strlen)(di->fsm.filename)
    979                                      + 32 /* misc */ );
    980      VG_(strcpy)(cmd, dsymutil);
    981      if (0) VG_(strcat)(cmd, "--verbose ");
    982      VG_(strcat)(cmd, "\"");
    983      VG_(strcat)(cmd, di->fsm.filename);
    984      VG_(strcat)(cmd, "\"");
    985      VG_(message)(Vg_DebugMsg, "run: %s\n", cmd);
    986      r = VG_(system)( cmd );
    987      if (r)
    988         VG_(message)(Vg_DebugMsg, "run: %s FAILED\n", dsymutil);
    989      ML_(dinfo_free)(cmd);
    990      dsymfilename = find_separate_debug_file(di->fsm.filename);
    991    }
    992 
    993    /* Try again to load it. */
    994    if (dsymfilename) {
    995       Bool valid;
    996 
    997       if (VG_(clo_verbosity) > 1)
    998          VG_(message)(Vg_DebugMsg, "   dsyms= %s\n", dsymfilename);
    999 
   1000       ok = map_image_aboard( di, &iid, dsymfilename );
   1001       if (!ok) goto fail;
   1002 
   1003       /* check it has the right uuid. */
   1004       vg_assert(have_uuid);
   1005       valid = iid.macho_img && iid.macho_img_szB > 0
   1006               && check_uuid_matches( (Addr)iid.macho_img,
   1007                                      iid.macho_img_szB, uuid );
   1008       if (!valid) {
   1009          if (VG_(clo_verbosity) > 0) {
   1010             VG_(message)(Vg_DebugMsg,
   1011                "WARNING: did not find expected UUID %02X%02X%02X%02X"
   1012                "-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"
   1013                " in dSYM dir\n",
   1014                (UInt)uuid[0], (UInt)uuid[1], (UInt)uuid[2], (UInt)uuid[3],
   1015                (UInt)uuid[4], (UInt)uuid[5], (UInt)uuid[6], (UInt)uuid[7],
   1016                (UInt)uuid[8], (UInt)uuid[9], (UInt)uuid[10],
   1017                (UInt)uuid[11], (UInt)uuid[12], (UInt)uuid[13],
   1018                (UInt)uuid[14], (UInt)uuid[15] );
   1019             VG_(message)(Vg_DebugMsg,
   1020                          "WARNING: for %s\n", di->fsm.filename);
   1021          }
   1022          unmap_image( &iid );
   1023          /* unmap_image zeroes the fields, so the following test makes
   1024             sense. */
   1025          goto fail;
   1026       }
   1027    }
   1028 
   1029    /* Right.  Finally we have our best try at the dwarf image, so go
   1030       on to reading stuff out of it. */
   1031 
   1032   read_the_dwarf:
   1033    if (iid.macho_img && iid.macho_img_szB > 0) {
   1034       UChar* debug_info_img = NULL;
   1035       Word   debug_info_sz;
   1036       UChar* debug_abbv_img;
   1037       Word   debug_abbv_sz;
   1038       UChar* debug_line_img;
   1039       Word   debug_line_sz;
   1040       UChar* debug_str_img;
   1041       Word   debug_str_sz;
   1042       UChar* debug_ranges_img;
   1043       Word   debug_ranges_sz;
   1044       UChar* debug_loc_img;
   1045       Word   debug_loc_sz;
   1046       UChar* debug_name_img;
   1047       Word   debug_name_sz;
   1048 
   1049       debug_info_img =
   1050           getsectdata(iid.macho_img, iid.macho_img_szB,
   1051                       "__DWARF", "__debug_info", &debug_info_sz);
   1052       debug_abbv_img =
   1053           getsectdata(iid.macho_img, iid.macho_img_szB,
   1054                       "__DWARF", "__debug_abbrev", &debug_abbv_sz);
   1055       debug_line_img =
   1056           getsectdata(iid.macho_img, iid.macho_img_szB,
   1057                       "__DWARF", "__debug_line", &debug_line_sz);
   1058       debug_str_img =
   1059           getsectdata(iid.macho_img, iid.macho_img_szB,
   1060                       "__DWARF", "__debug_str", &debug_str_sz);
   1061       debug_ranges_img =
   1062           getsectdata(iid.macho_img, iid.macho_img_szB,
   1063                       "__DWARF", "__debug_ranges", &debug_ranges_sz);
   1064       debug_loc_img =
   1065           getsectdata(iid.macho_img, iid.macho_img_szB,
   1066                       "__DWARF", "__debug_loc", &debug_loc_sz);
   1067       debug_name_img =
   1068           getsectdata(iid.macho_img, iid.macho_img_szB,
   1069                       "__DWARF", "__debug_pubnames", &debug_name_sz);
   1070 
   1071       if (debug_info_img) {
   1072          if (VG_(clo_verbosity) > 1) {
   1073             if (0)
   1074             VG_(message)(Vg_DebugMsg,
   1075                          "Reading dwarf3 for %s (%#lx) from %s"
   1076                          " (%ld %ld %ld %ld %ld %ld)\n",
   1077                          di->fsm.filename, di->text_avma, dsymfilename,
   1078                          debug_info_sz, debug_abbv_sz, debug_line_sz,
   1079                          debug_str_sz, debug_ranges_sz, debug_loc_sz
   1080                          );
   1081             VG_(message)(Vg_DebugMsg,
   1082                "   reading dwarf3 from dsyms file\n");
   1083          }
   1084          /* The old reader: line numbers and unwind info only */
   1085          ML_(read_debuginfo_dwarf3) ( di,
   1086                                       debug_info_img, debug_info_sz,
   1087 				      NULL,           0,
   1088                                       debug_abbv_img, debug_abbv_sz,
   1089                                       debug_line_img, debug_line_sz,
   1090                                       debug_str_img,  debug_str_sz,
   1091                                       NULL, 0 /* ALT .debug_str */ );
   1092 
   1093          /* The new reader: read the DIEs in .debug_info to acquire
   1094             information on variable types and locations.  But only if
   1095             the tool asks for it, or the user requests it on the
   1096             command line. */
   1097          if (VG_(needs).var_info /* the tool requires it */
   1098              || VG_(clo_read_var_info) /* the user asked for it */) {
   1099             ML_(new_dwarf3_reader)(
   1100                di, debug_info_img,   debug_info_sz,
   1101 	           NULL,             0,
   1102                    debug_abbv_img,   debug_abbv_sz,
   1103                    debug_line_img,   debug_line_sz,
   1104                    debug_str_img,    debug_str_sz,
   1105                    debug_ranges_img, debug_ranges_sz,
   1106                    debug_loc_img,    debug_loc_sz,
   1107                    NULL, 0, /* ALT .debug_info */
   1108                    NULL, 0, /* ALT .debug_abbv */
   1109                    NULL, 0, /* ALT .debug_line */
   1110                    NULL, 0  /* ALT .debug_str */
   1111             );
   1112          }
   1113       }
   1114    }
   1115 
   1116    if (dsymfilename) ML_(dinfo_free)(dsymfilename);
   1117 
   1118   success:
   1119    if (ii.img)
   1120       unmap_image(&ii);
   1121    if (iid.img)
   1122       unmap_image(&iid);
   1123    return True;
   1124 
   1125    /* NOTREACHED */
   1126 
   1127   fail:
   1128    ML_(symerr)(di, True, "Error reading Mach-O object.");
   1129    if (ii.img)
   1130       unmap_image(&ii);
   1131    if (iid.img)
   1132       unmap_image(&iid);
   1133    return False;
   1134 }
   1135 
   1136 #endif // defined(VGO_darwin)
   1137 
   1138 /*--------------------------------------------------------------------*/
   1139 /*--- end                                                          ---*/
   1140 /*--------------------------------------------------------------------*/
   1141