debuginfo.c revision 9365e3f48bc3efe2486bf4bc04111a2d89db5520
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
119f207460d70d38c46c9e81996a3dcdf90961c6dbnjn   Copyright (C) 2000-2009 Julian Seward
12eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
34eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
35b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
40b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
41d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
42eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
43b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
486882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
49f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
50b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
51b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
54eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
55eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
56eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
574ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
584ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
59b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
60c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#elif defined(VGO_aix5)
624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_debuglog.h"
634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcproc.h"
644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcfile.h"
654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readxcoff.h"
66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
67f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
68f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
70eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
97f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
98f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
100c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
101c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
112eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
165eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* alloc_DebugInfo( const UChar* filename,
175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            const UChar* memname )
176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
179eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
180f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
181f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
1839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->handle    = handle_counter++;
1849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->filename  = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->memname   = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname)
186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                           : NULL;
187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
188f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      Now set up the debugging-output flags. */
190f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
191f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
192f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj        || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
193f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj                                          memname ));
194f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
200f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
201f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
203eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20959a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
21259a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->filename)   ML_(dinfo_free)(di->filename);
216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab)     ML_(dinfo_free)(di->symtab);
217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab)     ML_(dinfo_free)(di->loctab);
218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi)       ML_(dinfo_free)(di->cfsi);
219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs);
220c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (di->fpo)        ML_(dinfo_free)(di->fpo);
221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
223eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
23259a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
23659a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24059a2d18d0ddfa241850017252b0804d469187d79sewardj
24159a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
24259a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
24359a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
24459a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
24559a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
24659a2d18d0ddfa241850017252b0804d469187d79sewardj      }
24759a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
24859a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VGP_ppc32_aix5)
2934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "__unload";
2944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  elif defined(VGP_ppc64_aix5)
2954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "kunload64";
2964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  else
2974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
2984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
2994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
302eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
30633e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
30733e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
309738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
3124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         curr->filename ? curr->filename : (UChar*)"???",
3134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
31633e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
31733e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
332f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
334f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
336f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
360f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
363f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
364f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
394eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rx_map
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
399eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rw_map
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rx_map
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rw_map
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#if defined(VGO_aix5)
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj__attribute__((unused))
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#endif
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find the existing DebugInfo for (memname,filename) or if not found,
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   create one.  In the latter case memname and filename are strdup'd
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   into VG_AR_DINFO, and the new DebugInfo is added to
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debugInfo_list. */
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname )
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0==VG_(strcmp)(di->filename, filename)
479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ( (memname && di->memname)
480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ? 0==VG_(strcmp)(memname, di->memname)
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  : True ))
482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = alloc_DebugInfo(filename, memname);
486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
490b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
493eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rx_map);
506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rw_map);
507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* degenerate case: r-x section is empty */
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->rx_map_size == 0) {
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi == NULL);
510f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return;
511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* normal case: r-x section is nonempty */
513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (0) */
514f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->rx_map_size > 0);
515f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (1) */
516f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di2 = debugInfo_list; di2; di2 = di2->next) {
517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2 == di)
518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2->rx_map_size == 0)
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma
522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma);
523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di2 = NULL;
525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (2) */
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma >= di->rx_map_avma);
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size);
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word i;
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
578f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   segment has been mapped in, or unmapped.  When that happens it
582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tries to acquire/discard whatever info is available for the
583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   corresponding object.  This section contains the notification
584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   handlers. */
585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
5919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
5929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
5939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
5949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
5959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
5969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
5979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
5989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
599eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       ok, is_rx_map, is_rw_map;
605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
6069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong      di_handle;
607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        nread;
609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
611ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
612ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
621a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
625eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
6329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
6379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
642ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
64315728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
644ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
645ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
646ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
6479c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
648ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
649ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
650ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
651cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
652ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
653ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
654e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
655ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
656ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         fake_di.filename = filename;
657ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
658ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
6599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
6602ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
6612ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
662ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
663ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
6649c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
6659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
666ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
667ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
66815728ab41ea41bf731dcc74ac68354550ced2189bart
669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
683eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
702f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
703f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
704f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
708f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
7113026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If it is neither text-ish nor data-ish, we're not interested. */
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!(is_rx_map || is_rw_map))
7249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7265a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
7275a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
7285a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
7295a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
730cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(fd)) {
731cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Err(fd) != VKI_EACCES) {
7325a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         DebugInfo fake_di;
7335a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
7345a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         fake_di.filename = filename;
7355a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
7365a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
7375a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7385a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
739cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) );
740cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   VG_(close)( sr_Res(fd) );
7415a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7425a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread == 0)
7435a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7445a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread < 0) {
7455a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
7465a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
7475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      fake_di.filename = filename;
7485a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
7495a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7505a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
7515a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
7525a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7538b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
7548b68b64759254d514d98328c496cbd88cde4c9a5njn   // Nb: AIX5 doesn't use this file and so isn't represented here.
7558b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_linux)
7565a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
7575a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7588b68b64759254d514d98328c496cbd88cde4c9a5njn#elif defined(VGO_darwin)
759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!ML_(is_macho_object_file)( buf1k, (SizeT)nread ))
760f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
7628b68b64759254d514d98328c496cbd88cde4c9a5njn#  error "unknown OS"
763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
7645a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ );
768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rx_map) {
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rx_map = True;
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_avma = a;
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_size = seg->end + 1 - seg->start;
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_foff = seg->offset;
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rw_map) {
785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rw_map = True;
786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_avma = a;
787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_size = seg->end + 1 - seg->start;
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_foff = seg->offset;
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If we don't have an rx and rw mapping, or if we already have
7959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      debuginfo for this mapping for whatever reason, go no
7969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      further. */
7979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) )
7989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Ok, so, finally, let's try to read the debuginfo. */
8019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(di->filename);
8029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ start ELF OBJECT "
8049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* We're going to read symbols and debug info for the avma
8099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
8109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      +rw_map_size).  First get rid of any other DebugInfos which
8119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      overlap either of those ranges (to avoid total confusion). */
8129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   discard_DebugInfos_which_overlap_with( di );
8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* .. and acquire new info. */
8158b68b64759254d514d98328c496cbd88cde4c9a5njn   // Nb: AIX5 doesn't use this file and so isn't represented here.
8168b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_linux)
8179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ok = ML_(read_elf_debug_info)( di );
8188b68b64759254d514d98328c496cbd88cde4c9a5njn#elif defined(VGO_darwin)
819f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   ok = ML_(read_macho_debug_info)( di );
820f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
8218b68b64759254d514d98328c496cbd88cde4c9a5njn#  error "unknown OS"
822f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
8239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ok) {
8259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Canonicalising the "
8279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   "acquired info ------\n");
828f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* invalidate the CFI unwind cache. */
829f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
8309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* prepare read data for use */
8319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(canonicaliseTables)( di );
8329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* notify m_redir about it */
8339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
8349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(redir_notify_new_DebugInfo)( di );
8359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Note that we succeeded */
8369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->have_dinfo = True;
8379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(di->handle > 0);
8389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = di->handle;
839f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Check invariants listed in
840f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
841f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         priv_storage.h. */
842f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      check_CFSI_related_invariants(di);
843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
8459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
8469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
8479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         this DebugInfo?  No - it contains info on the rw/rx
8489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         mappings, at least. */
8499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di_handle = 0;
850f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->have_dinfo == False);
8519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
852eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ end ELF OBJECT "
8569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
858eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return di_handle;
860eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
861eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
862eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
863eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
867f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
868a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
869f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
870f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
871f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
882f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
885f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
886f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
887f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
888f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
889f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
890eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
891eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
892c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
893c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
894c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
895c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
896c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   SizeT total_size,
897c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   PtrdiffT unknown_purpose__reloc )
898c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
899c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    r, sz_exename;
900c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
901c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char   exename[VKI_PATH_MAX];
902c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  pdbname = NULL;
903c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  dot;
904c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
905c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
906c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
907c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
908c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
909c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
910738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
911c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
912c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         "LOAD_PDB_DEBUGINFO(fd=%d, avma=%#lx, total_size=%lu, "
913738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "uu_reloc=%#lx)\n",
914c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fd_obj, avma_obj, total_size, unknown_purpose__reloc
915c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
916c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
917c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
918c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
919c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
920c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
921c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
922c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
923c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
9249c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
925c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
926c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
927c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
928c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
929c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
930c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
931c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
932c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
933c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
934c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
935c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
936c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
937c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
938c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
939738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
940c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
941c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
942c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Try to find a matching PDB file from which to read debuginfo.
943c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      Windows PE files have symbol tables and line number information,
944c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      but MSVC doesn't seem to use them. */
945c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Why +5 ?  Because in the worst case, we could find a dot as the
946c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      last character of pdbname, and we'd then put "pdb" right after
947c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      it, hence extending it a bit. */
948c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
949c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(strcpy)(pdbname, exename);
950c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(pdbname[sz_exename+5-1] == 0);
951c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   dot = VG_(strrchr)(pdbname, '.');
952c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (!dot)
953c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* there's no dot in the exe's name ?! */
954c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (dot[1] == 0)
955c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* hmm, path ends in "." */
956c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
957c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ('A' <= dot[1] && dot[1] <= 'Z')
958c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(strcpy)(dot, ".PDB");
959c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   else
960c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(strcpy)(dot, ".pdb");
961c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
962c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(pdbname[sz_exename+5-1] == 0);
963c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
964c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
965c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
966cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
967738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
968c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
969c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
970738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
971c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
972c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
9739c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
974c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdb_mtime < obj_mtime ) {
975c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* PDB file is older than PE file - ignore it or we will either
976c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         (a) print wrong stack traces or more likely (b) crash. */
977738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
978738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   "Warning: Ignoring %s since it is older than %s\n",
979738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   pdbname, exename);
980c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
981c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
982c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
983c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
984cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
985738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
986c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
987c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
988c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
989c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Looks promising; go on to try and read stuff from it. */
990cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
9919c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
992c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(am_mmap_file_float_valgrind)( n_pdbimage, VKI_PROT_READ,
993c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                            fd_pdbimage, 0 );
994cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
995c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
996c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
997c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
998c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
999c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1000738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1001c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1002c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1003c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1004c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1005c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1006c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1007c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1008cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   { void* pdbimage = (void*)sr_Res(sres);
1009c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     DebugInfo* di = find_or_create_DebugInfo_for(exename, NULL/*membername*/ );
1010c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1011c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1012c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di && !di->have_rx_map && !di->have_rw_map);
1013c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1014c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1015c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1016c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
1017c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     ML_(read_pdb_debug_info)( di, avma_obj, unknown_purpose__reloc,
1018c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1019c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1020c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1021c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1022c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1023c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1024c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1025c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1026c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1027c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1028c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1029c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
10308b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
10314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
10344ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
10354ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/
10364ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
10374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
10384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10394ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_aix5)
10404ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10414ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* The supplied parameters describe a code segment and its associated
10424ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   data segment, that have recently been mapped in -- so we need to
10434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   read debug info for it -- or conversely, have recently been dumped,
10444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   in which case the relevant debug info has to be unloaded. */
10454ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_aix5_notify_segchange)(
10474ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   code_start,
10484ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   code_len,
10494ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   data_start,
10504ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   data_len,
10514ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* file_name,
10524ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* mem_name,
10534ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   is_mainexe,
10544ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   acquire )
10554ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
10569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong hdl = 0;
10579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1058f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* play safe; always invalidate the CFI cache.  Not
1059f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      that it should be used on AIX, but still .. */
1060f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
1061f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
10624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (acquire) {
10634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Bool       ok;
1065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* di;
1066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = find_or_create_DebugInfo_for( file_name, mem_name );
1067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
1068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0) {
1070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_present = True;
1071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_svma = 0; /* don't know yet */
1072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_bias = 0; /* don't know yet */
1073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_avma = code_start;
1074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_size = code_len;
1075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (data_len > 0) {
1077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_present = True;
1078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_svma = 0; /* don't know yet */
1079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_bias = 0; /* don't know yet */
1080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_avma = data_start;
1081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_size = data_len;
1082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* These need to be filled in in order to keep various
1085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         assertions in storage.c happy.  In particular see
1086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Comment_Regarding_Text_Range_Checks" in that file. */
1087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rx_map = True;
1088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_avma = code_start;
1089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_size = code_len;
1090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rw_map = True;
1091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_avma = data_start;
1092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_size = data_len;
1093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ok = ML_(read_xcoff_debug_info) ( di, is_mainexe );
1095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ok) {
1097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* prepare read data for use */
1098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(canonicaliseTables)( di );
1099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* notify m_redir about it */
1100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(redir_notify_new_DebugInfo)( di );
1101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note that we succeeded */
1102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_dinfo = True;
11039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         hdl = di->handle;
11049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(hdl > 0);
1105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Check invariants listed in
1106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
1107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            priv_storage.h. */
1108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         check_CFSI_related_invariants(di);
1109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /*  Something went wrong (eg. bad XCOFF file). */
1111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         discard_DebugInfo( di );
1112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di = NULL;
1113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
11144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   } else {
11164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Dump all the debugInfos whose text segments intersect
1118f7cdfe298805a91a35b8e0495d9034cbf21003f5sewardj         code_start/code_len. */
1119f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* CFI cache is always invalidated at start of this routine.
1120f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Hence it's safe to ignore the return value of
1121f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         discard_syms_in_range. */
1122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0)
1123f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         (void)discard_syms_in_range( code_start, code_len );
11244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
11269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
11279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return hdl;
11284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
11294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_aix5) */
11324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1139eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
11409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
11419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
11429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
11439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
11449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
11459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
11469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
11479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
11489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
11499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
11509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
11519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
11529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1158eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1169f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
1176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = di->text_present
1177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_size > 0
1178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_avma <= ptr
1179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && ptr < di->text_avma + di->text_size;
1180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
11945706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
11955706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
11965706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
11975706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
11985706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
11995706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
12005706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
12015706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
12025706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
12035706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
12045706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1217eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1219eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1220eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1221eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1222eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1226f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1227eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1228f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
12325706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1246eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1247eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1248eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
12496b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
12506b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
12516b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1254eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
12556b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
12566b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
12576b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Addr a, Char* buf, Int nbuf,
1258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1259c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1262f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1263c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1267eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
12686882443ef154bca367bc591287de641e43a9e108njn
12696b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
12706b7611bf42a0fbb62e047d8c43b008205bd21e75njn                   di->symtab[sno].name, buf, nbuf );
12716b7611bf42a0fbb62e047d8c43b008205bd21e75njn
12726b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
12736b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
12746b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
12756b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
12766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
12776b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
12786b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
12796b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
12806b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1283c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1290eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1291c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13026b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
13036b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1313f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13286b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13296b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13306b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13416b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13426b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13436b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13556b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13566b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13576b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13646b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
13656b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
13666b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
13676b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf )
1368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13696b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
13706b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
13716b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
13796b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
13806b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
13816b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
1382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13836b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
13846b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13856b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
13866b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
13876b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
13886b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
13896b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13926882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind) ( Char* name )
13936882443ef154bca367bc591287de641e43a9e108njn{
13946882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
13956882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
13966882443ef154bca367bc591287de641e43a9e108njn
13976882443ef154bca367bc591287de641e43a9e108njn   } else if (
13983026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
13996882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
14006882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
14013026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_aix5)
14026882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__start", name)            ||  // AIX aches
14033026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1404f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1405f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
14063026f71684a930286186aa10fef266c304672e8fsewardj#      else
14073026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
14083026f71684a930286186aa10fef266c304672e8fsewardj#      endif
14096882443ef154bca367bc591287de641e43a9e108njn       0) {
14106882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
14116882443ef154bca367bc591287de641e43a9e108njn
14126882443ef154bca367bc591287de641e43a9e108njn   } else {
14136882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
14146882443ef154bca367bc591287de641e43a9e108njn   }
14156882443ef154bca367bc591287de641e43a9e108njn}
14166882443ef154bca367bc591287de641e43a9e108njn
14176882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
14186882443ef154bca367bc591287de641e43a9e108njn{
14196882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
14206882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
14216882443ef154bca367bc591287de641e43a9e108njn   Char buf[50];
14226882443ef154bca367bc591287de641e43a9e108njn
14236882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
14246882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
14256b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
14266882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
14276882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
14286882443ef154bca367bc591287de641e43a9e108njn   } else {
14296882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
14306882443ef154bca367bc591287de641e43a9e108njn   }
14316882443ef154bca367bc591287de641e43a9e108njn}
14326882443ef154bca367bc591287de641e43a9e108njn
1433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1439c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
14436b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
14446b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
14456b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1459eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int used;
1462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1463f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1464f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
14654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
14667cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
14677cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
14705706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(strncpy_safely)(buf, di->filename, nbuf);
1474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (di->memname) {
14754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
14784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
1480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used);
14814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
14844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
14854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
14897cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
14907cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
14917cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
14927cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
14937cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
14947cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
14957cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1496f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1497f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1498f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1499eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1501eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1504e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1505eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1506e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1508e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
15115706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1514e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1515e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1520eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1521eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1523eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1532eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1533eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1546eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1551eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1552eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1559eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1560eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1561eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1562eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1563eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1564c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1565db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1566db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1567db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1568db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1570c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1571c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1576eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1592eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
15954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
15964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
15974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
15984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
15994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
16004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
16034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
16044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
16054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
16074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
16084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
16094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
16104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
16124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
16134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
16144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
16154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
16164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
16174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
16184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
16204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (0==VG_(strcmp)(name, si->symtab[i].name)
16214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
16224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
16234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
16244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
16254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
16264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16274ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
16284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
16294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
16304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
16314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1632e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1633e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1634e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1635e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1636e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1640e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1641e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1643eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1644e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1645eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1646eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1647eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1648e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1649e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1650e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1651e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1652e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1655e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1656e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1657e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1658eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1659e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1660e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1661e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1662eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1663e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1664e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1665e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1666e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1667e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1668e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1669e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1670e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1671e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1672e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1673e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1674e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1675e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1676e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1677e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1678e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1679e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1680e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1681e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1682e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1683e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1684e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1687e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1688e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1689e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1696e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1697e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1698e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
1704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
1708eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
17094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
17104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
17114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
1719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1720eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1725e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1726e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1727e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1728e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1729e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1730e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1732a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1733eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1734eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1735eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1738e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1739eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1741eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1744e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1746eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1747eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1751e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1756e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1762eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1763eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1766eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1767eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1768eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
17705e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17715e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
17725e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17735e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
17745e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
17755e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
17765e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
17775e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
17785e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
17795e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1780a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
17825e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
1789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
17945e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
17955e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
17965e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
17975e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
17985e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
17995e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
18005e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
18015e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
1802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1807eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1808eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1809eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
181272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1815b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
181972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
182072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
182172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
182272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
182372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
18243026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
18253026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
18263026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
182772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
182872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
182972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
183072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
183172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
183272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
183372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjstatic
183472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
183572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
183672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
183772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
183819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
18393026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
18403026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
18413026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
184272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
184372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
184472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
184572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
184672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
184772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
184872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
184972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
185072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
185119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
18527888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
185372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
185472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
185572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
185672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
185772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
18583026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
18593026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
18603026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
18613026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
18623026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
18633026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R13: return eec->uregs->r13;
18643026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R12: return eec->uregs->r12;
18653026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
18663026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
18673026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
18683026f71684a930286186aa10fef266c304672e8fsewardj#           else
18693026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
18703026f71684a930286186aa10fef266c304672e8fsewardj#           endif
187172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
187272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
187372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
187472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
187572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
187619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
187719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
187819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
187919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
188019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
188119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
188219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
188319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
188419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
188519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         return * ((UWord*)a);
188672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
188772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
188872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
188972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
189072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
189172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
189272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
189372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
189472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
189572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
189672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
189772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
189872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
189972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1900f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
1901f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1903f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
1904f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
190572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1906f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
1907f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
1908f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
1909f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
1910f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
1911f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
1912f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1913f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
1914f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
1915f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1916f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
1917f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
1918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
1919eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1920f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
1921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1922f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1923f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
1924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
1927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
1928f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
1929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1930f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
1931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1933f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
1934f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
1935f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
1936f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1937f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
1938f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
1939f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
1940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1943f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
1944f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1945f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
1946f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
1947f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
1948f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1949f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
1950f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1951f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
1952f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
1953f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
1954f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
1955f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
1956f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
1957f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
1958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1959f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
1960f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
1961f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
1962f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
1963f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
1964f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
1965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
1966f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
1967f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
1968f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
1969f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
1970f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
1971f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1972f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
1973f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
1974f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
1975f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
1976f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1977f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1978f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1979f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1980f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1981f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1982f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
1983f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
1984f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1985f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
1986f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
1987f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1988f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
1989f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
1990f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
1991f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1992f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
1993f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
1994f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1995f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
1996f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
1997f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
1998f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
1999f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
2000f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
2001f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
2002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2003f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
2004f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2005f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
2006f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
2007f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
2008f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2009f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
2010f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2011f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
2012f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
2013f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2014f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2015f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
20163c9cf3442185b5891e15450d6e3058aeff6796fetomstatic CFSICacheEnt* cfsi_cache__find ( Addr ip )
2017f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
20183c9cf3442185b5891e15450d6e3058aeff6796fetom   UWord         hash = ip % N_CFSI_CACHE;
20193c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce = &cfsi_cache[hash];
20203c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2021f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2022f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2023f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2024f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2025f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
20263c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
20273c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
20283c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
20293c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
20303c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
20313c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
20323c9cf3442185b5891e15450d6e3058aeff6796fetom      find_DiCfSI( &ce->di, &ce->ix, ip );
20333c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2034eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20353c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
20363c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
20373c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
20383c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
20393c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
20403c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2041eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
20423c9cf3442185b5891e15450d6e3058aeff6796fetom}
2043eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2044eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20453026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
20463c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
20473c9cf3442185b5891e15450d6e3058aeff6796fetom                          DebugInfo* di, DiCfSI* cfsi )
20483c9cf3442185b5891e15450d6e3058aeff6796fetom{
20493c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
20503c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
20513c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2052eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20533c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
205472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
205572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
20563026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
20573026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
20583026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xsp;
20593026f71684a930286186aa10fef266c304672e8fsewardj         break;
20603026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
20613026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xbp;
206272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
20633026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
20643026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
20653026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r13;
206672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
20673026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
20683026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r12;
20693026f71684a930286186aa10fef266c304672e8fsewardj         break;
20703026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
20713026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r11;
20723026f71684a930286186aa10fef266c304672e8fsewardj         break;
20733026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
20743026f71684a930286186aa10fef266c304672e8fsewardj#     else
20753026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
20763026f71684a930286186aa10fef266c304672e8fsewardj#     endif
20773026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
20787888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
20797888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2080f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
20817888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
20827888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
20833026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
20847888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
20857888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
20867888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2087f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
20883c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
208972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
209072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
209172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
209272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
20933c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
20943c9cf3442185b5891e15450d6e3058aeff6796fetom}
20953c9cf3442185b5891e15450d6e3058aeff6796fetom
20963c9cf3442185b5891e15450d6e3058aeff6796fetom
20973c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
20983026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
20993026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
21003c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
21013c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
21023c9cf3442185b5891e15450d6e3058aeff6796fetom{
21033c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce;
21043c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*    di;
21053c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*       cfsi;
21063c9cf3442185b5891e15450d6e3058aeff6796fetom
21073c9cf3442185b5891e15450d6e3058aeff6796fetom   ce = cfsi_cache__find(ip);
21083c9cf3442185b5891e15450d6e3058aeff6796fetom
21093c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
21103c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
21113c9cf3442185b5891e15450d6e3058aeff6796fetom
21123c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
21133c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
21143c9cf3442185b5891e15450d6e3058aeff6796fetom
21153026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
21163026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
21173026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
21183026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
21193026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
21203026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
21213026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
21223026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
21233026f71684a930286186aa10fef266c304672e8fsewardj                        min_accessible,  max_accessible, di, cfsi);
21243026f71684a930286186aa10fef266c304672e8fsewardj   }
21253026f71684a930286186aa10fef266c304672e8fsewardj#  else
21263026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
21273026f71684a930286186aa10fef266c304672e8fsewardj#  endif
21283c9cf3442185b5891e15450d6e3058aeff6796fetom}
21293c9cf3442185b5891e15450d6e3058aeff6796fetom
21303c9cf3442185b5891e15450d6e3058aeff6796fetom
21313026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
21323026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
21333026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
21343026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
21353026f71684a930286186aa10fef266c304672e8fsewardj
21363026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
21373026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
21383026f71684a930286186aa10fef266c304672e8fsewardj
21393026f71684a930286186aa10fef266c304672e8fsewardj   For arm, the unwound registers are: R11 R12 R13 R14 R15.
21403026f71684a930286186aa10fef266c304672e8fsewardj*/
21413026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
21423c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
21433c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
21443c9cf3442185b5891e15450d6e3058aeff6796fetom{
21453c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
21463c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
21473c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*            cfsi = NULL;
21483026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
21493c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt*      ce;
21503c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
21513026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
21523c9cf3442185b5891e15450d6e3058aeff6796fetom
21533026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
21543026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
21553026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
21563026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
21573026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
21583026f71684a930286186aa10fef266c304672e8fsewardj#  else
21593026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
21603026f71684a930286186aa10fef266c304672e8fsewardj#  endif
21613026f71684a930286186aa10fef266c304672e8fsewardj   ce = cfsi_cache__find(ipHere);
21623c9cf3442185b5891e15450d6e3058aeff6796fetom
21633c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
21643c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
21653c9cf3442185b5891e15450d6e3058aeff6796fetom
21663c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
21673c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
21683c9cf3442185b5891e15450d6e3058aeff6796fetom
21693c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
21703c9cf3442185b5891e15450d6e3058aeff6796fetom      VG_(printf)("found cfisi: ");
21713c9cf3442185b5891e15450d6e3058aeff6796fetom      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
21723c9cf3442185b5891e15450d6e3058aeff6796fetom   }
21733c9cf3442185b5891e15450d6e3058aeff6796fetom
21743026f71684a930286186aa10fef266c304672e8fsewardj   VG_(memset)(&uregsPrev, 0, sizeof(uregsPrev));
21753c9cf3442185b5891e15450d6e3058aeff6796fetom
21763c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
21773026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
21783026f71684a930286186aa10fef266c304672e8fsewardj                     min_accessible, max_accessible, di, cfsi);
21793c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
21803c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
218172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
218272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
218372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2185eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2188eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2189eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2191eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2193eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
21959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2196eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
2197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = *(Addr*)a;                       \
2198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2199eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
220372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
220472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2205f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
22063026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
220772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
220872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
220972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               ok = True;                               \
2210f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
221172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
221272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
221372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
221472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2217eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22183026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
22193026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
22209365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
22219365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
22223026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
22233026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how,  cfsi->ra_off);
22243026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
22253026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
22263026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
22273026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
22283026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
22293026f71684a930286186aa10fef266c304672e8fsewardj#  else
22303026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
22313026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2234eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22353026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2238eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2242c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2243c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2246c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2247c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2248c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2249c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2250c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2251c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2252c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2253c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2254c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2255c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2256c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2257c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2258c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2259c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2260c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2261c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2262c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2263c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2264c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2265c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2266c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2267c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2268c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2269c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2270c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2271c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2272c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2273c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2274c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2275c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2276c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2277c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2278c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2279c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2280c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2281c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2282c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2283c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2284c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2285c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2286c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2287c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2288c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2289c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2290c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2291c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2292c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2293c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2294c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2295c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2296c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2297c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2298c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2299c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2300c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2301c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2302c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2303c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2304c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2305c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2306c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2307c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2308c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2309c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2310c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2311c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2312c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2313c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2314c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2315c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2316c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2317c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2318c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2319c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2320c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2321c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2322c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2323c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2324c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2325c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2326c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2327c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2328c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2329c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2330c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2331c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2332c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2333c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2334c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2335c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2336c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2337c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2338c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2339c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2340c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2341c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2342c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2343c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2344c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2345c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2346c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2347c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2348c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2349c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2350c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2351c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2352c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2353c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2354c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *ipP = *(Addr *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals));
2355738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   *spP =           spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
2356738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                                            + fpo->cdwParams);
2357c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *fpP = *(Addr *)(spHere + 4*2);
2358c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2359c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2360c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2361c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2362c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2363c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2369588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2370588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   VG_(xaprintf_no_f_c)(dst, fmt, args) without having to resort to
2371588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2372588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2373738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2374588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2375588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //   VG_(xaprintf_no_f_c)(dstxa, format, ##args)
2376738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2377588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj#define  p2XA  VG_(xaprintf_no_f_c)
2378738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2379588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2380588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2381738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2382738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2383738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2384738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2385738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2386738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2387738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2393c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
23949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2398588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
240050fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
24049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
240950fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
241050fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
241150fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
241250fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
241350fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
241450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
241550fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
241650fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
241750fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
241850fde23467d92281b32dd537d0d9a590263628c3sewardj
241950fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2422a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
24249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2435588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2442eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24433c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2454738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
2455738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
2456738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
2457738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
2458738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
2459738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
2460738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
2461738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
2462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2464c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2465c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2469eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2470738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
2471738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
2472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2474738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar* basetag   = "auxwhat"; /* a constant */
2475738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar tagL[32], tagR[32], xagL[32], xagR[32];
2476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(frameNo >= -1);
2478738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
2479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2485738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
2486738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
2487738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
2488738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
2489738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
2490738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
2491738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
2492738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2493738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
2494738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
2495738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
2496738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
2497738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
2498738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
2499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2500b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2507738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2508738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2509738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2510738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\",",
2511738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2512738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2513738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2514738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2515738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2516738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2517738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2518738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2519738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2520738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2521738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2522738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2523738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2530b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2531738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2532738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2533738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2534738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\"",
2535738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2536738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2537738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2538738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2539738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2540738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2541738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2542738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2543738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2544738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2545738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2546738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2547738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2548738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2549738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2550738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2551738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2552738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2553738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2554738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2555738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2563738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2564738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2565738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2566738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t",
2567738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2568738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2569738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2570738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2571738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2572738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2573738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2574738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2575738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2576738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
2577738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2578738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2579738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2580738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2581738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2585738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2586738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
2587738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2588738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2589738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2590738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2591738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2592738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2593738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2594738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2595738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2596738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2597738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2598738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2599738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2600738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2601738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2602738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2603738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2604738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2605738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2606738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2607738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2608738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2609738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2610738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2611738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2612738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2613738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2621738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2622738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2623738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2624738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2625738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2626738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2627738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2628738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2629738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2630738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2631738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2639738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2640738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2641738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2642738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2643738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2644738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2645738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2646738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2647738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2648738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d",
2649738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2650738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2651738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2652738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2653738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2654738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2655738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2656738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2657738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2658738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2659738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2660738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2661738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
2662738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2663738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2671738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2672738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2673738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2674738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2675738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2676738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2677738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2678738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2679738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2680738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2681738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2682738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2683738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2684738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2685738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2686738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
2687738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2688738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2689738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2693738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2694738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
2695738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2696738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2697738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2698738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2699738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2700738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2701738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2702738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2703738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2704738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2705738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %t:%d",
2706738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2707738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2708738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2709738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2710738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2711738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2712738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2713738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2714738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2715738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2716738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2717738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2718738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2719738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
2720738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2721738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
2725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2726738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
2727738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
2728738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
2729738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2730738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
2731738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
2732738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
2733738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
2734738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
2735738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
2736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2738738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
2740738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
2741738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
2742738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
2743738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
2744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
2745738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
2746738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
2747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
2748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
2749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
2750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
2751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
2753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
2755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
2756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
2758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
2759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
2760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
2761a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
2762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
2763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
2764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
2765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
2769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
2770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
2774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
2775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
2776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
2777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
2780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
2781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
2782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
2783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
2784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
2785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
2786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
2787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
2788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
2789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
2790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
2792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
2794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
2795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
2798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
2799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
2800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
2801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
2803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
2804b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
2805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
2807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
2808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
2810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
2811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
2812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
2813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
2814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
2815b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
2816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
2818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
2819b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
2820b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
2821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
2822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
2823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
2824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
2826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
2827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
2828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
2829b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
2830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
2831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
2832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
2833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
2834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
2835b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
2836b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
2837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
2838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
2839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
2840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
2841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
2842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
2843c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
2844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
2845a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
2846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
28479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
28489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
2849588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
2850c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
2851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
28529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
28539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2854738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
2855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
2857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2866738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
2867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
2868738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
2869738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
2870738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
2871738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
2872738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
2873738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2874738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
2875738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
2876738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
2877738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
2878738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2879738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
2880738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
2881738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
2882738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
2883738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
2884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
2886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
2887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
2888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2889b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
2890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
2891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
2892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2893b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
2894b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2895738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
2896738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
2897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2898a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
2899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
2900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
2901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
2902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
29059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
2906b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
2907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
2908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
2909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
2915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
2916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
2918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
2919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
2921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
2922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
2923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
2924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
2925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
2926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
2927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
2928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
2929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
2930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
2931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
2932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
2933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
2934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
2935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
2936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
2937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
2938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
2939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
2940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
2942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
2943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
2944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
2945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
2946c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
2947b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
2948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
2949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
2950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
2951b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
2952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
2953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
2954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
29559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
2956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
2957588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
2958c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
2959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
29609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
29619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2962738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
2963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, -1/*frameNo*/, tid );
2965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2966738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
2967738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
2968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2969b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2970b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
2979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
2980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
2981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
2982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
2983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2987738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
2988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
2990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
2991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
2992738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
2993738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
2994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3012738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3013738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3022b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
3024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
3025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
3026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3028738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3030b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3032738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3033738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3050b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3051b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3052b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3053b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3054b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3055738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3056b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3057b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3058b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3059738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3060738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3066738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3067738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3070eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3071eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
30739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
30749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
30759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
30769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
30779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
30789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
30809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
30819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
30829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
30839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
30849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
30869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
30879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3088588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
30899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
30909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
30919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
30929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
309350fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
30949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
30959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
30969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
30989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
30999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
31009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
310250fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
310350fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
310450fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
310550fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
310650fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
310750fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
310850fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
310950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
311050fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
31119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
31139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
31149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
31159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
31169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
31179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
31189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
31199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
31209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
31219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
31239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
31249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
31269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
31279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
31289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
31299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
31309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
31319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
31329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3133588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
31369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
31379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3138588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
31419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
31429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3143588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
31469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
31479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3148588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
31519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
31529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
31539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31543c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
31559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
31569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
31579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
31589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
31599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
31609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
31619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
31639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
31649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
31659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
31669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
31679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
31689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
31699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3170588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31713c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
31729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
31739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
317450fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
31759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
317650fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
31779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
31789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
31799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
31809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
31819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
31829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
31839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
31849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
31859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
31869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
31879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
31889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3189588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
31903c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
31919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
31929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
319350fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
31949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
319550fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
31969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
31979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
31989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
31999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
32009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
32019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
32029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
32039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
32059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
32069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
32079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
32089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
32099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
32129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
32139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
32149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
32159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
32179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
32189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
32199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
32209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
32219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
32229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
32239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
32249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
32269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
32279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
32289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
32309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
32319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
32329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
32339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
32349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
32359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
32369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
32379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
32389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
32399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
32409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
32419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
32429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
32439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
32449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
32469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
32479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
32489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
32499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
32509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
32529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
32539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
32549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
32559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
32569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
32579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
32589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
32599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
32609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
32619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
32629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
32639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
32649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
32669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
32679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
32689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
32709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
32719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
32729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
32739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
32749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip = ip;
32759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp = 0;
32769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp = 0;
32779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
32799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
32809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
32819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
32829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
32839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
32849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
32859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
32869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
32879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
32889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
32899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
32909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
32919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
32929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
32939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
32949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
32959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
32969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
32979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
32989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
32999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
33009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
33019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
33029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
33039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
33049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
33059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
33069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
33079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
33089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
33099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
33109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
33119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
33129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
33139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
33149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
33159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
33169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
33179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
33189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3319588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
33209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
33219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
33229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
33249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
33259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
33289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
33299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
33309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
33319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
33329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
33339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
33359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
33369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
33379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
33389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
33399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
33419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
33429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
33439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
33459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
33469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
33479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
33489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
33499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
33509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
33519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
33539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
33549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
33559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
33569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
33589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
33599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
33609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
33619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
33639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
33649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
33659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
33679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
33689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
33699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
33709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
33719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
33739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
33749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
33759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
33769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
33779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
33789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
33799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
33819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
33829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
33839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
33849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
33859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
33879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
338850fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
33899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
33909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
33919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
33929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
33939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
33949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
33969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
33979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
33989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
33999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
34009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
34019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3402588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
34039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
34053c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
34069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
34079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
34089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
34099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
34119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
34129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
34139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
341550fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
34169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
341750fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
341850fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
341950fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
342050fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
342150fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
342250fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
342350fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
342450fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
34259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
34279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
34289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
34299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
34309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
34319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
34329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
34339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
34349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
34369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
34379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
34399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
34409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
34419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
34429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
34439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
34449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
34459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
344650fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
34479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
34489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
34499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
34509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
34519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
34529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
34549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
34569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
34589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
34609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
34629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
34639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3469e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
3470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3476e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
3477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3481e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
3482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3486e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
3487092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3488092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3489092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3490092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3491e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
3492092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3493092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3494092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3495092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3496e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
3497092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3498092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3499092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3500092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3501e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
3502092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3503092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3504092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3505092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3506e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
3507eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3510eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3511e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
3512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->filename;
3514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3516e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
3517bbec7728efefaa650970dd1f0282b77040287133sewardj{
3518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3519bbec7728efefaa650970dd1f0282b77040287133sewardj}
3520bbec7728efefaa650970dd1f0282b77040287133sewardj
3521e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
3522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3523eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3526e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
3527e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
3528e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/Addr*   avma,
3529e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/Addr*   tocptr,
3530e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/UInt*   size,
3531e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                  /*OUT*/HChar** name,
3532d264514038b82ea069f84478121c2e628b1ae0d4tom                                  /*OUT*/Bool*   isText,
3533d264514038b82ea069f84478121c2e628b1ae0d4tom                                  /*OUT*/Bool*   isIFunc )
3534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3536d264514038b82ea069f84478121c2e628b1ae0d4tom   if (avma)    *avma    = si->symtab[idx].addr;
3537d264514038b82ea069f84478121c2e628b1ae0d4tom   if (tocptr)  *tocptr  = si->symtab[idx].tocptr;
3538d264514038b82ea069f84478121c2e628b1ae0d4tom   if (size)    *size    = si->symtab[idx].size;
3539d264514038b82ea069f84478121c2e628b1ae0d4tom   if (name)    *name    = (HChar*)si->symtab[idx].name;
3540d264514038b82ea069f84478121c2e628b1ae0d4tom   if (isText)  *isText  = si->symtab[idx].isText;
3541d264514038b82ea069f84478121c2e628b1ae0d4tom   if (isIFunc) *isIFunc = si->symtab[idx].isIFunc;
3542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3550b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
35615706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3571e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
3572e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
3573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3581e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
3582e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
3583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            a, di, di->filename,
3584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3588b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3589b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3590b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3600b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
36135706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
36145706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
36155706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
36165706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
36175706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
36185706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3631092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3632092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3633092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3634092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3635092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3636092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di && di->filename) {
3654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int fnlen = VG_(strlen)(di->filename);
3656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3661d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j] = di->filename[i];
3664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (di->filename[i] == 0) break;
3665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3667d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3682