debuginfo.c revision 130f6f5a47a1557a454b24db6e08431da6c8b9c1
1eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Top level management of symbols and debugging information.   ---*/
4eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                  debuginfo.c ---*/
5eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
6eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*
8eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This file is part of Valgrind, a dynamic binary instrumentation
9eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   framework.
10eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
119eecbbb9a9cbbd30b903c09a9e04d8efc20bda33sewardj   Copyright (C) 2000-2010 Julian Seward
12eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
346c591e15c1d6402a2a755310f005f795b68e7e38sewardj#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
36b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
41b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
4213ac96dea734b3933a73524b991ac64fb48a4d57sewardj#include "pub_core_libcproc.h"   // VG_(getenv)
43d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
506882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
56eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
61b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
62c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
63f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
67eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
68c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
69c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
94f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
95f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
99eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
100f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
108eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
158eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
159eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* alloc_DebugInfo( const UChar* filename,
172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            const UChar* memname )
173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
177f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
178f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
1809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->handle    = handle_counter++;
1819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->filename  = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->memname   = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname)
183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                           : NULL;
184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
185452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
186452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
187f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
188f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj        || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
190f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj                                          memname ));
191f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
197f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
198f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20659a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
20959a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->filename)   ML_(dinfo_free)(di->filename);
213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab)     ML_(dinfo_free)(di->symtab);
214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab)     ML_(dinfo_free)(di->loctab);
215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi)       ML_(dinfo_free)(di->cfsi);
216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs);
217c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (di->fpo)        ML_(dinfo_free)(di->fpo);
218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
220eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
22959a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
23359a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
23759a2d18d0ddfa241850017252b0804d469187d79sewardj
23859a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
23959a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
24059a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
24159a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
24259a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
24359a2d18d0ddfa241850017252b0804d469187d79sewardj      }
24459a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
24559a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
2904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
29733e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
29833e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
300738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
3034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         curr->filename ? curr->filename : (UChar*)"???",
3044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
30733e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
30833e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
323f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
325f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
327f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
351f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
354f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
355f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rx_map
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rw_map
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rx_map
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rw_map
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
450eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
454eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find the existing DebugInfo for (memname,filename) or if not found,
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   create one.  In the latter case memname and filename are strdup'd
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   into VG_AR_DINFO, and the new DebugInfo is added to
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debugInfo_list. */
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname )
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0==VG_(strcmp)(di->filename, filename)
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ( (memname && di->memname)
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ? 0==VG_(strcmp)(memname, di->memname)
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  : True ))
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = alloc_DebugInfo(filename, memname);
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
482f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
483f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
484f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
485f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
487f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
488f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rx_map);
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rw_map);
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* degenerate case: r-x section is empty */
496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->rx_map_size == 0) {
497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi == NULL);
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return;
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* normal case: r-x section is nonempty */
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (0) */
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->rx_map_size > 0);
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (1) */
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di2 = debugInfo_list; di2; di2 = di2->next) {
505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2 == di)
506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2->rx_map_size == 0)
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma
510f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma);
511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di2 = NULL;
513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (2) */
514f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
515f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
516f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma >= di->rx_map_avma);
517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size);
518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word i;
522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
566f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   segment has been mapped in, or unmapped.  When that happens it
570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tries to acquire/discard whatever info is available for the
571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   corresponding object.  This section contains the notification
572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   handlers. */
573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
576eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
5799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
5809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
5819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
5829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
5839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
5849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
5859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
5869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
5889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
5904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       ok, is_rx_map, is_rw_map;
593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
5949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong      di_handle;
595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
596cec083d9a254e92623ed44e9dca080d224693c82sewardj   Int        nread, oflags;
597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
599ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
600ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
607eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
609a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
613eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
6209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
6259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
630ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
63115728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
632ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
633ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
634ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
6359c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
636ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
637ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
638ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
639cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
640ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
641ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
642e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
643ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
644ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         fake_di.filename = filename;
645ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
646ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
6479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
6482ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
6492ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
650ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
651ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
6529c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
6539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
654ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
655ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
65615728ab41ea41bf731dcc74ac68354550ced2189bart
657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
667eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
670eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
683eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
690f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
691f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
692f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
693b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
694b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
695b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
696b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
697b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
698b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
699b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
700b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
701b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
705f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
7083026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
711b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
712b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
713b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If it is neither text-ish nor data-ish, we're not interested. */
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!(is_rx_map || is_rw_map))
7249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7265a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
7275a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
7285a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
729cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
730cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
731cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
732cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
733cec083d9a254e92623ed44e9dca080d224693c82sewardj   fd = VG_(open)( filename, oflags, 0 );
734cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(fd)) {
735cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Err(fd) != VKI_EACCES) {
7365a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         DebugInfo fake_di;
7375a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
7385a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         fake_di.filename = filename;
7395a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
7405a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
7415a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7425a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
743cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) );
744cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   VG_(close)( sr_Res(fd) );
7455a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7465a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread == 0)
7475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7485a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread < 0) {
7495a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
7505a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
7515a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      fake_di.filename = filename;
7525a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
7535a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7545a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
7555a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
7565a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7578b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
7586e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
7595a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
7605a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7616e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
762f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!ML_(is_macho_object_file)( buf1k, (SizeT)nread ))
763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
7646e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
7656e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
7666e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
7675a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ );
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rx_map) {
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rx_map = True;
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_avma = a;
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_size = seg->end + 1 - seg->start;
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_foff = seg->offset;
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rw_map) {
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rw_map = True;
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_avma = a;
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_size = seg->end + 1 - seg->start;
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_foff = seg->offset;
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
795eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If we don't have an rx and rw mapping, or if we already have
7989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      debuginfo for this mapping for whatever reason, go no
7999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      further. */
8009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) )
8019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Ok, so, finally, let's try to read the debuginfo. */
8049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(di->filename);
8059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ start ELF OBJECT "
8079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* We're going to read symbols and debug info for the avma
8129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      +rw_map_size).  First get rid of any other DebugInfos which
8149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      overlap either of those ranges (to avoid total confusion). */
8159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   discard_DebugInfos_which_overlap_with( di );
8169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* .. and acquire new info. */
8186e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
8199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ok = ML_(read_elf_debug_info)( di );
8206e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
821f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   ok = ML_(read_macho_debug_info)( di );
8226e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
8236e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
8246e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
8259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ok) {
8279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Canonicalising the "
8299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   "acquired info ------\n");
830f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* invalidate the CFI unwind cache. */
831f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
8329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* prepare read data for use */
8339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(canonicaliseTables)( di );
8349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* notify m_redir about it */
8359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
8369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(redir_notify_new_DebugInfo)( di );
8379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Note that we succeeded */
8389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->have_dinfo = True;
8399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(di->handle > 0);
8409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = di->handle;
841f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Check invariants listed in
842f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
843f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         priv_storage.h. */
844f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      check_CFSI_related_invariants(di);
845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
8479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
8489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
8499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         this DebugInfo?  No - it contains info on the rw/rx
8509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         mappings, at least. */
8519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = 0;
852f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->have_dinfo == False);
8539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
854eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ end ELF OBJECT "
8589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
860eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return di_handle;
862eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
863eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
869f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
870a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
871f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
872f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
873f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
884f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
885eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
886eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
887f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
888f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
889f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
890f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
891f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
892eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
893eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
894c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
895c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
896c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
897c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
898c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   SizeT total_size,
899c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   PtrdiffT unknown_purpose__reloc )
900c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
90113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
902c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
903c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char   exename[VKI_PATH_MAX];
904c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  pdbname = NULL;
905c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  dot;
906c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
907c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
908c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
909c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
910c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
911c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
912738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
913c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
914cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
915cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "uu_reloc=%#lx\n",
916c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fd_obj, avma_obj, total_size, unknown_purpose__reloc
917c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
918c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
919c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
920c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
921c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
922c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
923c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
924c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
925c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
9269c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
927c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
928c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
929c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
930c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
931c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
932c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
933c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
934c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
935c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
936c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
937c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
938c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
939c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
940c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
941738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
942c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
943c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
94413ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
94513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
94613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
94713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
94813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
94913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
95013ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
95113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
95213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
95313ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
95413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
95513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
95613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
95713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
95813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
95913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
96013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
96113ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
96213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
96313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
96413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
96513ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
96613ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
96713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
96813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
96913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
97013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
97113ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
97213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
97313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
97413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
97513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(sprintf)(mashed, "%s/drive_%c%s",
97613ac96dea734b3933a73524b991ac64fb48a4d57sewardj                      wpfx, pdbname[0], &pdbname[2]);
97713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
97813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
97913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
98013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
98113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
98213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
98313ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
98413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
98513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
98613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
98713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(sprintf)(mashed, "%s/.wine/drive_%c%s",
98813ac96dea734b3933a73524b991ac64fb48a4d57sewardj                      home, pdbname[0], &pdbname[2]);
98913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
99013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
99113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
99213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
99313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
99413ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
99513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
99613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
99713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
99813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
999c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
100013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
100113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
100213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
100313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
100413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
100513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
100613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
100713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
100813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
100913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
101013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
101113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
101213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
101313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
101413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
101513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
101613ac96dea734b3933a73524b991ac64fb48a4d57sewardj
101713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
101813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
101913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
102013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
102113ac96dea734b3933a73524b991ac64fb48a4d57sewardj
102213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
102313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1024c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1025c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1026c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1027cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1028738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1029c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1030c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1031738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1032c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1033c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
10349c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
10357138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1036ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
10377138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
10387138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
10397138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
10407138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
10417138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
10427138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
10437138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1044738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1045ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1046ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1047ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1048c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1049c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1050c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1051cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1052738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1053c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1054c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1055c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1056cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1057cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1058cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1059cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1060cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1061cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1062cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1063cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1064cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
10659c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1066cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1067cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1068cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1069cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1070cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1071cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1072cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1073cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1074cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1075cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1076cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1077c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1078c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1079c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1080c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1081cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1082cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1083cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1084cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1085cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1086cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1087cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1088cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1089c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1090738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1091c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1092c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1093c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1094c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1095c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1096c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1097c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1098cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename, NULL/*membername*/ );
1099c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1100c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1101c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di && !di->have_rx_map && !di->have_rw_map);
1102c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1103c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1104c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1105c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
1106c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     ML_(read_pdb_debug_info)( di, avma_obj, unknown_purpose__reloc,
1107c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1108c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1109c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1110c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1111c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1112c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1113cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1114cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1115cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1116cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                                 "%lu syms, %lu src locs, %lu fpo recs\n",
1117cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                     di->symtab_used, di->loctab_used, di->fpo_size);
1118cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1119c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1120c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1121c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1122c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1123c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1124c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
11258b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
11264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11274ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1129eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1130eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1131eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
11349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
11359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
11369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
11379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
11389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
11399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
11409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
11419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
11429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
11439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
11449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
11459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
11469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1147eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1148eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1149eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1150eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1151eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1152eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1159f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
117051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
117151c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
117251c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
117351c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         inRange = di->have_rx_map
117451c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj                   && di->rx_map_size > 0
117551c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj                   && di->rx_map_avma <= ptr
117651c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj                   && ptr < di->rx_map_avma + di->rx_map_size;
1177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
11915706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
11925706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
11935706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
11945706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
11955706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
11965706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
11975706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
11985706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
11995706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
12005706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
12015706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1214eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1217eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1218eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1219eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1223f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1224eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1225f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
12295706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1234eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1238eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1243eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
12466b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
12476b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
12486b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1251eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
12526b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
12536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
12546b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Addr a, Char* buf, Int nbuf,
1255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1256c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1257eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1259f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1260c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1261eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
12656882443ef154bca367bc591287de641e43a9e108njn
12666b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
12676b7611bf42a0fbb62e047d8c43b008205bd21e75njn                   di->symtab[sno].name, buf, nbuf );
12686b7611bf42a0fbb62e047d8c43b008205bd21e75njn
12696b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
12706b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
12716b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
12726b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
12736b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
12746b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
12756b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
12766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
12776b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1278eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1280c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1288c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1290eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12996b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
13006b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1302eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1310f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13256b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13266b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13276b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13386b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13396b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13406b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13526b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13546b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13616b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
13626b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
13636b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
13646b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf )
1365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13666b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
13676b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
13686b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
13766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
13776b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
13786b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
1379eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13806b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
13816b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13826b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
13836b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
13846b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
13856b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
13866b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1388eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13896882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind) ( Char* name )
13906882443ef154bca367bc591287de641e43a9e108njn{
13916882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
13926882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
13936882443ef154bca367bc591287de641e43a9e108njn
13946882443ef154bca367bc591287de641e43a9e108njn   } else if (
13953026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
13966882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
13976882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
13983026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1399f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1400f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
14013026f71684a930286186aa10fef266c304672e8fsewardj#      else
14023026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
14033026f71684a930286186aa10fef266c304672e8fsewardj#      endif
14046882443ef154bca367bc591287de641e43a9e108njn       0) {
14056882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
14066882443ef154bca367bc591287de641e43a9e108njn
14076882443ef154bca367bc591287de641e43a9e108njn   } else {
14086882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
14096882443ef154bca367bc591287de641e43a9e108njn   }
14106882443ef154bca367bc591287de641e43a9e108njn}
14116882443ef154bca367bc591287de641e43a9e108njn
14126882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
14136882443ef154bca367bc591287de641e43a9e108njn{
14146882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
14156882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
14166882443ef154bca367bc591287de641e43a9e108njn   Char buf[50];
14176882443ef154bca367bc591287de641e43a9e108njn
14186882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
14196882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
14206b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
14216882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
14226882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
14236882443ef154bca367bc591287de641e43a9e108njn   } else {
14246882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
14256882443ef154bca367bc591287de641e43a9e108njn   }
14266882443ef154bca367bc591287de641e43a9e108njn}
14276882443ef154bca367bc591287de641e43a9e108njn
1428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1434c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
14386b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
14396b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
14406b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1454eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1455eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14564ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int used;
1457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1458f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1459f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
14604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
14617cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
14627cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
14655706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(strncpy_safely)(buf, di->filename, nbuf);
1469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (di->memname) {
14704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
14734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
1475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used);
14764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
14794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
14804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
14847cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
14857cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
14867cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
14877cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
14887cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
14897cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
14907cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1491f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1492f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1493f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1494eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1495eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1499e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1501e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1503e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
15065706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1509e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1510e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1512eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1523eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1546eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1557eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1559c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1560db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1561db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1562db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1563db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1564eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1565c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1566c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1576eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
15904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
15914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
15924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
15934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
15944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
15954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
15984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
15994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
16004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
16024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
16034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
16044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
16054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
16074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
16084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
16094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
16104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
16114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
16124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
16134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
16154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (0==VG_(strcmp)(name, si->symtab[i].name)
16164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
16174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
16184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
16194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
16204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
16214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
16234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
16244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
16254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
16264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1627e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1628e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1629e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1630e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1631e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1632eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1633eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1634eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1635e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1636e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1639e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1643e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1644e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1645e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1646e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1647e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1648eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1649eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1650e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1651e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1652e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1654e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1655e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1656e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1657eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1658e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1659e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1660e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1661e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1662e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1663e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1664e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1665e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1666e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1667e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1668e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1669e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1670e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1671e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1672e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1673e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1674e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1675e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1676e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1677e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1678e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1679e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1682e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1683e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1684e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1691e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1692e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1693e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
169914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
170414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
170514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
17074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
17084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
17094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
171714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
171814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
171914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
172014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
172114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1728e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1729e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1730e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1731e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1732e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1733e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1734eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1735a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1739eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1741e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1746eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1747e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1754e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1759e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1762eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1763eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1766eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1767eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1768eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1770eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1771eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1772eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
17735e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17745e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
17755e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17765e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
17775e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
17785e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
17795e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
17805e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
17815e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
17825e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1783a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
17855e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
179214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
179314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         UChar* dirname = NULL;
179414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
179514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
179614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
179714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
179814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
179914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
180014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
180114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* prefix = VG_(clo_fullpath_after)[i];
180214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* str    = VG_(strstr)(dirname, prefix);
180314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
180414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
180514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
180614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
180714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
180814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
180914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
181014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
181114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
181214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
181314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
181414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
181514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
181614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
18175dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
1818eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1821eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
18235e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
18245e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
18255e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
18265e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
18275e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
18285e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
18295e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
18305e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
1831eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1832eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1834eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1835eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1837eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1838eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
184172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
184872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
184972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
185072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
185172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
185272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
18533026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
18543026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
18553026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
185672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
185772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
185872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
185972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
186072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
186172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
1862f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
1863f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
186472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
186572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
186672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
186772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
186819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
18693026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
18703026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
18713026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
187272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
187372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
187472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
187572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
187672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
187772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
187872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
187972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
188072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
188119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
18827888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
18830b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Shl: return wL << wR;
18840b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Shr: return wL >> wR;
18850b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Eq: return wL == wR ? 1 : 0;
1886130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
1887130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
1888130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
1889130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
18900b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Ne: return wL != wR ? 1 : 0;
189172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
189272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
189372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
189472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
189572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
18963026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
18973026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
18983026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
18993026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
19003026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
19013026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
19023026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
1903fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
1904fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
1905b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
1906b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
1907b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
1908b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
1909b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
19103026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
19113026f71684a930286186aa10fef266c304672e8fsewardj#           else
19123026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
19133026f71684a930286186aa10fef266c304672e8fsewardj#           endif
191472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
191572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
191672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
191772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
191872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
191919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
192019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
192119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
192219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
192319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
192419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
192519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
192619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
192719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
192819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         return * ((UWord*)a);
192972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
193072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
193172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
193272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
193372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
193472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
193572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
193672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
193772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
193872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
193972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
194072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
194172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
194272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1943f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
1944f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
1945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1946f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
1947f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
194872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1949f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
1950f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
1951f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
1952f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
1953f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
1954f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
1955f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1956f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
1957f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
1958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1959f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
1960f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
1961eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
1962eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1963f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
1964eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1966f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
1967eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
1968eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1969b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
1970b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
1971f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
1972eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1973f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1975eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1976f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
1977f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
1978f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
1979f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1980f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
1981f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
1982f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
1983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1984eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1985eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1986f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
1987f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1988f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
1989f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
1990f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
1991f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1992f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
1993f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1994f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
1995f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
1996f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
1997f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
1998f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
1999f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
2000f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
2001f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2002f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2003f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2004f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2005f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2006f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2007f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2008f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2009f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2010f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2011f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2012f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2013f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2014f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2015f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2016f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2017f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2018f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2019f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2020f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2021f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2022f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2023f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2024f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2025f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2026f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2027f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2028f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
2029f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2030f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2031f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
2032f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
2033f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
2034f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2035f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2036f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2037f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2038f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
2039f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
2040f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
2041f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
2042f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
2043f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
2044f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
2045eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2046f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
2047f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2048f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
2049f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
2050f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
2051f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2052f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
2053f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2054f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
2055f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
2056f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2057f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2058f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2059f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic inline CFSICacheEnt* cfsi_cache__find ( Addr ip )
2060f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
20613c9cf3442185b5891e15450d6e3058aeff6796fetom   UWord         hash = ip % N_CFSI_CACHE;
20623c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce = &cfsi_cache[hash];
20633c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2064f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2065f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2066f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2067f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2068f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
20693c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
20703c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
20713c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
20723c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
20733c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
20743c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
20753c9cf3442185b5891e15450d6e3058aeff6796fetom      find_DiCfSI( &ce->di, &ce->ix, ip );
20763c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20783c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
20793c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
20803c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
20813c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
20823c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
20833c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2084eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
20853c9cf3442185b5891e15450d6e3058aeff6796fetom}
2086eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2087eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2088f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
20893026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
20903c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
20913c9cf3442185b5891e15450d6e3058aeff6796fetom                          DebugInfo* di, DiCfSI* cfsi )
20923c9cf3442185b5891e15450d6e3058aeff6796fetom{
20933c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
20943c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
20953c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2096eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20973c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
209872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
209972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
21003026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
21013026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
21023026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xsp;
21033026f71684a930286186aa10fef266c304672e8fsewardj         break;
21043026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
21053026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xbp;
210672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
21073026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
21083026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
21093026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r13;
211072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
21113026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
21123026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r12;
21133026f71684a930286186aa10fef266c304672e8fsewardj         break;
21143026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
21153026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r11;
21163026f71684a930286186aa10fef266c304672e8fsewardj         break;
2117fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
2118fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         cfa = cfsi->cfa_off + uregs->r7;
2119fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2120b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2121b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
2122b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->sp;
2123b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2124b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2125b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
2126b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         Addr a = uregs->sp + cfsi->cfa_off;
2127b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2128b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
2129b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = *(Addr*)a;
2130b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2131b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2132b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2133b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2134b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2135b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
2136b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->fp;
2137b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
21383026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
21393026f71684a930286186aa10fef266c304672e8fsewardj#     else
21403026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
21413026f71684a930286186aa10fef266c304672e8fsewardj#     endif
21423026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
21437888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
21447888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2145f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
21467888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
21477888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
21483026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
21497888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
21507888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
21517888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2152f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
21533c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
215472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
215572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
215672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
215772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
21583c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
21593c9cf3442185b5891e15450d6e3058aeff6796fetom}
21603c9cf3442185b5891e15450d6e3058aeff6796fetom
21613c9cf3442185b5891e15450d6e3058aeff6796fetom
21623c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
21633026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
21643026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
21653c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
21663c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
21673c9cf3442185b5891e15450d6e3058aeff6796fetom{
21683c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce;
21693c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*    di;
2170d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   DiCfSI*       cfsi __attribute__((unused));
21713c9cf3442185b5891e15450d6e3058aeff6796fetom
21723c9cf3442185b5891e15450d6e3058aeff6796fetom   ce = cfsi_cache__find(ip);
21733c9cf3442185b5891e15450d6e3058aeff6796fetom
21743c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
21753c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
21763c9cf3442185b5891e15450d6e3058aeff6796fetom
21773c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
21783c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
21793c9cf3442185b5891e15450d6e3058aeff6796fetom
21803026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
21813026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
21823026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
21833026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
21843026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
21853026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
21863026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
21873026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
21883026f71684a930286186aa10fef266c304672e8fsewardj                        min_accessible,  max_accessible, di, cfsi);
21893026f71684a930286186aa10fef266c304672e8fsewardj   }
2190b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2191b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2192b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2193b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2194b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2195b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
2196b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                        min_accessible,  max_accessible, di, cfsi);
2197b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2198b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
21993026f71684a930286186aa10fef266c304672e8fsewardj#  else
22003026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
22013026f71684a930286186aa10fef266c304672e8fsewardj#  endif
22023c9cf3442185b5891e15450d6e3058aeff6796fetom}
22033c9cf3442185b5891e15450d6e3058aeff6796fetom
22043c9cf3442185b5891e15450d6e3058aeff6796fetom
22053026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
22063026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
22073026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
22083026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
22093026f71684a930286186aa10fef266c304672e8fsewardj
22103026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
22113026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
22123026f71684a930286186aa10fef266c304672e8fsewardj
2213fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
22143026f71684a930286186aa10fef266c304672e8fsewardj*/
22153026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
22163c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
22173c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
22183c9cf3442185b5891e15450d6e3058aeff6796fetom{
22193c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
22203c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*            cfsi = NULL;
22213026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
22223c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt*      ce;
2223d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
22243026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
22253c9cf3442185b5891e15450d6e3058aeff6796fetom
22263026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
22273026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
22283026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
22293026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2230b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2231b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
22323026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
22333026f71684a930286186aa10fef266c304672e8fsewardj#  else
22343026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
22353026f71684a930286186aa10fef266c304672e8fsewardj#  endif
22363026f71684a930286186aa10fef266c304672e8fsewardj   ce = cfsi_cache__find(ipHere);
22373c9cf3442185b5891e15450d6e3058aeff6796fetom
22383c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
22393c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
22403c9cf3442185b5891e15450d6e3058aeff6796fetom
22413c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
22423c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
22433c9cf3442185b5891e15450d6e3058aeff6796fetom
22443c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
22453c9cf3442185b5891e15450d6e3058aeff6796fetom      VG_(printf)("found cfisi: ");
22463c9cf3442185b5891e15450d6e3058aeff6796fetom      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
22473c9cf3442185b5891e15450d6e3058aeff6796fetom   }
22483c9cf3442185b5891e15450d6e3058aeff6796fetom
2249f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
22503c9cf3442185b5891e15450d6e3058aeff6796fetom
22513c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
22523026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
22533026f71684a930286186aa10fef266c304672e8fsewardj                     min_accessible, max_accessible, di, cfsi);
22543c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
22553c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
225672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
225772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
225872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2259eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2261eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2262eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2263eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2265eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2266eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2267eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2268eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2269eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
22709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2271eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
2272eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = *(Addr*)a;                       \
2273eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2274eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2275eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2277eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
227872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
227972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2280f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
22813026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
228272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
228372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2284d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2285f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
228672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
228772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
228872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
228972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2290eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22933026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
22943026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
22959365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
22969365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
22973026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
22983026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how,  cfsi->ra_off);
22993026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
23003026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
23013026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
23023026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
2303fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi->r7_how,  cfsi->r7_off);
2304b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2305b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
2306b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
2307b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
23083026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
23093026f71684a930286186aa10fef266c304672e8fsewardj#  else
23103026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
23113026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
23153026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2322c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2323c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2324c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2325c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2326c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2327c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2328c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2329c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2330c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2331c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2332c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2333c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2334c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2335c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2336c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2337c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2338c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2339c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2340c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2341c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2342c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2343c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2344c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2345c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2346c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2347c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2348c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2349c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2350c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2351c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2352c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2353c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2354c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2355c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2356c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2357c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2358c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2359c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2360c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2361c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2362c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2363c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2364c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2365c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2366c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2367c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2368c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2369c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2370c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2371c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2372c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2373c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2374c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2375c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2376c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2377c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2378c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2379c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2380c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2381c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2382c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2383c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2384c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2385c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2386c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2387c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2388c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2389c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2390c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2391c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2392c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2393c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2394c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2395c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2396c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2397c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2398c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2399c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2400c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2401c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2402c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2403c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2404c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2405c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2406c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2407c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2408c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2409c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2410c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2411c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2412c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2413c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2414c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2415c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2416c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2417c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2418c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2419c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2420c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2421c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2422c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2423c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2424c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2425c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2426c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2427c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2428c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2429c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2430c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2431c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2432c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2433c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2434c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *ipP = *(Addr *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals));
2435738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   *spP =           spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
2436738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                                            + fpo->cdwParams);
2437c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *fpP = *(Addr *)(spHere + 4*2);
2438c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2439c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2440c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2441c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2442c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2443c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2449588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2450588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   VG_(xaprintf_no_f_c)(dst, fmt, args) without having to resort to
2451588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2452588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2453738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2454588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2455588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //   VG_(xaprintf_no_f_c)(dstxa, format, ##args)
2456738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2457588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj#define  p2XA  VG_(xaprintf_no_f_c)
2458738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2459588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2460588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2461738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2462738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2463738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2464738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2465738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2466738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2467738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2473c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
24749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2478588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
248050fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
24849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
248950fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
249050fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
249150fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
249250fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
249350fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
249450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
249550fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
249650fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
249750fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
249850fde23467d92281b32dd537d0d9a590263628c3sewardj
249950fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2500b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2502a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
25049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2515588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2517b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2519b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25233c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2530b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2534738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
2535738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
2536738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
2537738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
2538738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
2539738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
2540738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
2541738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
2542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2544c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2545c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2550738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
2551738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
2552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2554738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar* basetag   = "auxwhat"; /* a constant */
2555738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar tagL[32], tagR[32], xagL[32], xagR[32];
2556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2557d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
2558d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
2559d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2560d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
2561d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
2562d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2563d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
2564d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
2565d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2566d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
2567738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
2568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2574738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
2575738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
2576738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
2577738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
2578738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
2579738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
2580738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
2581738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2582738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
2583738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
2584738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
2585738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
2586738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
2587738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
2588b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2589b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2590b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2596738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2597738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2598738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2599738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\",",
2600738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2601738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2602738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2603738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2604738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2605738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2606738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2607738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2608738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2609738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2610738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2611738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2612738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2620738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2621738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2622738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2623738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\"",
2624738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2625738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2626738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2627738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2628738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2629738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2630738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2631738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2632738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2633738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2634738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2635738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2636738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2637738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2638738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2639738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2640738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2641738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2642738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2643738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2644738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2652738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2653738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2654738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2655738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t",
2656738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2657738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2658738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2659738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2660738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2661738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2662738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2663738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2664738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2665738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
2666738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2667738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2668738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2669738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2670738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2674738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2675738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
2676738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2677738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2678738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2679738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2680738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2681738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2682738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2683738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2684738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2685738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2686738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2687738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2688738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2689738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2690738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2691738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2692738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2693738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2694738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2695738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2696738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2697738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2698738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2699738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2700738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2701738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2702738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2710738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2711738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2712738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2713738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2714738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2715738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2716738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2717738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2718738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2719738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2720738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2728738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2729738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2730738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2731738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2732738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2733738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2734738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2735738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2736738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2737738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d",
2738738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2739738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2740738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2741738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2742738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2743738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2744738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2745738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2746738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2747738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2748738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2749738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2750738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
2751738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2752738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2760738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2761738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2762738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2763738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2764738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2765738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2766738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2767738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2768738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2769738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2770738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2771738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2772738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2773738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2774738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2775738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
2776738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2777738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2778738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2782738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2783738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
2784738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2785738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2786738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2787738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2788738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2789738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2791738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2792738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2793738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2794738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %t:%d",
2795738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2796738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2797738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2798738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2799738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2800738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2801738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2802738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2803738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2804738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2805738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2806738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2807738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2808738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
2809738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2810738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
2814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2815738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
2816738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
2817738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
2818738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2819738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
2820738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
2821738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
2822738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
2823738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
2824738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
2825eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2827738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
2829738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
2830738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
2831738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
2832738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
2833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
2834738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
2835738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
2836b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
2837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
2838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
2839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
2840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
2842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
2844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
2845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
2847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
2848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
2849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
2850a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
2851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
2852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
2853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
2854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
2858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
2859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
2863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
2864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
2865b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
2866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
2869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
2870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
2871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
2872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
2873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
2874b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
2875b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
2876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
2877b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
2878b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
2879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
2881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2882b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
2883b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
2884b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
2887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
2888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
2889b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
2890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
2892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
2893b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
2894b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
2896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
2897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
2899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
2900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
2901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
2902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
2903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
2904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
2905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2906b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
2907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
2908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
2909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
2910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
2911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
2912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
2913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
2915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
2916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
2917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
2918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
2919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
2920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
2921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
2922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
2923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
2924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
2925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
2926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
2927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
2928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
2929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
2930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
2931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
2932c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
2933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
2934a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
2935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
29369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
29379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
2938588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
2939c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
2940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
29419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
29429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2943738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
2944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
2946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2947b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2951b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2955738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
2956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
2957738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
2958738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
2959738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
2960738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
2961738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
2962738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2963738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
2964738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
2965738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
2966738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
2967738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2968738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
2969738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
2970738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
2971738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
2972738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
2973eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
2977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
2979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
2980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
2981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
2983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2984738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
2985738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
2986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2987a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
2988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
2990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
2991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
29949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
2995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
2996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3035c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
30449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3046588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3047c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
30499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
30509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3051738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3053d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3054d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3056738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3057738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
3068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
3069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
3070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
3071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
3072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
3073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3077738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
3080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
3081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
3082738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3083738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
3088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3102738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3103738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3112b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
3114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
3115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
3116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3118738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3120b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3122738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3123738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3140b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3141b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3142b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3143b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3144b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3145738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3146b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3147b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3148b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3149738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3150738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3156738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3157738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
31639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
31649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
31659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
31669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
31679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
31689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
31709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
31719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
31729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
31739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
31749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
31769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
31779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3178588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
31799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
31809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
31819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
31829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
318350fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
31849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
31859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
31869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
31889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
31899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
31909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
319250fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
319350fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
319450fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
319550fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
319650fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
319750fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
319850fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
319950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
320050fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
32019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
32039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
32049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
32059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
32069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
32079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
32089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
32099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
32109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
32119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
32139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
32149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
32169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
32179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
32189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
32199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
32209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
32219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
32229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3223588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
32269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
32279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3228588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
32319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
32329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3233588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
32369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
32379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3238588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
32419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
32429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
32439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32443c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
32459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
32469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
32479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
32489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
32499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
32509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
32519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
32539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
32549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
32559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
32579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
32589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
32599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3260588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32613c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
32629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
32639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
326450fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
32659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
326650fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
32679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
32689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
32699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
32709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
32719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
32729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
32739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
32749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
32769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
32779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
32789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3279588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
32803c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
32819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
32829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
328350fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
32849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
328550fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
32869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
32879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
32889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
32899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
32909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
32919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
32929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
32939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
32959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
32969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
32989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
32999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
33029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
33039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
33049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
33059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
33079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
33089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
33099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
33109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
33119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
33129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
33139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
33159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
33169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
33179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
33199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
33209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
33219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
33229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
33239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
33249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
33259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
33269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
33279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
33289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
33299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
33309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
33319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
33329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
33339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
33359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
33369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
33379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
33389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
33399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
33419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
33429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
33439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
33449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
33459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
33469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
33479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
33489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
33499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
33509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
33519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
33529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
33539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
33559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
33569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
33579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
33599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
33609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
33619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
33629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
33639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
33659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
33669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
33679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
33689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
33699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
33709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
33719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
33729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
33739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
33749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
33759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
33769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
33779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
33789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
33799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
33809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
33819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
33829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
33839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
33849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
33859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
33869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
33879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
33889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
33899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
33909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
33919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
33929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
33939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
33949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
33959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
33969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
33979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
33989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
33999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
34009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
34019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
34029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
34039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
34049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3405588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
34069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
34089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
34119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
34159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
34169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
34179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
34189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
34199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
34219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
34229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
34239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
34249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
34259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
34279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
34289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
34299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
34319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
34329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
34339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
34349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
34359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
34369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
34379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
34399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
34409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
34419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
34429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
34449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
34459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
34469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
34479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
34499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
34509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
34519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
34539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
34549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
34559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
34569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
34579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
34599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
34609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
34619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
34629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
34639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
34649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
34659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
34679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
34689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
34699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
34709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
34719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
34739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
347450fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
34759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
34769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
34779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
34789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
34799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
34809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
34829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
34839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
34849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
34859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
34869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
34879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3488588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
34899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
34913c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
34929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
34939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
34949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
34959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
34979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
34989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
34999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
350150fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
35029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
350350fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
350450fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
350550fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
350650fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
350750fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
350850fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
350950fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
351050fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
35119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
35139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
35149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
35159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
35169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
35179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
35189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
35199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
35209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
35229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
35239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
35259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
35269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
35279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
35289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
35299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
35309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
35319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
353250fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
35339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
35349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
35359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
35369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
35379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
35389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
35409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
35429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
35449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
35469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
35489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
35499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3555e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
3556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3560eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3561eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3562e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
3563eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3565eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3566eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3567e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
3568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3572e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
3573092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3574092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3575092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3576092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3577e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
3578092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3579092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3580092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3581092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3582e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
3583092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3584092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3585092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3586092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3587e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
3588092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3589092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3590092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3591092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3592e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
3593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3596eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3597e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
3598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->filename;
3600eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3602e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
3603bbec7728efefaa650970dd1f0282b77040287133sewardj{
3604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3605bbec7728efefaa650970dd1f0282b77040287133sewardj}
3606bbec7728efefaa650970dd1f0282b77040287133sewardj
3607e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
3608eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3609eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3610eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3611eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3612e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
3613e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
3614e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/Addr*   avma,
3615e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/Addr*   tocptr,
3616e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/UInt*   size,
3617e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/HChar** name,
3618d264514038b82ea069f84478121c2e628b1ae0d4tom                                  /*OUT*/Bool*   isText,
3619d264514038b82ea069f84478121c2e628b1ae0d4tom                                  /*OUT*/Bool*   isIFunc )
3620eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3621eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3622d264514038b82ea069f84478121c2e628b1ae0d4tom   if (avma)    *avma    = si->symtab[idx].addr;
3623d264514038b82ea069f84478121c2e628b1ae0d4tom   if (tocptr)  *tocptr  = si->symtab[idx].tocptr;
3624d264514038b82ea069f84478121c2e628b1ae0d4tom   if (size)    *size    = si->symtab[idx].size;
3625d264514038b82ea069f84478121c2e628b1ae0d4tom   if (name)    *name    = (HChar*)si->symtab[idx].name;
3626d264514038b82ea069f84478121c2e628b1ae0d4tom   if (isText)  *isText  = si->symtab[idx].isText;
3627d264514038b82ea069f84478121c2e628b1ae0d4tom   if (isIFunc) *isIFunc = si->symtab[idx].isIFunc;
3628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
36475706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3657e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
3658e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
3659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3667e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
3668e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
3669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            a, di, di->filename,
3670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
36995706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
37005706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
37015706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
37025706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
37035706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
37045706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3717092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3718092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3719092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3720092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3721092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3722092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di && di->filename) {
3740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int fnlen = VG_(strlen)(di->filename);
3742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3747d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j] = di->filename[i];
3750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (di->filename[i] == 0) break;
3751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3753d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3763eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3766eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3767eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3768