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