debuginfo.c revision f98e1c03ce4bea1fb092cdea5571c41f29f6df9b
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
114d474d086188fd1f29fa97dbd84d8ea2e589a9b8sewardj   Copyright (C) 2000-2008 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   Stabs reader greatly improved by Nick Nethercote, Apr 02.
33eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This module was also extensively hacked on by Jeremy Fitzhardinge
34eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and Tom Hughes.
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
384cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
40b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
41eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
42eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
43eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
48eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
5072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
51b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_stacktrace.h" // VG_(get_StackTrace)
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
56b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
62b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#elif defined(VGO_aix5)
644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_debuglog.h"
654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcproc.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcfile.h"
674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readxcoff.h"
684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
69eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
96f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
97f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
100c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
165eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* alloc_DebugInfo( const UChar* filename,
174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            const UChar* memname )
175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
179f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
180f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
1829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->handle    = handle_counter++;
1839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->filename  = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->memname   = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname)
185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                           : NULL;
186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
187f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
188f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      Now set up the debugging-output flags. */
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
190f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
191f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj        || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
192f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj                                          memname ));
193f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
199f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
200f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
203eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20859a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
21159a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->filename)   ML_(dinfo_free)(di->filename);
215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab)     ML_(dinfo_free)(di->symtab);
216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab)     ML_(dinfo_free)(di->loctab);
217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi)       ML_(dinfo_free)(di->cfsi);
218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs);
219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
221eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
23059a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
23459a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
23859a2d18d0ddfa241850017252b0804d469187d79sewardj
23959a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
24059a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
24159a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
24259a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
24359a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
24459a2d18d0ddfa241850017252b0804d469187d79sewardj      }
24559a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
24659a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VGP_ppc32_aix5)
2914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "__unload";
2924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  elif defined(VGP_ppc64_aix5)
2934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "kunload64";
2944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  else
2954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
2964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
2974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
30433e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
30533e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
307a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                         "Discarding syms at %#lx-%#lx in %s due to %s()",
308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
3104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         curr->filename ? curr->filename : (UChar*)"???",
3114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
31433e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
31533e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
330f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
332f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
334f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
358f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
361f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
362f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rx_map
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
397eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rw_map
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rx_map
404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rw_map
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#if defined(VGO_aix5)
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj__attribute__((unused))
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#endif
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find the existing DebugInfo for (memname,filename) or if not found,
466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   create one.  In the latter case memname and filename are strdup'd
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   into VG_AR_DINFO, and the new DebugInfo is added to
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debugInfo_list. */
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname )
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0==VG_(strcmp)(di->filename, filename)
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ( (memname && di->memname)
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ? 0==VG_(strcmp)(memname, di->memname)
479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  : True ))
480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = alloc_DebugInfo(filename, memname);
484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rx_map);
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rw_map);
505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* degenerate case: r-x section is empty */
506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->rx_map_size == 0) {
507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi == NULL);
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return;
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
510f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* normal case: r-x section is nonempty */
511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (0) */
512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->rx_map_size > 0);
513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (1) */
514f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di2 = debugInfo_list; di2; di2 = di2->next) {
515f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2 == di)
516f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2->rx_map_size == 0)
518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma);
521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di2 = NULL;
523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (2) */
524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma >= di->rx_map_avma);
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size);
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word i;
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
5764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   segment has been mapped in, or unmapped.  When that happens it
580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tries to acquire/discard whatever info is available for the
581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   corresponding object.  This section contains the notification
582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   handlers. */
583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
5899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
5909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
5919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
5929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
5939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
5949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
5959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
5969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
597eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
5989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
599eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       ok, is_rx_map, is_rw_map;
603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
6049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong      di_handle;
605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        nread;
607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
609ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
610ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
617eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
619a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
623eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
6309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
6359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
640ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
64115728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
642ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
643ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
644ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
64515728ab41ea41bf731dcc74ac68354550ced2189bart   vg_assert(statres.isError || ! VKI_S_ISLNK(statbuf.st_mode));
646ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
647ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
648ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
649ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   if (statres.isError) {
650ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
651ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
652e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
653ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
654ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         fake_di.filename = filename;
655ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
656ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
6579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
6582ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
6592ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
660ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
661ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
662ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   if (! VKI_S_ISREG(statbuf.st_mode))
6639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
664ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
665ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
66615728ab41ea41bf731dcc74ac68354550ced2189bart
66715728ab41ea41bf731dcc74ac68354550ced2189bart   /* Peer at the first few bytes of the file, to see if it is an ELF */
66815728ab41ea41bf731dcc74ac68354550ced2189bart   /* object file. Ignore the file if we do not have read permission. */
669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (fd.isError) {
67215728ab41ea41bf731dcc74ac68354550ced2189bart      if (fd.err != VKI_EACCES)
67315728ab41ea41bf731dcc74ac68354550ced2189bart      {
674d5dea1dabc523d3f96bafd52ae9586abd8797416bart         DebugInfo fake_di;
67515728ab41ea41bf731dcc74ac68354550ced2189bart         VG_(memset)(&fake_di, 0, sizeof(fake_di));
67615728ab41ea41bf731dcc74ac68354550ced2189bart         fake_di.filename = filename;
67715728ab41ea41bf731dcc74ac68354550ced2189bart         ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
67815728ab41ea41bf731dcc74ac68354550ced2189bart      }
6799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   nread = VG_(read)( fd.res, buf1k, sizeof(buf1k) );
682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(close)( fd.res );
683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
684d5dea1dabc523d3f96bafd52ae9586abd8797416bart   if (nread == 0)
6859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
686d5dea1dabc523d3f96bafd52ae9586abd8797416bart   if (nread < 0) {
687d5dea1dabc523d3f96bafd52ae9586abd8797416bart      DebugInfo fake_di;
688d5dea1dabc523d3f96bafd52ae9586abd8797416bart      VG_(memset)(&fake_di, 0, sizeof(fake_di));
689d5dea1dabc523d3f96bafd52ae9586abd8797416bart      fake_di.filename = filename;
690d5dea1dabc523d3f96bafd52ae9586abd8797416bart      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
6919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We're only interested in mappings of ELF object files. */
696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
6979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
709eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
720eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
728eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
732eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
735eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  if defined(VGP_x86_linux)
736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  elif defined(VGP_amd64_linux) \
739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If it is neither text-ish nor data-ish, we're not interested. */
751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!(is_rx_map || is_rw_map))
7529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ );
757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rx_map) {
762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rx_map = True;
763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_avma = a;
764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_size = seg->end + 1 - seg->start;
765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_foff = seg->offset;
766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
770eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rw_map) {
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rw_map = True;
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_avma = a;
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_size = seg->end + 1 - seg->start;
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_foff = seg->offset;
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If we don't have an rx and rw mapping, or if we already have
7849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      debuginfo for this mapping for whatever reason, go no
7859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      further. */
7869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) )
7879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Ok, so, finally, let's try to read the debuginfo. */
7909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(di->filename);
7919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
7929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ start ELF OBJECT "
7939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
7949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
7959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
7969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
7979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* We're going to read symbols and debug info for the avma
7989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
7999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      +rw_map_size).  First get rid of any other DebugInfos which
8009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      overlap either of those ranges (to avoid total confusion). */
8019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   discard_DebugInfos_which_overlap_with( di );
8029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* .. and acquire new info. */
8049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ok = ML_(read_elf_debug_info)( di );
8059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ok) {
8079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Canonicalising the "
8099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   "acquired info ------\n");
810f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* invalidate the CFI unwind cache. */
811f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
8129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* prepare read data for use */
8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(canonicaliseTables)( di );
8149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* notify m_redir about it */
8159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
8169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(redir_notify_new_DebugInfo)( di );
8179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Note that we succeeded */
8189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->have_dinfo = True;
8199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(di->handle > 0);
8209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = di->handle;
821f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Check invariants listed in
822f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
823f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         priv_storage.h. */
824f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      check_CFSI_related_invariants(di);
825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
8279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
8289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
8299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         this DebugInfo?  No - it contains info on the rw/rx
8309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         mappings, at least. */
8319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = 0;
832f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->have_dinfo == False);
8339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
834eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ end ELF OBJECT "
8389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return di_handle;
842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
843eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
844eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
845eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
846eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
848eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
849f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
850a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
851f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
852f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
853f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
854eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
855eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
856eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
857eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
858eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
859eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
860eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
861eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
862eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
863eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  if defined(VGP_x86_linux)
865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
867f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
868f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
869f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
870f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
871f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_linux) */
8754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
8784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
8794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/
8804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
8814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
8824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_aix5)
8844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* The supplied parameters describe a code segment and its associated
8864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   data segment, that have recently been mapped in -- so we need to
8874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   read debug info for it -- or conversely, have recently been dumped,
8884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   in which case the relevant debug info has to be unloaded. */
8894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_aix5_notify_segchange)(
8914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   code_start,
8924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   code_len,
8934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   data_start,
8944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   data_len,
8954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* file_name,
8964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* mem_name,
8974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   is_mainexe,
8984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   acquire )
8994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
9009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong hdl = 0;
9019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
902f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* play safe; always invalidate the CFI cache.  Not
903f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      that it should be used on AIX, but still .. */
904f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
905f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
9064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (acquire) {
9074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Bool       ok;
909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* di;
910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = find_or_create_DebugInfo_for( file_name, mem_name );
911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0) {
914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_present = True;
915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_svma = 0; /* don't know yet */
916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_bias = 0; /* don't know yet */
917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_avma = code_start;
918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_size = code_len;
919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (data_len > 0) {
921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_present = True;
922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_svma = 0; /* don't know yet */
923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_bias = 0; /* don't know yet */
924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_avma = data_start;
925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_size = data_len;
926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* These need to be filled in in order to keep various
929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         assertions in storage.c happy.  In particular see
930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Comment_Regarding_Text_Range_Checks" in that file. */
931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rx_map = True;
932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_avma = code_start;
933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_size = code_len;
934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rw_map = True;
935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_avma = data_start;
936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_size = data_len;
937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ok = ML_(read_xcoff_debug_info) ( di, is_mainexe );
939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ok) {
941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* prepare read data for use */
942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(canonicaliseTables)( di );
943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* notify m_redir about it */
944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(redir_notify_new_DebugInfo)( di );
945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note that we succeeded */
946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_dinfo = True;
9479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         hdl = di->handle;
9489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(hdl > 0);
949f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Check invariants listed in
950f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
951f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            priv_storage.h. */
952f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         check_CFSI_related_invariants(di);
953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /*  Something went wrong (eg. bad XCOFF file). */
955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         discard_DebugInfo( di );
956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di = NULL;
957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
9584ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
9594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   } else {
9604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Dump all the debugInfos whose text segments intersect
962f7cdfe298805a91a35b8e0495d9034cbf21003f5sewardj         code_start/code_len. */
963f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* CFI cache is always invalidated at start of this routine.
964f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Hence it's safe to ignore the return value of
965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         discard_syms_in_range. */
966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0)
967f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         (void)discard_syms_in_range( code_start, code_len );
9684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
9694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
9709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
9719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return hdl;
9724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
9734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
9744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
9754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_aix5) */
9764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
977eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
978eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
979eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
980eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
981eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
982eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
9849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
9859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
9869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
9879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
9889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
9899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
9909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
9919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
9929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
9939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
9949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
9959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
9969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
997eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
998eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
999eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1000eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1001eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1009f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1012eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1013f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
1020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = di->text_present
1021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_size > 0
1022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_avma <= ptr
1023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && ptr < di->text_avma + di->text_size;
1024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
1038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->bss_avma + di->bss_size);
1039eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1050eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1051eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1053eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1054eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1055eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1056eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1060f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1061eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1062f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
1066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1069eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1070eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1072eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1073eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1074eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1075eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1079eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1080eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1081eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
1082eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Caller supplies buf and nbuf.  If demangle is False, don't do
1083eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   demangling, regardless of VG_(clo_demangle) -- probably because the
1084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   call has come from VG_(get_fnname_nodemangle)().  findText
1085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1087eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool get_sym_name ( Bool demangle, Addr a, Char* buf, Int nbuf,
1089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool findText, /*OUT*/OffT* offsetP )
1091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1093f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        offset;
1095eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1099eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (demangle) {
1100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(demangle) ( True/*do C++ demangle*/,
1101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                      di->symtab[sno].name, buf, nbuf );
1102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(strncpy_safely) ( buf, di->symtab[sno].name, nbuf );
1104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1105eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (offsetP) *offsetP = (OffT)offset;
1108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1112eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1113eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1114eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      len = VG_(sprintf)(buf2, "%c%d",
1116eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1117eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1118eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1119eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1120eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1121eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1122eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1123eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1124eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1125eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1126eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1127eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1129eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1130eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1131eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1135f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1140eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1141eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1142eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1143eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1144eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1145eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1146eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1147eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1148eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1149eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
1151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1158eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1159eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
1162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
1174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1179eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names,
1181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and don't show offsets. */
1182eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
1183eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/False, a, buf, nbuf,
1185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1189eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1191eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
1192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   do Z-demangling, match anywhere in function, and don't show
1193eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   offsets. */
1194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_Z_demangle_only) ( Addr a, Char* buf, Int nbuf )
1195eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1196eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define N_TMPBUF 4096 /* arbitrary, 4096 == ERRTXT_LEN */
1197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char tmpbuf[N_TMPBUF];
1198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool ok;
1199eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(nbuf > 0);
1200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ok = get_sym_name ( /*demangle*/False, a, tmpbuf, N_TMPBUF,
1201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_fun*/True,
1202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*text syms only*/True,
1204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*offsetP*/NULL );
1205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tmpbuf[N_TMPBUF-1] = 0; /* paranoia */
1206eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (!ok)
1207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* We have something, at least.  Try to Z-demangle it. */
1210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(demangle)( False/*don't do C++ demangling*/, tmpbuf, buf, nbuf);
1211eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[nbuf-1] = 0; /* paranoia */
1213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1214eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef N_TMPBUF
1215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/OffT* offset )
1224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
1227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ok = get_sym_name ( /*demangle*/False, data_addr, dname, n_dname,
1228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
12434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int used;
1244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1245f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1246f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
12474ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
12487cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
12497cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
1252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(strncpy_safely)(buf, di->filename, nbuf);
1255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (di->memname) {
12564ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
12574ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
12584ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
12594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
12604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
1261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used);
12624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
12634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
12644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
12654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
12664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1267eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1268eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1269eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
12707cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
12717cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
12727cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
12737cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
12747cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
12757cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
12767cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1277f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1278f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1279f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* VG_(find_seginfo) ( Addr a )
1286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
1290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1302f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1314f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1333f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1340c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1341db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1342db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1343db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1344db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1346c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1347c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
13714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
13724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
13734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
13744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
13754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
13764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
13794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
13804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
13814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
13834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
13844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
13854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
13864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
13884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
13894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
13904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
13914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
13924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
13934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
13944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
13954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
13964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (0==VG_(strcmp)(name, si->symtab[i].name)
13974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
13984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
13994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
14004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
14014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
14024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
14034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
14044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
14054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
14064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
14074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1408e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1409e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1410e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1411e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1412e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1413eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1414eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1415eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1416e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1417e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1418eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1419eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1420e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1421eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1422eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1423eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1424e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1425e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1426e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1427e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1428e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1429eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1430eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1431e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1432e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1433e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1435e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1436e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1437e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1438eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1439e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1440e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1441e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1442e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1443e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1444e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1445e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1446e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1447e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1448e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1449e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1450e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1451e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1452e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1453e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1454e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1455e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1456e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1457e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1458e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1459e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1460e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1463e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1464e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1465e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1467eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1468eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1472e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1473e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1474e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
1480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
1484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
14854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
14864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
14874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1493eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1494eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
1495eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1497eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1499eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1501e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1502e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1503e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1504e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1505e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1506e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1507eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1508a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1509eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1510eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1511eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1512eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1514e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1520e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1521eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1523eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1527e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1532e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1533eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
1546a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (!know_srcloc && know_objname) {
1551eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(" (in ");
1552eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(buf_obj);
1553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(")");
1554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else if (know_objname && !know_srcloc) {
1556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("(within ");
1557eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_obj);
1558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
1559eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1560eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1561eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1562eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1563eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
1564eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1565eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1566eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
1569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1576eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
157972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
158672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
158772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
158872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
158972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
159072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
159172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr ipHere;
159272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr spHere;
159372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr fpHere;
159472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr min_accessible;
159572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr max_accessible;
159672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
159772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
159872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
159972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
160072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
160172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
160272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjstatic
160372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
160472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
160572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
160672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
160719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
160872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr* e = VG_(indexXA)( exprs, ix );
160972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
161072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
161172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
161272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
161372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
161472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
161572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
161672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
161772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
161819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
16197888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
162072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
162172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
162272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
162372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
162472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
162572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_IP: return (Addr)eec->ipHere;
162672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_SP: return (Addr)eec->spHere;
162772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_FP: return (Addr)eec->fpHere;
162872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
162972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
163072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
163172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
163272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
163319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
163419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
163519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
163619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
163719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
163819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
163919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
164019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
164119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
164219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         return * ((UWord*)a);
164372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
164472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
164572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
164672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
164772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
164872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
164972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
165072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
165172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
165272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
165372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
165472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
165572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
165672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1657f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
1658f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
1659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1660f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
1661f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
166272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1663f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
1664f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
1665f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
1666f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
1667f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
1668f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
1669f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1670f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
1671f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
1672f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1673f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
1674f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
1675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
1676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1677f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
1678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1679f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1680f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
1681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
1682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
1684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
1685f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1687f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1690f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
1691f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
1692f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
1693f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1694f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
1695f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
1696f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1700f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
1701f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1702f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
1703f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
1704f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
1705f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1706f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
1707f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1708f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
1709f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
1710f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
1711f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
1712f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
1713f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
1714f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
1715f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1716f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
1717f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
1718f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
1719f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
1720f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
1721f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
1722f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
1723f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
1724f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
1725f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
1726f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
1727f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
1728f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1729f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
1730f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
1731f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
1732f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
1733f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1734f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1735f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1736f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1737f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1738f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1739f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
1740f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
1741f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1742f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
1743f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
1744f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1745f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
1746f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
1747f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
1748f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1749f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
1750f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
1751f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1752f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
1753f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
1754f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
1755f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
1756f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
1757f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
1758f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1760f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
1761f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1762f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
1763f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
1764f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
1765f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1766f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
1767f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1768f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
1769f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
1770f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1771f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1772f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1773f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.
1774f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Given an IP/SP/FP triple, produce the IP/SP/FP values for the
1775f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   previous frame, if possible. */
1776f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Returns True if OK.  If not OK, *{ip,sp,fp}P are not changed. */
1777f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* NOTE: this function may rearrange the order of entries in the
1778f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo list. */
1779f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjBool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
1780f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        /*MOD*/Addr* spP,
1781f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        /*MOD*/Addr* fpP,
1782f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        Addr min_accessible,
1783f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        Addr max_accessible )
1784f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1785f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       ok;
1786f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
1787f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DiCfSI*    cfsi = NULL;
1788f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Addr       cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
1789f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1790f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CfiExprEvalContext eec;
1791f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1792f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_q = 0, n_m = 0;
1793f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
1794f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
1795f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
1796f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1797f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   { UWord hash = (*ipP) % N_CFSI_CACHE;
1798f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     CFSICacheEnt* ce = &cfsi_cache[hash];
1799f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1800f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
1801f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* found an entry in the cache .. */
1802f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     } else {
1803f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* not found in cache.  Search and update. */
1804f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        n_m++;
1805f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        ce->ip = *ipP;
1806f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        find_DiCfSI( &ce->di, &ce->ix, *ipP );
1807f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     }
1808f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1809f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (UNLIKELY(ce->di == (DebugInfo*)1)) {
1810f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* no DiCfSI for this address */
1811f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        cfsi = NULL;
1812f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        di = NULL;
1813f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     } else {
1814f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* found a DiCfSI for this address */
1815f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        di = ce->di;
1816f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        cfsi = &di->cfsi[ ce->ix ];
1817f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     }
1818eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1819f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1820f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (UNLIKELY(cfsi == NULL))
1821f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return False; /* no info.  Nothing we can do. */
1822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1823eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0) {
1824eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(printf)("found cfisi: ");
1825f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
1826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1827eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipPrev = spPrev = fpPrev = 0;
1829eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1830eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipHere = *ipP;
1831eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   spHere = *spP;
1832eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   fpHere = *fpP;
1833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
183472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* First compute the CFA. */
183572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
183672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
183772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_SPREL:
183872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + spHere;
183972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
184072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_FPREL:
184172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + fpHere;
184272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
184372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_EXPR:
18447888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
18457888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
1846f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
18477888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
18487888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
18497888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.ipHere = ipHere;
18507888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.spHere = spHere;
18517888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.fpHere = fpHere;
18527888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
18537888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
18547888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
1855f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
18567888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (!ok) return False;
185772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
185872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
185972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
186072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
186172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
186272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
186372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
1864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
1866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
1867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
1868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
1869eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
1870eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
1871eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
1872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
1873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
1874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
18759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
1876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = *(Addr*)a;                       \
1878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
1879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
1880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
1881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
1882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
188372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
188472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
1885f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
188672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.ipHere = ipHere;                     \
188772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.spHere = spHere;                     \
188872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.fpHere = fpHere;                     \
188972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
189072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
189172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               ok = True;                               \
1892f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
189372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
189472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
189572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
189672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
1897eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
1898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
1899eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1900eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(ipPrev, ipHere, cfsi->ra_how, cfsi->ra_off);
1901eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(spPrev, spHere, cfsi->sp_how, cfsi->sp_off);
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(fpPrev, fpHere, cfsi->fp_how, cfsi->fp_off);
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1904eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
1905eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *ipP = ipPrev;
1907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *spP = spPrev;
1908eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *fpP = fpPrev;
1909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
1916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
1917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
1921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
1922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
1923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
1924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
1925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool data_address_is_in_var ( /*OUT*/UWord* offset,
19269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
1927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
1928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
1929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
1930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_bias )
1931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
193250fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
1933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
1934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
1935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
19369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
1938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
1939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
194150fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
194250fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
194350fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
194450fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
194550fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
194650fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
194750fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
194850fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
194950fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
195050fde23467d92281b32dd537d0d9a590263628c3sewardj
195150fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
1952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
1954a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
1955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
19569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
1957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
1961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
1962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
1963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
1964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1967b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, data_bias );
1968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1969b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
1970b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
1971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
1972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (res.kind == GXR_Value
1976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
1977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
1978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
1979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
1980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
1981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Format the acquired information into dname1[0 .. n_dname-1] and
1987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname2[0 .. n_dname-1] in an understandable way.  Not so easy.
1988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If frameNo is -1, this is assumed to be a global variable; else
1989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   a local variable. */
1990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void format_message ( /*OUT*/Char* dname1,
1991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             /*OUT*/Char* dname2,
1992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      n_dname,
1993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
1994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
1995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             OffT     var_offset,
1996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             OffT     residual_offset,
1997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
1998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
1999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2000eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool have_descr, have_srcloc;
2002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(frameNo >= -1);
2006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(dname1 && dname2 && n_dname > 1);
2007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[0] = dname2[0] = '\0';
2014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
2029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
2043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
2044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s",
2054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2055a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
2059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        declared at dsyms7.c:17, in frame #1 of thread 1 */
2064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2068a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
2072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
2073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d",
2098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
2099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2110a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable");
2114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        a global variable declared at dsyms7.c:17 */
2119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2123a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable declared at %s:%d",
2127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
2128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
2131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
2136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characterised by (ip,sp,fp), and if so write its description into
2137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname{1,2}[0..n_dname-1], and return True.  If not, return
2138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   False. */
2139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
2140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool consider_vars_in_frame ( /*OUT*/Char* dname1,
2141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /*OUT*/Char* dname2,
2142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Int n_dname,
2143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
2144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
2145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
2146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
2147eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
2149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
2151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
2152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
2154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
2155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
2156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
2157a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
2158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
2159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
2160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
2161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
2165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
2166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
2170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
2171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
2172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
2173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
2176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
2177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
2178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
2179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
2180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
2181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
2182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
2183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
2184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
2185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
2186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
2188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
2190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
2191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
2194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
2195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
2196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
2197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
2199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
2200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
2201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
2203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
2204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
2206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
2207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
2208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
2209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
2210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
2211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
2212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
2214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
2215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
2216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
2217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
2218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
2219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
2220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
2222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
2223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
2224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
2225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
2226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
2227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
2228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
2229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
2230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
2231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
2232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
2233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
2234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
2235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
2236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
2237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
2238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
2239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         SizeT       offset;
2240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
2241a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
2242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
22439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
22449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
22459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     data_addr, di->data_bias )) {
2246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            OffT residual_offset = 0;
2247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
22489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
22499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
2251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
2253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2261eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Try to form some description of data_addr by looking at the DWARF3
2263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
2264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   frames in the stacks of all threads.  Result (or as much as will
2265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   fit) is put into into dname{1,2}[0 .. n_dname-1] and is guaranteed
2266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to be zero terminated. */
2267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_data_description)( /*OUT*/Char* dname1,
2268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                /*OUT*/Char* dname2,
2269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Int  n_dname,
2270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Addr data_addr )
2271eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
2273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
2274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
2275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
2277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
2278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
2279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
2281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
2283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2285a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
2286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
2287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
2288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
2289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
22929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
2293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
2294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
2295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
2296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
2302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
2303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
2305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
2306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
2308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
2309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
2310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
2311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
2312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
2313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
2314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
2315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
2316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
2317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
2318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
2319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
2320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
2321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
2322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
2323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
2324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
2325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
2326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
2327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
2329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
2330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
2331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
2332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
2333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         SizeT offset;
2334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
2335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
2336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
2337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
2338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
2339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
2340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
2341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
23429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
2343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
2344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     data_addr, di->data_bias )) {
2345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            OffT residual_offset = 0;
2346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
23479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
23489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
2350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, -1/*frameNo*/, tid );
2352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            dname1[n_dname-1] = dname2[n_dname-1] = 0;
2354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
2360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
2361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
2362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
2364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
2365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
2366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
2367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
2368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
2369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
2376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
2377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
2378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
2383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
2385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
2386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
2391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
2392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
2393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
2397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      dname1[n_dname-1] = dname2[n_dname-1] = 0;
2398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
2402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
2403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
2404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
2405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
2406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Re ip_delta in the next loop: There's a subtlety in the meaning
2407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of the IP values in a stack obtained from VG_(get_StackTrace).
2408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      The innermost value really is simply the thread's program
2409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      counter at the time the snapshot was taken.  However, all the
2410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      other values are actually return addresses, and so point just
2411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      after the call instructions.  Hence they notionally reflect not
2412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      what the program counters were at the time those calls were
2413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      made, but what they will be when those calls return.  This can
2414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      be of significance should an address range happen to end at the
2415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      end of a call instruction -- we may ignore the range when in
2416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      fact it should be considered.  Hence, back up the IPs by 1 for
2417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all non-innermost IPs.  Note that VG_(get_StackTrace_wrk) itself
2418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      has to use the same trick in order to use CFI data to unwind the
2419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack (as documented therein in comments). */
2420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
2421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
2422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
2423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
2424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
2425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word ip_delta = j == 0 ? 0 : 1;
2426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  ips[j] - ip_delta,
2429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
2430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
2434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
2435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
2436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
2437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
2438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
2439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
2440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
2441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
2442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
2443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
2444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
2445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
2446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
2447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         time, but this time don't subtract 1 from the IP.  GDB
2448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         handles this example with no difficulty, which leads me to
2449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         believe that either (1) I misunderstood something, or (2) GDB
2450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         has an equivalent kludge. */
2451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  ips[j],
2454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
2455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
2461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
2464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
24679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
24689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
24699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
24709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
24719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
24729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
24739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
24749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
24759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
24769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
24779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
24789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
24799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
24809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
24819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
24829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Addr ip, Addr data_bias, DiVariable* var,
24839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
24849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
24859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
24869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
248750fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
24889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
24899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
24909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
24919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
24929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
24939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
24949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
24959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
249650fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
249750fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
249850fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
249950fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
250050fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
250150fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
250250fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
250350fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
250450fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
25059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
25079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
25089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
25099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
25109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
25119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
25129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
25139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
25149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
25159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
25179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
25189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
25209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
25219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
25229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
25239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
25249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
25259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
25269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
25279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
25309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
25319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
25329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
25359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
25369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
25379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
25409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
25419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
25429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
25459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
25469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
25479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (res_sp_6k.kind == GXR_Value) {
25499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
25509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
25519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
25529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
25539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
25549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
25559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
25569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
25579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
25589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
25599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
25609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
25619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
25629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
25639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
25649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(res.kind == GXR_Value);
25669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
25679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
256850fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
25699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
257050fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
25719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
25729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
25739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
25749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
25759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
25769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
25779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
25789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
25799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
25809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
25819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
25829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
25839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, data_bias );
25849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(res.kind == GXR_Value);
25859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
25869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
258750fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
25889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
258950fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
25909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
25919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
25929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
25939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
25949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
25959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
25969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
25979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
25989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
25999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
26009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
26019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
26029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
26039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
26069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
26079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
26089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
26099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
26119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
26129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
26139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
26149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
26159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
26169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
26179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
26189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
26209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
26219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
26229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
26249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
26259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
26269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
26279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
26289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
26299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
26309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
26319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
26329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
26339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
26349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
26359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
26369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
26379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
26389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
26409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
26419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
26429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
26439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
26449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
26469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
26479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
26489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
26499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
26509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
26519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
26529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
26539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
26549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
26559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
26569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
26579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
26589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
26609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
26619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
26629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
26649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
26659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
26669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
26679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
26689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip = ip;
26699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp = 0;
26709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp = 0;
26719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
26729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
26739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
26749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
26759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
26769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
26779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
26789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
26799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
26809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
26819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
26829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
26839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
26849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
26859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
26869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
26879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
26889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
26899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
26909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
26919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
26929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
26939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
26949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
26959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
26969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
26979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
26989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
26999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
27009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
27019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
27029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
27039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
27049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
27059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
27069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
27079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
27089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
27099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
27109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
27119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
27129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
27139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       di->data_bias, var, arrays_only );
27149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
27159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
27169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
27189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
27199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
27229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
27239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
27249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
27259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
27269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
27279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
27299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
27309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
27319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
27329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
27339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
27359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
27369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
27379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
27399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
27409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
27419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
27429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
27439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
27449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
27459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
27479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
27489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
27499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
27509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
27529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
27539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
27549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
27559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
27579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
27589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
27599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
27619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
27629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
27639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
27649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
27659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
27679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
27689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
27699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
27709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
27719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
27729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
27739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
27759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
27769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
27779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
27789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
27799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
27819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
278250fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
27839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
27849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
27859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
27869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
27879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
27889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
27909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
27919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
27929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
27939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
27949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
27959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
27969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            res = ML_(evaluate_trivial_GX)( var->gexpr, di->data_bias );
27979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
27989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
27999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (res.kind != GXR_Value) {
28009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
28019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
28029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
28039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
28059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
28069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
28079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
280950fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
28109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
281150fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
281250fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
281350fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
281450fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
281550fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
281650fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
281750fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
281850fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
28199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
28219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
28229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
28239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
28249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
28259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
28269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
28279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
28289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
28309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
28319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
28339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
28349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
28359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
28369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
28379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
28389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
28399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
284050fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
28419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
28429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
28439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
28449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
28459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
28469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
28489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
28509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
28529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
28549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
28569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
28579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
2862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst DebugInfo* VG_(next_seginfo)(const DebugInfo* di)
2865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
2867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
2868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
2869eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2870eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjAddr VG_(seginfo_get_text_avma)(const DebugInfo* di)
2872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
2874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjSizeT VG_(seginfo_get_text_size)(const DebugInfo* di)
2877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2878b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
2879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2881092b6268cc4a38ae9ee41d1e3355937536ddc579bartAddr VG_(seginfo_get_plt_avma)(const DebugInfo* di)
2882092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
2883092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
2884092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
2885092b6268cc4a38ae9ee41d1e3355937536ddc579bart
2886092b6268cc4a38ae9ee41d1e3355937536ddc579bartSizeT VG_(seginfo_get_plt_size)(const DebugInfo* di)
2887092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
2888092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
2889092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
2890092b6268cc4a38ae9ee41d1e3355937536ddc579bart
2891092b6268cc4a38ae9ee41d1e3355937536ddc579bartAddr VG_(seginfo_get_gotplt_avma)(const DebugInfo* di)
2892092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
2893092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
2894092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
2895092b6268cc4a38ae9ee41d1e3355937536ddc579bart
2896092b6268cc4a38ae9ee41d1e3355937536ddc579bartSizeT VG_(seginfo_get_gotplt_size)(const DebugInfo* di)
2897092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
2898092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
2899092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
2900092b6268cc4a38ae9ee41d1e3355937536ddc579bart
2901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_soname)(const DebugInfo* di)
2902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
2904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2905eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2906b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_filename)(const DebugInfo* di)
2907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->filename;
2909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjULong VG_(seginfo_get_text_bias)(const DebugInfo* di)
2912bbec7728efefaa650970dd1f0282b77040287133sewardj{
2913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
2914bbec7728efefaa650970dd1f0282b77040287133sewardj}
2915bbec7728efefaa650970dd1f0282b77040287133sewardj
2916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjInt VG_(seginfo_syms_howmany) ( const DebugInfo *si )
2917eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
2919eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2920eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid VG_(seginfo_syms_getidx) ( const DebugInfo *si,
2922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      Int idx,
2923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Addr*   avma,
29244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                               /*OUT*/Addr*   tocptr,
2925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                               /*OUT*/UInt*   size,
2926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/HChar** name,
2927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Bool*   isText )
2928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
2930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (avma)   *avma   = si->symtab[idx].addr;
29314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (tocptr) *tocptr = si->symtab[idx].tocptr;
29324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (size)   *size   = si->symtab[idx].size;
29334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (name)   *name   = (HChar*)si->symtab[idx].name;
2934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (isText) *isText = si->symtab[idx].isText;
2935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
2940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
2943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
2944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
2945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
2947b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
2948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
2949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
2950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
2951b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
2952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
2953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
2954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
2955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
2959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
2960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
2961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
2962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjVgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
2964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   Addr a)
2965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2967b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
2968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2969b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2970b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
2972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
2973a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld data=%#lx,%ld bss=%#lx,%ld\n",
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            a, di, di->filename,
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
2977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
2979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
2981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
2982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
2983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
2984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
2987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
2988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
2990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
2993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
2994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
2995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
2996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3016092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3017092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3018092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3019092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3020092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3021092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di && di->filename) {
3039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int fnlen = VG_(strlen)(di->filename);
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3046d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j] = di->filename[i];
3049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (di->filename[i] == 0) break;
3050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3052d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3062eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3063eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3064eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3065eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3066eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3067eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3068