debuginfo.c revision f6716dd8f025c9ace67541f3360d7f4523496d8a
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
1103f8d3fc25f5a45c5826259d1b33b7f310117279sewardj   Copyright (C) 2000-2012 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
1710f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardjDebugInfo* alloc_DebugInfo( const UChar* filename )
172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
176f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
177f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
179a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
180a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1816b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.maps     = VG_(newXA)(
1826b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_zalloc), "di.debuginfo.aDI.3",
1836b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_free), sizeof(struct _DebugInfoMapping));
184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
185452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
186452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
187f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1880f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
195f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
196f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
199eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
203eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20459a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
20759a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
2106b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.maps)     VG_(deleteXA)(di->fsm.maps);
211a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
212f1e1aa691d7a2f0f2f933daf060bec5ae6938705philippe   if (di->soname)       ML_(dinfo_free)(di->soname);
213a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
214a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi)         ML_(dinfo_free)(di->cfsi);
215a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
216a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
218a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
219a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
220a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
221a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
222a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
223a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
224a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
225a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
226a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
227a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
228a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
229a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
230a5cace0c2a3e212931badbf6398a0cd98393121asewardj
231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
24159a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
24559a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
248eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24959a2d18d0ddfa241850017252b0804d469187d79sewardj
25059a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
25159a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
25259a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
25359a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
25459a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
25559a2d18d0ddfa241850017252b0804d469187d79sewardj      }
25659a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
25759a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
3024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
30933e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
31033e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
312738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
315a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
316a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                                            : (UChar*)"???",
3174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
32033e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
32133e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
336f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
338f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
340f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
364f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
367f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
368f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3926b5625bb609b154766d2e138b61e15655f60b710sewardj/* Do the basic mappings of the two DebugInfos overlap in any way? */
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3956b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
3986b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) {
3996b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i);
4006b5625bb609b154766d2e138b61e15655f60b710sewardj      for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
4016b5625bb609b154766d2e138b61e15655f60b710sewardj         struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
4026b5625bb609b154766d2e138b61e15655f60b710sewardj         if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size))
4036b5625bb609b154766d2e138b61e15655f60b710sewardj            return True;
4046b5625bb609b154766d2e138b61e15655f60b710sewardj      }
4056b5625bb609b154766d2e138b61e15655f60b710sewardj   }
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
4366b5625bb609b154766d2e138b61e15655f60b710sewardj   Clearly diRef must have its mapping information set to 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
4550f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4560f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4570f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
4580f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardjstatic DebugInfo* find_or_create_DebugInfo_for ( UChar* filename )
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
463a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
464a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4680f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
477f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
478f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
479f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
481f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
482f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
483f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
4846b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool has_nonempty_rx = False;
4856b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool cfsi_fits = False;
4866b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
487f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
488f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
491a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
492a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
4936b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
4946b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
4956b5625bb609b154766d2e138b61e15655f60b710sewardj      /* We are interested in r-x mappings only */
4966b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map->rx)
497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
4986b5625bb609b154766d2e138b61e15655f60b710sewardj
4996b5625bb609b154766d2e138b61e15655f60b710sewardj      /* degenerate case: r-x section is empty */
5006b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->size == 0)
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5026b5625bb609b154766d2e138b61e15655f60b710sewardj      has_nonempty_rx = True;
5036b5625bb609b154766d2e138b61e15655f60b710sewardj
5046b5625bb609b154766d2e138b61e15655f60b710sewardj      /* normal case: r-x section is nonempty */
5056b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (0) */
5066b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(map->size > 0);
5076b5625bb609b154766d2e138b61e15655f60b710sewardj
5086b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (1) */
5096b5625bb609b154766d2e138b61e15655f60b710sewardj      for (di2 = debugInfo_list; di2; di2 = di2->next) {
5106b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di2 == di)
5116b5625bb609b154766d2e138b61e15655f60b710sewardj            continue;
5126b5625bb609b154766d2e138b61e15655f60b710sewardj         for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
5136b5625bb609b154766d2e138b61e15655f60b710sewardj            struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
5146b5625bb609b154766d2e138b61e15655f60b710sewardj            if (!map2->rx || map2->size == 0)
5156b5625bb609b154766d2e138b61e15655f60b710sewardj               continue;
5166b5625bb609b154766d2e138b61e15655f60b710sewardj            vg_assert(!ranges_overlap(map->avma,  map->size,
5176b5625bb609b154766d2e138b61e15655f60b710sewardj                                      map2->avma, map2->size));
5186b5625bb609b154766d2e138b61e15655f60b710sewardj         }
5196b5625bb609b154766d2e138b61e15655f60b710sewardj      }
5206b5625bb609b154766d2e138b61e15655f60b710sewardj      di2 = NULL;
5216b5625bb609b154766d2e138b61e15655f60b710sewardj
5226b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (2) */
5236b5625bb609b154766d2e138b61e15655f60b710sewardj      if (di->cfsi) {
5246b5625bb609b154766d2e138b61e15655f60b710sewardj         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
5256b5625bb609b154766d2e138b61e15655f60b710sewardj         /* Assume the csfi fits completely into one individual mapping
5266b5625bb609b154766d2e138b61e15655f60b710sewardj            for now. This might need to be improved/reworked later. */
5276b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di->cfsi_minavma >= map->avma &&
5286b5625bb609b154766d2e138b61e15655f60b710sewardj             di->cfsi_maxavma <  map->avma + map->size)
5296b5625bb609b154766d2e138b61e15655f60b710sewardj            cfsi_fits = True;
5306b5625bb609b154766d2e138b61e15655f60b710sewardj      }
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5326b5625bb609b154766d2e138b61e15655f60b710sewardj
5336b5625bb609b154766d2e138b61e15655f60b710sewardj   /* degenerate case: all r-x sections are empty */
5346b5625bb609b154766d2e138b61e15655f60b710sewardj   if (!has_nonempty_rx) {
5356b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(di->cfsi == NULL);
5366b5625bb609b154766d2e138b61e15655f60b710sewardj      return;
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5386b5625bb609b154766d2e138b61e15655f60b710sewardj
5396b5625bb609b154766d2e138b61e15655f60b710sewardj   /* invariant (2) - cont. */
5406b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->cfsi)
5416b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(cfsi_fits);
5426b5625bb609b154766d2e138b61e15655f60b710sewardj
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
582f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
589f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
592731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
593731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
594731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
595731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
596731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
597731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
598731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
599731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
600731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
601731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
602731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
603731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
604731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
605731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
606731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
607731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
608731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
609731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
610731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
611731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
612731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
613731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
614731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
615731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
616731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
617731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
618731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
619731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
620731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
6216b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges specified in the _DebugInfoFsm mapping array. First
6226b5625bb609b154766d2e138b61e15655f60b710sewardj      get rid of any other DebugInfos which overlap any of those
6236b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges (to avoid total confusion). */
624731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
625731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
626731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* .. and acquire new info. */
627731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGO_linux)
628731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
629731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
630731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
631731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
632731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
633731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
634731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
635731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
636731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
637731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
638731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
639731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
640731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      cfsi_cache__invalidate();
641731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
642731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
643731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
644731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
645731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
646731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
647731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
648731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      tl_assert(di->handle > 0);
649731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
650731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Check invariants listed in
651731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
652731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         priv_storage.h. */
653731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      check_CFSI_related_invariants(di);
654731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
655731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
656731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
657731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
658731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
659731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
660731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
661731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
662731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
663731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
664731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
665731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
666731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
667731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
668731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
669731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
670731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
671731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
672731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
6799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
6809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
6815f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   If use_fd is not -1, that is used instead of the filename; this
6825f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   avoids perturbing fcntl locks, which are released by simply
6835f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   re-opening and closing the same file (even via different fd!).
6845f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
6859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
6869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
6879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
6889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
6899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
6909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6925f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
696731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
6985f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   Int        actual_fd, oflags;
6995f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   SysRes     preadres;
700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
702ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
703ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7055f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(use_fd >= -1);
7065f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
714a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
7259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
7309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7320ab84fe82d1e25c2e0544d08826df42caa44ded1bart   /*
7330ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * Cannot read from these magic files:
7340ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- WARNING: Serious error when reading debug info
7350ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- When reading debug info from /proc/xen/privcmd:
7360ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- can't read file to inspect ELF header
7370ab84fe82d1e25c2e0544d08826df42caa44ded1bart    */
7380ab84fe82d1e25c2e0544d08826df42caa44ded1bart   if (VG_(strncmp)(filename, "/proc/xen/", 10) == 0)
7390ab84fe82d1e25c2e0544d08826df42caa44ded1bart      return 0;
7400ab84fe82d1e25c2e0544d08826df42caa44ded1bart
741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
744ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
74515728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
746ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
747ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
748ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
7499c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
750ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
751ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
752ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
753cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
754ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
755ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
756e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
757ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
758a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
759ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
760ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
7619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
7622ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
7632ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
764ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
765ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
7669c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
7679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
768ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
769ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
77015728ab41ea41bf731dcc74ac68354550ced2189bart
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
795eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
804f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
805f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
806f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
807b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
808b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
809b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
810b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
811b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
812b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
813b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
814b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
815b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
819731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
820731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
8215db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32)
822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
8243026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
827b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
828b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
829b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
830eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
832eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
834731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
835731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
836731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
837731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
841eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
842731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
843731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
8449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
845eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8465a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
8475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
8485a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
849cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
850cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
851cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
852cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
8535f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8545f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8555f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      SysRes fd = VG_(open)( filename, oflags, 0 );
8565f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      if (sr_isError(fd)) {
8575f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         if (sr_Err(fd) != VKI_EACCES) {
8585f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            DebugInfo fake_di;
8595f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            VG_(memset)(&fake_di, 0, sizeof(fake_di));
8605f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            fake_di.fsm.filename = filename;
8615f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            ML_(symerr)(&fake_di, True,
8625f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                        "can't open file to inspect ELF header");
8635f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         }
8645f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         return 0;
8655a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
8665f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = sr_Res(fd);
8675f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   } else {
8685f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = use_fd;
8695a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8705a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8715f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   preadres = VG_(pread)( actual_fd, buf1k, sizeof(buf1k), 0 );
8725f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8735f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      VG_(close)( actual_fd );
8745f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   }
8755f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8765f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_isError(preadres)) {
8775a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
8785a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
879a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      fake_di.fsm.filename = filename;
8805a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
8815a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8825a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8835f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_Res(preadres) == 0)
8845f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      return 0;
8855f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
8865a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8878b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
8886e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
889f7c9714ea0cde18daaecb896278e85e780d3bd75sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
8905a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8916e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
8925f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
893f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
8946e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
8956e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
8966e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
8975a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
9000f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
9036b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Note the details about the mapping. */
9046b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping map;
9056b5625bb609b154766d2e138b61e15655f60b710sewardj   map.avma = a;
9066b5625bb609b154766d2e138b61e15655f60b710sewardj   map.size = seg->end + 1 - seg->start;
9076b5625bb609b154766d2e138b61e15655f60b710sewardj   map.foff = seg->offset;
9086b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rx   = is_rx_map;
9096b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rw   = is_rw_map;
9106b5625bb609b154766d2e138b61e15655f60b710sewardj   map.ro   = is_ro_map;
9116b5625bb609b154766d2e138b61e15655f60b710sewardj   VG_(addToXA)(di->fsm.maps, &map);
9126b5625bb609b154766d2e138b61e15655f60b710sewardj
9136b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Update flags about what kind of mappings we've already seen. */
9146b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rx_map |= is_rx_map;
9156b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rw_map |= is_rw_map;
9166b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_ro_map |= is_ro_map;
917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
918731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
919731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
920731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
921731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
922731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
923731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
9249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
925731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
926731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
927731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
928731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
9299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
930eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
937f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
938a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
939f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
940f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
941f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
946eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
952f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
955f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
956f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
957f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
959f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
961eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
962731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
963731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* This is a MacOSX 10.7 32-bit only special.  See comments on the
964731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
965731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
966731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
967731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
968ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj#  if defined(VGP_x86_darwin) && (DARWIN_VERS == DARWIN_10_7 || DARWIN_VERS == DARWIN_10_8)
969731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
970731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
971731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (do_nothing /* wrong platform */)
972731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
973731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
974731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
975731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
976731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
977731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
978731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
979731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
980731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
981731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
982731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
983731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
984731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
9856b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping *map = NULL;
9866b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
987731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
988731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
989731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
990731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
991731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
992731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
993731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
994731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
995731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
996731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
9976b5625bb609b154766d2e138b61e15655f60b710sewardj      /* Try to find a mapping matching the memory area. */
9986b5625bb609b154766d2e138b61e15655f60b710sewardj      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
9996b5625bb609b154766d2e138b61e15655f60b710sewardj         map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10006b5625bb609b154766d2e138b61e15655f60b710sewardj         if (map->ro && map->avma == a && map->size == len)
10016b5625bb609b154766d2e138b61e15655f60b710sewardj            break;
10026b5625bb609b154766d2e138b61e15655f60b710sewardj         map = NULL;
10036b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10046b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map)
10056b5625bb609b154766d2e138b61e15655f60b710sewardj         continue; /* this isn't an upgrade of an r-- mapping */
1006731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
1007731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
1008731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
1009731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
1010731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
1011731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
10126b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Do the upgrade.  Simply update the flags of the mapping
10136b5625bb609b154766d2e138b61e15655f60b710sewardj      and pretend we never saw the RO map at all. */
1014731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
10156b5625bb609b154766d2e138b61e15655f60b710sewardj   map->rx = True;
10166b5625bb609b154766d2e138b61e15655f60b710sewardj   map->ro = False;
1017731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
1018731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
10196b5625bb609b154766d2e138b61e15655f60b710sewardj   /* See if there are any more ro mappings */
10206b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10216b5625bb609b154766d2e138b61e15655f60b710sewardj      map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10226b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->ro) {
10236b5625bb609b154766d2e138b61e15655f60b710sewardj         di->fsm.have_ro_map = True;
10246b5625bb609b154766d2e138b61e15655f60b710sewardj         break;
10256b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10266b5625bb609b154766d2e138b61e15655f60b710sewardj   }
10276b5625bb609b154766d2e138b61e15655f60b710sewardj
10286b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Check if we're now in an accept state and read debuginfo.  Finally. */
10296b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
10306b5625bb609b154766d2e138b61e15655f60b710sewardj      ULong di_handle __attribute__((unused))
10316b5625bb609b154766d2e138b61e15655f60b710sewardj         = di_notify_ACHIEVE_ACCEPT_STATE( di );
10326b5625bb609b154766d2e138b61e15655f60b710sewardj      /* di_handle is ignored. That's not a problem per se -- it just
10336b5625bb609b154766d2e138b61e15655f60b710sewardj         means nobody will ever be able to refer to this debuginfo by
10346b5625bb609b154766d2e138b61e15655f60b710sewardj         handle since nobody will know what the handle value is. */
10356b5625bb609b154766d2e138b61e15655f60b710sewardj   }
1036731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1037731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1038731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1039c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1040c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1041c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1042c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
104354c45db2f978055aeca91aaccb05aac825523e6csewardj                                   SizeT total_size, PtrdiffT bias_obj )
1044c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
104513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1046c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
1047c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char   exename[VKI_PATH_MAX];
1048c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  pdbname = NULL;
1049c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  dot;
1050c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1051c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1052c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1053c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1054c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1055c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1056738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1057c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1058cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
105954c45db2f978055aeca91aaccb05aac825523e6csewardj         "bias=%#lx\n",
106054c45db2f978055aeca91aaccb05aac825523e6csewardj         fd_obj, avma_obj, total_size, bias_obj
1061c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1062c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1063c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1064c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1065c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1066c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1067c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1068c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
1069c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
10709c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1071c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1072c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
1073c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
1074c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
1075c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
1076c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
1077c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
1078c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
1079c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
1080c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
1081c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
1082c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
1083c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1084c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1085738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1086c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1087c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
108813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
108913ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
109013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
109113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
109213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
109313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
109413ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
109513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
109613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
109713ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
109813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
109913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
110013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
110113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
110213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
110313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
110413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
110513ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
110613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
110713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
110813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
110913ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
111013ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
111113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
111213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
111313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
111413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
111513ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
111613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
111713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
111813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
111998500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/drive_%c%s",
112098500e2ee5f63f9c0af57835f7620d30848115f4bart                       wpfx, pdbname[0], &pdbname[2]);
112113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
112213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
112313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
112413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
112513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
112613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
112713ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
112813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
112913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
113013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
113198500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/.wine/drive_%c%s",
113298500e2ee5f63f9c0af57835f7620d30848115f4bart		       home, pdbname[0], &pdbname[2]);
113313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
113413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
113513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
113613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
113713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
113813ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
113913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
114013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
114113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
114213ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1143c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
114413ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
114513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
114613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
114713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
114813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
114913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
115013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
115113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
115213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
115313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
115413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
115513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
115613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
115713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
115813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
115913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
116013ac96dea734b3933a73524b991ac64fb48a4d57sewardj
116113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
116213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
116313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
116413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
116513ac96dea734b3933a73524b991ac64fb48a4d57sewardj
116613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
116713ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1168c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1169c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1170c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1171cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1172738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1173c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1174c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1175738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1176c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1177c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
11789c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
11797138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1180ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
11817138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
11827138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
11837138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
11847138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
11857138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
11867138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
11877138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1188738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1189ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1190ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1191ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1192c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1193c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1194c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1195cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1196738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1197c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1198c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1199c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1200cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1201cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1202cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1203cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1204cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1205cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1206cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1207cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1208cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
12099c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1210cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1211cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1212cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1213cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1214cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1215cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1216cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1217cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1218cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1219cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1220cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1221c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1222c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1223c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1224c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1225cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1226cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1227cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1228cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1229cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1230cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1231cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1232cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1233c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1234738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1235c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1236c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1237c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1238c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1239c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1240c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1241c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12420f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1243c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1245a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1246c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1247c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1248c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1249c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
125054c45db2f978055aeca91aaccb05aac825523e6csewardj     ML_(read_pdb_debug_info)( di, avma_obj, bias_obj,
1251c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1252c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1253c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1254c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1255c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1256c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1257cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1258cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1259cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1260cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                                 "%lu syms, %lu src locs, %lu fpo recs\n",
1261cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                     di->symtab_used, di->loctab_used, di->fpo_size);
1262cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1263c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1264c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1265c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1266c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1267c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1268c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12698b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
12704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
12714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1272eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1273eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1274eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1275eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1277eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
12799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
12809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
12819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
12829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
12839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
12849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
12859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
12869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
12879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
12889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
12899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12916b5625bb609b154766d2e138b61e15655f60b710sewardjstruct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di,
12926b5625bb609b154766d2e138b61e15655f60b710sewardj                                                 Addr lo, Addr hi )
12936b5625bb609b154766d2e138b61e15655f60b710sewardj{
12946b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
12956b5625bb609b154766d2e138b61e15655f60b710sewardj   vg_assert(lo <= hi);
12966b5625bb609b154766d2e138b61e15655f60b710sewardj
12976b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Optimization: Try to use the last matched rx mapping first */
12986b5625bb609b154766d2e138b61e15655f60b710sewardj   if (   di->last_rx_map
12996b5625bb609b154766d2e138b61e15655f60b710sewardj       && lo >= di->last_rx_map->avma
13006b5625bb609b154766d2e138b61e15655f60b710sewardj       && hi <  di->last_rx_map->avma + di->last_rx_map->size)
13016b5625bb609b154766d2e138b61e15655f60b710sewardj      return di->last_rx_map;
13026b5625bb609b154766d2e138b61e15655f60b710sewardj
13036b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
13046b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
13056b5625bb609b154766d2e138b61e15655f60b710sewardj      if (   map->rx && map->size > 0
13066b5625bb609b154766d2e138b61e15655f60b710sewardj          && lo >= map->avma && hi < map->avma + map->size) {
13076b5625bb609b154766d2e138b61e15655f60b710sewardj         di->last_rx_map = map;
13086b5625bb609b154766d2e138b61e15655f60b710sewardj         return map;
13096b5625bb609b154766d2e138b61e15655f60b710sewardj      }
13106b5625bb609b154766d2e138b61e15655f60b710sewardj   }
13116b5625bb609b154766d2e138b61e15655f60b710sewardj
13126b5625bb609b154766d2e138b61e15655f60b710sewardj   return NULL;
13136b5625bb609b154766d2e138b61e15655f60b710sewardj}
13146b5625bb609b154766d2e138b61e15655f60b710sewardj
13156b5625bb609b154766d2e138b61e15655f60b710sewardj
1316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1328f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1332f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
133951c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
134051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
134151c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1342a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
13436b5625bb609b154766d2e138b61e15655f60b710sewardj                   && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL);
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
13585706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
13595706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13605706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
13615706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
13625706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
13635706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
13645706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13655706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
13665706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
13675706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
13685706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1380eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1390f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1392f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
13965706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1400eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1401eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1405eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1408eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1409eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1412eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
14136b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
14146b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
14156b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1418eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
14196b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
14206b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
14216b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Addr a, Char* buf, Int nbuf,
1422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1423c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1424eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1426f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1427c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1428eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1431eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
14326882443ef154bca367bc591287de641e43a9e108njn
1433a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
14346b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
1435a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   di->symtab[sno].pri_name, buf, nbuf );
14366b7611bf42a0fbb62e047d8c43b008205bd21e75njn
14376b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
14386b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
14396b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
14406b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
14416b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
14426b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
14436b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
14446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
14456b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1446eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1448c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1450eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1451eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1452eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1453eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1454eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1455eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1456c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1457eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1459eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1463eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14676b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
14686b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1478f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14936b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
14946b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14956b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1496b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1501eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1504eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1505eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15066b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
15076b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15086b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15206b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
15216b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15226b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15296b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
15306b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
15316b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
15326b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf )
1533eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15346b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
15356b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
15366b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
15446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
15456b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
15466b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15486b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
15496b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15506b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
15516b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
15526b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
15536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
15546b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15575db15403e889d4db339b342bc2a824ef0bfaa654sewardj/* mips-linux only: find the offset of current address. This is needed for
15585db15403e889d4db339b342bc2a824ef0bfaa654sewardj   stack unwinding for MIPS.
15595db15403e889d4db339b342bc2a824ef0bfaa654sewardj*/
15605db15403e889d4db339b342bc2a824ef0bfaa654sewardjBool VG_(get_inst_offset_in_function)( Addr a,
15615db15403e889d4db339b342bc2a824ef0bfaa654sewardj                                       /*OUT*/PtrdiffT* offset )
15625db15403e889d4db339b342bc2a824ef0bfaa654sewardj{
15635db15403e889d4db339b342bc2a824ef0bfaa654sewardj   Char fnname[64];
15645db15403e889d4db339b342bc2a824ef0bfaa654sewardj   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
15655db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*below-main-renaming*/False,
15665db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         a, fnname, 64,
15675db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*match_anywhere_in_sym*/True,
15685db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*show offset?*/True,
15695db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*data syms only please*/True,
15705db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         offset );
15715db15403e889d4db339b342bc2a824ef0bfaa654sewardj}
15725db15403e889d4db339b342bc2a824ef0bfaa654sewardj
15736882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind) ( Char* name )
15746882443ef154bca367bc591287de641e43a9e108njn{
15756882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
15766882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
15776882443ef154bca367bc591287de641e43a9e108njn
15786882443ef154bca367bc591287de641e43a9e108njn   } else if (
15793026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
15806882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
15816882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
15823026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
15853026f71684a930286186aa10fef266c304672e8fsewardj#      else
15863026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
15873026f71684a930286186aa10fef266c304672e8fsewardj#      endif
15886882443ef154bca367bc591287de641e43a9e108njn       0) {
15896882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
15906882443ef154bca367bc591287de641e43a9e108njn
15916882443ef154bca367bc591287de641e43a9e108njn   } else {
15926882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
15936882443ef154bca367bc591287de641e43a9e108njn   }
15946882443ef154bca367bc591287de641e43a9e108njn}
15956882443ef154bca367bc591287de641e43a9e108njn
15966882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
15976882443ef154bca367bc591287de641e43a9e108njn{
15986882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
15996882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
16006882443ef154bca367bc591287de641e43a9e108njn   Char buf[50];
16016882443ef154bca367bc591287de641e43a9e108njn
16026882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
16036882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
16046b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
16056882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
16066882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
16076882443ef154bca367bc591287de641e43a9e108njn   } else {
16086882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
16096882443ef154bca367bc591287de641e43a9e108njn   }
16106882443ef154bca367bc591287de641e43a9e108njn}
16116882443ef154bca367bc591287de641e43a9e108njn
1612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1618c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
16226b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
16236b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
16246b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1641f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1642f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
16434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
16447cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
16457cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16485706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1651a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
16524ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
16567cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
16577cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
16587cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
16597cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
16607cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
16617cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
16627cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1663f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1664f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1665f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1666eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1667eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1670eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1671e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1673e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1675e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16785706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1681e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1682e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1693f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1705f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1708eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1709eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1720eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1724f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1728eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1731c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1732db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1733db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1734db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1735db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1737c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1738c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1739eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1741eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1746eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1747eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
17624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
17634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
17644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
17654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
17664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
17674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
17704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
17714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
17724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
17744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
17754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
17764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
17774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
17794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
17804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
17814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
17824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
17834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
17844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
17854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
17864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
1787a5cace0c2a3e212931badbf6398a0cd98393121asewardj         UChar* pri_name = si->symtab[i].pri_name;
1788a5cace0c2a3e212931badbf6398a0cd98393121asewardj         tl_assert(pri_name);
1789a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
17904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
17914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
17924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
17934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
17944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
1795a5cace0c2a3e212931badbf6398a0cd98393121asewardj         UChar** sec_names = si->symtab[i].sec_names;
1796a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
1797a5cace0c2a3e212931badbf6398a0cd98393121asewardj            tl_assert(sec_names[0]);
1798a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
1799a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
1800a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   && (require_pToc ? si->symtab[i].tocptr : True)) {
1801a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pEnt = si->symtab[i].addr;
1802a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pToc = si->symtab[i].tocptr;
1803a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
1804a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
1805a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
1806a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
1807a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
18084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
18094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
18104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
18114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
18124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
18134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1814e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1815e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1816e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1817e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1818e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1821eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1822e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1823e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1824eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1825eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1826e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1827eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1829eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1830e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1831e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1832e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1833e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1834e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1835eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1837e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1838e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1839e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1841e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1842e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1843e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1844eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1845e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1846e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1847e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1848e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1849e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1850e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1851e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1852e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1853e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1854e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1855e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1856e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1857e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1858e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1859e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1860e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1861e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1862e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1863e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1864e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1865e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1866e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1869e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1870e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1871e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1878e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1879e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1880e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1885eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
188614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1887eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1888eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1889eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1890eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
189114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
189214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1893eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
18944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
18954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
18964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1897eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1899eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1900eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1901eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
190414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
190514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
190614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
190714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
190814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1913eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1914eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1915e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1916e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1917e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1918e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1919e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1920e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1922a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1928e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1930eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1934e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1941e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1946e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1958eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1959eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
19605e40abad4504416c59f0b29c1cfc8087201213a9njn      //
19615e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
19625e40abad4504416c59f0b29c1cfc8087201213a9njn      //
19635e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
19645e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
19655e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
19665e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
19675e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
19685e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
19695e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1970a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1971eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
19725e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1973eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1975eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1976eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1977eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1978eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
197914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
198014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         UChar* dirname = NULL;
198114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
198214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
198314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
198414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
198514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
198614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
198714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
198814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* prefix = VG_(clo_fullpath_after)[i];
198914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* str    = VG_(strstr)(dirname, prefix);
199014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
199114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
199214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
199314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
199414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
199514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
199614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
199714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
199814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
199914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
200014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
200114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
200214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
200314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
20045dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
2005eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
2006eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
2007eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2008eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2009eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
20105e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
20115e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
20125e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
20135e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
20145e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
20155e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
20165e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
20175e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
2018eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2019eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2020eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2021eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
2022eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2023eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
2024eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
2025eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
2026eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2027eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
202872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
2033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
203572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
203672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
203772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
203872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
203972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
20403026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
20413026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
20423026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
204372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
204472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
204572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
204672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
204772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
204872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
2049f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
2050f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
205172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
205272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
205372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
205472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
205519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
20563026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
20573026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
20583026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
205972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
206072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
206172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
206272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
206372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
206472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
206572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
2066f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Add: return wL + wR;
2067f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Sub: return wL - wR;
2068f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_And: return wL & wR;
2069f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Mul: return wL * wR;
2070f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shl: return wL << wR;
2071f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shr: return wL >> wR;
2072f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Eq: return wL == wR ? 1 : 0;
2073f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2074f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2075f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2076f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
2077f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ne: return wL != wR ? 1 : 0;
207872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
207972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
208072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
208172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
208272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
20833026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
20843026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
20853026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
20863026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
20873026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
20883026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
20893026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2090fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2091fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2092b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2093b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
2094b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
2095b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
2096b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
20975db15403e889d4db339b342bc2a824ef0bfaa654sewardj#           elif defined(VGA_mips32)
20985db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_IP: return eec->uregs->pc;
20995db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_SP: return eec->uregs->sp;
21005db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_BP: return eec->uregs->fp;
21015db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_MIPS_RA: return eec->uregs->ra;
21023026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
21033026f71684a930286186aa10fef266c304672e8fsewardj#           else
21043026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
21053026f71684a930286186aa10fef266c304672e8fsewardj#           endif
210672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
210772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
210872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
210972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
211072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
211119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
211219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
211319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
211419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
2115720e6b71b171885281afab634ce4d667c1f262bcsewardj             || a > eec->max_accessible - sizeof(UWord) + 1) {
211619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
211719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
211819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
211919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
212086781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
212172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
212272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
212372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
212472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
212572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
212672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
212772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
212872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
212972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
213072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
213172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
213272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
213372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
213472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2135f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
2136f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2138f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
2139f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
214072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2141f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
2142f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2143f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2144f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
2145f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
2146f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2147f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2148f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2149f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2150f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2151f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2152f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2155f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2157f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2158f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2159eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2168f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2169f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2170f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2171f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2172f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2173f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2174f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2178f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2179f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2180f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2181f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
2182f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
2183f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2184f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2185f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2186f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
2187f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2188f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2189f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
2190f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
2191f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
2192f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
2193f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2194f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2195f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2196f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2197f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2198f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2199f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2200f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2201f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2202f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2203f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2204f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2205f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2206f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2207f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2208f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2209f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2210f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2211f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2212f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2213f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2214f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2215f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2216f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2217f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2218f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2219f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2220f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
2221f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2222f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2223f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
2224f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
2225f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
2226f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2227f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2228f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2229f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2230f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
2231f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
2232f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
2233f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
2234f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
2235f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
2236f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
2237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2238f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
2239f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2240f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
2241f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
2242f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
2243f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2244f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
2245f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2246f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
2247f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
2248f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2249f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2250f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2251f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic inline CFSICacheEnt* cfsi_cache__find ( Addr ip )
2252f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
22533c9cf3442185b5891e15450d6e3058aeff6796fetom   UWord         hash = ip % N_CFSI_CACHE;
22543c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce = &cfsi_cache[hash];
22553c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2256f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2257f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2258f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2259f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2260f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
22613c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
22623c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
22633c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
22643c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
22653c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
22663c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
22673c9cf3442185b5891e15450d6e3058aeff6796fetom      find_DiCfSI( &ce->di, &ce->ix, ip );
22683c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2269eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22703c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
22713c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
22723c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
22733c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
22743c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
22753c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
22773c9cf3442185b5891e15450d6e3058aeff6796fetom}
2278eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2279eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2280f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
22813026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
22823c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
22833c9cf3442185b5891e15450d6e3058aeff6796fetom                          DebugInfo* di, DiCfSI* cfsi )
22843c9cf3442185b5891e15450d6e3058aeff6796fetom{
22853c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
22863c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
22873c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22893c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
229072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
229172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
22923026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
22933026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
22943026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xsp;
22953026f71684a930286186aa10fef266c304672e8fsewardj         break;
22963026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
22973026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xbp;
229872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
22993026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
23003026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
23013026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r13;
230272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
23033026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
23043026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r12;
23053026f71684a930286186aa10fef266c304672e8fsewardj         break;
23063026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
23073026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r11;
23083026f71684a930286186aa10fef266c304672e8fsewardj         break;
2309fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
2310fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         cfa = cfsi->cfa_off + uregs->r7;
2311fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2312b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2313b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
2314b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->sp;
2315b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2316b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2317b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
2318b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         Addr a = uregs->sp + cfsi->cfa_off;
2319b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2320b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
232186781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2322b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2323b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2324b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2325b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2326b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2327b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
2328b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->fp;
2329b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
23305db15403e889d4db339b342bc2a824ef0bfaa654sewardj#     elif defined(VGA_mips32)
23315db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_SPREL:
23325db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = cfsi->cfa_off + uregs->sp;
23335db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23345db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIR_SAME:
23355db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = uregs->fp;
23365db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23375db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_BPREL:
23385db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = cfsi->cfa_off + uregs->fp;
23395db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23403026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
23413026f71684a930286186aa10fef266c304672e8fsewardj#     else
23423026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
23433026f71684a930286186aa10fef266c304672e8fsewardj#     endif
23443026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
23457888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
23467888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2347f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
23487888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
23497888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
23503026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
23517888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
23527888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
23537888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2354f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
23553c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
235672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
235772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
235872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
235972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
23603c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
23613c9cf3442185b5891e15450d6e3058aeff6796fetom}
23623c9cf3442185b5891e15450d6e3058aeff6796fetom
23633c9cf3442185b5891e15450d6e3058aeff6796fetom
23643c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
23653026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
23663026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
23673c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
23683c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
23693c9cf3442185b5891e15450d6e3058aeff6796fetom{
23703c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce;
23713c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*    di;
2372d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   DiCfSI*       cfsi __attribute__((unused));
23733c9cf3442185b5891e15450d6e3058aeff6796fetom
23743c9cf3442185b5891e15450d6e3058aeff6796fetom   ce = cfsi_cache__find(ip);
23753c9cf3442185b5891e15450d6e3058aeff6796fetom
23763c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
23773c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
23783c9cf3442185b5891e15450d6e3058aeff6796fetom
23793c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
23803c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
23813c9cf3442185b5891e15450d6e3058aeff6796fetom
23823026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
23833026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
23843026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
23853026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
23863026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
23873026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
23883026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
23893026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
23903026f71684a930286186aa10fef266c304672e8fsewardj                        min_accessible,  max_accessible, di, cfsi);
23913026f71684a930286186aa10fef266c304672e8fsewardj   }
2392b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2393b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2394b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2395b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2396b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2397b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
2398b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                        min_accessible,  max_accessible, di, cfsi);
2399b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2400b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
24013026f71684a930286186aa10fef266c304672e8fsewardj#  else
24023026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
24033026f71684a930286186aa10fef266c304672e8fsewardj#  endif
24043c9cf3442185b5891e15450d6e3058aeff6796fetom}
24053c9cf3442185b5891e15450d6e3058aeff6796fetom
24063c9cf3442185b5891e15450d6e3058aeff6796fetom
24073026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
24083026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
24093026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
24103026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
24113026f71684a930286186aa10fef266c304672e8fsewardj
24123026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
24133026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
24143026f71684a930286186aa10fef266c304672e8fsewardj
2415fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
24163026f71684a930286186aa10fef266c304672e8fsewardj*/
24173026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
24183c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
24193c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
24203c9cf3442185b5891e15450d6e3058aeff6796fetom{
24213c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
24223c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*            cfsi = NULL;
24233026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
24243c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt*      ce;
2425d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
24263026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
24273c9cf3442185b5891e15450d6e3058aeff6796fetom
24283026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
24293026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
24303026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
24313026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2432b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2433b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
24345db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  elif defined(VGA_mips32)
24355db15403e889d4db339b342bc2a824ef0bfaa654sewardj   ipHere = uregsHere->pc;
24363026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
24373026f71684a930286186aa10fef266c304672e8fsewardj#  else
24383026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
24393026f71684a930286186aa10fef266c304672e8fsewardj#  endif
24403026f71684a930286186aa10fef266c304672e8fsewardj   ce = cfsi_cache__find(ipHere);
24413c9cf3442185b5891e15450d6e3058aeff6796fetom
24423c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
24433c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
24443c9cf3442185b5891e15450d6e3058aeff6796fetom
24453c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
24463c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
24473c9cf3442185b5891e15450d6e3058aeff6796fetom
24483c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
24493c9cf3442185b5891e15450d6e3058aeff6796fetom      VG_(printf)("found cfisi: ");
24503c9cf3442185b5891e15450d6e3058aeff6796fetom      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
24513c9cf3442185b5891e15450d6e3058aeff6796fetom   }
24523c9cf3442185b5891e15450d6e3058aeff6796fetom
2453f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
24543c9cf3442185b5891e15450d6e3058aeff6796fetom
24553c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
24563026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
24573026f71684a930286186aa10fef266c304672e8fsewardj                     min_accessible, max_accessible, di, cfsi);
24583c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
24593c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
246072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
246172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
246272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2463eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2467eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2468eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
24749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
247686781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
248272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
248372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2484f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
24853026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
248672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
248772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2488d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
249072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
249172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
249272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
249372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2494eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2495eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24973026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
24983026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
24999365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
25009365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
25013026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
25023026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how,  cfsi->ra_off);
25033026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
25043026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
25053026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
25063026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
2507fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi->r7_how,  cfsi->r7_off);
2508b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2509b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
2510b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
2511b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
25125db15403e889d4db339b342bc2a824ef0bfaa654sewardj#  elif defined(VGA_mips32)
25135db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off);
25145db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
25155db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
25163026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
25173026f71684a930286186aa10fef266c304672e8fsewardj#  else
25183026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
25193026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2520eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2521eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25233026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2530c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2531c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2532c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2533c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2534c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2535c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2536c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2537c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2538c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2539c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2540c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2541c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2542c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2543c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2544c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2545c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2546c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2547c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2548c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2549c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2550c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2551c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2552c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2553c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2554c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2555c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2556c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2557c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2558c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2559c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2560c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2561c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2562c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2563c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2564c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2565c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2566c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2567c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2568c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2569c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2570c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2571c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2572c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2573c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2574c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2575c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2576c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2577c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2578c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2579c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2580c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2581c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2582c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2583c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2584c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2585c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2586c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2587c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2588c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2589c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2590c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2591c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2592c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2593c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2594c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2595c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2596c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2597c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2598c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2599c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2600c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2601c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2602c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2603c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2604c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2605c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2606c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2607c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2608c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2609c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2610c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2611c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2612c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2613c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2614c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2615c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2616c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2617c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2618c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2619c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2620c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2621c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2622c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2623c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2624c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2625c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2626c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2627c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2628c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2629c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2630c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2631c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2632c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2633c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2634c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2635c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2636c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2637c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2638c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2639c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2640c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2641c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
264286781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
264386781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
264486781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
264586781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
2646c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2647c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2648c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2649c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2650c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2651c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2657588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2658b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   VG_(xaprintf)(dst, fmt, args) without having to resort to
2659588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2660588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2661738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2662588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2663b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   //   VG_(xaprintf)(dstxa, format, ##args)
2664738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2665b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart#define  p2XA  VG_(xaprintf)
2666738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2667588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2668588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2669738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2670738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2671738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2672738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2673738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2674738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2675738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2681c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
26829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2686588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
268850fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
26929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
269750fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
269850fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
269950fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
270050fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
270150fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
270250fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
270350fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
270450fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
270550fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
270650fde23467d92281b32dd537d0d9a590263628c3sewardj
270750fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2710a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
27129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2723588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
27313c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2742738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
2743738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
2744738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
2745738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
2746738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
2747738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
2748738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
2749738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
2750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2752c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2753c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2758738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
2759738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
2760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2762738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar* basetag   = "auxwhat"; /* a constant */
2763738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar tagL[32], tagR[32], xagL[32], xagR[32];
2764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2765d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
2766d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
2767d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2768d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
2769d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
2770d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2771d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
2772d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
2773d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2774d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
2775738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
2776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2782738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
2783738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
2784738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
2785738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
2786738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
2787738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
2788738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
2789738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
2791738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
2792738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
2793738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
2794738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
2795738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
2796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2804738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2805738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2806738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2807b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\",",
2808738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2809738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2810738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2811738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2812738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2813738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2814738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2815738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2816738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2817738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2818738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2819738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2820738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2828738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2829738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2830738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2831b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\"",
2832738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2833738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2834738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2835738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2836738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2837b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
2838738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2839738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2840738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2841738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2842b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2843738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2844738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2845738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2846738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2847738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2848738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2849738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2850738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2851738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2852738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2860738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2861738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2862738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2863b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS",
2864738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2865738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2866738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2867738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2868738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2869738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2870738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2871738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2872738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2873738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
2874738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2875738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2876738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2877738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2878738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2882738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2883738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
2884738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2885738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2886738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2887b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
2888738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2889738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2890738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2891738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2892738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2893738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2894b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
2895738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2896738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2897738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2898738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2899b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2900738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2901738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2902738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2903738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2904738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2905738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2906738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2907738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2908738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2909738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2910738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2918738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2919738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2920738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2921b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
2922738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2923738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2924738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2925738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2926738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2927738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2928738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2936738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2937738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2938738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2939b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
2940738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2941738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2942738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2943738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2944738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2945b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d",
2946738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2947738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2948738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2949738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2950b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2951738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2952738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2953738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2954738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2955738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2956738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2957738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2958738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
2959738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2960738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2967b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2968738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2969738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2970738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2971b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
2972738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2973738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2974738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2975738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2976738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2977738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2978738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2979738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2980738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2981738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2982738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2983738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
2984738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2985738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2986738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2990738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2991738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
2992738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2993738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2994738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2995b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
2996738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2997738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2998738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2999738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3000738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3001738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3002b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "a global variable declared at %pS:%d",
3003738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3004738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3005738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3006738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3007b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3008738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3009738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3010738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3011738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3012738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3013738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3014738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3015738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3016738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
3017738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3018738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
3022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3023738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
3024738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
3025738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
3026738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3027738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
3028738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
3029738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
3030738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
3031738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
3032738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
3033eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3034eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3035738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
3037738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
3038738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
3039738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
3040738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
3042738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
3043738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
3046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
3047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
3048eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
3050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
3052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
3053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
3055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
3056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
3057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
3058a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
3059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
3060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
3066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
3067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
3071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
3072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
3073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
3074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
3077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
3078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
3079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
3080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
3081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
3082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
3083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
3084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
3085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
3086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
3087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
3089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
3091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3140c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3142a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
31449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
31459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3146588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3147c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
31499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
31509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3151738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3163738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
3164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
3165738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3166738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3167738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3168738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3169738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3170738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3171738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3172738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3173738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3174738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3175738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3176738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
3177738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
3178738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
3179738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3180738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3192738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
3193738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
3194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3195a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
32029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3243c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
32529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3254588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3255c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
32579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
32589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3259738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3261d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3262d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3264738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3265738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
3276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
3277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
3278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
3279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
3280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
3281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3285738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
3288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
3289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
3290738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3291738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
3296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3310738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3311738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3320b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
3322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
3323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
3324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3326738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3328b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3330738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3331738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3348b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3349b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3350b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3351b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3352b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3353738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3354b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3355b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3356b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3357738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3358738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3364738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3365738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
33719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
33729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
33739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
33749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
33759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
33769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
33789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
33799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
33809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
33819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
33829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
33849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
33859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3386588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
33879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
33889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
33899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
33909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
339150fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
33929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
33939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
33949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
33969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
33979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
33989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
340050fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
340150fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
340250fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
340350fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
340450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
340550fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
340650fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
340750fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
340850fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
34099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
34119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
34129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
34139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
34159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
34169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
34179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
34189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
34199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
34219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
34229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
34249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
34259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
34269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
34279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
34289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
34299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3431588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
34349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3436588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
34399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3441588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
34449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3446588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
34499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
34509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
34519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34523c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
34539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
34549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
34559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
34569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
34579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
34589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
34599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
34619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
34629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
34639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
34659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
34669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
34679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3468588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34693c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
34709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
34719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
347250fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
34739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
347450fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
34759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
34769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
34779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
34789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
34799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
34809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
34819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
34829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
34849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
34859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
34869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3487588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34883c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
34899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
34909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
349150fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
34929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
349350fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
34949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
34959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
34969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
34979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
34989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
34999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
35009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
35019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
35039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
35049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
35079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
35109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
35119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
35129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
35139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
35159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
35169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
35179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
35189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
35199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
35209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
35219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
35239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
35249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
35259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
35279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
35289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
35299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
35309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
35319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
35329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
35339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
35349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
35359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
35369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
35379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
35389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
35399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
35409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
35439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
35449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
35459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
35469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
35479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
35499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
35509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
35519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
35529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
35539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
35549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
35559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
35569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
35579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
35589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
35599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
35619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
35639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
35649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
35659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
35679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
35689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
35699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
35709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
35719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
35739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
35749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
35759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
35769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
35779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
35789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
35799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
35809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
35819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
35829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
35839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
35849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
35859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
35869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
35879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
35889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
35899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
35909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
35919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
35929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
35939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
35949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
35959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
35969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
35979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
35989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
35999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
36009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
36019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
36029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
36039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
36049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
36059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
36069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
36079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
36089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
36099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
36109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
36119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
36129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3613588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
36149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
36159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
36169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
36189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
36199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
36229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
36239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
36249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
36259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
36269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
36279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
36299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
36309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
36319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
36329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
36339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
36359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
36369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
36379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
36399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
36409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
36419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
36429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
36439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
36449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
36459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
36479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
36489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
36499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
36509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
36529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
36539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
36549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
36559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
36579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
36589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
36599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
36619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
36629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
36639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
36649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
36659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
36679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
36689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
36699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
36709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
36719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
36729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
36739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
36759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
36769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
36779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
36789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
36799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
36819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
368250fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
36839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
36849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
36859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
36869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
36879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
36889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
36909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
36919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
36929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
36939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
36949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
36959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3696588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
36979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
36993c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
37009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
37019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
37029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
37039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
37059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
37069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
37079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
370950fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
37109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
371150fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
371250fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
371350fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
371450fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
371550fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
371650fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
371750fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
371850fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
37199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
37219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
37229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
37239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
37249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
37259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
37269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
37279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
37289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
37309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
37319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
37339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
37349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
37359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
37369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
37379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
37389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
37399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
374050fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
37419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
37429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
37439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
37449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
37459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
37469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
37489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
37509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
37529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
37549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
37569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
37579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3763e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
3764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3768eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3770e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
3771eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3773eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3774eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3775e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
3776eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3778eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3779eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3780e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
3781092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3782092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3783092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3784092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3785e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
3786092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3787092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3788092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3789092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3790e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
3791092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3792092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3793092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3794092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3795e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
3796092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3797092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3798092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3799092b6268cc4a38ae9ee41d1e3355937536ddc579bart
380068347837b3d82e48f85daff33ec7ba528891e4e7bartAddr VG_(DebugInfo_get_got_avma)(const DebugInfo* di)
380168347837b3d82e48f85daff33ec7ba528891e4e7bart{
380268347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_avma : 0;
380368347837b3d82e48f85daff33ec7ba528891e4e7bart}
380468347837b3d82e48f85daff33ec7ba528891e4e7bart
380568347837b3d82e48f85daff33ec7ba528891e4e7bartSizeT VG_(DebugInfo_get_got_size)(const DebugInfo* di)
380668347837b3d82e48f85daff33ec7ba528891e4e7bart{
380768347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_size : 0;
380868347837b3d82e48f85daff33ec7ba528891e4e7bart}
380968347837b3d82e48f85daff33ec7ba528891e4e7bart
3810e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
3811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3815e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
3816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3817a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
3818eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3820e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
3821bbec7728efefaa650970dd1f0282b77040287133sewardj{
3822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3823bbec7728efefaa650970dd1f0282b77040287133sewardj}
3824bbec7728efefaa650970dd1f0282b77040287133sewardj
3825e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
3826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3827eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3829eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3830e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
3831e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
3832a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    avma,
3833a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    tocptr,
3834a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UInt*    size,
3835a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UChar**  pri_name,
3836a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UChar*** sec_names,
3837a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isText,
3838a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isIFunc )
3839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3841a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (avma)      *avma      = si->symtab[idx].addr;
3842a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (tocptr)    *tocptr    = si->symtab[idx].tocptr;
3843a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
3844a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
3845a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (sec_names) *sec_names = si->symtab[idx].sec_names;
3846a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
3847a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
3848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3865b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
38675706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3874b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3875b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3877e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
3878e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
3879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3882b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3883b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3884b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3887e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
3888e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
3889a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
3890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3893b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3894b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3906b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
39195706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
39205706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
39215706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
39225706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
39235706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
39245706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3937092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3938092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3939092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3940092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3941092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3942092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3947b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3951b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3959a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
3960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3961a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         Int fnlen = VG_(strlen)(di->fsm.filename);
3962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3967d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3969a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            name[j] = di->fsm.filename[i];
3970a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            if (di->fsm.filename[i] == 0) break;
3971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3973d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3984eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3985eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3986eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3987eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3988