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