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)(§, §s_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