• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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       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. */
cmp_DiSym_by_start_then_name(const void * v1,const void * v2)394 static 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. */
tidy_up_cand_syms(XArray * syms,Bool trace_symtab)407 static 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 
file_exists_p(const HChar * path)495 static 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. */
505 static HChar *
find_separate_debug_file(const HChar * executable_name)506 find_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. */
getsectdata(DiSlice img,const HChar * segname,const HChar * sectname,Addr * svma)596 static 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| */
check_uuid_matches(DiSlice sli,UChar * uuid)639 static 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. */
is_systemish_library_name(const HChar * name)682 static 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 
ML_(read_macho_debug_info)700 Bool 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