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