debuginfo.c revision f76d27a697a7b0bf3b84490baf60623fc96a23af
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   Stabs reader greatly improved by Nick Nethercote, Apr 02.
33eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This module was also extensively hacked on by Jeremy Fitzhardinge
34eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and Tom Hughes.
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
384cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
40b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
41eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
42eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
43eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
46d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
47eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
48b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
49eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
50b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
5172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
536882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
54f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
56b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
57b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
58b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
60eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
61eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
64b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
65c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#elif defined(VGO_aix5)
674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_debuglog.h"
684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcproc.h"
694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcfile.h"
704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readxcoff.h"
71f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
72f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
73f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
75eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
100c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
101c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
102f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
103f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
104c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
105c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
106c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
110f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
111f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
114f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
116eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
117eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* alloc_DebugInfo( const UChar* filename,
180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            const UChar* memname )
181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
185f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
186f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
1889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->handle    = handle_counter++;
1899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->filename  = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di->memname   = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname)
191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                           : NULL;
192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
193f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
194f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      Now set up the debugging-output flags. */
195f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
196f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
197f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj        || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
198f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj                                          memname ));
199f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
205f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
206f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
21459a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
21759a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->filename)   ML_(dinfo_free)(di->filename);
221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab)     ML_(dinfo_free)(di->symtab);
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab)     ML_(dinfo_free)(di->loctab);
223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi)       ML_(dinfo_free)(di->cfsi);
224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs);
225c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (di->fpo)        ML_(dinfo_free)(di->fpo);
226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
228eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
23759a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
24159a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24559a2d18d0ddfa241850017252b0804d469187d79sewardj
24659a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
24759a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
24859a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
24959a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
25059a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
25159a2d18d0ddfa241850017252b0804d469187d79sewardj      }
25259a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
25359a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
290eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VGP_ppc32_aix5)
2984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "__unload";
2994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  elif defined(VGP_ppc64_aix5)
3004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "kunload64";
3014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  else
3024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
3034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
3044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
31133e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
31233e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
314a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                         "Discarding syms at %#lx-%#lx in %s due to %s()",
315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
3174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         curr->filename ? curr->filename : (UChar*)"???",
3184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
32133e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
32233e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
337f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
339f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
341f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
365f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
368f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
369f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
399eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rx_map
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rw_map
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rx_map
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rw_map
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#if defined(VGO_aix5)
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj__attribute__((unused))
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#endif
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
467eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find the existing DebugInfo for (memname,filename) or if not found,
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   create one.  In the latter case memname and filename are strdup'd
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   into VG_AR_DINFO, and the new DebugInfo is added to
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debugInfo_list. */
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname )
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0==VG_(strcmp)(di->filename, filename)
484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ( (memname && di->memname)
485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ? 0==VG_(strcmp)(memname, di->memname)
486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  : True ))
487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
490b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = alloc_DebugInfo(filename, memname);
491b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
492b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
493b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
494b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
495b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
497eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
510f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rx_map);
511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->have_rw_map);
512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* degenerate case: r-x section is empty */
513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->rx_map_size == 0) {
514f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi == NULL);
515f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return;
516f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* normal case: r-x section is nonempty */
518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (0) */
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di->rx_map_size > 0);
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (1) */
521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di2 = debugInfo_list; di2; di2 = di2->next) {
522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2 == di)
523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2->rx_map_size == 0)
525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma);
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di2 = NULL;
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (2) */
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma >= di->rx_map_avma);
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size);
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word i;
539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   segment has been mapped in, or unmapped.  When that happens it
587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tries to acquire/discard whatever info is available for the
588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   corresponding object.  This section contains the notification
589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   handlers. */
590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
592eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
594eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
595eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
5969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
5979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
5989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
5999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
6009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
6019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
6029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
6039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
604eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
606eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       ok, is_rx_map, is_rw_map;
610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
6119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong      di_handle;
612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        nread;
614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
616ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
617ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
624eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
626a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
630eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
6379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
6429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
647ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
64815728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
649ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
650ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
651ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
6529c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
653ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
654ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
655ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
656cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
657ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
658ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
659e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
660ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
661ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         fake_di.filename = filename;
662ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
663ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
6649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
6652ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
6662ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
667ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
668ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
6699c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
6709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
671ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
672ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
67315728ab41ea41bf731dcc74ac68354550ced2189bart
674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
710f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
713f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  elif defined(VGA_amd64) || defined(VGA_ppc32) || defined(VGA_ppc64)
714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If it is neither text-ish nor data-ish, we're not interested. */
725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!(is_rx_map || is_rw_map))
7269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7285a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
7295a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
7305a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
7315a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
732cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(fd)) {
733cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Err(fd) != VKI_EACCES) {
7345a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         DebugInfo fake_di;
7355a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
7365a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         fake_di.filename = filename;
7375a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
7385a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
7395a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7405a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
741cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) );
742cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   VG_(close)( sr_Res(fd) );
7435a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7445a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread == 0)
7455a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7465a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread < 0) {
7475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
7485a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
7495a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      fake_di.filename = filename;
7505a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
7515a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
7525a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
7535a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
7545a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
7555a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* We're only interested in mappings of ELF object files. */
756f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(HAVE_ELF)
7575a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
7585a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(HAVE_MACHO)
760f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!ML_(is_macho_object_file)( buf1k, (SizeT)nread ))
761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
762f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  error "unknown executable type"
764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
7655a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ );
769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rx_map) {
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rx_map = True;
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_avma = a;
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_size = seg->end + 1 - seg->start;
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_foff = seg->offset;
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rw_map) {
786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rw_map = True;
787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_avma = a;
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_size = seg->end + 1 - seg->start;
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_foff = seg->offset;
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If we don't have an rx and rw mapping, or if we already have
7969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      debuginfo for this mapping for whatever reason, go no
7979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      further. */
7989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) )
7999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Ok, so, finally, let's try to read the debuginfo. */
8029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(di->filename);
8039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ start ELF OBJECT "
8059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                "------------------------------\n");
8069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("------ name = %s\n", di->filename);
8079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TRACE_SYMTAB("\n");
8089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* We're going to read symbols and debug info for the avma
8109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
8119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      +rw_map_size).  First get rid of any other DebugInfos which
8129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      overlap either of those ranges (to avoid total confusion). */
8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   discard_DebugInfos_which_overlap_with( di );
8149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* .. and acquire new info. */
816f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(HAVE_ELF)
8179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ok = ML_(read_elf_debug_info)( di );
818f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(HAVE_MACHO)
819f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   ok = ML_(read_macho_debug_info)( di );
820f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
821f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  error "unknown executable type"
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) {
910c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "");
911c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
912c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         "LOAD_PDB_DEBUGINFO(fd=%d, avma=%#lx, total_size=%lu, "
913c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         "uu_reloc=%#lx)",
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) {
939c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s", 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)) {
967c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s",
968c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
969c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
970c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s", 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. */
977c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "Warning: Ignoring %s since it is older than %s",
978c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname, exename);
979c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
980c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
981c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
982c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
983cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
984c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s", pdbname);
985c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
986c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
987c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
988c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Looks promising; go on to try and read stuff from it. */
989cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
9909c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
991c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(am_mmap_file_float_valgrind)( n_pdbimage, VKI_PROT_READ,
992c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                            fd_pdbimage, 0 );
993cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
994c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
995c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
996c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
997c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
998c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
999c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s", pdbname);
1000c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1001c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1002c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1003c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1004c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1005c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1006c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1007cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   { void* pdbimage = (void*)sr_Res(sres);
1008c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     DebugInfo* di = find_or_create_DebugInfo_for(exename, NULL/*membername*/ );
1009c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1010c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1011c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di && !di->have_rx_map && !di->have_rw_map);
1012c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1013c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1014c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1015c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
1016c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     ML_(read_pdb_debug_info)( di, avma_obj, unknown_purpose__reloc,
1017c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1018c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1019c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1020c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1021c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1022c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1023c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1024c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1025c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1026c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1027c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1028c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
10294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_linux) */
10304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
10334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
10344ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/
10354ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
10364ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
10374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_aix5)
10394ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10404ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* The supplied parameters describe a code segment and its associated
10414ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   data segment, that have recently been mapped in -- so we need to
10424ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   read debug info for it -- or conversely, have recently been dumped,
10434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   in which case the relevant debug info has to be unloaded. */
10444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
10459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_aix5_notify_segchange)(
10464ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   code_start,
10474ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   code_len,
10484ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   data_start,
10494ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   data_len,
10504ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* file_name,
10514ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* mem_name,
10524ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   is_mainexe,
10534ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   acquire )
10544ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
10559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ULong hdl = 0;
10569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1057f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* play safe; always invalidate the CFI cache.  Not
1058f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      that it should be used on AIX, but still .. */
1059f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
1060f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
10614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (acquire) {
10624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Bool       ok;
1064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* di;
1065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = find_or_create_DebugInfo_for( file_name, mem_name );
1066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
1067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0) {
1069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_present = True;
1070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_svma = 0; /* don't know yet */
1071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_bias = 0; /* don't know yet */
1072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_avma = code_start;
1073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_size = code_len;
1074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (data_len > 0) {
1076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_present = True;
1077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_svma = 0; /* don't know yet */
1078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_bias = 0; /* don't know yet */
1079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_avma = data_start;
1080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_size = data_len;
1081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* These need to be filled in in order to keep various
1084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         assertions in storage.c happy.  In particular see
1085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Comment_Regarding_Text_Range_Checks" in that file. */
1086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rx_map = True;
1087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_avma = code_start;
1088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_size = code_len;
1089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rw_map = True;
1090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_avma = data_start;
1091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_size = data_len;
1092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ok = ML_(read_xcoff_debug_info) ( di, is_mainexe );
1094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ok) {
1096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* prepare read data for use */
1097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(canonicaliseTables)( di );
1098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* notify m_redir about it */
1099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(redir_notify_new_DebugInfo)( di );
1100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note that we succeeded */
1101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_dinfo = True;
11029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         hdl = di->handle;
11039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(hdl > 0);
1104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Check invariants listed in
1105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
1106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            priv_storage.h. */
1107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         check_CFSI_related_invariants(di);
1108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /*  Something went wrong (eg. bad XCOFF file). */
1110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         discard_DebugInfo( di );
1111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di = NULL;
1112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
11134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   } else {
11154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Dump all the debugInfos whose text segments intersect
1117f7cdfe298805a91a35b8e0495d9034cbf21003f5sewardj         code_start/code_len. */
1118f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* CFI cache is always invalidated at start of this routine.
1119f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Hence it's safe to ignore the return value of
1120f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         discard_syms_in_range. */
1121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0)
1122f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         (void)discard_syms_in_range( code_start, code_len );
11234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
11259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
11269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return hdl;
11274ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
11284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
11304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_aix5) */
11314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
11399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
11409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
11419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
11429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
11439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
11449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
11459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
11469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
11479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
11489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
11499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
11509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
11519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1152eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1164f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1168f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
1175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = di->text_present
1176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_size > 0
1177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_avma <= ptr
1178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && ptr < di->text_avma + di->text_size;
1179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
11935706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
11945706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
11955706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
11965706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
11975706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
11985706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
11995706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
12005706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
12015706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
12025706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
12035706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1218eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1219eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1220eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1221eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1225f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1226eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1227f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
12315706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1235eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1238eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1243eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1246eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1247eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
12486b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
12496b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
12506b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1253eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
12546b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
12556b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
12566b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Addr a, Char* buf, Int nbuf,
1257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1258c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1259eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1261f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1262c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1263eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1266eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
12676882443ef154bca367bc591287de641e43a9e108njn
12686b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
12696b7611bf42a0fbb62e047d8c43b008205bd21e75njn                   di->symtab[sno].name, buf, nbuf );
12706b7611bf42a0fbb62e047d8c43b008205bd21e75njn
12716b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
12726b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
12736b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
12746b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
12756b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
12766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
12776b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
12786b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
12796b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1282c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1290c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13016b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
13026b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1312f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13276b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13286b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13296b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13406b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13416b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13426b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13546b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
13556b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13566b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13636b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
13646b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
13656b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
13666b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf )
1367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13686b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
13696b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
13706b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
13786b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
13796b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
13806b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
1381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
13826b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
13836b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
13846b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
13856b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
13866b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
13876b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
13886b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13916882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind) ( Char* name )
13926882443ef154bca367bc591287de641e43a9e108njn{
13936882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
13946882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
13956882443ef154bca367bc591287de641e43a9e108njn
13966882443ef154bca367bc591287de641e43a9e108njn   } else if (
13976882443ef154bca367bc591287de641e43a9e108njn#if defined(VGO_linux)
13986882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
13996882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
14006882443ef154bca367bc591287de641e43a9e108njn#elif defined(VGO_aix5)
14016882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__start", name)            ||  // AIX aches
1402f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
1403f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1404f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
14056882443ef154bca367bc591287de641e43a9e108njn#else
14066882443ef154bca367bc591287de641e43a9e108njn#      error Unknown OS
14076882443ef154bca367bc591287de641e43a9e108njn#endif
14086882443ef154bca367bc591287de641e43a9e108njn       0) {
14096882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
14106882443ef154bca367bc591287de641e43a9e108njn
14116882443ef154bca367bc591287de641e43a9e108njn   } else {
14126882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
14136882443ef154bca367bc591287de641e43a9e108njn   }
14146882443ef154bca367bc591287de641e43a9e108njn}
14156882443ef154bca367bc591287de641e43a9e108njn
14166882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
14176882443ef154bca367bc591287de641e43a9e108njn{
14186882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
14196882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
14206882443ef154bca367bc591287de641e43a9e108njn   Char buf[50];
14216882443ef154bca367bc591287de641e43a9e108njn
14226882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
14236882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
14246b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
14256882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
14266882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
14276882443ef154bca367bc591287de641e43a9e108njn   } else {
14286882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
14296882443ef154bca367bc591287de641e43a9e108njn   }
14306882443ef154bca367bc591287de641e43a9e108njn}
14316882443ef154bca367bc591287de641e43a9e108njn
1432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1438c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
14426b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
14436b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
14446b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1459eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int used;
1461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1462f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1463f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
14644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
14657cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
14667cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
14695706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(strncpy_safely)(buf, di->filename, nbuf);
1473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (di->memname) {
14744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
14774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
1479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used);
14804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
14814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
14824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
14834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
14844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
14887cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
14897cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
14907cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
14917cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
14927cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
14937cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
14947cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1495f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1496f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1497f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1499eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* VG_(find_seginfo) ( Addr a )
1504eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
15085706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1512eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1521f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1523eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1535eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1546eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1557eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1559c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1560db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1561db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1562db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1563db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1564eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1565c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1566c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1571eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1576eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
15904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
15914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
15924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
15934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
15944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
15954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
15984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
15994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
16004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
16024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
16034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
16044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
16054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
16074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
16084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
16094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
16104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
16114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
16124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
16134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
16154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (0==VG_(strcmp)(name, si->symtab[i].name)
16164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
16174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
16184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
16194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
16204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
16214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
16224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
16234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
16244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
16254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
16264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1627e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1628e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1629e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1630e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1631e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1632eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1633eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1634eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1635e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1636e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1639e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1643e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1644e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1645e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1646e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1647e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1648eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1649eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1650e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1651e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1652e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1654e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1655e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1656e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1657eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1658e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1659e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1660e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1661e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1662e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1663e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1664e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1665e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1666e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1667e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1668e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1669e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1670e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1671e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1672e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1673e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1674e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1675e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1676e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1677e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1678e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1679e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1682e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1683e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1684e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1691e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1692e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1693e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
1703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
17044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
17054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
17064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1708eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1709eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
1714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1720e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1721e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1722e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1723e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1724e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1725e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1727a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1728eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1732eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1733e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1734eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1735eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1739e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1741eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1746e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1747eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1751e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1762eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1763eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
17655e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17665e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
17675e40abad4504416c59f0b29c1cfc8087201213a9njn      //
17685e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
17695e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
17705e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
17715e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
17725e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
17735e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
17745e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1775a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1776eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
17775e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1778eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1779eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1780eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
1784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
17895e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
17905e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
17915e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
17925e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
17935e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
17945e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
17955e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
17965e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
1797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
180772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
181472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
181572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
181672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
181772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
181872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
181972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr ipHere;
182072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr spHere;
182172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr fpHere;
182272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr min_accessible;
182372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr max_accessible;
182472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
182572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
182672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
182772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
182872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
182972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
183072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjstatic
183172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
183272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
183372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
183472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
183519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
183672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr* e = VG_(indexXA)( exprs, ix );
183772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
183872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
183972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
184072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
184172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
184272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
184372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
184472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
184572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
184619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
18477888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
184872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
184972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
185072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
185172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
185272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
185372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_IP: return (Addr)eec->ipHere;
185472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_SP: return (Addr)eec->spHere;
185572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_FP: return (Addr)eec->fpHere;
185672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
185772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
185872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
185972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
186072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
186119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
186219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
186319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
186419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
186519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
186619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
186719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
186819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
186919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
187019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         return * ((UWord*)a);
187172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
187272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
187372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
187472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
187572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
187672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
187772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
187872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
187972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
188072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
188172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
188272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
188372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
188472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1885f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
1886f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
1887eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1888f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
1889f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
189072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1891f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
1892f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
1893f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
1894f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
1895f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
1896f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
1897f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1898f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
1899f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
1900f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1901f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
1902f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
1904eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1905f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
1906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1907f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1908f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
1909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
1912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
1913f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
1914eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1915f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
1916eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1917eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1918f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
1919f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
1920f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
1921f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1922f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
1923f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
1924f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1928f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
1929f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1930f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
1931f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
1932f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
1933f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1934f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
1935f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1936f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
1937f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
1938f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
1939f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
1940f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
1941f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
1942f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
1943f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1944f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
1945f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
1946f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
1947f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
1948f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
1949f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
1950f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
1951f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
1952f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
1953f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
1954f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
1955f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
1956f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1957f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
1958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
1959f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
1960f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
1961f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1962f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1963f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1964f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1966f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1967f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
1968f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
1969f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1970f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
1971f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
1972f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1973f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
1974f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
1975f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
1976f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1977f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
1978f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
1979f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1980f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
1981f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
1982f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
1983f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
1984f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
1985f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
1986f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
1987eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1988f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
1989f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1990f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
1991f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
1992f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
1993f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1994f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
1995f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1996f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
1997f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
1998f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1999f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2000f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2001f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.
2002f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Given an IP/SP/FP triple, produce the IP/SP/FP values for the
2003f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   previous frame, if possible. */
2004f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Returns True if OK.  If not OK, *{ip,sp,fp}P are not changed. */
2005f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* NOTE: this function may rearrange the order of entries in the
2006f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo list. */
2007f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjBool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
2008f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        /*MOD*/Addr* spP,
2009f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        /*MOD*/Addr* fpP,
2010f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        Addr min_accessible,
2011f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        Addr max_accessible )
2012f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2013f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       ok;
2014f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2015f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DiCfSI*    cfsi = NULL;
2016f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Addr       cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
2017f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2018f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CfiExprEvalContext eec;
2019f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2020f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_q = 0, n_m = 0;
2021f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2022f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2023f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2024f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2025f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   { UWord hash = (*ipP) % N_CFSI_CACHE;
2026f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     CFSICacheEnt* ce = &cfsi_cache[hash];
2027f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2028f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
2029f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* found an entry in the cache .. */
2030f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     } else {
2031f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* not found in cache.  Search and update. */
2032f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        n_m++;
2033f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        ce->ip = *ipP;
2034f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        find_DiCfSI( &ce->di, &ce->ix, *ipP );
2035f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     }
2036f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2037f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (UNLIKELY(ce->di == (DebugInfo*)1)) {
2038f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* no DiCfSI for this address */
2039f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        cfsi = NULL;
2040f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        di = NULL;
2041f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     } else {
2042f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        /* found a DiCfSI for this address */
2043f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        di = ce->di;
2044f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj        cfsi = &di->cfsi[ ce->ix ];
2045f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     }
2046eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2047f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2048f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (UNLIKELY(cfsi == NULL))
2049f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return False; /* no info.  Nothing we can do. */
2050eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2051eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0) {
2052eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(printf)("found cfisi: ");
2053f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
2054eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2055eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2056eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipPrev = spPrev = fpPrev = 0;
2057eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2058eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipHere = *ipP;
2059eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   spHere = *spP;
2060eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   fpHere = *fpP;
2061eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
206272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* First compute the CFA. */
206372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
206472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
206572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_SPREL:
206672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + spHere;
206772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
206872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_FPREL:
206972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + fpHere;
207072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
207172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_EXPR:
20727888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
20737888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2074f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
20757888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
20767888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
20777888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.ipHere = ipHere;
20787888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.spHere = spHere;
20797888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.fpHere = fpHere;
20807888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
20817888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
20827888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2083f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
20847888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (!ok) return False;
208572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
208672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
208772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
208872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
208972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
209072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
209172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2092eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2093eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2094eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2095eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2096eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2097eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2099eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
21039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
2105eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = *(Addr*)a;                       \
2106eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2108eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
211172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
211272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
211472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.ipHere = ipHere;                     \
211572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.spHere = spHere;                     \
211672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.fpHere = fpHere;                     \
211772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
211872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
211972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               ok = True;                               \
2120f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
212172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
212272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
212372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
212472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2125eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2126eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2127eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(ipPrev, ipHere, cfsi->ra_how, cfsi->ra_off);
2129eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(spPrev, spHere, cfsi->sp_how, cfsi->sp_off);
2130eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(fpPrev, fpHere, cfsi->fp_how, cfsi->fp_off);
2131eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *ipP = ipPrev;
2135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *spP = spPrev;
2136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *fpP = fpPrev;
2137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2139eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2140eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2143c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2144c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2145c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2146c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2147c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2148c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2149c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2150c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2151c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2152c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2153c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2154c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2155c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2156c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2157c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2158c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2159c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2160c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2161c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2162c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2163c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2164c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2165c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2166c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2167c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2168c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2169c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2170c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2171c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2172c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2173c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2174c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2175c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2176c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2177c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2178c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2179c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2180c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2181c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2182c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2183c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2184c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2185c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2186c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2187c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2188c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2189c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2190c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2191c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2192c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2193c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2194c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2195c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2196c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2197c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2198c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2199c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2200c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2201c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2202c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2203c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2204c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2205c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2206c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2207c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2208c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2209c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2210c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2211c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2212c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2213c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2214c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2215c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2216c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2217c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2218c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2219c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2220c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2221c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2222c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2223c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2224c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2225c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2226c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2227c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2228c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2229c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2230c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2231c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2232c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2233c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2234c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2235c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2236c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2237c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2238c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2239c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2240c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2241c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2242c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2243c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2246c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2247c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2248c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2249c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2250c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2251c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2252c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2253c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2254c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2255c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *ipP = *(Addr *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals));
2256c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *spP =           spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1 + fpo->cdwParams);
2257c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   *fpP = *(Addr *)(spHere + 4*2);
2258c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2259c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2260c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2261c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2262c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2263c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2274c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
22759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2279588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
228150fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
22859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
229050fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
229150fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
229250fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
229350fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
229450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
229550fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
229650fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
229750fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
229850fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
229950fde23467d92281b32dd537d0d9a590263628c3sewardj
230050fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2303a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
23059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2316588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (res.kind == GXR_Value
2325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Format the acquired information into dname1[0 .. n_dname-1] and
2336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname2[0 .. n_dname-1] in an understandable way.  Not so easy.
2337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If frameNo is -1, this is assumed to be a global variable; else
2338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   a local variable. */
2339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void format_message ( /*OUT*/Char* dname1,
2340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             /*OUT*/Char* dname2,
2341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      n_dname,
2342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2344c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2345c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool have_descr, have_srcloc;
2351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(frameNo >= -1);
2355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(dname1 && dname2 && n_dname > 1);
2356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[0] = dname2[0] = '\0';
2363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
2378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
2392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
2393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s",
2403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2404a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
2408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        declared at dsyms7.c:17, in frame #1 of thread 1 */
2413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2417a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
2421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
2422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
2444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d",
2447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
2448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2459a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable");
2463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        a global variable declared at dsyms7.c:17 */
2468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
2470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
2471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
2472a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart         (char*)(VG_(indexXA)(described,0)) );
2473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
2474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
2475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable declared at %s:%d",
2476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
2477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
2480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
2485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characterised by (ip,sp,fp), and if so write its description into
2486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname{1,2}[0..n_dname-1], and return True.  If not, return
2487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   False. */
2488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
2489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool consider_vars_in_frame ( /*OUT*/Char* dname1,
2490b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /*OUT*/Char* dname2,
2491b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Int n_dname,
2492b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
2493b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
2494b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
2495b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
2496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
2498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
2500b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
2501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
2503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
2504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
2505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
2506a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
2507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
2508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
2509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
2510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
2514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
2515b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2517b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
2519b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
2520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
2521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
2522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
2525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
2526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
2527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
2528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
2529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
2530b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
2531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
2532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
2533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
2534b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
2535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
2537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
2539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
2540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
2543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
2544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
2545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
2546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
2548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
2549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
2550b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
2552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
2553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
2555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
2556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
2557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
2558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
2559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
2560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
2561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
2563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
2564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
2565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
2566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
2567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
2568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
2569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
2571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
2572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
2573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
2574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
2575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
2576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
2577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
2578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
2579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
2580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
2581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
2582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
2583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
2584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
2585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
2586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
2587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
2588c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
2589b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
2590a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
2591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
25929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
25939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
2594588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
2595c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
2596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
25979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
25989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
2600b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
2602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2609eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2610eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Try to form some description of data_addr by looking at the DWARF3
2612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
2613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   frames in the stacks of all threads.  Result (or as much as will
2614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   fit) is put into into dname{1,2}[0 .. n_dname-1] and is guaranteed
2615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to be zero terminated. */
2616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_data_description)( /*OUT*/Char* dname1,
2617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                /*OUT*/Char* dname2,
2618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Int  n_dname,
2619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Addr data_addr )
2620eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
2622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
2623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
2624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
2626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
2627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
2628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
2630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
2632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2634a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
2635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
2636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
2637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
2638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
2639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
26419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
2642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
2643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
2644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
2645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
2651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
2652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
2654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
2655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
2657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
2658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
2659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
2660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
2661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
2662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
2663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
2664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
2665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
2666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
2667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
2668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
2669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
2670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
2671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
2672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
2673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
2674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
2675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
2676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
2678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
2679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
2680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
2681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
2682c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
2683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
2684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
2685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
2686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
2687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
2688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
2689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
2690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
26919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
2692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
2693588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
2694c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
2695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
26969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
26979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
2698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
2699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, -1/*frameNo*/, tid );
2701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            dname1[n_dname-1] = dname2[n_dname-1] = 0;
2703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
2709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
2710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
2711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
2713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
2714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
2715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
2716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
2717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
2718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
2725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
2726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
2727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
2732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
2734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
2735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
2740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
2741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
2742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
2746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      dname1[n_dname-1] = dname2[n_dname-1] = 0;
2747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
2751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
2752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
2753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
2754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
2755b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
2756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
2757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
2758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
2759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
2760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
2761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2763b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
2764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
2765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
2769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
2770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
2771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
2772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
2773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
2774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
2775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
2776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
2777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
2778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
2779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
2780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
2781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
2782b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
2783b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
2784b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
2785b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
2786b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
2787b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj          && consider_vars_in_frame( dname1, dname2, n_dname,
2788b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
2789b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
2790b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
2791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
2797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
2800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
28039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
28049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
28059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
28069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
28079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
28089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
28109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
28119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
28129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
28139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
28149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
28169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
28179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
2818588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
28199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
28209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
28219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
28229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
282350fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
28249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
28259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
28269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
28289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
28299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
28309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
283250fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
283350fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
283450fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
283550fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
283650fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
283750fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
283850fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
283950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
284050fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
28419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
28439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
28449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
28459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
28469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
28479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
28489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
28499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
28509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
28519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
28539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
28549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
28569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
28579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
28589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
28599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
28609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
28619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
28629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
2863588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
28649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
28669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
28679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
2868588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
28699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
28719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
28729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
2873588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
28749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
28769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
28779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
2878588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
28799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
28819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
28829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
28839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (res_sp_6k.kind == GXR_Value) {
28859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
28869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
28879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
28889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
28899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
28909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
28919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
28929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
28939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
28949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
28959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
28969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
28979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
28989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
28999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
2900588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
29019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(res.kind == GXR_Value);
29029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
29039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
290450fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
29059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
290650fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
29079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
29089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
29099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
29109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
29119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
29129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
29139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
29149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
29159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
29169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
29179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
29189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
2919588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
29209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(res.kind == GXR_Value);
29219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
29229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
292350fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
29249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
292550fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
29269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
29279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
29289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
29299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
29309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
29319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
29329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
29339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
29349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
29359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
29369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
29379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
29389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
29399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
29429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
29439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
29449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
29459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
29479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
29489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
29499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
29509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
29519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
29529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
29539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
29549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
29569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
29579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
29589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
29609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
29619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
29629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
29639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
29649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
29659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
29669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
29679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
29689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
29699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
29709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
29719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
29729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
29739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
29749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
29769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
29779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
29789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
29799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
29809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
29829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
29839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
29849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
29859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
29869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
29879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
29889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
29899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
29909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
29919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
29929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
29939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
29949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
29969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
29979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
29989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
29999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
30009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
30019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
30029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
30039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
30049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip = ip;
30059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp = 0;
30069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp = 0;
30079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
30099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
30109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
30119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
30129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
30139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
30149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
30159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
30169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
30179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
30189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
30199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
30209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
30219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
30229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
30239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
30249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
30259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
30269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
30279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
30289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
30299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
30309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
30319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
30329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
30339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
30349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
30359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
30369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
30379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
30389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
30399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
30409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
30419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
30429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
30439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
30449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
30459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
30469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
30479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
30489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3049588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
30509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
30519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
30529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
30549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
30559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
30589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
30599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
30609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
30619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
30629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
30639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
30659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
30669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
30679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
30689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
30699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
30719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
30729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
30739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
30759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
30769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
30779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
30789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
30799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
30809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
30819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
30839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
30849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
30859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
30869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
30889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
30899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
30909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
30919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
30939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
30949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
30959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
30969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
30979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
30989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
30999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
31009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
31019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
31039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
31049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
31059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
31069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
31079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
31089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
31099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
31119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
31129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
31139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
31149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
31159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
31179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
311850fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
31199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
31209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
31219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
31229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
31239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
31249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
31269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
31279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
31289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
31299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
31309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
31319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3132588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
31339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
31359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (res.kind != GXR_Value) {
31369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
31379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
31389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
31399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
31419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
31429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
31439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
314550fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
31469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
314750fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
314850fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
314950fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
315050fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
315150fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
315250fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
315350fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
315450fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
31559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
31579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
31589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
31599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
31609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
31619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
31629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
31639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
31649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
31669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
31679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
31699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
31709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
31719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
31729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
31739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
31749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
31759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
317650fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
31779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
31789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
31799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
31809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
31819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
31829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
31849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
31869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
31889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
31909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
31929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
31939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
31949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst DebugInfo* VG_(next_seginfo)(const DebugInfo* di)
3200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjAddr VG_(seginfo_get_text_avma)(const DebugInfo* di)
3207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjSizeT VG_(seginfo_get_text_size)(const DebugInfo* di)
3212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3214eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3216092b6268cc4a38ae9ee41d1e3355937536ddc579bartAddr VG_(seginfo_get_plt_avma)(const DebugInfo* di)
3217092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3218092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3219092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3220092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3221092b6268cc4a38ae9ee41d1e3355937536ddc579bartSizeT VG_(seginfo_get_plt_size)(const DebugInfo* di)
3222092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3223092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3224092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3225092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3226092b6268cc4a38ae9ee41d1e3355937536ddc579bartAddr VG_(seginfo_get_gotplt_avma)(const DebugInfo* di)
3227092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3228092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3229092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3230092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3231092b6268cc4a38ae9ee41d1e3355937536ddc579bartSizeT VG_(seginfo_get_gotplt_size)(const DebugInfo* di)
3232092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3233092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3234092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3235092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_soname)(const DebugInfo* di)
3237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_filename)(const DebugInfo* di)
3242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->filename;
3244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3246c4431bfe04c7490ea2d74939d222d87f13f30960njnPtrdiffT VG_(seginfo_get_text_bias)(const DebugInfo* di)
3247bbec7728efefaa650970dd1f0282b77040287133sewardj{
3248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3249bbec7728efefaa650970dd1f0282b77040287133sewardj}
3250bbec7728efefaa650970dd1f0282b77040287133sewardj
3251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjInt VG_(seginfo_syms_howmany) ( const DebugInfo *si )
3252eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3253eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3254eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3255eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid VG_(seginfo_syms_getidx) ( const DebugInfo *si,
3257eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      Int idx,
3258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Addr*   avma,
32594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                               /*OUT*/Addr*   tocptr,
3260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                               /*OUT*/UInt*   size,
3261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/HChar** name,
3262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Bool*   isText )
3263eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (avma)   *avma   = si->symtab[idx].addr;
32664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (tocptr) *tocptr = si->symtab[idx].tocptr;
32674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (size)   *size   = si->symtab[idx].size;
32684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (name)   *name   = (HChar*)si->symtab[idx].name;
3269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (isText) *isText = si->symtab[idx].isText;
3270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
32895706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjVgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
3300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   Addr a)
3301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3309a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld data=%#lx,%ld bss=%#lx,%ld\n",
3310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            a, di, di->filename,
3311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
33405706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
33415706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
33425706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
33435706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
33445706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
33455706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3358092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3359092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3360092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3361092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3362092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3363092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di && di->filename) {
3381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int fnlen = VG_(strlen)(di->filename);
3383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3388d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j] = di->filename[i];
3391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (di->filename[i] == 0) break;
3392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3394d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3405eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3408eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3409