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