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