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