1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Top level management of symbols and debugging information. ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- debuginfo.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2000-2010 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 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#include "pub_core_basics.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" /* self */ 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_demangle.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" // VG_(getenv) 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" // VG_(redir_notify_{new,delete}_SegInfo) 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" // VG_PLAT_USES_PPCTOC 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_oset.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_ume.h" 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_misc.h" /* dinfo_zalloc/free */ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_d3basics.h" /* ML_(pp_GX) */ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_tytypes.h" 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_storage.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_readdwarf.h" 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_readstabs.h" 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readelf.h" 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readdwarf3.h" 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readpdb.h" 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_aix5) 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "pub_core_debuglog.h" 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "pub_core_libcproc.h" 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "pub_core_libcfile.h" 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readxcoff.h" 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readmacho.h" 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include "priv_readpdb.h" 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The _svma / _avma / _image / _bias naming scheme ---*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* JRS 11 Jan 07: I find the different kinds of addresses involved in 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debuginfo reading confusing. Recently I arrived at some 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminology which makes it clearer (to me, at least). There are 3 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown kinds of address used in the debuginfo reading process: 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stated VMAs - the address where (eg) a .so says a symbol is, that 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is, what it tells you if you consider the .so in 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isolation 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actual VMAs - the address where (eg) said symbol really wound up 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown after the .so was mapped into memory 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown image addresses - pointers into the copy of the .so (etc) 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown transiently mmaped aboard whilst we read its info 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Additionally I use the term 'bias' to denote the difference 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown between stated and actual VMAs for a given entity. 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This terminology is not used consistently, but a start has been 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown made. readelf.c and the call-frame info reader in readdwarf.c now 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use it. Specifically, various variables and structure fields have 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown been annotated with _avma / _svma / _image / _bias. In places _img 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is used instead of _image for the sake of brevity. 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- fwdses ---*/ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cfsi_cache__invalidate ( void ); 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Root structure ---*/ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The root structure for the entire debug info system. It is a 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown linked list of DebugInfos. */ 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic DebugInfo* debugInfo_list = NULL; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find 'di' in the debugInfo_list and move it one step closer the the 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown front of the list, so as to make subsequent searches for it 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cheaper. When used in a controlled way, makes a major improvement 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in some DebugInfo-search-intensive situations, most notably stack 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unwinding on amd64-linux. */ 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void move_DebugInfo_one_step_forward ( DebugInfo* di ) 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo *di0, *di1, *di2; 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di == debugInfo_list) 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* already at head of list */ 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di != NULL); 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di0 = debugInfo_list; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di1 = NULL; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2 = NULL; 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di0 == NULL || di0 == di) break; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2 = di1; 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di1 = di0; 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di0 = di0->next; 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di0 == di); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di0 != NULL && di1 != NULL && di2 != NULL) { 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* tmp; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* di0 points to di, di1 to its predecessor, and di2 to di1's 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown predecessor. Swap di0 and di1, that is, move di0 one step 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown closer to the start of the list. */ 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di2->next == di1); 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di1->next == di0); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = di0->next; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2->next = di0; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di0->next = di1; 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di1->next = tmp; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di0 != NULL && di1 != NULL && di2 == NULL) { 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* it's second in the list. */ 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(debugInfo_list == di1); 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di1->next == di0); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di1->next = di0->next; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di0->next = di1; 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debugInfo_list = di0; 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Notification (acquire/discard) helpers ---*/ 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Gives out unique abstract handles for allocated DebugInfos. See 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comment in priv_storage.h, declaration of struct _DebugInfo, for 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown details. */ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong handle_counter = 1; 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate and zero out a new DebugInfo record. */ 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDebugInfo* alloc_DebugInfo( const UChar* filename, 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const UChar* memname ) 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool traceme; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(filename); 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo)); 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->handle = handle_counter++; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->memname = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname) 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : NULL; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc. 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Now set up the debugging-output flags. */ 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown traceme 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(string_match)( VG_(clo_trace_symtab_patt), filename ) 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt), 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memname )); 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (traceme) { 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->trace_symtab = VG_(clo_trace_symtab); 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->trace_cfi = VG_(clo_trace_cfi); 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->ddump_syms = VG_(clo_debug_dump_syms); 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->ddump_line = VG_(clo_debug_dump_line); 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->ddump_frames = VG_(clo_debug_dump_frames); 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Free a DebugInfo, and also all the stuff hanging off it. */ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_DebugInfo ( DebugInfo* di ) 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i, j, n; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct strchunk *chunk, *next; 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TyEnt* ent; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GExpr* gexpr; 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di != NULL); 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->filename) ML_(dinfo_free)(di->filename); 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->symtab) ML_(dinfo_free)(di->symtab); 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->loctab) ML_(dinfo_free)(di->loctab); 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->cfsi) ML_(dinfo_free)(di->cfsi); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->fpo) ML_(dinfo_free)(di->fpo); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (chunk = di->strchunks; chunk != NULL; chunk = next) { 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown next = chunk->next; 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(chunk); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Delete the two admin arrays. These lists exist primarily so 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we can visit each object exactly once when we need to 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delete them. */ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->admin_tyents) { 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = VG_(sizeXA)(di->admin_tyents); 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) { 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i); 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dump anything hanging off this ent */ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(TyEnt__make_EMPTY)(ent); 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)(di->admin_tyents); 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->admin_tyents = NULL; 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->admin_gexprs) { 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = VG_(sizeXA)(di->admin_gexprs); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) { 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(gexpr); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)(di->admin_gexprs); 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->admin_gexprs = NULL; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dump the variable info. This is kinda complex: we must take 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown care not to free items which reside in either the admin lists 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (as we have just freed them) or which reside in the DebugInfo's 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown string table. */ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->varinfo) { 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) { 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i); 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!scope) continue; 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* iterate over all entries in 'scope' */ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(scope); 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiAddrRange* arange = VG_(OSetGen_Next)(scope); 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!arange) break; 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* for each var in 'arange' */ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arange->vars); 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) { 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j); 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(var); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nothing to free in var: all the pointer fields refer 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to stuff either on an admin list, or in 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown .strchunks */ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)(arange->vars); 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Don't free arange itself, as OSetGen_Destroy does 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that */ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_Destroy)(scope); 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)(di->varinfo); 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(di); 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 'si' is a member of debugInfo_list. Find it, remove it from the 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown list, notify m_redir that this has happened, and free all storage 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reachable from it. 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void discard_DebugInfo ( DebugInfo* di ) 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_aix5) 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* reason = "__unload"; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_aix5) 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* reason = "kunload64"; 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* reason = "munmap"; 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo** prev_next_ptr = &debugInfo_list; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* curr = debugInfo_list; 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (curr) { 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr == di) { 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Found it; remove from list and free it. */ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr->have_dinfo 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Discarding syms at %#lx-%#lx in %s due to %s()\n", 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_avma, 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_avma + di->text_size, 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr->filename ? curr->filename : (UChar*)"???", 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reason); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(*prev_next_ptr == curr); 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *prev_next_ptr = curr->next; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr->have_dinfo) 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_notify_delete_DebugInfo)( curr ); 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free_DebugInfo(curr); 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prev_next_ptr = &curr->next; 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr = curr->next; 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found. */ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Repeatedly scan debugInfo_list, looking for DebugInfos with text 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AVMAs intersecting [start,start+length), and call discard_DebugInfo 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to get rid of them. This modifies the list, hence the multiple 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iterations. Returns True iff any such DebugInfos were found. 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool discard_syms_in_range ( Addr start, SizeT length ) 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool anyFound = False; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* curr; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = False; 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr = debugInfo_list; 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr == NULL) 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr->text_present 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && curr->text_size > 0 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (start+length - 1 < curr->text_avma 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || curr->text_avma + curr->text_size - 1 < start)) { 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no overlap */ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = True; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr = curr->next; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) break; 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyFound = True; 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_DebugInfo( curr ); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return anyFound; 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Does [s1,+len1) overlap [s2,+len2) ? Note: does not handle 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wraparound at the end of the address space -- just asserts in that 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case. */ 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 ) 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr e1, e2; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len1 == 0 || len2 == 0) 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e1 = s1 + len1 - 1; 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e2 = s2 + len2 - 1; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Assert that we don't have wraparound. If we do it would imply 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that file sections are getting mapped around the end of the 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address space, which sounds unlikely. */ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(s1 <= e1); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(s2 <= e2); 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e1 < s2 || e2 < s1) return False; 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any way? */ 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 ) 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di1); 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di2); 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di1->have_rx_map && di2->have_rx_map 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ranges_overlap(di1->rx_map_avma, di1->rx_map_size, 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2->rx_map_avma, di2->rx_map_size)) 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di1->have_rx_map && di2->have_rw_map 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ranges_overlap(di1->rx_map_avma, di1->rx_map_size, 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2->rw_map_avma, di2->rw_map_size)) 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di1->have_rw_map && di2->have_rx_map 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ranges_overlap(di1->rw_map_avma, di1->rw_map_size, 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2->rx_map_avma, di2->rx_map_size)) 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di1->have_rw_map && di2->have_rw_map 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ranges_overlap(di1->rw_map_avma, di1->rw_map_size, 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2->rw_map_avma, di2->rw_map_size)) 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Discard all elements of debugInfo_list whose .mark bit is set. 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void discard_marked_DebugInfos ( void ) 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* curr; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr = debugInfo_list; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!curr) 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (curr->mark) 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown curr = curr->next; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!curr) break; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_DebugInfo( curr ); 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Discard any elements of debugInfo_list which overlap with diRef. 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Clearly diRef must have its rx_ and rw_ mapping information set to 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown something sane. */ 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_aix5) 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef ) 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Mark all the DebugInfos in debugInfo_list that need to be 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deleted. First, clear all the mark bits; then set them if they 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown overlap with siRef. Since siRef itself is in this list we at 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown least expect its own mark bit to be set. */ 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di; di = di->next) { 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->mark = do_DebugInfos_overlap( di, diRef ); 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di == diRef) { 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->mark); 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->mark = False; 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_marked_DebugInfos(); 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the existing DebugInfo for (memname,filename) or if not found, 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown create one. In the latter case memname and filename are strdup'd 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown into VG_AR_DINFO, and the new DebugInfo is added to 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debugInfo_list. */ 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname ) 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(filename); 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di; di = di->next) { 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->filename); 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)(di->filename, filename) 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ( (memname && di->memname) 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? 0==VG_(strcmp)(memname, di->memname) 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : True )) 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di) { 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = alloc_DebugInfo(filename, memname); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di); 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->next = debugInfo_list; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debugInfo_list = di; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di; 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Debuginfo reading for 'di' has just been successfully completed. 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Check that the invariants stated in 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown priv_storage.h are observed. */ 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void check_CFSI_related_invariants ( DebugInfo* di ) 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di2 = NULL; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di); 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This fn isn't called until after debuginfo for this object has 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown been successfully read. And that shouldn't happen until we have 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both a r-x and rw- mapping for the object. Hence: */ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->have_rx_map); 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->have_rw_map); 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* degenerate case: r-x section is empty */ 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->rx_map_size == 0) { 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi == NULL); 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* normal case: r-x section is nonempty */ 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* invariant (0) */ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->rx_map_size > 0); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* invariant (1) */ 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di2 = debugInfo_list; di2; di2 = di2->next) { 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di2 == di) 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di2->rx_map_size == 0) 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma); 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2 = NULL; 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* invariant (2) */ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->cfsi) { 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_minavma >= di->rx_map_avma); 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size); 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* invariants (3) and (4) */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->cfsi) { 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i; 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_used > 0); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_size > 0); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < di->cfsi_used; i++) { 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiCfSI* cfsi = &di->cfsi[i]; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cfsi->len > 0); 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cfsi->base >= di->cfsi_minavma); 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma); 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i > 0) { 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiCfSI* cfsip = &di->cfsi[i-1]; 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cfsip->base + cfsip->len <= cfsi->base); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_used == 0); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->cfsi_size == 0); 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM ---*/ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(di_initialise) ( void ) 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's actually very little to do here, since everything 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown centers around the DebugInfos in debugInfo_list, they are 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown created and destroyed on demand, and each one is treated more or 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown less independently. */ 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(debugInfo_list == NULL); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* flush the CFI fast query cache. */ 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/ 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin) 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The debug info system is driven by notifications that a text 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment has been mapped in, or unmapped. When that happens it 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tries to acquire/discard whatever info is available for the 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown corresponding object. This section contains the notification 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handlers. */ 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notify the debuginfo system about a new mapping. This is the way 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new debug information gets loaded. If allow_SkFileV is True, it 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will try load debug info if the mapping at 'a' belongs to Valgrind; 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whereas normally (False) it will not do that. This allows us to 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown carefully control when the thing will read symbols from the 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind executable itself. 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If a call to VG_(di_notify_mmap) causes debug info to be read, then 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the returned ULong is an abstract handle which can later be used to 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown refer to the debuginfo read as a result of this specific mapping, 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in later queries to m_debuginfo. In this case the handle value 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will be one or above. If the returned value is zero, no debug info 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown was read. */ 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 601f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy StepanovUWord nacl_head; 602f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovchar *nacl_file; 603f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#define FOURGIG (1ULL << 32) 604f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 605f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovint LoadNaClDebugInfo(Addr a); 606f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovint LoadNaClDebugInfo(Addr a) { 607f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#if defined(VGO_linux) 608f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov DebugInfo *di; 609f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov SizeT rw_start = 0; 610f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov const NSegment *seg; 611f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 612f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov //VG_(am_show_nsegments)(0, "kcc"); 613f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov //VG_(printf)("<<%s: a=%p\n", __FUNCTION__, (void*)a); 614f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov nacl_head = (unsigned long)a; 615f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov vg_assert(nacl_file); 616f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di = find_or_create_DebugInfo_for(nacl_file, NULL); 617f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov vg_assert(di); 618f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 619f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov // di->trace_symtab = 1; 620f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 621f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov seg = VG_(am_find_nsegment)(a); 622f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov while (1) { 623f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov if (seg->hasR && seg->hasW && !seg->hasX) { 624f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov rw_start = seg->start; 625f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov // VG_(printf)("rw_start = %p\n", (void*)rw_start); 626f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov break; 627f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 628f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov seg = VG_(am_next_nsegment)((NSegment*)seg, True); 629f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov vg_assert(seg); 630f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 631f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov vg_assert(rw_start); 632f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 633f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->have_rx_map = True; 634f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rx_map_avma = nacl_head; 635f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rx_map_size = FOURGIG; 636f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rx_map_foff = 0; 637f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->have_rw_map = True; 638f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rw_map_avma = nacl_head; 639f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rw_map_size = FOURGIG; 640f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->rw_map_foff = rw_start - nacl_head; 641f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 642f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov discard_DebugInfos_which_overlap_with( di ); 643f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov if (ML_(read_elf_debug_info)(di)) { 644f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->soname = "NaCl"; 645f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov TRACE_SYMTAB("\n------ Canonicalising the " 646f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov "acquired info ------\n"); 647f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov /* invalidate the CFI unwind cache. */ 648f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov cfsi_cache__invalidate(); 649f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov /* prepare read data for use */ 650f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov ML_(canonicaliseTables)( di ); 651f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov /* notify m_redir about it */ 652f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov TRACE_SYMTAB("\n------ Notifying m_redir ------\n"); 653f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(redir_notify_new_DebugInfo)( di ); 654f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov /* Note that we succeeded */ 655f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov di->have_dinfo = True; 656f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov vg_assert(di->handle > 0); 657f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov /* Check invariants listed in 658f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in 659f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov priv_storage.h. */ 660f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov check_CFSI_related_invariants(di); 661f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } else { 662f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(printf)("Can't read NaCl debug info\n"); 663f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(exit)(1); 664f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 665f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#endif // VGO_linux 666f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov return 0; 667f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov} 668f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const * seg; 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* filename; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok, is_rx_map, is_rw_map; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong di_handle; 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes fd; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nread, oflags; 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf1k[1024]; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes statres; 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat statbuf; 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In short, figure out if this mapping is of interest to us, and 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if so, try to guess what ld.so is doing and when/if we should 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read debug info. */ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg = VG_(am_find_nsegment)(a); 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(seg); 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n", 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->start, seg->end, 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' ); 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* guaranteed by aspacemgr-linux.c, sane_NSegment() */ 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(seg->end > seg->start); 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ignore non-file mappings */ 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ! (seg->kind == SkFileC 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (seg->kind == SkFileV && allow_SkFileV)) ) 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If the file doesn't have a name, we're hosed. Give up. */ 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown filename = VG_(am_get_filename)( (NSegment*)seg ); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!filename) 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("di_notify_mmap-2: %s\n", filename); 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Only try to read debug information from regular files. */ 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown statres = VG_(stat)(filename, &statbuf); 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stat dereferences symlinks, so we don't expect it to succeed and 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown yet produce something that is a symlink. */ 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode)); 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Don't let the stat call fail silently. Filter out some known 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sources of noise before complaining, though. */ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(statres)) { 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo fake_di; 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL; 7231b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown#ifdef ANDROID 7241b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown quiet |= VG_(strstr)(filename, "/dev/__properties__") != NULL; 7251b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown#endif 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!quiet && VG_(clo_verbosity) > 1) { 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&fake_di, 0, sizeof(fake_di)); 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fake_di.filename = filename; 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(symerr)(&fake_di, True, "failed to stat64/stat this file"); 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finally, the point of all this stattery: if it's not a regular file, 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't try to read debug info from it. */ 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! VKI_S_ISREG(statbuf.mode)) 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no uses of statbuf below here. */ 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we have to guess if this is a text-like mapping, a data-like 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping, neither or both. The rules are: 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown text if: x86-linux r and x 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown other-linux r and x and not w 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data if: x86-linux r and w 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown other-linux r and w and not x 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Background: On x86-linux, objects are typically mapped twice: 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whereas ppc32-linux mysteriously does this: 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The third mapping should not be considered to have executable 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code in. Therefore a test which works for both is: r and x and 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NOT w. Reading symbols from the rwx segment -- which overlaps 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the r-x segment in the file -- causes the redirection mechanism 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to redirect to addresses in that third segment, which is wrong 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and causes crashes. 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown produce executables with a single rwx segment rather than a 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (r-x,rw-) pair. That means the rules have to be modified thusly: 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86-linux: consider if r and x 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all others: consider if r and x and not w 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2009 Aug 16: apply similar kludge to ppc32-linux. 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See http://bugs.kde.org/show_bug.cgi?id=190820 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rx_map = False; 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rw_map = False; 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_ppc32) 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rx_map = seg->hasR && seg->hasX; 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rw_map = seg->hasR && seg->hasW; 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rx_map = seg->hasR && seg->hasX && !seg->hasW; 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is_rw_map = seg->hasR && seg->hasW && !seg->hasX; 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n", 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)is_rx_map, (Int)is_rw_map); 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If it is neither text-ish nor data-ish, we're not interested. */ 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(is_rx_map || is_rw_map)) 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Peer at the first few bytes of the file, to see if it is an ELF */ 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* object file. Ignore the file if we do not have read permission. */ 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(buf1k, 0, sizeof(buf1k)); 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oflags = VKI_O_RDONLY; 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VKI_O_LARGEFILE) 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oflags |= VKI_O_LARGEFILE; 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd = VG_(open)( filename, oflags, 0 ); 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(fd)) { 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_Err(fd) != VKI_EACCES) { 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo fake_di; 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&fake_di, 0, sizeof(fake_di)); 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fake_di.filename = filename; 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header"); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) ); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)( sr_Res(fd) ); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nread == 0) 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nread < 0) { 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo fake_di; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&fake_di, 0, sizeof(fake_di)); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fake_di.filename = filename; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header"); 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nread > 0 && nread <= sizeof(buf1k) ); 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We're only interested in mappings of object files. */ 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: AIX5 doesn't use this file and so isn't represented here. 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread )) 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ML_(is_macho_object_file)( buf1k, (SizeT)nread )) 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "unknown OS" 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* See if we have a DebugInfo for this filename. If not, 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown create one. */ 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ ); 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di); 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_rx_map) { 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We have a text-like mapping. Note the details. */ 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->have_rx_map) { 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_rx_map = True; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rx_map_avma = a; 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rx_map_size = seg->end + 1 - seg->start; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rx_map_foff = seg->offset; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: complain about a second text-like mapping */ 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_rw_map) { 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We have a data-like mapping. Note the details. */ 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->have_rw_map) { 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_rw_map = True; 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rw_map_avma = a; 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rw_map_size = seg->end + 1 - seg->start; 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rw_map_foff = seg->offset; 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: complain about a second data-like mapping */ 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we don't have an rx and rw mapping, or if we already have 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debuginfo for this mapping for whatever reason, go no 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown further. */ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) ) 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, so, finally, let's try to read the debuginfo. */ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->filename); 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n"); 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("------ start ELF OBJECT " 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "------------------------------\n"); 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("------ name = %s\n", di->filename); 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n"); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We're going to read symbols and debug info for the avma 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ranges [rx_map_avma, +rx_map_size) and [rw_map_avma, 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +rw_map_size). First get rid of any other DebugInfos which 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown overlap either of those ranges (to avoid total confusion). */ 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_DebugInfos_which_overlap_with( di ); 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* .. and acquire new info. */ 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: AIX5 doesn't use this file and so isn't represented here. 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = ML_(read_elf_debug_info)( di ); 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = ML_(read_macho_debug_info)( di ); 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "unknown OS" 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n------ Canonicalising the " 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "acquired info ------\n"); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* invalidate the CFI unwind cache. */ 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* prepare read data for use */ 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(canonicaliseTables)( di ); 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* notify m_redir about it */ 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n------ Notifying m_redir ------\n"); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_notify_new_DebugInfo)( di ); 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that we succeeded */ 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_dinfo = True; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(di->handle > 0); 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di_handle = di->handle; 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check invariants listed in 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown priv_storage.h. */ 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_CFSI_related_invariants(di); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n------ ELF reading failed ------\n"); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Something went wrong (eg. bad ELF file). Should we delete 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this DebugInfo? No - it contains info on the rw/rx 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mappings, at least. */ 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di_handle = 0; 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->have_dinfo == False); 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n"); 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("------ name = %s\n", di->filename); 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("------ end ELF OBJECT " 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "------------------------------\n"); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRACE_SYMTAB("\n"); 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di_handle; 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unmap is simpler - throw away any SegInfos intersecting 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [a, a+len). */ 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(di_notify_munmap)( Addr a, SizeT len ) 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool anyFound; 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len); 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyFound = discard_syms_in_range(a, len); 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (anyFound) 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Uh, this doesn't do anything at all. IIRC glibc (or ld.so, I don't 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown remember) does a bunch of mprotects on itself, and if we follow 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown through here, it causes the debug info for that object to get 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discarded. */ 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot ) 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool exe_ok = toBool(prot & VKI_PROT_EXEC); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exe_ok = exe_ok || toBool(prot & VKI_PROT_READ); 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && !exe_ok) { 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool anyFound = discard_syms_in_range(a, len); 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (anyFound) 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------- PDB (windows debug info) reading --------- */ 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* this should really return ULong, as per VG_(di_notify_mmap). */ 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj, 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT total_size, 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT unknown_purpose__reloc ) 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, r, sz_exename; 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong obj_mtime, pdb_mtime; 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char exename[VKI_PATH_MAX]; 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* pdbname = NULL; 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dot; 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd_pdbimage; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT n_pdbimage; 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat stat_buf; 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 0) { 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "LOAD_PDB_DEBUGINFO(fd=%d, avma=%#lx, total_size=%lu, " 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "uu_reloc=%#lx)\n", 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd_obj, avma_obj, total_size, unknown_purpose__reloc 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 'fd' refers to the .exe/.dll we're dealing with. Get its modification 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown time into obj_mtime. */ 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = VG_(fstat)(fd_obj, &stat_buf); 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (r == -1) 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; /* stat failed ?! */ 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(r == 0); 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obj_mtime = stat_buf.mtime; 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and get its name into exename[]. */ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */ 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(exename, 0, sizeof(exename)); 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* convert exename from a symlink to real name .. overwrites the 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old contents of the buffer. Ick. */ 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 ); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sz_exename == -1) 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; /* readlink failed ?! */ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename)); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(exename[sizeof(exename)-1] == 0); 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 0) { 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try to get the PDB file name from the executable. */ 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname = ML_(find_name_of_pdb_file)(exename); 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pdbname) { 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */ 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So we successfully extracted a name from the PE file. But it's 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown likely to be of the form 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e:\foo\bar\xyzzy\wibble.pdb 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and we need to change it into something we can actually open 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in Wine-world, which basically means turning it into 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We also take into account $WINEPREFIX, if it is set. 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For the moment, if the name isn't fully qualified, just forget it 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (we'd have to root around to find where the pdb actually is) 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Change all the backslashes to forward slashes */ 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; pdbname[i]; i++) { 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pdbname[i] == '\\') 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname[i] = '/'; 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is_quald 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z') 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && pdbname[1] == ':' 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && pdbname[2] == '/'; 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* home = VG_(getenv)("HOME"); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* wpfx = VG_(getenv)("WINEPREFIX"); 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_quald && wpfx) { 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Change e:/foo/bar/xyzzy/wibble.pdb 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/; 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB); 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(mashed, "%s/drive_%c%s", 1050f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov wpfx, VG_(tolower)(pdbname[0]), &pdbname[2]); 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mashed[mashedSzB-1] == 0); 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(pdbname); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname = mashed; 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (is_quald && home && !wpfx) { 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Change e:/foo/bar/xyzzy/wibble.pdb 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/; 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB); 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(mashed, "%s/.wine/drive_%c%s", 1062f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov home, VG_(tolower)(pdbname[0]), &pdbname[2]); 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mashed[mashedSzB-1] == 0); 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(pdbname); 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname = mashed; 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's not a fully qualified path, or neither $HOME nor $WINE 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are set (strange). Give up. */ 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free)(pdbname); 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname = NULL; 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try s/exe/pdb/ if we don't have a valid pdbname. */ 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!pdbname) { 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try to find a matching PDB file from which to read debuginfo. 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Windows PE files have symbol tables and line number information, 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but MSVC doesn't seem to use them. */ 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Why +5 ? Because in the worst case, we could find a dot as the 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last character of pdbname, and we'd then put "pdb" right after 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it, hence extending it a bit. */ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5); 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(pdbname, exename); 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(pdbname[sz_exename+5-1] == 0); 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dot = VG_(strrchr)(pdbname, '.'); 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!dot) 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; /* there's no dot in the exe's name ?! */ 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dot[1] == 0) 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; /* hmm, path ends in "." */ 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ('A' <= dot[1] && dot[1] <= 'Z') 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(dot, ".PDB"); 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(dot, ".pdb"); 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(pdbname[sz_exename+5-1] == 0); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* See if we can find it, and check it's in-dateness. */ 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(stat)(pdbname, &stat_buf); 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n", 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname); 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 0) 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname); 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdb_mtime = stat_buf.mtime; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (obj_mtime > pdb_mtime + 60ULL) { 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* PDB file is older than PE file. Really, the PDB should be 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newer than the PE, but that doesn't always seem to be the 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case. Allow the PDB to be up to one minute older. 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Otherwise, it's probably out of date, in which case ignore it 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or we will either (a) print wrong stack traces or more likely 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (b) crash. 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: %s (mtime = %llu)\n" 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " is older than %s (mtime = %llu)\n", 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbname, pdb_mtime, exename, obj_mtime); 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(open)(pdbname, VKI_O_RDONLY, 0); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Looks promising; go on to try and read stuff from it. */ 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd_pdbimage = sr_Res(sres); 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_pdbimage = stat_buf.size; 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_mmap_file_float_valgrind)( n_pdbimage, VKI_PROT_READ, 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd_pdbimage, 0 ); 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(fd_pdbimage); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto out; 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 0) 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname); 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* play safe; always invalidate the CFI cache. I don't know if 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is necessary, but anyway .. */ 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* dump old info for this range, if any */ 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_syms_in_range( avma_obj, total_size ); 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { void* pdbimage = (void*)sr_Res(sres); 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di = find_or_create_DebugInfo_for(exename, NULL/*membername*/ ); 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this di must be new, since we just nuked any old stuff in the range */ 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di && !di->have_rx_map && !di->have_rw_map); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!di->have_dinfo); 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* don't set up any of the di-> fields; let 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(read_pdb_debug_info) do it. */ 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(read_pdb_debug_info)( di, avma_obj, unknown_purpose__reloc, 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pdbimage, n_pdbimage, pdbname, pdb_mtime ); 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // JRS fixme: take notice of return value from read_pdb_debug_info, 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // and handle failure 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di->have_dinfo); // fails if PDB read failed 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage ); 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(fd_pdbimage); 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out: 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pdbname) ML_(dinfo_free)(pdbname); 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* defined(VGO_linux) || defined(VGO_darwin) */ 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/ 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------*/ 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_aix5) 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The supplied parameters describe a code segment and its associated 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data segment, that have recently been mapped in -- so we need to 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read debug info for it -- or conversely, have recently been dumped, 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in which case the relevant debug info has to be unloaded. */ 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong VG_(di_aix5_notify_segchange)( 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr code_start, 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word code_len, 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_start, 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word data_len, 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* file_name, 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* mem_name, 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is_mainexe, 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool acquire ) 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong hdl = 0; 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* play safe; always invalidate the CFI cache. Not 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that it should be used on AIX, but still .. */ 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi_cache__invalidate(); 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (acquire) { 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = find_or_create_DebugInfo_for( file_name, mem_name ); 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di); 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (code_len > 0) { 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_present = True; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_svma = 0; /* don't know yet */ 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_bias = 0; /* don't know yet */ 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_avma = code_start; 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->text_size = code_len; 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data_len > 0) { 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_present = True; 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_svma = 0; /* don't know yet */ 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_bias = 0; /* don't know yet */ 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_avma = data_start; 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_size = data_len; 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These need to be filled in in order to keep various 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assertions in storage.c happy. In particular see 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Comment_Regarding_Text_Range_Checks" in that file. */ 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_rx_map = True; 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rx_map_avma = code_start; 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rx_map_size = code_len; 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_rw_map = True; 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rw_map_avma = data_start; 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->rw_map_size = data_len; 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = ML_(read_xcoff_debug_info) ( di, is_mainexe ); 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* prepare read data for use */ 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(canonicaliseTables)( di ); 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* notify m_redir about it */ 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_notify_new_DebugInfo)( di ); 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that we succeeded */ 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->have_dinfo = True; 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hdl = di->handle; 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(hdl > 0); 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check invariants listed in 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown priv_storage.h. */ 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_CFSI_related_invariants(di); 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Something went wrong (eg. bad XCOFF file). */ 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_DebugInfo( di ); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = NULL; 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dump all the debugInfos whose text segments intersect 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code_start/code_len. */ 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CFI cache is always invalidated at start of this routine. 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence it's safe to ignore the return value of 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown discard_syms_in_range. */ 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (code_len > 0) 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)discard_syms_in_range( code_start, code_len ); 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hdl; 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* defined(VGO_aix5) */ 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO ---*/ 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(di_discard_ALL_debuginfo)( void ) 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo *di, *di2; 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = debugInfo_list; 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (di) { 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di2 = di->next; 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("XXX rm %p\n", di); 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free_DebugInfo( di ); 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = di2; 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Use of symbol table & location info to create ---*/ 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- plausible-looking stack dumps. ---*/ 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Search all symtabs that we know about to locate ptr. If found, set 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi to the relevant DebugInfo, and *symno to the symtab entry 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *number within that. If not found, *psi is set to NULL. 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If findText==True, only text symbols are searched for. 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If findText==False, only data symbols are searched for. 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi, 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Word* symno, 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool match_anywhere_in_sym, 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool findText ) 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sno; 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool inRange; 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (findText) { 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Consider any symbol in the r-x mapped area to be text. 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See Comment_Regarding_Text_Range_Checks in storage.c for 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown details. */ 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inRange = di->have_rx_map 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->rx_map_size > 0 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->rx_map_avma <= ptr 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->rx_map_avma + di->rx_map_size; 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inRange = (di->data_present 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->data_size > 0 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->data_avma <= ptr 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->data_avma + di->data_size) 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (di->sdata_present 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sdata_size > 0 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sdata_avma <= ptr 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->sdata_avma + di->sdata_size) 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (di->bss_present 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->bss_size > 0 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->bss_avma <= ptr 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->bss_avma + di->bss_size) 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (di->sbss_present 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sbss_size > 0 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sbss_avma <= ptr 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->sbss_avma + di->sbss_size) 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (di->rodata_present 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->rodata_size > 0 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->rodata_avma <= ptr 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->rodata_avma + di->rodata_size); 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!inRange) continue; 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sno = ML_(search_one_symtab) ( 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di, ptr, match_anywhere_in_sym, findText ); 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sno == -1) goto not_found; 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *symno = sno; 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi = di; 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not_found: 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi = NULL; 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Search all loctabs that we know about to locate ptr. If found, set 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi to the relevant DebugInfo, and *locno to the loctab entry 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *number within that. If not found, *pdi is set to NULL. */ 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi, 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Word* locno ) 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word lno; 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_present 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_size > 0 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_avma <= ptr 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ptr < di->text_avma + di->text_size) { 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lno = ML_(search_one_loctab) ( di, ptr ); 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lno == -1) goto not_found; 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *locno = lno; 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi = di; 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not_found: 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pdi = NULL; 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The whole point of this whole big deal: map a code address to a 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown plausible symbol name. Returns False if no idea; otherwise True. 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Caller supplies buf and nbuf. If do_cxx_demangling is False, don't do 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown C++ demangling, regardless of VG_(clo_demangle) -- probably because the 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call has come from VG_(get_fnname_raw)(). findText 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicates whether we're looking for a text symbol or a data symbol 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -- caller must choose one kind or the other. */ 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling, 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool do_below_main_renaming, 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a, Char* buf, Int nbuf, 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool match_anywhere_in_sym, Bool show_offset, 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool findText, /*OUT*/PtrdiffT* offsetP ) 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sno; 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT offset; 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText ); 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di == NULL) 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(demangle) ( do_cxx_demangling, do_z_demangling, 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->symtab[sno].name, buf, nbuf ); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the below-main hack */ 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // To reduce the endless nuisance of multiple different names 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // for "the frame below main()" screwing up the testsuite, change all 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // known incarnations of said into a single name, "(below main)", if 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // --show-below-main=yes. 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( do_below_main_renaming && ! VG_(clo_show_below_main) && 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) ) 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(buf, "(below main)", nbuf); 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset = a - di->symtab[sno].addr; 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (offsetP) *offsetP = offset; 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show_offset && offset != 0) { 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf2[12]; 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* symend = buf + VG_(strlen)(buf); 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* end = buf + nbuf; 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len; 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = VG_(sprintf)(buf2, "%c%ld", 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset < 0 ? '-' : '+', 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset < 0 ? -offset : offset); 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(len < (Int)sizeof(buf2)); 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len < (end - symend)) { 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *cp = buf2; 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)(symend, cp, len+1); 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[nbuf-1] = 0; /* paranoia */ 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ppc64-linux only: find the TOC pointer (R2 value) that should be in 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown force at the entry point address of the function containing 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest_code_addr. Returns 0 if not known. */ 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(get_tocptr) ( Addr guest_code_addr ) 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* si; 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word sno; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown search_all_symtabs ( guest_code_addr, 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &si, &sno, 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True/*match_anywhere_in_fun*/, 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True/*consider text symbols only*/ ); 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (si == NULL) 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return si->symtab[sno].tocptr; 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is available to tools... always demangle C++ names, 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown match anywhere in function, but don't show offsets. */ 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf ) 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True, 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/True, 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, buf, nbuf, 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_fun*/True, 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/False, 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*text syms only*/True, 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*offsetP*/NULL ); 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is available to tools... always demangle C++ names, 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown match anywhere in function, and show offset if nonzero. */ 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf ) 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True, 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/True, 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, buf, nbuf, 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_fun*/True, 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/True, 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*text syms only*/True, 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*offsetP*/NULL ); 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is available to tools... always demangle C++ names, 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown only succeed if 'a' matches first instruction of function, 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and don't show offsets. */ 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf ) 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True, 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/True, 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, buf, nbuf, 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_fun*/False, 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/False, 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*text syms only*/True, 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*offsetP*/NULL ); 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is only available to core... don't C++-demangle, don't Z-demangle, 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't rename below-main, match anywhere in function, and don't show 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offsets. */ 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf ) 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False, 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/False, 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, buf, nbuf, 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_fun*/True, 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/False, 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*text syms only*/True, 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*offsetP*/NULL ); 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is only available to core... don't demangle C++ names, but do 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do Z-demangling and below-main-renaming, match anywhere in function, and 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't show offsets. */ 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf ) 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True, 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/True, 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, buf, nbuf, 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_fun*/True, 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/False, 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*text syms only*/True, 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*offsetP*/NULL ); 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVg_FnNameKind VG_(get_fnname_kind) ( Char* name ) 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_STREQ("main", name)) { 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Vg_FnNameMain; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_STREQ("__libc_start_main", name) || // glibc glibness 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_STREQ("generic_start_main", name) || // Yellow Dog doggedness 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_aix5) 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_STREQ("__start", name) || // AIX aches 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // See readmacho.c for an explanation of this. 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_STREQ("start_according_to_valgrind", name) || // Darwin, darling 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0) { 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Vg_FnNameBelowMain; 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Vg_FnNameNormal; 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip ) 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We don't need a big buffer; all the special names are small. 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown #define BUFLEN 50 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf[50]; 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We don't demangle, because it's faster not to, and the special names 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // we're looking for won't be demangled. 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) { 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[BUFLEN-1] = '\0'; // paranoia 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(get_fnname_kind)(buf); 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Vg_FnNameNormal; // Don't know the name, treat it as normal. 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Looks up data_addr in the collection of data symbols, and if found 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown puts its name (or as much as will fit) into dname[0 .. n_dname-1], 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which is guaranteed to be zero terminated. Also data_addr's offset 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from the symbol start is put into *offset. */ 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_datasym_and_offset)( Addr data_addr, 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Char* dname, Int n_dname, 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/PtrdiffT* offset ) 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_dname > 1); 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False, 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*below-main-renaming*/False, 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, dname, n_dname, 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*match_anywhere_in_sym*/True, 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*show offset?*/False, 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*data syms only please*/False, 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset ); 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dname[n_dname-1] = 0; 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a code address to the name of a shared object file or the 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable. Returns False if no idea; otherwise True. Doesn't 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown require debug info. Caller supplies buf and nbuf. */ 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf ) 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int used; 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const NSegment *seg; 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* filename; 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(nbuf > 0); 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Look in the debugInfo_list to find the name. In most cases we 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expect this to produce a result. */ 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_present 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_size > 0 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_avma <= a 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a < di->text_avma + di->text_size) { 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(buf, di->filename, nbuf); 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->memname) { 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used = VG_(strlen)(buf); 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (used < nbuf) 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(&buf[used], "(", nbuf-used); 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used = VG_(strlen)(buf); 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (used < nbuf) 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used); 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used = VG_(strlen)(buf); 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (used < nbuf) 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(&buf[used], ")", nbuf-used); 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[nbuf-1] = 0; 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Last-ditch fallback position: if we don't find the address in 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the debugInfo_list, ask the address space manager whether it 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown knows the name of the file associated with this mapping. This 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allows us to print the names of exe/dll files in the stack trace 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when running programs under wine. */ 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (seg = VG_(am_find_nsegment(a))) != NULL 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (filename = VG_(am_get_filename)(seg)) != NULL ) { 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(buf, filename, nbuf); 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a code address to its DebugInfo. Returns NULL if not found. Doesn't 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown require debug info. */ 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDebugInfo* VG_(find_DebugInfo) ( Addr a ) 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_search = 0; 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search++; 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_present 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_size > 0 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_avma <= a 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a < di->text_avma + di->text_size) { 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == (n_search & 0xF)) 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move_DebugInfo_one_step_forward( di ); 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di; 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a code address to a filename. Returns True if successful. */ 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_filename)( Addr a, Char* filename, Int n_filename ) 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* si; 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word locno; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown search_all_loctabs ( a, &si, &locno ); 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (si == NULL) 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename); 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a code address to a line number. Returns True if successful. */ 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_linenum)( Addr a, UInt* lineno ) 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* si; 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word locno; 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown search_all_loctabs ( a, &si, &locno ); 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (si == NULL) 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *lineno = si->loctab[locno].lineno; 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a code address to a filename/line number/dir name info. 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See prototype for detailed description of behaviour. 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_filename_linenum) ( Addr a, 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Char* filename, Int n_filename, 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Char* dirname, Int n_dirname, 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Bool* dirname_available, 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/UInt* lineno ) 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* si; 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word locno; 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( (dirname == NULL && dirname_available == NULL) 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (dirname != NULL && dirname_available != NULL) ); 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown search_all_loctabs ( a, &si, &locno ); 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (si == NULL) { 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dirname_available) { 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dirname_available = False; 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dirname = 0; 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename); 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *lineno = si->loctab[locno].lineno; 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dirname) { 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* caller wants directory info too .. */ 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_dirname > 0); 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (si->loctab[locno].dirname) { 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* .. and we have some */ 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dirname_available = True; 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(dirname, si->loctab[locno].dirname, 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_dirname); 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* .. but we don't have any */ 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dirname_available = False; 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dirname = 0; 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a function name to its entry point and toc pointer. Is done by 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sequential search of all symbol tables, so is very slow. To 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mitigate the worst performance effects, you may specify a soname 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern, and only objects matching that pattern are searched. 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore specify "*" to search all the objects. On TOC-afflicted 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platforms, a symbol is deemed to be found only if it has a nonzero 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TOC pointer. */ 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name, 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr* pEnt, Addr* pToc) 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool require_pToc = False; 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* si; 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown require_pToc = True; 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (si = debugInfo_list; si; si = si->next) { 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname); 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(string_match)(sopatt, si->soname)) { 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" ... skip\n"); 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < si->symtab_used; i++) { 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)(name, si->symtab[i].name) 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (require_pToc ? si->symtab[i].tocptr : True)) { 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pEnt = si->symtab[i].addr; 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *pToc = si->symtab[i].tocptr; 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VG_(describe_IP): print into buf info on code address, function 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name and filename. */ 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy str into buf starting at n, but not going past buf[n_buf-1] 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and always ensuring that buf is zero-terminated. */ 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str ) 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_buf > 0); 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n >= 0 && n < n_buf); 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; n < n_buf-1 && *str != 0; n++,str++) 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[n] = *str; 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n >= 0 && n < n_buf); 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[n] = '\0'; 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return n; 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same as putStr, but escaping chars for XML output, and 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown also not adding more than count chars to n_buf. */ 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str ) 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char alt[2]; 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_buf > 0); 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count >= 0 && count < n_buf); 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n >= 0 && n < n_buf); 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; *str != 0; str++) { 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count >= 0); 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (count <= 0) 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto done; 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (*str) { 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case '&': 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (count < 5) goto done; 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStr( n, n_buf, buf, "&"); 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count -= 5; 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case '<': 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (count < 4) goto done; 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStr( n, n_buf, buf, "<"); 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count -= 4; 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case '>': 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (count < 4) goto done; 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStr( n, n_buf, buf, ">"); 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count -= 4; 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (count < 1) goto done; 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alt[0] = *str; 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alt[1] = 0; 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStr( n, n_buf, buf, alt ); 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count -= 1; 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done: 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count >= 0); /* should not go -ve in loop */ 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n >= 0 && n < n_buf); 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return n; 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf) 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define APPEND(_str) \ 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStr(n, n_buf, buf, _str) 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define APPEND_ESC(_count,_str) \ 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = putStrEsc(n, n_buf, (_count), buf, (_str)) 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define BUF_LEN 4096 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lineno; 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar ibuf[50]; 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n = 0; 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UChar buf_fn[BUF_LEN]; 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UChar buf_obj[BUF_LEN]; 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UChar buf_srcloc[BUF_LEN]; 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UChar buf_dirname[BUF_LEN]; 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0; 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool know_dirinfo = False; 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool know_fnname = VG_(clo_sym_offsets) 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN) 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : VG_(get_fnname) (eip, buf_fn, BUF_LEN); 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN); 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool know_srcloc = VG_(get_filename_linenum)( 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eip, 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_srcloc, BUF_LEN, 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_dirname, BUF_LEN, &know_dirinfo, 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &lineno 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_fn [ sizeof(buf_fn)-1 ] = 0; 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_obj [ sizeof(buf_obj)-1 ] = 0; 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_srcloc [ sizeof(buf_srcloc)-1 ] = 0; 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_dirname[ sizeof(buf_dirname)-1 ] = 0; 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_xml)) { 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool human_readable = True; 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* maybe_newline = human_readable ? "\n " : ""; 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* maybe_newline2 = human_readable ? "\n " : ""; 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print in XML format, dumping in as much info as we know. 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ensure all tags are balanced even if the individual strings 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are too long. Allocate 1/10 of BUF_LEN to the object name, 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6/10s to the function name, 1/10 to the directory name and 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1/10 to the file name, leaving 1/10 for all the fixed-length 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stuff. */ 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<frame>"); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip); 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(ibuf); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_objname) { 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<obj>"); 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND_ESC(1*BUF_LEN/10, buf_obj); 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</obj>"); 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_fnname) { 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<fn>"); 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND_ESC(6*BUF_LEN/10, buf_fn); 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</fn>"); 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_srcloc) { 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_dirinfo) { 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<dir>"); 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND_ESC(1*BUF_LEN/10, buf_dirname); 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</dir>"); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<file>"); 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND_ESC(1*BUF_LEN/10, buf_srcloc); 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</file>"); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("<line>"); 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(ibuf,"%d",lineno); 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(ibuf); 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</line>"); 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(maybe_newline2); 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("</frame>"); 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Print for humans to read */ 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Possible forms: 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: really (a.c:20) 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: really (in /foo/a.out) 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: really (in ???) 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: ??? (in /foo/a.out) 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: ??? (a.c:20) 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 0x80483BF: ??? 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip); 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(ibuf); 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_fnname) { 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(buf_fn); 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("???"); 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (know_srcloc) { 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(" ("); 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Get the directory name, if any, possibly pruned, into dirname. 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* dirname = NULL; 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_n_fullpath_after) > 0) { 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dirname = buf_dirname; 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Remove leading prefixes from the dirname. 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If user supplied --fullpath-after=foo, this will remove 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // a leading string which matches '.*foo' (not greedy). 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(clo_n_fullpath_after); i++) { 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* prefix = VG_(clo_fullpath_after)[i]; 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* str = VG_(strstr)(dirname, prefix); 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (str) { 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dirname = str + VG_(strlen)(prefix); 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* remove leading "./" */ 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dirname[0] == '.' && dirname[1] == '/') 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dirname += 2; 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do we have any interesting directory name to show? If so 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // add it in. 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dirname && dirname[0] != 0) { 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(dirname); 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND("/"); 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(buf_srcloc); 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(":"); 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(ibuf,"%d",lineno); 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(ibuf); 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(")"); 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (know_objname) { 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(" (in "); 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(buf_obj); 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(")"); 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (know_fnname) { 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: do this in two steps because "??)" is a trigraph! 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(" (in ???"); 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown APPEND(")"); 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef APPEND 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef APPEND_ESC 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef BUF_LEN 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: FOR UNWINDING THE STACK USING ---*/ 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- DWARF3 .eh_frame INFO ---*/ 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Gather up all the constant pieces of info needed to evaluate 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a CfiExpr into one convenient struct. */ 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown D3UnwindRegs* uregs; 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr min_accessible; 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr max_accessible; 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CfiExprEvalContext; 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Evaluate the CfiExpr rooted at ix in exprs given the context eec. 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ok is set to False on failure, but not to True on success. The 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller must set it to True before calling. */ 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord evalCfiExpr ( XArray* exprs, Int ix, 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CfiExprEvalContext* eec, Bool* ok ) 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord wL, wR; 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a; 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CfiExpr* e; 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(Addr) == sizeof(UWord)); 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e = VG_(indexXA)( exprs, ix ); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cex_Binop: 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok ); 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(*ok)) return 0; 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok ); 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(*ok)) return 0; 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Cex.Binop.op) { 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cop_Add: return wL + wR; 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cop_Sub: return wL - wR; 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cop_And: return wL & wR; 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cop_Mul: return wL * wR; 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: goto unhandled; 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cex_CfiReg: 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Cex.CfiReg.reg) { 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_amd64) 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_IA_IP: return eec->uregs->xip; 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_IA_SP: return eec->uregs->xsp; 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_IA_BP: return eec->uregs->xbp; 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_arm) 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_ARM_R15: return eec->uregs->r15; 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_ARM_R14: return eec->uregs->r14; 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_ARM_R13: return eec->uregs->r13; 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Creg_ARM_R12: return eec->uregs->r12; 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_ppc32) || defined(VGA_ppc64) 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported arch" 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: goto unhandled; 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cex_Const: 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return e->Cex.Const.con; 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Cex_Deref: 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok ); 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(*ok)) return 0; 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a < eec->min_accessible 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (a + sizeof(UWord) - 1) > eec->max_accessible) { 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ok = False; 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* let's hope it doesn't trap! */ 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return * ((UWord*)a); 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto unhandled; 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled: 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n\nevalCfiExpr: unhandled\n"); 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(ppCfiExpr)( exprs, ix ); 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Search all the DebugInfos in the entire system, to find the DiCfSI 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that pertains to 'ip'. 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If found, set *diP to the DebugInfo in which it resides, and 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ixP to the index in that DebugInfo's cfsi array. 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If not found, set *diP to (DebugInfo*)1 and *ixP to zero. 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP, 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Word* ixP, 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip ) 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i = -1; 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_search = 0; 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_steps = 0; 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search++; 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("search for %#lx\n", ip); 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word j; 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_steps++; 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Use the per-DebugInfo summary address ranges to skip 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inapplicable DebugInfos quickly. */ 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->cfsi_used == 0) 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma) 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It might be in this DebugInfo. Search it. */ 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = ML_(search_one_cfitab)( di, ip ); 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(j >= -1 && j < (Word)di->cfsi_used); 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j != -1) { 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = j; 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* found it */ 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i == -1) { 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we didn't find it. */ 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *diP = (DebugInfo*)1; 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ixP = 0; 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* found it. */ 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ensure that di is 4-aligned (at least), so it can't possibly 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be equal to (DebugInfo*)1. */ 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di && VG_IS_4_ALIGNED(di)); 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i >= 0 && i < di->cfsi_used); 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *diP = di; 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ixP = i; 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start of performance-enhancing hack: once every 64 (chosen 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hackily after profiling) successful searches, move the found 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo one step closer to the start of the list. This 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown makes future searches cheaper. For starting konqueror on 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64, this in fact reduces the total amount of searching 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done by the above find-the-right-DebugInfo loop by more than 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a factor of 20. */ 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((n_search & 0xF) == 0) { 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move di one step closer to the start of the list. */ 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move_DebugInfo_one_step_forward( di ); 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* End of performance-enhancing hack. */ 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && ((n_search & 0x7FFFF) == 0)) 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("find_DiCfSI: %lu searches, " 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%lu DebugInfos looked at\n", 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search, n_steps); 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Now follows a mechanism for caching queries to find_DiCfSI, since 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they are extremely frequent on amd64-linux, during stack unwinding. 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Each cache entry binds an ip value to a (di, ix) pair. Possible 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values: 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di is non-null, ix >= 0 ==> cache slot in use, "di->cfsi[ix]" 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di is (DebugInfo*)1 ==> cache slot in use, no associated di 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di is NULL ==> cache slot not in use 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence simply zeroing out the entire cache invalidates all 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entries. 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Why not map ip values directly to DiCfSI*'s? Because this would 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cause problems if/when the cfsi array is moved due to resizing. 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Instead we cache .cfsi array index value, which should be invariant 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown across resizing. (That said, I don't think the current 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implementation will resize whilst during queries, since the DiCfSI 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown records are added all at once, when the debuginfo for an object is 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read, and is not changed ever thereafter. */ 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_CFSI_CACHE 511 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { Addr ip; DebugInfo* di; Word ix; } 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CFSICacheEnt; 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE]; 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cfsi_cache__invalidate ( void ) { 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache)); 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline CFSICacheEnt* cfsi_cache__find ( Addr ip ) 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord hash = ip % N_CFSI_CACHE; 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CFSICacheEnt* ce = &cfsi_cache[hash]; 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_q = 0, n_m = 0; 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_q++; 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && 0 == (n_q & 0x1FFFFF)) 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQ %lu %lu\n", n_q, n_m); 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) { 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* found an entry in the cache .. */ 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* not found in cache. Search and update. */ 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_m++; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ce->ip = ip; 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown find_DiCfSI( &ce->di, &ce->ix, ip ); 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(ce->di == (DebugInfo*)1)) { 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no DiCfSI for this address */ 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* found a DiCfSI for this address */ 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ce; 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr compute_cfa ( D3UnwindRegs* uregs, 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr min_accessible, Addr max_accessible, 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di, DiCfSI* cfsi ) 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CfiExprEvalContext eec; 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr cfa; 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compute the CFA. */ 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = 0; 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (cfsi->cfa_how) { 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_amd64) 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_IA_SPREL: 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->xsp; 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_IA_BPREL: 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->xbp; 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_arm) 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_ARM_R13REL: 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->r13; 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_ARM_R12REL: 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->r12; 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_ARM_R11REL: 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->r11; 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_ARM_R7REL: 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = cfsi->cfa_off + uregs->r7; 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_ppc32) || defined(VGA_ppc64) 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported arch" 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIC_EXPR: /* available on all archs */ 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("CFIC_EXPR: "); 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off); 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.uregs = uregs; 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.min_accessible = min_accessible; 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.max_accessible = max_accessible; 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = True; 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok ); 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) return 0; 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cfa; 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get the call frame address (CFA) given an IP/SP/FP triple. */ 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: This function may rearrange the order of entries in the 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo list. */ 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp, 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr min_accessible, Addr max_accessible ) 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CFSICacheEnt* ce; 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiCfSI* cfsi; 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ce = cfsi_cache__find(ip); 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(ce == NULL)) 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; /* no info. Nothing we can do. */ 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = ce->di; 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi = &di->cfsi[ ce->ix ]; 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Temporary impedance-matching kludge so that this keeps working 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown on x86-linux and amd64-linux. */ 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_amd64) 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { D3UnwindRegs uregs; 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uregs.xip = ip; 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uregs.xsp = sp; 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uregs.xbp = fp; 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return compute_cfa(&uregs, 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown min_accessible, max_accessible, di, cfsi); 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; /* indicates failure */ 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main function for DWARF2/3 CFI-based stack unwinding. Given a 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set of registers in UREGS, modify it to hold the register values 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the previous frame, if possible. Returns True if successful. 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If not successful, *UREGS is not changed. 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For x86 and amd64, the unwound registers are: {E,R}IP, 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown {E,R}SP, {E,R}BP. 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For arm, the unwound registers are: R7 R11 R12 R13 R14 R15. 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere, 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr min_accessible, 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr max_accessible ) 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiCfSI* cfsi = NULL; 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr cfa, ipHere = 0; 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CFSICacheEnt* ce; 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CfiExprEvalContext eec; 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown D3UnwindRegs uregsPrev; 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_amd64) 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipHere = uregsHere->xip; 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_arm) 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipHere = uregsHere->r15; 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_ppc32) || defined(VGA_ppc64) 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ce = cfsi_cache__find(ipHere); 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(ce == NULL)) 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* no info. Nothing we can do. */ 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di = ce->di; 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfsi = &di->cfsi[ ce->ix ]; 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("found cfisi: "); 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(ppDiCfSI)(di->cfsi_exprs, cfsi); 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev)); 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First compute the CFA. */ 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cfa = compute_cfa(uregsHere, 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown min_accessible, max_accessible, di, cfsi); 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(cfa == 0)) 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we know the CFA, use it to roll back the registers we're 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interested in. */ 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define COMPUTE(_prev, _here, _how, _off) \ 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (_how) { \ 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIR_UNKNOWN: \ 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; \ 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIR_SAME: \ 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _prev = _here; break; \ 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIR_MEMCFAREL: { \ 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a = cfa + (Word)_off; \ 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a < min_accessible \ 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || a > max_accessible-sizeof(Addr)) \ 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; \ 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _prev = *(Addr*)a; \ 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIR_CFAREL: \ 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _prev = cfa + (Word)_off; \ 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case CFIR_EXPR: \ 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) \ 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(ppCfiExpr)(di->cfsi_exprs,_off); \ 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.uregs = uregsHere; \ 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.min_accessible = min_accessible; \ 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown eec.max_accessible = max_accessible; \ 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = True; \ 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \ 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) return False; \ 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: \ 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); \ 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_x86) || defined(VGA_amd64) 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off); 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off); 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off); 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_arm) 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how, cfsi->ra_off); 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off); 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off); 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off); 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown COMPUTE(uregsPrev.r7, uregsHere->r7, cfsi->r7_how, cfsi->r7_off); 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGA_ppc32) || defined(VGA_ppc64) 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef COMPUTE 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *uregsHere = uregsPrev; 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: FOR UNWINDING THE STACK USING ---*/ 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- MSVC FPO INFO ---*/ 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP, 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/Addr* spP, 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/Addr* fpP, 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr min_accessible, 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr max_accessible ) 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i; 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FPO_DATA* fpo = NULL; 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr spHere; 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_search = 0; 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UWord n_steps = 0; 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search++; 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("search FPO for %#lx\n", *ipP); 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_steps++; 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Use the per-DebugInfo summary address ranges to skip 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inapplicable DebugInfos quickly. */ 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->fpo == NULL) 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma) 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = ML_(search_one_fpotab)( di, *ipP ); 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i != -1) { 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word j; 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* debug printing only */ 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("look for %#lx size %ld i %ld\n", 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ipP, di->fpo_size, i); 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < di->fpo_size; j++) 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("[%02ld] %#x %d\n", 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize); 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i >= 0 && i < di->fpo_size); 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpo = &di->fpo[i]; 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fpo == NULL) 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && ((n_search & 0x7FFFF) == 0)) 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VG_(use_FPO_info): %lu searches, " 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%lu DebugInfos looked at\n", 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search, n_steps); 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start of performance-enhancing hack: once every 64 (chosen 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hackily after profiling) successful searches, move the found 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo one step closer to the start of the list. This makes 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown future searches cheaper. For starting konqueror on amd64, this 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in fact reduces the total amount of searching done by the above 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown find-the-right-DebugInfo loop by more than a factor of 20. */ 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((n_search & 0x3F) == 0) { 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move si one step closer to the start of the list. */ 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //move_DebugInfo_one_step_forward( di ); 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* End of performance-enhancing hack. */ 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("found fpo: "); 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //ML_(ppFPO)(fpo); 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Stack layout is: 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %esp-> 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4*.cbRegs {%edi, %esi, %ebp, %ebx} 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4*.cdwLocals 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return_pc 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4*.cdwParams 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prior_%esp-> 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Typical code looks like: 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sub $4*.cdwLocals,%esp 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Alternative to above for >=4KB (and sometimes for smaller): 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mov $size,%eax 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call __chkstk # WinNT performs page-by-page probe! 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __chkstk is much like alloc(), except that on return 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %eax= 5+ &CALL. Thus it could be used as part of 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Position Independent Code to locate the Global Offset Table. 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push %ebx 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push %ebp 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push %esi 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Other once-only instructions often scheduled >here<. 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push %edi 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If the pc is within the first .cbProlog bytes of the function, 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then you must disassemble to see how many registers have been pushed, 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because instructions in the prolog may be scheduled for performance. 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown registers not pushed when .cbRegs < 4. This seems somewhat strange 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because %ebp is the register whose usage you want to minimize, 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown yet it is in the first half of the PUSH list. 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I don't know what happens when the compiler constructs an outgoing CALL. 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %esp could move if outgoing parameters are PUSHed, and this affects 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown traceback for errors during the PUSHes. */ 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spHere = *spP; 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ipP = *(Addr *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)); 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *spP = spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + fpo->cdwParams); 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *fpP = *(Addr *)(spHere + 4*2); 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES ---*/ 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- FROM DWARF3 DEBUG INFO ---*/ 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------*/ 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Try to make p2XA(dst, fmt, args..) turn into 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(xaprintf_no_f_c)(dst, fmt, args) without having to resort to 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vararg macros. As usual with everything to do with varargs, it's 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an ugly hack. 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //#define p2XA(dstxa, format, args...) 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(xaprintf_no_f_c)(dstxa, format, ##args) 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define p2XA VG_(xaprintf_no_f_c) 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a zero-terminating byte to DST, which must be an XArray* of 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar. */ 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void zterm_XA ( XArray* dst ) 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar zero = 0; 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void) VG_(addBytesToXA)( dst, &zero, 1 ); 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Evaluate the location expression/list for var, to see whether or 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not data_addr falls within the variable. If so also return the 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset of data_addr from the start of the variable. Note that 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs, which supplies ip,sp,fp values, will be NULL for global 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown variables, and non-NULL for local variables. */ 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset, 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* /* TyEnt */ tyents, 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var, 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RegSummary* regs, 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr, 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const DebugInfo* di ) 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MaybeULong mul; 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT var_szB; 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GXResult res; 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool show = False; 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(var->name); 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(var->gexpr); 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out how big the variable is. */ 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mul = ML_(sizeOfType)(tyents, var->typeR); 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this var has a type whose size is unknown, zero, or 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown impossibly large, it should never have been added. ML_(addVar) 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should have rejected it. */ 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.b == True); 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.ul > 0); 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32)); 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* After this point, we assume we can truncate mul.ul to a host word 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown safely (without loss of info). */ 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var_szB = (SizeT)mul.ul; /* NB: truncate to host word */ 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show) { 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ", 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var->name ); 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(pp_TyEnt_C_ishly)( tyents, var->typeR ); 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ignore zero-sized vars; they can never match anything. */ 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (var_szB == 0) { 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show) 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VVVV: -> Fail (variable is zero sized)\n"); 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di ); 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show) { 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VVVV: -> "); 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(pp_GXResult)( res ); 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res.kind == GXR_Addr 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && res.word <= data_addr 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && data_addr < res.word + var_szB) { 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *offset = data_addr - res.word; 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Format the acquired information into DN(AME)1 and DN(AME)2, which 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are XArray*s of HChar, that have been initialised by the caller. 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Resulting strings will be zero terminated. Information is 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown formatted in an understandable way. Not so easy. If frameNo is 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -1, this is assumed to be a global variable; else a local 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown variable. */ 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1, 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/XArray* /* of HChar */ dn2, 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr, 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var, 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT var_offset, 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT residual_offset, 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* /*UChar*/ described, 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int frameNo, 2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid ) 2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool have_descr, have_srcloc; 2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool xml = VG_(clo_xml); 2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* vo_plural = var_offset == 1 ? "" : "s"; 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* ro_plural = residual_offset == 1 ? "" : "s"; 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* basetag = "auxwhat"; /* a constant */ 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar tagL[32], tagR[32], xagL[32], xagR[32]; 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(frameNo >= -1); 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(dn1 && dn2); 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(described); 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(var && var->name); 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have_descr = VG_(sizeXA)(described) > 0 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && *(UChar*)VG_(indexXA)(described,0) != '\0'; 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have_srcloc = var->fileName && var->lineNo > 0; 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0; 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(tagL, "<%s>", basetag); // <auxwhat> 2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(tagR, "</%s>", basetag); // </auxwhat> 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(xagL, "<x%s>", basetag); // <xauxwhat> 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat> 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define TAGL(_xa) p2XA(_xa, "%s", tagL) 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define TAGR(_xa) p2XA(_xa, "%s", tagR) 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define XAGL(_xa) p2XA(_xa, "%s", xagL) 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define XAGR(_xa) p2XA(_xa, "%s", xagR) 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define TXTL(_xa) p2XA(_xa, "%s", "<text>") 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define TXTR(_xa) p2XA(_xa, "%s", "</text>") 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------ local cases ------ */ 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) { 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no srcloc, no description: 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 543 bytes inside local var "a", 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in frame #1 of thread 1 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside local var \"%t\",", 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn2 ); 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "in frame #%d of thread %d", frameNo, (Int)tid ); 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn2 ); 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside local var \"%s\",", 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "in frame #%d of thread %d", frameNo, (Int)tid ); 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= 0 && have_srcloc && (!have_descr) ) { 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no description: 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 543 bytes inside local var "a" 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown declared at dsyms7.c:17, in frame #1 of thread 1 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside local var \"%t\"", 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGL( dn2 ); 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTL( dn2 ); 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %t:%d, in frame #%d of thread %d", 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo, frameNo, (Int)tid ); 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTR( dn2 ); 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: also do <dir> 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " <file>%t</file> <line>%d</line> ", 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo ); 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGR( dn2 ); 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside local var \"%s\"", 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %s:%d, in frame #%d of thread %d", 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo, frameNo, (Int)tid ); 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= 0 && (!have_srcloc) && have_descr ) { 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no srcloc: 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in frame #1 of thread 1 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %t%t", 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn2 ); 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "in frame #%d of thread %d", frameNo, (Int)tid ); 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn2 ); 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %s%s", 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "in frame #%d of thread %d", frameNo, (Int)tid ); 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= 0 && have_srcloc && have_descr ) { 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2, 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown declared at dsyms7.c:17, in frame #1 of thread 1 */ 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %t%t,", 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGL( dn2 ); 2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTL( dn2 ); 2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %t:%d, in frame #%d of thread %d", 2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo, frameNo, (Int)tid ); 2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTR( dn2 ); 2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: also do <dir> 2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " <file>%t</file> <line>%d</line> ", 2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo ); 2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGR( dn2 ); 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %s%s,", 2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %s:%d, in frame #%d of thread %d", 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo, frameNo, (Int)tid ); 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------ global cases ------ */ 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) { 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no srcloc, no description: 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 543 bytes inside global var "a" 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside global var \"%t\"", 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside global var \"%s\"", 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= -1 && have_srcloc && (!have_descr) ) { 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no description: 2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 543 bytes inside global var "a" 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown declared at dsyms7.c:17 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside global var \"%t\"", 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGL( dn2 ); 2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTL( dn2 ); 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %t:%d", 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo); 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTR( dn2 ); 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: also do <dir> 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " <file>%t</file> <line>%d</line> ", 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo ); 2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGR( dn2 ); 2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside global var \"%s\"", 2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var_offset, vo_plural, var->name ); 2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "declared at %s:%d", 2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo); 2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= -1 && (!have_srcloc) && have_descr ) { 2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no srcloc: 2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2, 2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a global variable 2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %t%t,", 2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn2 ); 2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a global variable"); 2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn2 ); 2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %s%s,", 2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (char*)(VG_(indexXA)(described,0)) ); 2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a global variable"); 2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( frameNo >= -1 && have_srcloc && have_descr ) { 2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2, 2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a global variable declared at dsyms7.c:17 */ 2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGL( dn1 ); 2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %t%t,", 2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TAGR( dn1 ); 2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGL( dn2 ); 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTL( dn2 ); 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a global variable declared at %t:%d", 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo); 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TXTR( dn2 ); 2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: also do <dir> 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " <file>%t</file> <line>%d</line> ", 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo ); 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XAGR( dn2 ); 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn1, 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Location 0x%lx is %lu byte%s inside %s%s,", 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, residual_offset, ro_plural, var->name, 2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (HChar*)(VG_(indexXA)(described,0)) ); 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p2XA( dn2, 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a global variable declared at %s:%d", 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName, var->lineNo); 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Zero terminate both strings */ 2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dn1 ); 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dn2 ); 2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef TAGL 2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef TAGR 2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef XAGL 2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef XAGR 2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef TXTL 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef TXTR 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Determine if data_addr is a local variable in the frame 2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown characterised by (ip,sp,fp), and if so write its description at the 2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ends of DNAME{1,2}, which are XArray*s of HChar, that have been 2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown initialised by the caller, zero terminate both, and return True. 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If it's not a local variable in said frame, return False. */ 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1, 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/XArray* /* of HChar */ dname2, 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr, 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip, Addr sp, Addr fp, 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shown to user: */ 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid, Int frameNo ) 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i; 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RegSummary regs; 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt n_search = 0; 2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt n_steps = 0; 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search++; 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp); 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first, find the DebugInfo that pertains to 'ip'. */ 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di; di = di->next) { 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_steps++; 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* text segment missing? unlikely, but handle it .. */ 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->text_present || di->text_size == 0) 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok. So does this text mapping bracket the ip? */ 2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_avma <= ip && ip < di->text_avma + di->text_size) 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Didn't find it. Strange -- means ip is a code address outside 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of any mapped text segment. Unlikely but not impossible -- app 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could be generating code to run. */ 2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di) 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && ((n_search & 0x1) == 0)) 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("consider_vars_in_frame: %u searches, " 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%u DebugInfos looked at\n", 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search, n_steps); 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start of performance-enhancing hack: once every ??? (chosen 2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hackily after profiling) successful searches, move the found 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo one step closer to the start of the list. This makes 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown future searches cheaper. */ 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((n_search & 0xFFFF) == 0) { 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move si one step closer to the start of the list. */ 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move_DebugInfo_one_step_forward( di ); 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* End of performance-enhancing hack. */ 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* any var info at all? */ 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->varinfo) 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Work through the scopes from most deeply nested outwards, 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown looking for code address ranges that bracket 'ip'. The 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown variables on each such address range found are in scope right 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now. Don't descend to level zero as that is the global 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scope. */ 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = sp; 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = fp; 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* "for each scope, working outwards ..." */ 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) { 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* vars; 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word j; 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiAddrRange* arange; 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* this_scope 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = *(OSet**)VG_(indexXA)( di->varinfo, i ); 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: considering scope %ld\n", (Word)i); 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!this_scope) 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the set of variables in this scope that 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bracket the program counter. */ 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arange = VG_(OSetGen_LookupWithCmp)( 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this_scope, &ip, 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(cmp_for_DiAddrRange_range) 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!arange) 3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stay sane */ 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arange->aMin <= arange->aMax); 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It must bracket the ip we asked for, else 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(cmp_for_DiAddrRange_range) is somehow broken. */ 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arange->aMin <= ip && ip <= arange->aMax); 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It must have an attached XArray of DiVariables. */ 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vars = arange->vars; 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(vars); 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But it mustn't cover the entire address range. We only 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expect that to happen for the global scope (level 0), which 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we're not looking at here. Except, it may cover the entire 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address range, but in that case the vars array must be 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown empty. */ 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(! (arange->aMin == (Addr)0 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && arange->aMax == ~(Addr)0 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(sizeXA)(vars) > 0) ); 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < VG_(sizeXA)( vars ); j++) { 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j ); 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT offset; 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: var:name=%s %#lx-%#lx %#lx\n", 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->name,arange->aMin,arange->aMax,ip); 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data_address_is_in_var( &offset, di->admin_tyents, 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var, ®s, 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, di )) { 3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT residual_offset = 0; 3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* described = ML_(describe_type)( &residual_offset, 3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->admin_tyents, 3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->typeR, offset ); 3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown format_message( dname1, dname2, 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var, offset, residual_offset, 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown described, frameNo, tid ); 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)( described ); 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Try to form some description of DATA_ADDR by looking at the DWARF3 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown debug info we have. This considers all global variables, and all 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frames in the stacks of all threads. Result is written at the ends 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of DNAME{1,2}V, which are XArray*s of HChar, that have been 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown initialised by the caller, and True is returned. If no description 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is created, False is returned. Regardless of the return value, 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DNAME{1,2}V are guaranteed to be zero terminated after the call. 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that after the call, DNAME{1,2} may have more than one 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trailing zero, so callers should establish the useful text length 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown using VG_(strlen) on the contents, rather than VG_(sizeXA) on the 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray itself. 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_data_description)( 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/ void* /* really, XArray* of HChar */ dname1v, 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*MOD*/ void* /* really, XArray* of HChar */ dname2v, 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define N_FRAMES 8 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES]; 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt n_frames; 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr stack_min, stack_max; 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found; 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word j; 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* dname1 = (XArray*)dname1v; 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* dname2 = (XArray*)dname2v; 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr); 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, see if data_addr is (or is part of) a global variable. 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Loop over the DebugInfos we have. Check data_addr against the 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown outermost scope of all of them, as that should be a global 3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scope. */ 3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* global_scope; 3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word gs_size; 3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr zero; 3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiAddrRange* global_arange; 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i; 3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* vars; 3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* text segment missing? unlikely, but handle it .. */ 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->text_present || di->text_size == 0) 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* any var info at all? */ 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->varinfo) 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* perhaps this object didn't contribute any vars at all? */ 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(sizeXA)( di->varinfo ) == 0) 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 ); 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(global_scope); 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gs_size = VG_(OSetGen_Size)( global_scope ); 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The global scope might be completely empty if this 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown compilation unit declared locals but nothing global. */ 3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (gs_size == 0) 3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But if it isn't empty, then it must contain exactly one 3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown element, which covers the entire address range. */ 3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(gs_size == 1); 3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fish out the global scope and check it is as expected. */ 3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zero = 0; 3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown global_arange 3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(OSetGen_Lookup)( global_scope, &zero ); 3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The global range from (Addr)0 to ~(Addr)0 must exist */ 3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(global_arange); 3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(global_arange->aMin == (Addr)0 3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && global_arange->aMax == ~(Addr)0); 3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Any vars in this range? */ 3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!global_arange->vars) 3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, there are some vars in the global scope of this 3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo. Wade through them and see if the data addresses 3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of any of them bracket data_addr. */ 3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vars = global_arange->vars; 3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(sizeXA)( vars ); i++) { 3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT offset; 3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i ); 3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(var->name); 3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note we use a NULL RegSummary* here. It can't make any 3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sense for a global variable to have a location expression 3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which depends on a SP/FP/IP value. So don't supply any. 3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This means, if the evaluation of the location 3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression/list requires a register, we have to let it 3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fail. */ 3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (data_address_is_in_var( &offset, di->admin_tyents, var, 3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL/* RegSummary* */, 3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, di )) { 3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PtrdiffT residual_offset = 0; 3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* described = ML_(describe_type)( &residual_offset, 3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->admin_tyents, 3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->typeR, offset ); 3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown format_message( dname1, dname2, 3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, var, offset, residual_offset, 3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown described, -1/*frameNo*/, tid ); 3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deleteXA)( described ); 3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, well it's not a global variable. So now let's snoop around 3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the stacks of all the threads. First try to figure out which 3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread's stack data_addr is in. */ 3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- KLUDGE --- Try examining the top frame of all thread stacks. 3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This finds variables which are not stack allocated but are not 3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown globally visible either; specifically it appears to pick up 3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown variables which are visible only within a compilation unit. 3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown These will have the address range of the compilation unit and 3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tend to live at Scope level 1. */ 3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(thread_stack_reset_iter)(&tid); 3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) { 3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stack_min >= stack_max) 3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; /* ignore obviously stupid cases */ 3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (consider_vars_in_frame( dname1, dname2, 3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, 3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_IP)(tid), 3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_SP)(tid), 3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_FP)(tid), tid, 0 )) { 3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- end KLUDGE --- */ 3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Perhaps it's on a thread's stack? */ 3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = False; 3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(thread_stack_reset_iter)(&tid); 3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) { 3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stack_min >= stack_max) 3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; /* ignore obviously stupid cases */ 3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stack_min - VG_STACK_REDZONE_SZB <= data_addr 3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && data_addr <= stack_max) { 3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = True; 3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) { 3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We conclude data_addr is in thread tid's stack. Unwind the 3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack to get a bunch of (ip,sp,fp) triples describing the 3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frames, and for each frame, consider the local variables. */ 3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES, 3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sps, fps, 0/*first_ip_delta*/ ); 3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* As a result of KLUDGE above, starting the loop at j = 0 3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown duplicates examination of the top frame and so isn't necessary. 3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Oh well. */ 3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_frames >= 0 && n_frames <= N_FRAMES); 3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < n_frames; j++) { 3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (consider_vars_in_frame( dname1, dname2, 3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, 3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ips[j], 3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sps[j], fps[j], tid, j )) { 3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now, it appears that gcc sometimes appears to produce 3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown location lists whose ranges don't actually cover the call 3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction, even though the address of the variable in 3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown question is passed as a parameter in the call. AFAICS this 3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is simply a bug in gcc - how can the variable be claimed not 3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exist in memory (on the stack) for the duration of a call in 3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which its address is passed? But anyway, in the particular 3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case I investigated (memcheck/tests/varinfo6.c, call to croak 3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown on line 2999, local var budget declared at line 3115 3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appearing not to exist across the call to mainSort on line 3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on 3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64), the variable's location list does claim it exists 3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown starting at the first byte of the first instruction after the 3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call instruction. So, call consider_vars_in_frame a second 3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown time, but this time add 1 to the IP. GDB handles this 3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown example with no difficulty, which leads me to believe that 3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either (1) I misunderstood something, or (2) GDB has an 3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown equivalent kludge. */ 3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j > 0 /* this is a non-innermost frame */ 3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && consider_vars_in_frame( dname1, dname2, 3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, 3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ips[j] + 1, 3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sps[j], fps[j], tid, j )) { 3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We didn't find anything useful. */ 3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname1 ); 3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zterm_XA( dname2 ); 3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef N_FRAMES 3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////// 3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// // 3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Support for other kinds of queries to the Dwarf3 var info // 3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// // 3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////// 3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if the variable 'var' has a location that is linearly 3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dependent on a stack pointer value, or a frame pointer value, and 3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if it is, add a description of it to 'blocks'. Otherwise ignore 3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. If 'arrays_only' is True, also ignore it unless it has an 3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown array type. */ 3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks, 3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* /* TyEnt */ tyents, 3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip, const DebugInfo* di, DiVariable* var, 3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool arrays_only ) 3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GXResult res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k; 3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RegSummary regs; 3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MaybeULong mul; 3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isVec; 3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TyEnt* ty; 3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0&&debug) 3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("adeps: var %s\n", var->name ); 3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out how big the variable is. */ 3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mul = ML_(sizeOfType)(tyents, var->typeR); 3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this var has a type whose size is unknown, zero, or 3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown impossibly large, it should never have been added. ML_(addVar) 3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should have rejected it. */ 3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.b == True); 3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.ul > 0); 3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32)); 3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* After this point, we assume we can truncate mul.ul to a host word 3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown safely (without loss of info). */ 3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* skip if non-array and we're only interested in arrays */ 3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR ); 3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ty); 3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty)); 3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty->tag == Te_UNKNOWN) 3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* perhaps we should complain in this case? */ 3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isVec = ty->tag == Te_TyArray; 3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arrays_only && !isVec) 3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR); 3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" %s\n", var->name);} 3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do some test evaluations of the variable's location expression, 3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in order to guess whether it is sp-relative, fp-relative, or 3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown none. A crude hack, which can be interpreted roughly as finding 3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first derivative of the location expression w.r.t. the 3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supplied frame and stack pointer values. */ 3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = 0; 3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = 6 * 1024; 3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = 0; 3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = 7 * 1024; 3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = 6 * 1024; 3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = 0; 3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = 7 * 1024; 3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = 0; 3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(res_sp_6k.kind == res_sp_7k.kind); 3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(res_sp_6k.kind == res_fp_6k.kind); 3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(res_sp_6k.kind == res_fp_7k.kind); 3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res_sp_6k.kind == GXR_Addr) { 3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown StackBlock block; 3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GXResult res; 3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord sp_delta = res_sp_7k.word - res_sp_6k.word; 3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord fp_delta = res_fp_7k.word - res_fp_6k.word; 3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(sp_delta == 0 || sp_delta == 1024); 3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(fp_delta == 0 || fp_delta == 1024); 3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp_delta == 0 && fp_delta == 0) { 3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* depends neither on sp nor fp, so it can't be a stack 3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown local. Ignore it. */ 3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp_delta == 1024 && fp_delta == 0) { 3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = regs.fp = 0; 3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(res.kind == GXR_Addr); 3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" %5ld .. %5ld (sp) %s\n", 3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res.word, res.word + ((UWord)mul.ul) - 1, var->name); 3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.base = res.word; 3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.szB = (SizeT)mul.ul; 3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.spRel = True; 3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.isVec = isVec; 3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( &block.name[0], 0, sizeof(block.name) ); 3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (var->name) 3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 ); 3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.name[ sizeof(block.name)-1 ] = 0; 3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(addToXA)( blocks, &block ); 3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp_delta == 0 && fp_delta == 1024) { 3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = regs.fp = 0; 3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di ); 3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(res.kind == GXR_Addr); 3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)(" %5ld .. %5ld (FP) %s\n", 3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res.word, res.word + ((UWord)mul.ul) - 1, var->name); 3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.base = res.word; 3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.szB = (SizeT)mul.ul; 3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.spRel = False; 3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.isVec = isVec; 3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( &block.name[0], 0, sizeof(block.name) ); 3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (var->name) 3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 ); 3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block.name[ sizeof(block.name)-1 ] = 0; 3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(addToXA)( blocks, &block ); 3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get an XArray of StackBlock which describe the stack (auto) blocks 3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for this ip. The caller is expected to free the XArray at some 3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point. If 'arrays_only' is True, only array-typed blocks are 3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown returned; otherwise blocks of all types are returned. */ 3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* /* really, XArray* of StackBlock */ 3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only ) 3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is a derivation of consider_vars_in_frame() above. */ 3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i; 3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RegSummary regs; 3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1", 3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free), 3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(StackBlock) ); 3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt n_search = 0; 3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt n_steps = 0; 3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search++; 3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip); 3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first, find the DebugInfo that pertains to 'ip'. */ 3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di; di = di->next) { 3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_steps++; 3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* text segment missing? unlikely, but handle it .. */ 3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->text_present || di->text_size == 0) 3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok. So does this text mapping bracket the ip? */ 3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_avma <= ip && ip < di->text_avma + di->text_size) 3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Didn't find it. Strange -- means ip is a code address outside 3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of any mapped text segment. Unlikely but not impossible -- app 3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could be generating code to run. */ 3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di) 3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; /* currently empty */ 3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && ((n_search & 0x1) == 0)) 3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, " 3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%u DebugInfos looked at\n", 3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_search, n_steps); 3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start of performance-enhancing hack: once every ??? (chosen 3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hackily after profiling) successful searches, move the found 3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo one step closer to the start of the list. This makes 3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown future searches cheaper. */ 3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((n_search & 0xFFFF) == 0) { 3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move si one step closer to the start of the list. */ 3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move_DebugInfo_one_step_forward( di ); 3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* End of performance-enhancing hack. */ 3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* any var info at all? */ 3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->varinfo) 3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; /* currently empty */ 3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Work through the scopes from most deeply nested outwards, 3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown looking for code address ranges that bracket 'ip'. The 3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown variables on each such address range found are in scope right 3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now. Don't descend to level zero as that is the global 3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scope. */ 3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.ip = ip; 3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.sp = 0; 3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs.fp = 0; 3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* "for each scope, working outwards ..." */ 3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) { 3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* vars; 3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word j; 3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiAddrRange* arange; 3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* this_scope 3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = *(OSet**)VG_(indexXA)( di->varinfo, i ); 3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: considering scope %ld\n", (Word)i); 3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!this_scope) 3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the set of variables in this scope that 3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bracket the program counter. */ 3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arange = VG_(OSetGen_LookupWithCmp)( 3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this_scope, &ip, 3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(cmp_for_DiAddrRange_range) 3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!arange) 3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stay sane */ 3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arange->aMin <= arange->aMax); 3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It must bracket the ip we asked for, else 3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(cmp_for_DiAddrRange_range) is somehow broken. */ 3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arange->aMin <= ip && ip <= arange->aMax); 3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It must have an attached XArray of DiVariables. */ 3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vars = arange->vars; 3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(vars); 3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But it mustn't cover the entire address range. We only 3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expect that to happen for the global scope (level 0), which 3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we're not looking at here. Except, it may cover the entire 3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address range, but in that case the vars array must be 3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown empty. */ 3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(! (arange->aMin == (Addr)0 3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && arange->aMax == ~(Addr)0 3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(sizeXA)(vars) > 0) ); 3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < VG_(sizeXA)( vars ); j++) { 3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j ); 3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("QQQQ: var:name=%s %#lx-%#lx %#lx\n", 3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->name,arange->aMin,arange->aMax,ip); 3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown analyse_deps( res, di->admin_tyents, ip, 3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di, var, arrays_only ); 3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get an array of GlobalBlock which describe the global blocks owned 3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by the shared object characterised by the given di_handle. Asserts 3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if the handle is invalid. The caller is responsible for freeing 3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the array at some point. If 'arrays_only' is True, only 3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown array-typed blocks are returned; otherwise blocks of all types are 3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown returned. */ 3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* /* really, XArray* of GlobalBlock */ 3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle, 3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool arrays_only ) 3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is a derivation of consider_vars_in_frame() above. */ 3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XArray* gvars; /* XArray* of GlobalBlock */ 3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word nScopes, scopeIx; 3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The first thing to do is find the DebugInfo that 3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pertains to 'di_handle'. */ 3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(di_handle > 0); 3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di; di = di->next) { 3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->handle == di_handle) 3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this fails, we were unable to find any DebugInfo with the 3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown given handle. This is considered an error on the part of the 3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller. */ 3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(di != NULL); 3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we'll put the collected variables in here. */ 3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1", 3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(dinfo_free), sizeof(GlobalBlock) ); 3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(gvars); 3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* any var info at all? */ 3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!di->varinfo) 3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return gvars; 3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we'll iterate over all the variables we can find, even if 3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it seems senseless to visit stack-allocated variables */ 3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate over all scopes */ 3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nScopes = VG_(sizeXA)( di->varinfo ); 3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (scopeIx = 0; scopeIx < nScopes; scopeIx++) { 3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate over each (code) address range at the current scope */ 3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiAddrRange* range; 3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* /* of DiAddrInfo */ scope 3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx ); 3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(scope); 3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)(scope); 3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (range = VG_(OSetGen_Next)(scope)) ) { 3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate over each variable in the current address range */ 3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word nVars, varIx; 3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(range->vars); 3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nVars = VG_(sizeXA)( range->vars ); 3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (varIx = 0; varIx < nVars; varIx++) { 3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isVec; 3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GXResult res; 3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MaybeULong mul; 3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GlobalBlock gb; 3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TyEnt* ty; 3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DiVariable* var = VG_(indexXA)( range->vars, varIx ); 3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(var->name); 3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name ); 3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now figure out if this variable has a constant address 3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (that is, independent of FP, SP, phase of moon, etc), 3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and if so, what the address is. Any variable with a 3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown constant address is deemed to be a global so we collect 3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. */ 3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr); 3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); } 3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = ML_(evaluate_trivial_GX)( var->gexpr, di ); 3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not a constant address => not interesting */ 3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res.kind != GXR_Addr) { 3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("FAIL\n"); 3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, it's a constant address. See if we want to collect 3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. */ 3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("%#lx\n", res.word); 3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out how big the variable is. */ 3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mul = ML_(sizeOfType)(di->admin_tyents, var->typeR); 3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this var has a type whose size is unknown, zero, or 3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown impossibly large, it should never have been added. 3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(addVar) should have rejected it. */ 3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.b == True); 3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mul.ul > 0); 3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32)); 3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* After this point, we assume we can truncate mul.ul to a 3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown host word safely (without loss of info). */ 3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* skip if non-array and we're only interested in 3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arrays */ 3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL, 3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->typeR ); 3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ty); 3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty)); 3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty->tag == Te_UNKNOWN) 3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; /* perhaps we should complain in this case? */ 3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isVec = ty->tag == Te_TyArray; 3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arrays_only && !isVec) continue; 3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, so collect it! */ 3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(var->name); 3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(di->soname); 3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("XXXX %s %s %d\n", var->name, 3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var->fileName?(HChar*)var->fileName 3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown :"??",var->lineNo); 3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&gb, 0, sizeof(gb)); 3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gb.addr = res.word; 3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gb.szB = (SizeT)mul.ul; 3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gb.isVec = isVec; 3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1); 3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1); 3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0); 3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0); 3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(addToXA)( gvars, &gb ); 3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (varIx = 0; varIx < nVars; varIx++) */ 3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */ 3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */ 3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return gvars; 3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- DebugInfo accessor functions ---*/ 3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di) 3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di == NULL) 3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return debugInfo_list; 3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->next; 3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di) 3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->text_present ? di->text_avma : 0; 3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di) 3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->text_present ? di->text_size : 0; 3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di) 3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->plt_present ? di->plt_avma : 0; 3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di) 3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->plt_present ? di->plt_size : 0; 3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di) 3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->gotplt_present ? di->gotplt_avma : 0; 3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di) 3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->gotplt_present ? di->gotplt_size : 0; 3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst UChar* VG_(DebugInfo_get_soname)(const DebugInfo* di) 3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->soname; 3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst UChar* VG_(DebugInfo_get_filename)(const DebugInfo* di) 3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->filename; 3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di) 3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return di->text_present ? di->text_bias : 0; 3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si ) 3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return si->symtab_used; 3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si, 3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int idx, 3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Addr* avma, 3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Addr* tocptr, 3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/UInt* size, 3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/HChar** name, 3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Bool* isText, 3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Bool* isIFunc ) 3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(idx >= 0 && idx < si->symtab_used); 3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (avma) *avma = si->symtab[idx].addr; 3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tocptr) *tocptr = si->symtab[idx].tocptr; 3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size) *size = si->symtab[idx].size; 3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (name) *name = (HChar*)si->symtab[idx].name; 3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isText) *isText = si->symtab[idx].isText; 3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isIFunc) *isIFunc = si->symtab[idx].isIFunc; 3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- SectKind query functions ---*/ 3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert a VgSectKind to a string, which must be copied if you want 3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to change it. */ 3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst HChar* VG_(pp_SectKind)( VgSectKind kind ) 3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (kind) { 3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectUnknown: return "Unknown"; 3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectText: return "Text"; 3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectData: return "Data"; 3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectBSS: return "BSS"; 3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectGOT: return "GOT"; 3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectPLT: return "PLT"; 3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectOPD: return "OPD"; 3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Vg_SectGOTPLT: return "GOTPLT"; 3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vg_assert(0); 3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given an address 'a', make a guess of which section of which object 3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it comes from. If name is non-NULL, then the last n_name-1 3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown characters of the object's name is put in name[0 .. n_name-2], and 3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name[n_name-1] is set to zero (guaranteed zero terminated). */ 3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name, 3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a) 3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di; 3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgSectKind res = Vg_SectUnknown; 3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (di = debugInfo_list; di != NULL; di = di->next) { 3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld " 3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "data=%#lx,%ld bss=%#lx,%ld\n", 3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, di, di->filename, 3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->got_avma, di->got_size, 3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->plt_avma, di->plt_size, 3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->data_avma, di->data_size, 3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown di->bss_avma, di->bss_size); 3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->text_present 3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->text_size > 0 3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->text_avma && a < di->text_avma + di->text_size) { 3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectText; 3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->data_present 3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->data_size > 0 3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->data_avma && a < di->data_avma + di->data_size) { 3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectData; 3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->sdata_present 3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sdata_size > 0 3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) { 3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectData; 3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->bss_present 3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->bss_size > 0 3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->bss_avma && a < di->bss_avma + di->bss_size) { 3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectBSS; 3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->sbss_present 3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->sbss_size > 0 3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) { 3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectBSS; 3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->plt_present 3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->plt_size > 0 3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->plt_avma && a < di->plt_avma + di->plt_size) { 3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectPLT; 3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->got_present 3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->got_size > 0 3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->got_avma && a < di->got_avma + di->got_size) { 3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectGOT; 3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->gotplt_present 3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->gotplt_size > 0 3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) { 3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectGOTPLT; 3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->opd_present 3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && di->opd_size > 0 3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a >= di->opd_avma && a < di->opd_avma + di->opd_size) { 3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = Vg_SectOPD; 3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we could also check for .eh_frame, if anyone really cares */ 3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( (di == NULL && res == Vg_SectUnknown) 3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (di != NULL && res != Vg_SectUnknown) ); 3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (name) { 3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n_name >= 8); 3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di && di->filename) { 3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j; 3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fnlen = VG_(strlen)(di->filename); 3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int start_at = 1 + fnlen - n_name; 3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (start_at < 0) start_at = 0; 3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(start_at < fnlen); 3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = start_at; j = 0; 3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(j >= 0 && j < n_name); 3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i >= 0 && i <= fnlen); 3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name[j] = di->filename[i]; 3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (di->filename[i] == 0) break; 3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; j++; 3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i == fnlen); 3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(snprintf)(name, n_name, "%s", "???"); 3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name[n_name-1] = 0; 3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3866