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-2015 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 
ML_(is_macho_object_file)98 Bool 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. */
unmap_image(DiSlice * sli)132 static 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. */
map_image_aboard(DebugInfo * di,const HChar * filename)147 static 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. */
298 static
read_symtab(XArray * syms,struct _DebugInfo * di,DiCursor symtab_cur,UInt symtab_count,DiCursor strtab_cur,UInt strtab_sz)299 void 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       // Lots of user function names get prepended with an underscore.  Eg. the
369       // function 'f' becomes the symbol '_f'.  And the "below main"
370       // function is called "start".  So we skip the leading underscore, and
371       // if we see 'start' and --show-below-main=no, we rename it as
372       // "start_according_to_valgrind", which makes it easy to spot later
373       // and display as "(below main)".
374       if (disym.pri_name[0] == '_') {
375          disym.pri_name++;
376       }
377       else if (!VG_(clo_show_below_main) && VG_STREQ(disym.pri_name, "start")) {
378          if (s_a_t_v == NULL)
379             s_a_t_v = ML_(addStr)(di, "start_according_to_valgrind", -1);
380          vg_assert(s_a_t_v);
381          disym.pri_name = s_a_t_v;
382       }
383 
384       vg_assert(disym.pri_name);
385       VG_(addToXA)( syms, &disym );
386       ML_(dinfo_free)(name);
387    }
388 }
389 
390 
391 /* Compare DiSyms by their start address, and for equal addresses, use
392    the primary name as a secondary sort key. */
cmp_DiSym_by_start_then_name(const void * v1,const void * v2)393 static Int cmp_DiSym_by_start_then_name ( const void* v1, const void* v2 )
394 {
395    const DiSym* s1 = (const DiSym*)v1;
396    const DiSym* s2 = (const DiSym*)v2;
397    if (s1->avmas.main < s2->avmas.main) return -1;
398    if (s1->avmas.main > s2->avmas.main) return 1;
399    return VG_(strcmp)(s1->pri_name, s2->pri_name);
400 }
401 
402 /* 'cand' is a bunch of candidate symbols obtained by reading
403    nlist-style symbol table entries.  Their ends may overlap, so sort
404    them and truncate them accordingly.  The code in this routine is
405    copied almost verbatim from read_symbol_table() in readxcoff.c. */
tidy_up_cand_syms(XArray * syms,Bool trace_symtab)406 static void tidy_up_cand_syms ( /*MOD*/XArray* /* of DiSym */ syms,
407                                 Bool trace_symtab )
408 {
409    Word nsyms, i, j, k, m;
410 
411    nsyms = VG_(sizeXA)(syms);
412 
413    VG_(setCmpFnXA)(syms, cmp_DiSym_by_start_then_name);
414    VG_(sortXA)(syms);
415 
416    /* We only know for sure the start addresses (actual VMAs) of
417       symbols, and an overestimation of their end addresses.  So sort
418       by start address, then clip each symbol so that its end address
419       does not overlap with the next one along.
420 
421       There is a small refinement: if a group of symbols have the same
422       address, treat them as a group: find the next symbol along that
423       has a higher start address, and clip all of the group
424       accordingly.  This clips the group as a whole so as not to
425       overlap following symbols.  This leaves prefersym() in
426       storage.c, which is not nlist-specific, to later decide which of
427       the symbols in the group to keep.
428 
429       Another refinement is that we need to get rid of symbols which,
430       after clipping, have identical starts, ends, and names.  So the
431       sorting uses the name as a secondary key.
432    */
433 
434    for (i = 0; i < nsyms; i++) {
435       for (k = i+1;
436            k < nsyms
437              && ((DiSym*)VG_(indexXA)(syms,i))->avmas.main
438                  == ((DiSym*)VG_(indexXA)(syms,k))->avmas.main;
439            k++)
440          ;
441       /* So now [i .. k-1] is a group all with the same start address.
442          Clip their ending addresses so they don't overlap [k].  In
443          the normal case (no overlaps), k == i+1. */
444       if (k < nsyms) {
445          DiSym* next = (DiSym*)VG_(indexXA)(syms,k);
446          for (m = i; m < k; m++) {
447             DiSym* here = (DiSym*)VG_(indexXA)(syms,m);
448             vg_assert(here->avmas.main < next->avmas.main);
449             if (here->avmas.main + here->size > next->avmas.main)
450                here->size = next->avmas.main - here->avmas.main;
451          }
452       }
453       i = k-1;
454       vg_assert(i <= nsyms);
455    }
456 
457    j = 0;
458    if (nsyms > 0) {
459       j = 1;
460       for (i = 1; i < nsyms; i++) {
461          DiSym *s_j1, *s_j, *s_i;
462          vg_assert(j <= i);
463          s_j1 = (DiSym*)VG_(indexXA)(syms, j-1);
464          s_j  = (DiSym*)VG_(indexXA)(syms, j);
465          s_i  = (DiSym*)VG_(indexXA)(syms, i);
466          if (s_i->avmas.main != s_j1->avmas.main
467              || s_i->size != s_j1->size
468              || 0 != VG_(strcmp)(s_i->pri_name, s_j1->pri_name)) {
469             *s_j = *s_i;
470             j++;
471          } else {
472             if (trace_symtab)
473                VG_(printf)("nlist cleanup: dump duplicate avma %010lx  %s\n",
474                            s_i->avmas.main, s_i->pri_name );
475          }
476       }
477    }
478    vg_assert(j >= 0 && j <= nsyms);
479    VG_(dropTailXA)(syms, nsyms - j);
480 }
481 
482 
483 /*------------------------------------------------------------*/
484 /*---                                                      ---*/
485 /*--- Mach-O top-level processing                          ---*/
486 /*---                                                      ---*/
487 /*------------------------------------------------------------*/
488 
489 #if !defined(APPLE_DSYM_EXT_AND_SUBDIRECTORY)
490 #define APPLE_DSYM_EXT_AND_SUBDIRECTORY ".dSYM/Contents/Resources/DWARF/"
491 #endif
492 
493 
file_exists_p(const HChar * path)494 static Bool file_exists_p(const HChar *path)
495 {
496    struct vg_stat sbuf;
497    SysRes res = VG_(stat)(path, &sbuf);
498    return sr_isError(res) ? False : True;
499 }
500 
501 
502 /* Search for an existing dSYM file as a possible separate debug file.
503    Adapted from gdb. */
504 static HChar *
find_separate_debug_file(const HChar * executable_name)505 find_separate_debug_file (const HChar *executable_name)
506 {
507    const HChar *basename_str;
508    HChar *dot_ptr;
509    HChar *slash_ptr;
510    HChar *dsymfile;
511 
512    /* Make sure the object file name itself doesn't contain ".dSYM" in it or we
513       will end up with an infinite loop where after we add a dSYM symbol file,
514       it will then enter this function asking if there is a debug file for the
515       dSYM file itself.  */
516    if (VG_(strcasestr) (executable_name, ".dSYM") == NULL)
517    {
518       /* Check for the existence of a .dSYM file for a given executable.  */
519       basename_str = VG_(basename) (executable_name);
520       dsymfile = ML_(dinfo_zalloc)("di.readmacho.dsymfile",
521                     VG_(strlen) (executable_name)
522                     + VG_(strlen) (APPLE_DSYM_EXT_AND_SUBDIRECTORY)
523                     + VG_(strlen) (basename_str)
524                     + 1
525                  );
526 
527       /* First try for the dSYM in the same directory as the original file.  */
528       VG_(strcpy) (dsymfile, executable_name);
529       VG_(strcat) (dsymfile, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
530       VG_(strcat) (dsymfile, basename_str);
531 
532       if (file_exists_p (dsymfile))
533          return dsymfile;
534 
535       /* Now search for any parent directory that has a '.' in it so we can find
536          Mac OS X applications, bundles, plugins, and any other kinds of files.
537          Mac OS X application bundles wil have their program in
538          "/some/path/MyApp.app/Contents/MacOS/MyApp" (or replace ".app" with
539          ".bundle" or ".plugin" for other types of bundles).  So we look for any
540          prior '.' character and try appending the apple dSYM extension and
541          subdirectory and see if we find an existing dSYM file (in the above
542          MyApp example the dSYM would be at either:
543          "/some/path/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp" or
544          "/some/path/MyApp.dSYM/Contents/Resources/DWARF/MyApp".  */
545       VG_(strcpy) (dsymfile, VG_(dirname) (executable_name));
546       while ((dot_ptr = VG_(strrchr) (dsymfile, '.')))
547       {
548          /* Find the directory delimiter that follows the '.' character since
549             we now look for a .dSYM that follows any bundle extension.  */
550          slash_ptr = VG_(strchr) (dot_ptr, '/');
551          if (slash_ptr)
552          {
553              /* NULL terminate the string at the '/' character and append
554                 the path down to the dSYM file.  */
555             *slash_ptr = '\0';
556             VG_(strcat) (slash_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
557             VG_(strcat) (slash_ptr, basename_str);
558             if (file_exists_p (dsymfile))
559                return dsymfile;
560          }
561 
562          /* NULL terminate the string at the '.' character and append
563             the path down to the dSYM file.  */
564          *dot_ptr = '\0';
565          VG_(strcat) (dot_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY);
566          VG_(strcat) (dot_ptr, basename_str);
567          if (file_exists_p (dsymfile))
568             return dsymfile;
569 
570          /* NULL terminate the string at the '.' locatated by the strrchr()
571             function again.  */
572          *dot_ptr = '\0';
573 
574          /* We found a previous extension '.' character and did not find a
575             dSYM file so now find previous directory delimiter so we don't
576             try multiple times on a file name that may have a version number
577             in it such as "/some/path/MyApp.6.0.4.app".  */
578          slash_ptr = VG_(strrchr) (dsymfile, '/');
579          if (!slash_ptr)
580             break;
581          /* NULL terminate the string at the previous directory character
582             and search again.  */
583          *slash_ptr = '\0';
584       }
585    }
586 
587    return NULL;
588 }
589 
590 
591 /* Given a DiSlice covering the entire Mach-O thin image, find the
592    DiSlice for the specified (segname, sectname) pairing, if
593    possible.  Also return the section's .addr field in *svma if
594    svma is non-NULL. */
getsectdata(DiSlice img,const HChar * segname,const HChar * sectname,Addr * svma)595 static DiSlice getsectdata ( DiSlice img,
596                              const HChar *segname, const HChar *sectname,
597                              /*OUT*/Addr* svma )
598 {
599    DiCursor cur = ML_(cur_from_sli)(img);
600 
601    struct MACH_HEADER mh;
602    ML_(cur_step_get)(&mh, &cur, sizeof(mh));
603 
604    Int c;
605    for (c = 0; c < mh.ncmds; c++) {
606       struct load_command cmd;
607       ML_(cur_read_get)(&cmd, cur, sizeof(cmd));
608       if (cmd.cmd == LC_SEGMENT_CMD) {
609          struct SEGMENT_COMMAND seg;
610          ML_(cur_read_get)(&seg, cur, sizeof(seg));
611          if (0 == VG_(strncmp(&seg.segname[0],
612                               segname, sizeof(seg.segname)))) {
613             DiCursor sects_cur = ML_(cur_plus)(cur, sizeof(seg));
614             Int s;
615             for (s = 0; s < seg.nsects; s++) {
616                struct SECTION sect;
617                ML_(cur_step_get)(&sect, &sects_cur, sizeof(sect));
618                if (0 == VG_(strncmp(sect.sectname, sectname,
619                                     sizeof(sect.sectname)))) {
620                   DiSlice res = img;
621                   res.ioff = sect.offset;
622                   res.szB = sect.size;
623                   if (svma) *svma = (Addr)sect.addr;
624                   return res;
625                }
626             }
627 
628          }
629       }
630       cur = ML_(cur_plus)(cur, cmd.cmdsize);
631    }
632 
633    return DiSlice_INVALID;
634 }
635 
636 
637 /* Brute force just simply search for uuid[0..15] in |sli| */
check_uuid_matches(DiSlice sli,UChar * uuid)638 static Bool check_uuid_matches ( DiSlice sli, UChar* uuid )
639 {
640    if (sli.szB < 16)
641       return False;
642 
643    /* Work through the slice in 1 KB chunks. */
644    UChar  first    = uuid[0];
645    DiOffT min_off  = sli.ioff;
646    DiOffT max1_off = sli.ioff + sli.szB;
647    DiOffT curr_off = min_off;
648    vg_assert(min_off < max1_off);
649    while (1) {
650       vg_assert(curr_off >= min_off && curr_off <= max1_off);
651       if (curr_off == max1_off) break;
652       DiOffT avail = max1_off - curr_off;
653       vg_assert(avail > 0 && avail <= max1_off);
654       if (avail > 1024) avail = 1024;
655       UChar buf[1024];
656       SizeT nGot = ML_(img_get_some)(buf, sli.img, curr_off, avail);
657       vg_assert(nGot >= 1 && nGot <= avail);
658       UInt i;
659       /* Scan through the 1K chunk we got, looking for the start char. */
660       for (i = 0; i < (UInt)nGot; i++) {
661          if (LIKELY(buf[i] != first))
662             continue;
663          /* first char matches.  See if we can get 16 bytes at this
664             offset, and compare. */
665          if (curr_off + i < max1_off && max1_off - (curr_off + i) >= 16) {
666             UChar buff16[16];
667             ML_(img_get)(&buff16[0], sli.img, curr_off + i, 16);
668             if (0 == VG_(memcmp)(&buff16[0], &uuid[0], 16))
669                return True;
670          }
671       }
672       curr_off += nGot;
673    }
674    return False;
675 }
676 
677 
678 /* Heuristic kludge: return True if this looks like an installed
679    standard library; hence we shouldn't consider automagically running
680    dsymutil on it. */
is_systemish_library_name(const HChar * name)681 static Bool is_systemish_library_name ( const HChar* name )
682 {
683    vg_assert(name);
684    if (0 == VG_(strncasecmp)(name, "/usr/", 5)
685        || 0 == VG_(strncasecmp)(name, "/bin/", 5)
686        || 0 == VG_(strncasecmp)(name, "/sbin/", 6)
687        || 0 == VG_(strncasecmp)(name, "/opt/", 5)
688        || 0 == VG_(strncasecmp)(name, "/sw/", 4)
689        || 0 == VG_(strncasecmp)(name, "/System/", 8)
690        || 0 == VG_(strncasecmp)(name, "/Library/", 9)
691        || 0 == VG_(strncasecmp)(name, "/Applications/", 14)) {
692       return True;
693    } else {
694       return False;
695    }
696 }
697 
698 
ML_(read_macho_debug_info)699 Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
700 {
701    DiSlice  msli         = DiSlice_INVALID; // the main image
702    DiSlice  dsli         = DiSlice_INVALID; // the debuginfo image
703    DiCursor sym_cur      = DiCursor_INVALID;
704    DiCursor dysym_cur    = DiCursor_INVALID;
705    HChar*   dsymfilename = NULL;
706    Bool     have_uuid    = False;
707    UChar    uuid[16];
708    Word     i;
709    const DebugInfoMapping* rx_map = NULL;
710    const DebugInfoMapping* rw_map = NULL;
711 
712    /* mmap the object file to look for di->soname and di->text_bias
713       and uuid and nlist */
714 
715    /* This should be ensured by our caller (that we're in the accept
716       state). */
717    vg_assert(di->fsm.have_rx_map);
718    vg_assert(di->fsm.have_rw_map);
719 
720    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
721       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
722       if (map->rx && !rx_map)
723          rx_map = map;
724       if (map->rw && !rw_map)
725          rw_map = map;
726       if (rx_map && rw_map)
727          break;
728    }
729    vg_assert(rx_map);
730    vg_assert(rw_map);
731 
732    if (VG_(clo_verbosity) > 1)
733       VG_(message)(Vg_DebugMsg,
734                    "%s (rx at %#lx, rw at %#lx)\n", di->fsm.filename,
735                    rx_map->avma, rw_map->avma );
736 
737    VG_(memset)(&uuid, 0, sizeof(uuid));
738 
739    msli = map_image_aboard( di, di->fsm.filename );
740    if (!ML_(sli_is_valid)(msli)) {
741       ML_(symerr)(di, False, "Connect to main image failed.");
742       goto fail;
743    }
744 
745    vg_assert(msli.img != NULL && msli.szB > 0);
746 
747    /* Poke around in the Mach-O header, to find some important
748       stuff. */
749    // Find LC_SYMTAB and LC_DYSYMTAB, if present.
750    // Read di->soname from LC_ID_DYLIB if present,
751    //    or from LC_ID_DYLINKER if present,
752    //    or use "NONE".
753    // Get di->text_bias (aka slide) based on the corresponding LC_SEGMENT
754    // Get uuid for later dsym search
755 
756    di->text_bias = 0;
757 
758    {
759       DiCursor cmd_cur = ML_(cur_from_sli)(msli);
760 
761       struct MACH_HEADER mh;
762       ML_(cur_step_get)(&mh, &cmd_cur, sizeof(mh));
763 
764       /* Now cur_cmd points just after the Mach header, right at the
765          start of the load commands, which is where we need it to start
766          the following loop. */
767 
768       Int c;
769       for (c = 0; c < mh.ncmds; c++) {
770          struct load_command cmd;
771          ML_(cur_read_get)(&cmd, cmd_cur, sizeof(cmd));
772 
773          if (cmd.cmd == LC_SYMTAB) {
774             sym_cur = cmd_cur;
775          }
776          else if (cmd.cmd == LC_DYSYMTAB) {
777             dysym_cur = cmd_cur;
778          }
779          else if (cmd.cmd == LC_ID_DYLIB && mh.filetype == MH_DYLIB) {
780             // GrP fixme bundle?
781             struct dylib_command dcmd;
782             ML_(cur_read_get)(&dcmd, cmd_cur, sizeof(dcmd));
783             DiCursor dylibname_cur
784                = ML_(cur_plus)(cmd_cur, dcmd.dylib.name.offset);
785             HChar* dylibname
786                = ML_(cur_read_strdup)(dylibname_cur, "di.rmdi.1");
787             HChar* soname = VG_(strrchr)(dylibname, '/');
788             if (!soname) soname = dylibname;
789             else soname++;
790             di->soname = ML_(dinfo_strdup)("di.readmacho.dylibname",
791                                            soname);
792             ML_(dinfo_free)(dylibname);
793          }
794          else if (cmd.cmd==LC_ID_DYLINKER  &&  mh.filetype==MH_DYLINKER) {
795             struct dylinker_command dcmd;
796             ML_(cur_read_get)(&dcmd, cmd_cur, sizeof(dcmd));
797             DiCursor dylinkername_cur
798                = ML_(cur_plus)(cmd_cur, dcmd.name.offset);
799             HChar* dylinkername
800                = ML_(cur_read_strdup)(dylinkername_cur, "di.rmdi.2");
801             HChar* soname = VG_(strrchr)(dylinkername, '/');
802             if (!soname) soname = dylinkername;
803             else soname++;
804             di->soname = ML_(dinfo_strdup)("di.readmacho.dylinkername",
805                                            soname);
806             ML_(dinfo_free)(dylinkername);
807          }
808 
809          // A comment from Julian about why varinfo[35] fail:
810          //
811          // My impression is, from comparing the output of otool -l for these
812          // executables with the logic in ML_(read_macho_debug_info),
813          // specifically the part that begins "else if (cmd->cmd ==
814          // LC_SEGMENT_CMD) {", that it's a complete hack which just happens
815          // to work ok for text symbols.  In particular, it appears to assume
816          // that in a "struct load_command" of type LC_SEGMENT_CMD, the first
817          // "struct SEGMENT_COMMAND" inside it is going to contain the info we
818          // need.  However, otool -l shows, and also the Apple docs state,
819          // that a struct load_command may contain an arbitrary number of
820          // struct SEGMENT_COMMANDs, so I'm not sure why it's OK to merely
821          // snarf the first.  But I'm not sure about this.
822          //
823          // The "Try for __DATA" block below simply adds acquisition of data
824          // svma/bias values using the same assumption.  It also needs
825          // (probably) to deal with bss sections, but I don't understand how
826          // this all ties together really, so it requires further study.
827          //
828          // If you can get your head around the relationship between MachO
829          // segments, sections and load commands, this might be relatively
830          // easy to fix properly.
831          //
832          // Basically we need to come up with plausible numbers for di->
833          // {text,data,bss}_{avma,svma}, from which the _bias numbers are
834          // then trivially derived.  Then I think the debuginfo reader should
835          // work pretty well.
836          else if (cmd.cmd == LC_SEGMENT_CMD) {
837             struct SEGMENT_COMMAND seg;
838             ML_(cur_read_get)(&seg, cmd_cur, sizeof(seg));
839             /* Try for __TEXT */
840             if (!di->text_present
841                 && 0 == VG_(strcmp)(&seg.segname[0], "__TEXT")
842                 /* DDD: is the  next line a kludge? -- JRS */
843                 && seg.fileoff == 0 && seg.filesize != 0) {
844                di->text_present = True;
845                di->text_svma = (Addr)seg.vmaddr;
846                di->text_avma = rx_map->avma;
847                di->text_size = seg.vmsize;
848                di->text_bias = di->text_avma - di->text_svma;
849                /* Make the _debug_ values be the same as the
850                   svma/bias for the primary object, since there is
851                   no secondary (debuginfo) object, but nevertheless
852                   downstream biasing of Dwarf3 relies on the
853                   _debug_ values. */
854                di->text_debug_svma = di->text_svma;
855                di->text_debug_bias = di->text_bias;
856             }
857             /* Try for __DATA */
858             if (!di->data_present
859                 && 0 == VG_(strcmp)(&seg.segname[0], "__DATA")
860                 /* && DDD:seg->fileoff == 0 */ && seg.filesize != 0) {
861                di->data_present = True;
862                di->data_svma = (Addr)seg.vmaddr;
863                di->data_avma = rw_map->avma;
864                di->data_size = seg.vmsize;
865                di->data_bias = di->data_avma - di->data_svma;
866                di->data_debug_svma = di->data_svma;
867                di->data_debug_bias = di->data_bias;
868             }
869          }
870          else if (cmd.cmd == LC_UUID) {
871              ML_(cur_read_get)(&uuid, cmd_cur, sizeof(uuid));
872              have_uuid = True;
873          }
874          // Move the cursor along
875          cmd_cur = ML_(cur_plus)(cmd_cur, cmd.cmdsize);
876       }
877    }
878 
879    if (!di->soname) {
880       di->soname = ML_(dinfo_strdup)("di.readmacho.noname", "NONE");
881    }
882 
883    if (di->trace_symtab) {
884       VG_(printf)("\n");
885       VG_(printf)("SONAME = %s\n", di->soname);
886       VG_(printf)("\n");
887    }
888 
889    /* Now we have the base object to hand.  Read symbols from it. */
890 
891    // We already asserted that ..
892    vg_assert(msli.img != NULL && msli.szB > 0);
893 
894    if (ML_(cur_is_valid)(sym_cur) && ML_(cur_is_valid)(dysym_cur)) {
895 
896       struct symtab_command   symcmd;
897       struct dysymtab_command dysymcmd;
898 
899       ML_(cur_read_get)(&symcmd,   sym_cur,   sizeof(symcmd));
900       ML_(cur_read_get)(&dysymcmd, dysym_cur, sizeof(dysymcmd));
901 
902       /* Read nlist symbol table */
903       DiCursor syms = DiCursor_INVALID;
904       DiCursor strs = DiCursor_INVALID;
905       XArray* /* DiSym */ candSyms = NULL;
906       Word nCandSyms;
907 
908       if (msli.szB < symcmd.stroff + symcmd.strsize
909           || msli.szB < symcmd.symoff + symcmd.nsyms
910                                         * sizeof(struct NLIST)) {
911          ML_(symerr)(di, False, "Invalid Mach-O file (5 too small).");
912          goto fail;
913       }
914       if (dysymcmd.ilocalsym + dysymcmd.nlocalsym > symcmd.nsyms
915           || dysymcmd.iextdefsym + dysymcmd.nextdefsym > symcmd.nsyms) {
916          ML_(symerr)(di, False, "Invalid Mach-O file (bad symbol table).");
917          goto fail;
918       }
919 
920       syms = ML_(cur_plus)(ML_(cur_from_sli)(msli), symcmd.symoff);
921       strs = ML_(cur_plus)(ML_(cur_from_sli)(msli), symcmd.stroff);
922 
923       if (VG_(clo_verbosity) > 1)
924          VG_(message)(Vg_DebugMsg,
925             "   reading syms   from primary file (%d %d)\n",
926             dysymcmd.nextdefsym, dysymcmd.nlocalsym );
927 
928       /* Read candidate symbols into 'candSyms', so we can truncate
929          overlapping ends and generally tidy up, before presenting
930          them to ML_(addSym). */
931       candSyms = VG_(newXA)(
932                     ML_(dinfo_zalloc), "di.readmacho.candsyms.1",
933                     ML_(dinfo_free), sizeof(DiSym)
934                  );
935 
936       // extern symbols
937       read_symtab(candSyms,
938                   di,
939                   ML_(cur_plus)(syms,
940                                 dysymcmd.iextdefsym * sizeof(struct NLIST)),
941                   dysymcmd.nextdefsym, strs, symcmd.strsize);
942       // static and private_extern symbols
943       read_symtab(candSyms,
944                   di,
945                   ML_(cur_plus)(syms,
946                                 dysymcmd.ilocalsym * sizeof(struct NLIST)),
947                   dysymcmd.nlocalsym, strs, symcmd.strsize);
948 
949       /* tidy up the cand syms -- trim overlapping ends.  May resize
950          candSyms. */
951       tidy_up_cand_syms( candSyms, di->trace_symtab );
952 
953       /* and finally present them to ML_(addSym) */
954       nCandSyms = VG_(sizeXA)( candSyms );
955       for (i = 0; i < nCandSyms; i++) {
956          DiSym* cand = (DiSym*) VG_(indexXA)( candSyms, i );
957          vg_assert(cand->pri_name != NULL);
958          vg_assert(cand->sec_names == NULL);
959          if (di->trace_symtab)
960             VG_(printf)("nlist final: acquire  avma %010lx-%010lx  %s\n",
961                         cand->avmas.main, cand->avmas.main + cand->size - 1,
962                         cand->pri_name );
963          ML_(addSym)( di, cand );
964       }
965       VG_(deleteXA)( candSyms );
966    }
967 
968    /* If there's no UUID in the primary, don't even bother to try and
969       read any DWARF, since we won't be able to verify it matches.
970       Our policy is not to load debug info unless we can verify that
971       it matches the primary.  Just declare success at this point.
972       And don't complain to the user, since that would cause us to
973       complain on objects compiled without -g.  (Some versions of
974       XCode are observed to omit a UUID entry for object linked(?)
975       without -g.  Others don't appear to omit it.) */
976    if (!have_uuid)
977       goto success;
978 
979    /* mmap the dSYM file to look for DWARF debug info.  If successful,
980       use the .macho_img and .macho_img_szB in dsli. */
981 
982    dsymfilename = find_separate_debug_file( di->fsm.filename );
983 
984    /* Try to load it. */
985    if (dsymfilename) {
986       Bool valid;
987 
988       if (VG_(clo_verbosity) > 1)
989          VG_(message)(Vg_DebugMsg, "   dSYM= %s\n", dsymfilename);
990 
991       dsli = map_image_aboard( di, dsymfilename );
992       if (!ML_(sli_is_valid)(dsli)) {
993          ML_(symerr)(di, False, "Connect to debuginfo image failed "
994                                 "(first attempt).");
995          goto fail;
996       }
997 
998       /* check it has the right uuid. */
999       vg_assert(have_uuid);
1000       valid = dsli.img && dsli.szB > 0 && check_uuid_matches( dsli, uuid );
1001       if (valid)
1002          goto read_the_dwarf;
1003 
1004       if (VG_(clo_verbosity) > 1)
1005          VG_(message)(Vg_DebugMsg, "   dSYM does not have "
1006                                    "correct UUID (out of date?)\n");
1007    }
1008 
1009    /* There was no dsym file, or it doesn't match.  We'll have to try
1010       regenerating it, unless --dsymutil=no, in which case just complain
1011       instead. */
1012 
1013    /* If this looks like a lib that we shouldn't run dsymutil on, just
1014       give up.  (possible reasons: is system lib, or in /usr etc, or
1015       the dsym dir would not be writable by the user, or we're running
1016       as root) */
1017    vg_assert(di->fsm.filename);
1018    if (is_systemish_library_name(di->fsm.filename))
1019       goto success;
1020 
1021    if (!VG_(clo_dsymutil)) {
1022       if (VG_(clo_verbosity) == 1) {
1023          VG_(message)(Vg_DebugMsg, "%s:\n", di->fsm.filename);
1024       }
1025       if (VG_(clo_verbosity) > 0)
1026          VG_(message)(Vg_DebugMsg, "%sdSYM directory %s; consider using "
1027                       "--dsymutil=yes\n",
1028                       VG_(clo_verbosity) > 1 ? "   " : "",
1029                       dsymfilename ? "has wrong UUID" : "is missing");
1030       goto success;
1031    }
1032 
1033    /* Run dsymutil */
1034 
1035    { Int r;
1036      const HChar* dsymutil = "/usr/bin/dsymutil ";
1037      HChar* cmd = ML_(dinfo_zalloc)( "di.readmacho.tmp1",
1038                                      VG_(strlen)(dsymutil)
1039                                      + VG_(strlen)(di->fsm.filename)
1040                                      + 32 /* misc */ );
1041      VG_(strcpy)(cmd, dsymutil);
1042      if (0) VG_(strcat)(cmd, "--verbose ");
1043      VG_(strcat)(cmd, "\"");
1044      VG_(strcat)(cmd, di->fsm.filename);
1045      VG_(strcat)(cmd, "\"");
1046      VG_(message)(Vg_DebugMsg, "run: %s\n", cmd);
1047      r = VG_(system)( cmd );
1048      if (r)
1049         VG_(message)(Vg_DebugMsg, "run: %s FAILED\n", dsymutil);
1050      ML_(dinfo_free)(cmd);
1051      dsymfilename = find_separate_debug_file(di->fsm.filename);
1052    }
1053 
1054    /* Try again to load it. */
1055    if (dsymfilename) {
1056       Bool valid;
1057 
1058       if (VG_(clo_verbosity) > 1)
1059          VG_(message)(Vg_DebugMsg, "   dsyms= %s\n", dsymfilename);
1060 
1061       dsli = map_image_aboard( di, dsymfilename );
1062       if (!ML_(sli_is_valid)(dsli)) {
1063          ML_(symerr)(di, False, "Connect to debuginfo image failed "
1064                                 "(second attempt).");
1065          goto fail;
1066       }
1067 
1068       /* check it has the right uuid. */
1069       vg_assert(have_uuid);
1070       vg_assert(have_uuid);
1071       valid = dsli.img && dsli.szB > 0 && check_uuid_matches( dsli, uuid );
1072       if (!valid) {
1073          if (VG_(clo_verbosity) > 0) {
1074             VG_(message)(Vg_DebugMsg,
1075                "WARNING: did not find expected UUID %02X%02X%02X%02X"
1076                "-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"
1077                " in dSYM dir\n",
1078                (UInt)uuid[0], (UInt)uuid[1], (UInt)uuid[2], (UInt)uuid[3],
1079                (UInt)uuid[4], (UInt)uuid[5], (UInt)uuid[6], (UInt)uuid[7],
1080                (UInt)uuid[8], (UInt)uuid[9], (UInt)uuid[10],
1081                (UInt)uuid[11], (UInt)uuid[12], (UInt)uuid[13],
1082                (UInt)uuid[14], (UInt)uuid[15] );
1083             VG_(message)(Vg_DebugMsg,
1084                          "WARNING: for %s\n", di->fsm.filename);
1085          }
1086          unmap_image( &dsli );
1087          /* unmap_image zeroes out dsli, so it's safe for "fail:" to
1088             re-try unmap_image. */
1089          goto fail;
1090       }
1091    }
1092 
1093    /* Right.  Finally we have our best try at the dwarf image, so go
1094       on to reading stuff out of it. */
1095 
1096   read_the_dwarf:
1097    if (ML_(sli_is_valid)(dsli) && dsli.szB > 0) {
1098       // "_mscn" is "mach-o section"
1099       DiSlice debug_info_mscn
1100          = getsectdata(dsli, "__DWARF", "__debug_info", NULL);
1101       DiSlice debug_abbv_mscn
1102          = getsectdata(dsli, "__DWARF", "__debug_abbrev", NULL);
1103       DiSlice debug_line_mscn
1104          = getsectdata(dsli, "__DWARF", "__debug_line", NULL);
1105       DiSlice debug_str_mscn
1106          = getsectdata(dsli, "__DWARF", "__debug_str", NULL);
1107       DiSlice debug_ranges_mscn
1108          = getsectdata(dsli, "__DWARF", "__debug_ranges", NULL);
1109       DiSlice debug_loc_mscn
1110          = getsectdata(dsli, "__DWARF", "__debug_loc", NULL);
1111 
1112       /* It appears (jrs, 2014-oct-19) that section "__eh_frame" in
1113          segment "__TEXT" appears in both the main and dsym files, but
1114          only the main one gives the right results.  Since it's in the
1115          __TEXT segment, we calculate the __eh_frame avma using its
1116          svma and the text bias, and that sounds reasonable. */
1117       Addr eh_frame_svma = 0;
1118       DiSlice eh_frame_mscn
1119          = getsectdata(msli, "__TEXT", "__eh_frame", &eh_frame_svma);
1120 
1121       if (ML_(sli_is_valid)(eh_frame_mscn)) {
1122          vg_assert(di->text_bias == di->text_debug_bias);
1123          ML_(read_callframe_info_dwarf3)(di, eh_frame_mscn,
1124                                          eh_frame_svma + di->text_bias,
1125                                          True/*is_ehframe*/);
1126       }
1127 
1128       if (ML_(sli_is_valid)(debug_info_mscn)) {
1129          if (VG_(clo_verbosity) > 1) {
1130             if (0)
1131             VG_(message)(Vg_DebugMsg,
1132                          "Reading dwarf3 for %s (%#lx) from %s"
1133                          " (%lld %lld %lld %lld %lld %lld)\n",
1134                          di->fsm.filename, di->text_avma, dsymfilename,
1135                          debug_info_mscn.szB, debug_abbv_mscn.szB,
1136                          debug_line_mscn.szB, debug_str_mscn.szB,
1137                          debug_ranges_mscn.szB, debug_loc_mscn.szB
1138                          );
1139             VG_(message)(Vg_DebugMsg,
1140                "   reading dwarf3 from dsyms file\n");
1141          }
1142          /* The old reader: line numbers and unwind info only */
1143          ML_(read_debuginfo_dwarf3) ( di,
1144                                       debug_info_mscn,
1145 				      DiSlice_INVALID, /* .debug_types */
1146                                       debug_abbv_mscn,
1147                                       debug_line_mscn,
1148                                       debug_str_mscn,
1149                                       DiSlice_INVALID /* ALT .debug_str */ );
1150 
1151          /* The new reader: read the DIEs in .debug_info to acquire
1152             information on variable types and locations or inline info.
1153             But only if the tool asks for it, or the user requests it on
1154             the command line. */
1155          if (VG_(clo_read_var_info) /* the user or tool asked for it */
1156              || VG_(clo_read_inline_info)) {
1157             ML_(new_dwarf3_reader)(
1158                di, debug_info_mscn,
1159                    DiSlice_INVALID, /* .debug_types */
1160                    debug_abbv_mscn,
1161                    debug_line_mscn,
1162                    debug_str_mscn,
1163                    debug_ranges_mscn,
1164                    debug_loc_mscn,
1165                    DiSlice_INVALID, /* ALT .debug_info */
1166                    DiSlice_INVALID, /* ALT .debug_abbv */
1167                    DiSlice_INVALID, /* ALT .debug_line */
1168                    DiSlice_INVALID  /* ALT .debug_str */
1169             );
1170          }
1171       }
1172    }
1173 
1174    if (dsymfilename) ML_(dinfo_free)(dsymfilename);
1175 
1176   success:
1177    unmap_image(&msli);
1178    unmap_image(&dsli);
1179    return True;
1180 
1181    /* NOTREACHED */
1182 
1183   fail:
1184    ML_(symerr)(di, True, "Error reading Mach-O object.");
1185    unmap_image(&msli);
1186    unmap_image(&dsli);
1187    return False;
1188 }
1189 
1190 #endif // defined(VGO_darwin)
1191 
1192 /*--------------------------------------------------------------------*/
1193 /*--- end                                                          ---*/
1194 /*--------------------------------------------------------------------*/
1195