debuginfo.c revision 05c459ea63c50a072cf1eb0868590e9c0b362f30
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
110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
12eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
346c591e15c1d6402a2a755310f005f795b68e7e38sewardj#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
36b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
41b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
4213ac96dea734b3933a73524b991ac64fb48a4d57sewardj#include "pub_core_libcproc.h"   // VG_(getenv)
43d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
506882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
545d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj#include "priv_image.h"
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
56b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
62b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
63c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
68eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
69c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
95f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
96f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
10420ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippestatic UInt CF_info_generation = 0;
1055c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void );
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
165eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1731636d33c13958b9c0e7d3059cdd5005746418eb2florianDebugInfo* alloc_DebugInfo( const HChar* filename )
174eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
178f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
179f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
181a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
182a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1836b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.maps     = VG_(newXA)(
1846b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_zalloc), "di.debuginfo.aDI.3",
1856b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_free), sizeof(struct _DebugInfoMapping));
186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
187452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
188452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1900f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
191f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
197f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
198f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20659a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
2079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
20859a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
2116b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.maps)     VG_(deleteXA)(di->fsm.maps);
212a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
213f1e1aa691d7a2f0f2f933daf060bec5ae6938705philippe   if (di->soname)       ML_(dinfo_free)(di->soname);
214a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
215a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di->inltab)       ML_(dinfo_free)(di->inltab);
2165c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_base)    ML_(dinfo_free)(di->cfsi_base);
2175c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_ix)    ML_(dinfo_free)(di->cfsi_m_ix);
2185c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)      ML_(dinfo_free)(di->cfsi_rd);
2195c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_pool)  VG_(deleteDedupPA)(di->cfsi_m_pool);
220a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
221a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
223a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
224a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
225a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
226a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
227a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
228a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
229a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
230a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
231a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
232a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
233a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
234a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
235a5cace0c2a3e212931badbf6398a0cd98393121asewardj
2362352e9843d8a616b9d829aef929d218aea9b4ae0philippe   if (di->strpool)
2372352e9843d8a616b9d829aef929d218aea9b4ae0philippe      VG_(deleteDedupPA) (di->strpool);
238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
24459a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
24859a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
251eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
25259a2d18d0ddfa241850017252b0804d469187d79sewardj
25359a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
25459a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
25559a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
25659a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
25759a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
25859a2d18d0ddfa241850017252b0804d469187d79sewardj      }
25959a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
26059a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
2837293d2530f8c60c1060f9f003e214cc341d35266philippe                  .strpool */
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3046bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* reason = "munmap";
3054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
31233e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
31333e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
315738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
318a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
3191636d33c13958b9c0e7d3059cdd5005746418eb2florian                                            : "???",
3204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
32333e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
32433e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
339f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
341f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
343f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
367f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
370f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
371f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
379eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
394eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3956b5625bb609b154766d2e138b61e15655f60b710sewardj/* Do the basic mappings of the two DebugInfos overlap in any way? */
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3986b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
4016b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) {
4026b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i);
4036b5625bb609b154766d2e138b61e15655f60b710sewardj      for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
4046b5625bb609b154766d2e138b61e15655f60b710sewardj         struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
4056b5625bb609b154766d2e138b61e15655f60b710sewardj         if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size))
4066b5625bb609b154766d2e138b61e15655f60b710sewardj            return True;
4076b5625bb609b154766d2e138b61e15655f60b710sewardj      }
4086b5625bb609b154766d2e138b61e15655f60b710sewardj   }
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
4396b5625bb609b154766d2e138b61e15655f60b710sewardj   Clearly diRef must have its mapping information set to something sane. */
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
453eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
457eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4580f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4590f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4600f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
4611636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic DebugInfo* find_or_create_DebugInfo_for ( HChar* filename )
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
466a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
467a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4710f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
481f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
482f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
483f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
484f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
485f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
4876b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool has_nonempty_rx = False;
4886b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool cfsi_fits = False;
4896b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
494a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
495a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
4966b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
4976b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
4986b5625bb609b154766d2e138b61e15655f60b710sewardj      /* We are interested in r-x mappings only */
4996b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map->rx)
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5016b5625bb609b154766d2e138b61e15655f60b710sewardj
5026b5625bb609b154766d2e138b61e15655f60b710sewardj      /* degenerate case: r-x section is empty */
5036b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->size == 0)
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5056b5625bb609b154766d2e138b61e15655f60b710sewardj      has_nonempty_rx = True;
5066b5625bb609b154766d2e138b61e15655f60b710sewardj
5076b5625bb609b154766d2e138b61e15655f60b710sewardj      /* normal case: r-x section is nonempty */
5086b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (0) */
5096b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(map->size > 0);
5106b5625bb609b154766d2e138b61e15655f60b710sewardj
5116b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (1) */
5126b5625bb609b154766d2e138b61e15655f60b710sewardj      for (di2 = debugInfo_list; di2; di2 = di2->next) {
5136b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di2 == di)
5146b5625bb609b154766d2e138b61e15655f60b710sewardj            continue;
5156b5625bb609b154766d2e138b61e15655f60b710sewardj         for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
5166b5625bb609b154766d2e138b61e15655f60b710sewardj            struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
5176b5625bb609b154766d2e138b61e15655f60b710sewardj            if (!map2->rx || map2->size == 0)
5186b5625bb609b154766d2e138b61e15655f60b710sewardj               continue;
5196b5625bb609b154766d2e138b61e15655f60b710sewardj            vg_assert(!ranges_overlap(map->avma,  map->size,
5206b5625bb609b154766d2e138b61e15655f60b710sewardj                                      map2->avma, map2->size));
5216b5625bb609b154766d2e138b61e15655f60b710sewardj         }
5226b5625bb609b154766d2e138b61e15655f60b710sewardj      }
5236b5625bb609b154766d2e138b61e15655f60b710sewardj      di2 = NULL;
5246b5625bb609b154766d2e138b61e15655f60b710sewardj
5256b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (2) */
5265c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd) {
5276b5625bb609b154766d2e138b61e15655f60b710sewardj         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
5286b5625bb609b154766d2e138b61e15655f60b710sewardj         /* Assume the csfi fits completely into one individual mapping
5296b5625bb609b154766d2e138b61e15655f60b710sewardj            for now. This might need to be improved/reworked later. */
5306b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di->cfsi_minavma >= map->avma &&
5316b5625bb609b154766d2e138b61e15655f60b710sewardj             di->cfsi_maxavma <  map->avma + map->size)
5326b5625bb609b154766d2e138b61e15655f60b710sewardj            cfsi_fits = True;
5336b5625bb609b154766d2e138b61e15655f60b710sewardj      }
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5356b5625bb609b154766d2e138b61e15655f60b710sewardj
5366b5625bb609b154766d2e138b61e15655f60b710sewardj   /* degenerate case: all r-x sections are empty */
5376b5625bb609b154766d2e138b61e15655f60b710sewardj   if (!has_nonempty_rx) {
5385c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd == NULL);
5396b5625bb609b154766d2e138b61e15655f60b710sewardj      return;
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5416b5625bb609b154766d2e138b61e15655f60b710sewardj
5426b5625bb609b154766d2e138b61e15655f60b710sewardj   /* invariant (2) - cont. */
5435c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)
5446b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(cfsi_fits);
5456b5625bb609b154766d2e138b61e15655f60b710sewardj
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
5475c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd) {
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
5515c3dba227192de63d86f65ec7d9597c132818c37philippe         DiCfSI* cfsi = &di->cfsi_rd[i];
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
5565c3dba227192de63d86f65ec7d9597c132818c37philippe            DiCfSI* cfsip = &di->cfsi_rd[i-1];
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
5825c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
583f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
584f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
585f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
594eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
595731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
596731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
597731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
598731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
599731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
600731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
601731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
602731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
603731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
604731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
605731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
606731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
607731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
608731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
609731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
610731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
611731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
612731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
613731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
614731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
615731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
616731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
617731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
618731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
619731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
620731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
621731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
622731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
623731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
6246b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges specified in the _DebugInfoFsm mapping array. First
6256b5625bb609b154766d2e138b61e15655f60b710sewardj      get rid of any other DebugInfos which overlap any of those
6266b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges (to avoid total confusion). */
627731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
628731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
629731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* .. and acquire new info. */
630731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGO_linux)
631731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
632731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
633731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
634731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
635731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
636731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
637731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
638731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
639731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
640731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
641731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
642731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
6435c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
644731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
645731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
6465c3dba227192de63d86f65ec7d9597c132818c37philippe      /* Check invariants listed in
6475c3dba227192de63d86f65ec7d9597c132818c37philippe         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
6485c3dba227192de63d86f65ec7d9597c132818c37philippe         priv_storage.h. */
6495c3dba227192de63d86f65ec7d9597c132818c37philippe      check_CFSI_related_invariants(di);
6505c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(finish_CFSI_arrays)(di);
651731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
652731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
653731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
654731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
655731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
656731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      tl_assert(di->handle > 0);
657731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
658731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
659731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
660731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
661731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
662731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
663731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
664731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
665731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
666731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
667731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
668731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
669731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
670731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
671731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
672731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
673731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
674731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
675731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
676731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
6839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
6849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
6855f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   If use_fd is not -1, that is used instead of the filename; this
6865f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   avoids perturbing fcntl locks, which are released by simply
6875f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   re-opening and closing the same file (even via different fd!).
6885f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
6899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
6909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
6919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
6929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
6939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
6949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6965f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
700731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
7025f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   Int        actual_fd, oflags;
7035f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   SysRes     preadres;
704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
706ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
707ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7095f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(use_fd >= -1);
7105f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
718a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
7299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
7323e7986312a0ffc7646b0552d4c4ea3744a870e73florian   filename = VG_(am_get_filename)( seg );
733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
7349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7360ab84fe82d1e25c2e0544d08826df42caa44ded1bart   /*
7370ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * Cannot read from these magic files:
7380ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- WARNING: Serious error when reading debug info
7390ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- When reading debug info from /proc/xen/privcmd:
7400ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- can't read file to inspect ELF header
7410ab84fe82d1e25c2e0544d08826df42caa44ded1bart    */
7420ab84fe82d1e25c2e0544d08826df42caa44ded1bart   if (VG_(strncmp)(filename, "/proc/xen/", 10) == 0)
7430ab84fe82d1e25c2e0544d08826df42caa44ded1bart      return 0;
7440ab84fe82d1e25c2e0544d08826df42caa44ded1bart
745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
748ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
74915728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
750ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
751ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
752ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
7539c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
754ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
755ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
756ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
757cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
758ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
759ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
760e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
761ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
762a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
763ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
764ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
7659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
7662ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
7672ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
768ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
769ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
7709c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
7719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
772ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
773ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
77415728ab41ea41bf731dcc74ac68354550ced2189bart
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
795eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
808f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
809f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
810f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
811b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
812b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
813b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
814b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
815b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
816b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
817b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
818b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
819b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
823731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
824731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
8254df0bfc0614379192c780c944415dc420d9cfe8epetarj#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
8264df0bfc0614379192c780c944415dc420d9cfe8epetarj      || defined(VGA_mips64)
827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
829f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) \
830f0c1250e324f6684757c6a15545366447ef1d64fsewardj        || defined(VGA_arm64)
831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
833b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
834b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
835b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
838eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
840731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
841731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
842731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
843731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
848731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
849731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
8509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
851eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8525a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
8535a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
8545a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
855cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
856cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
857cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
858cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
8595f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8605f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8615f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      SysRes fd = VG_(open)( filename, oflags, 0 );
8625f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      if (sr_isError(fd)) {
8635f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         if (sr_Err(fd) != VKI_EACCES) {
8645f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            DebugInfo fake_di;
8655f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            VG_(memset)(&fake_di, 0, sizeof(fake_di));
8665f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            fake_di.fsm.filename = filename;
8675f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            ML_(symerr)(&fake_di, True,
8685f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                        "can't open file to inspect ELF header");
8695f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         }
8705f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         return 0;
8715a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
8725f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = sr_Res(fd);
8735f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   } else {
8745f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = use_fd;
8755a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8765a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8775f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   preadres = VG_(pread)( actual_fd, buf1k, sizeof(buf1k), 0 );
8785f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8795f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      VG_(close)( actual_fd );
8805f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   }
8815f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8825f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_isError(preadres)) {
8835a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
8845a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
885a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      fake_di.fsm.filename = filename;
8865a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
8875a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8885a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8895f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_Res(preadres) == 0)
8905f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      return 0;
8915f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
8925a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8938b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
8946e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
895f7c9714ea0cde18daaecb896278e85e780d3bd75sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
8965a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8976e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
8985f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
899f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
9006e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
9016e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
9026e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
9035a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
9060f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
9096b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Note the details about the mapping. */
9106b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping map;
9116b5625bb609b154766d2e138b61e15655f60b710sewardj   map.avma = a;
9126b5625bb609b154766d2e138b61e15655f60b710sewardj   map.size = seg->end + 1 - seg->start;
9136b5625bb609b154766d2e138b61e15655f60b710sewardj   map.foff = seg->offset;
9146b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rx   = is_rx_map;
9156b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rw   = is_rw_map;
9166b5625bb609b154766d2e138b61e15655f60b710sewardj   map.ro   = is_ro_map;
9176b5625bb609b154766d2e138b61e15655f60b710sewardj   VG_(addToXA)(di->fsm.maps, &map);
9186b5625bb609b154766d2e138b61e15655f60b710sewardj
9196b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Update flags about what kind of mappings we've already seen. */
9206b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rx_map |= is_rx_map;
9216b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rw_map |= is_rw_map;
9226b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_ro_map |= is_ro_map;
923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
924731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
925731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
926731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
927731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
928731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
929731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
9309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
931731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
932731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
933731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
934731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
9359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
943f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
944a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
945f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
946f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
9475c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
958f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
959eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
961f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
962f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
963f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
9645c3dba227192de63d86f65ec7d9597c132818c37philippe         cfsi_m_cache__invalidate();
965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
966eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
967eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
968731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
969731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* This is a MacOSX 10.7 32-bit only special.  See comments on the
970731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
971731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
972731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
973731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
974ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#  if defined(VGP_x86_darwin) && (DARWIN_VERS >= DARWIN_10_7)
975731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
976731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
977731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (do_nothing /* wrong platform */)
978731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
979731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
980731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
981731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
982731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
983731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
984731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
985731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
986731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
987731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
988731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
989731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
990731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
9916b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping *map = NULL;
9926b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
993731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
994731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
995731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
996731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
997731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
998731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
999731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
1000731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
1001731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
1002731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
10036b5625bb609b154766d2e138b61e15655f60b710sewardj      /* Try to find a mapping matching the memory area. */
10046b5625bb609b154766d2e138b61e15655f60b710sewardj      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10056b5625bb609b154766d2e138b61e15655f60b710sewardj         map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10066b5625bb609b154766d2e138b61e15655f60b710sewardj         if (map->ro && map->avma == a && map->size == len)
10076b5625bb609b154766d2e138b61e15655f60b710sewardj            break;
10086b5625bb609b154766d2e138b61e15655f60b710sewardj         map = NULL;
10096b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10106b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map)
10116b5625bb609b154766d2e138b61e15655f60b710sewardj         continue; /* this isn't an upgrade of an r-- mapping */
1012731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
1013731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
1014731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
1015731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
1016731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
1017731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
10186b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Do the upgrade.  Simply update the flags of the mapping
10196b5625bb609b154766d2e138b61e15655f60b710sewardj      and pretend we never saw the RO map at all. */
1020731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
10216b5625bb609b154766d2e138b61e15655f60b710sewardj   map->rx = True;
10226b5625bb609b154766d2e138b61e15655f60b710sewardj   map->ro = False;
1023731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
1024731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
10256b5625bb609b154766d2e138b61e15655f60b710sewardj   /* See if there are any more ro mappings */
10266b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10276b5625bb609b154766d2e138b61e15655f60b710sewardj      map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10286b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->ro) {
10296b5625bb609b154766d2e138b61e15655f60b710sewardj         di->fsm.have_ro_map = True;
10306b5625bb609b154766d2e138b61e15655f60b710sewardj         break;
10316b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10326b5625bb609b154766d2e138b61e15655f60b710sewardj   }
10336b5625bb609b154766d2e138b61e15655f60b710sewardj
10346b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Check if we're now in an accept state and read debuginfo.  Finally. */
10356b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
10366b5625bb609b154766d2e138b61e15655f60b710sewardj      ULong di_handle __attribute__((unused))
10376b5625bb609b154766d2e138b61e15655f60b710sewardj         = di_notify_ACHIEVE_ACCEPT_STATE( di );
10386b5625bb609b154766d2e138b61e15655f60b710sewardj      /* di_handle is ignored. That's not a problem per se -- it just
10396b5625bb609b154766d2e138b61e15655f60b710sewardj         means nobody will ever be able to refer to this debuginfo by
10406b5625bb609b154766d2e138b61e15655f60b710sewardj         handle since nobody will know what the handle value is. */
10416b5625bb609b154766d2e138b61e15655f60b710sewardj   }
1042731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1043731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1044731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1045c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1046c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1047c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1048c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
104954c45db2f978055aeca91aaccb05aac825523e6csewardj                                   SizeT total_size, PtrdiffT bias_obj )
1050c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
105113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1052c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
105354fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian   HChar  exename[VKI_PATH_MAX];
10541636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* pdbname = NULL;
10551636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* dot;
1056c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1057c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1058c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1059c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1060c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1061c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1062738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1063c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1064cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
106554c45db2f978055aeca91aaccb05aac825523e6csewardj         "bias=%#lx\n",
106654c45db2f978055aeca91aaccb05aac825523e6csewardj         fd_obj, avma_obj, total_size, bias_obj
1067c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1068c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1069c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1070c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1071c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1072c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1073c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1074c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
1075c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
10769c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1077c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1078c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
1079c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
1080c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
1081c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
1082c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
1083c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
1084c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
1085c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
1086c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
1087c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
1088c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
1089c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1090c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1091738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1092c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1093c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
109413ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
109513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
109613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
109713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
109813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
109913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
110013ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
110113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
110213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
110313ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
110413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
110513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
110613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
110713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
110813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
110913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
111013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
111113ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
111213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
111313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
111413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
111513ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
111613ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
111713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
111813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
111913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
112013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
112113ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
112213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
112313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
112413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
112598500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/drive_%c%s",
112698500e2ee5f63f9c0af57835f7620d30848115f4bart                       wpfx, pdbname[0], &pdbname[2]);
112713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
112813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
112913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
113013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
113113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
113213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
113313ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
113413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
113513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
113613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
113798500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/.wine/drive_%c%s",
113898500e2ee5f63f9c0af57835f7620d30848115f4bart		       home, pdbname[0], &pdbname[2]);
113913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
114013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
114113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
114213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
114313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
114413ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
114513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
114613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
114713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
114813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1149c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
115013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
115113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
115213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
115313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
115413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
115513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
115613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
115713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
115813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
115913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
116013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
116113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
116213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
116313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
116413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
116513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
116613ac96dea734b3933a73524b991ac64fb48a4d57sewardj
116713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
116813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
116913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
117013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
117113ac96dea734b3933a73524b991ac64fb48a4d57sewardj
117213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
117313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1174c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1175c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1176c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1177cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1178738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1179c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1180c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1181738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1182c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1183c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
11849c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
11857138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1186ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
11877138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
11887138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
11897138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
11907138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
11917138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
11927138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
11937138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1194738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1195ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1196ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1197ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1198c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1199c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1200c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1201cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1203c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1204c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1205c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1206cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1207cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1208cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1209cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1210cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1211cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1212cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1213cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1214cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
12159c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1216cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1217cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1218cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1219cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1220cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1221cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1222cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1223cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1224cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1225cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1226cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1227c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1228c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1229c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1230c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1231cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1232cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1233cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1234cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1235cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1236cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1237cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1238cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1239c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1240738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1241c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1242c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1243c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
12445c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
1245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1246c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1247c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12480f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1249c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1250c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1251a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1252c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1253c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1254c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1255c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
125654c45db2f978055aeca91aaccb05aac825523e6csewardj     ML_(read_pdb_debug_info)( di, avma_obj, bias_obj,
1257c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1258c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1259c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1260c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1261c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1262c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1263cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1264cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1265cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1266a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                 "%lu syms, %lu src locs, "
1267a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                 "%lu src locs, %lu fpo recs\n",
1268a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     di->symtab_used, di->loctab_used,
1269a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     di->inltab_used, di->fpo_size);
1270cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1271c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1272c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1273c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1274c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1275c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1276c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12778b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
12784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
12794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
12879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
12889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
12899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
12909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
12919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
12929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
12939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
12949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
12959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
12969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
12979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12996b5625bb609b154766d2e138b61e15655f60b710sewardjstruct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di,
13006b5625bb609b154766d2e138b61e15655f60b710sewardj                                                 Addr lo, Addr hi )
13016b5625bb609b154766d2e138b61e15655f60b710sewardj{
13026b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
13036b5625bb609b154766d2e138b61e15655f60b710sewardj   vg_assert(lo <= hi);
13046b5625bb609b154766d2e138b61e15655f60b710sewardj
13056b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Optimization: Try to use the last matched rx mapping first */
13066b5625bb609b154766d2e138b61e15655f60b710sewardj   if (   di->last_rx_map
13076b5625bb609b154766d2e138b61e15655f60b710sewardj       && lo >= di->last_rx_map->avma
13086b5625bb609b154766d2e138b61e15655f60b710sewardj       && hi <  di->last_rx_map->avma + di->last_rx_map->size)
13096b5625bb609b154766d2e138b61e15655f60b710sewardj      return di->last_rx_map;
13106b5625bb609b154766d2e138b61e15655f60b710sewardj
13116b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
13126b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
13136b5625bb609b154766d2e138b61e15655f60b710sewardj      if (   map->rx && map->size > 0
13146b5625bb609b154766d2e138b61e15655f60b710sewardj          && lo >= map->avma && hi < map->avma + map->size) {
13156b5625bb609b154766d2e138b61e15655f60b710sewardj         di->last_rx_map = map;
13166b5625bb609b154766d2e138b61e15655f60b710sewardj         return map;
13176b5625bb609b154766d2e138b61e15655f60b710sewardj      }
13186b5625bb609b154766d2e138b61e15655f60b710sewardj   }
13196b5625bb609b154766d2e138b61e15655f60b710sewardj
13206b5625bb609b154766d2e138b61e15655f60b710sewardj   return NULL;
13216b5625bb609b154766d2e138b61e15655f60b710sewardj}
13226b5625bb609b154766d2e138b61e15655f60b710sewardj
1323a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1324a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*--- Types and functions for inlined IP cursor            ---*/
1325a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1326a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestruct _InlIPCursor {
1327a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Addr eip;             // Cursor used to describe calls at eip.
1328a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo* di;        // DebugInfo describing inlined calls at eip
1329a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1330a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_lopos; // The inlined fn calls covering eip are in
1331a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_hipos; // di->inltab[inltab_lopos..inltab_hipos].
1332a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // Note that not all inlined fn calls in this range
1333a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // are necessarily covering eip.
1334a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1335a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Int   curlevel;       // Current level to describe.
1336a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // 0 means to describe eip itself.
1337a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  cur_inltab;     // inltab pos for call inlined at current level.
1338a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  next_inltab;    // inltab pos for call inlined at next (towards main)
1339a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // level.
1340a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe};
1341a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1342a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Bool is_top(InlIPCursor *iipc)
1343a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1344a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->cur_inltab == -1;
1345a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1346a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1347a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Bool is_bottom(InlIPCursor *iipc)
1348a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1349a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->next_inltab == -1;
1350a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1351a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1352a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeBool VG_(next_IIPC)(InlIPCursor *iipc)
1353a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1354a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word i;
1355a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DiInlLoc *hinl = NULL;
1356a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word hinl_pos = -1;
1357a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo *di;
1358a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1359a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc == NULL)
1360a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1361a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1362a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->curlevel <= 0) {
1363a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel--;
1364a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1365a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1366a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1367a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di = iipc->di;
1368a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = iipc->inltab_lopos; i <= iipc->inltab_hipos; i++) {
1369a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= iipc->eip
1370a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && iipc->eip < di->inltab[i].addr_hi
1371a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && di->inltab[i].level < iipc->curlevel
1372a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && (!hinl || hinl->level < di->inltab[i].level)) {
1373a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl = &di->inltab[i];
1374a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl_pos = i;
1375a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1376a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1377a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1378a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->cur_inltab = iipc->next_inltab;
1379a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->next_inltab = hinl_pos;
1380a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->next_inltab < 0)
1381a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = 0; // no inlined call anymore, describe eip itself
1382a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   else
1383a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = di->inltab[iipc->next_inltab].level;
1384a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1385a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return True;
1386a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1387a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1388a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Forward */
1389a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1390a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                           /*OUT*/Word* locno );
1391a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1392a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Returns the position after which eip would be inserted in inltab.
1393a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (-1 if eip should be inserted before position 0).
1394a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   This is the highest position with an addr_lo <= eip.
1395a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   As inltab is sorted on addr_lo, dichotomic search can be done
1396a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (note that inltab might have duplicates addr_lo). */
1397a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Word inltab_insert_pos (DebugInfo *di, Addr eip)
1398a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1399a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word mid,
1400a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        lo = 0,
1401a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        hi = di->inltab_used-1;
1402a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= hi) {
1403a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      mid      = (lo + hi) / 2;
1404a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo) { hi = mid-1; continue; }
1405a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip > di->inltab[mid].addr_lo) { lo = mid+1; continue; }
1406a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo = mid; break;
1407a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1408a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1409a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= di->inltab_used-1 && di->inltab[lo].addr_lo <= eip)
1410a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo++;
1411a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#if 0
1412a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (mid = 0; mid <= di->inltab_used-1; mid++)
1413a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo)
1414a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1415a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (lo - 1 == mid - 1);
1416a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#endif
1417a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return lo - 1;
1418a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1419a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1420a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeInlIPCursor* VG_(new_IIPC)(Addr eip)
1421a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1422a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo*  di;
1423a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        locno;
1424a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        i;
1425a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   InlIPCursor *ret;
1426a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool        avail;
1427a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1428a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (!VG_(clo_read_inline_info))
1429a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No way we can find inlined calls.
1430a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1431a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the DebugInfo for eip */
1432a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   search_all_loctabs ( eip, &di, &locno );
1433a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di == NULL || di->inltab_used == 0)
1434a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No di (with inltab) containing eip.
1435a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1436a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the entry in di->inltab with the highest addr_lo that
1437a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      contains eip. */
1438a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We start from the highest pos in inltab after which eip would
1439a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      be inserted. */
1440a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = inltab_insert_pos (di, eip); i >= 0; i--) {
1441a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= eip && eip < di->inltab[i].addr_hi) {
1442a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1443a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1444a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      /* Stop the backward scan when reaching an addr_lo which
1445a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         cannot anymore contain eip : we know that all ranges before
1446a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         i also cannot contain eip. */
1447a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1448a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         return NULL;
1449a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1450a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1451a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (i < 0)
1452a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No entry containing eip.
1453a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1454a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We have found the highest entry containing eip.
1455a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      Build a cursor. */
1456a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret = ML_(dinfo_zalloc) ("dinfo.new_IIPC", sizeof(*ret));
1457a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->eip = eip;
1458a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->di = di;
1459a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_hipos = i;
1460a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = ret->inltab_hipos - 1; i >= 0; i--) {
1461a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1462a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1463a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break; /* Similar stop backward scan logic as above. */
1464a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1465a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_lopos = i + 1;
1466a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->curlevel = MAX_LEVEL;
1467a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->cur_inltab = -1;
1468a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->next_inltab = -1;
1469a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1470a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* MAX_LEVEL is higher than any stored level. We can use
1471a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(next_IIPC) to get to the 'real' first highest call level. */
1472a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   avail = VG_(next_IIPC) (ret);
1473a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (avail);
1474a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1475a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return ret;
1476a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1477a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1478a0a73939b0398b6608fd6dbde49820ce6530d12cphilippevoid VG_(delete_IIPC)(InlIPCursor *iipc)
1479a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1480a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc)
1481a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      ML_(dinfo_free)( iipc );
1482a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1483a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
14846b5625bb609b154766d2e138b61e15655f60b710sewardj
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1491b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1492b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1493b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1494b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1495b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1496b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
150851c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
150951c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
151051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1511a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
15126b5625bb609b154766d2e138b61e15655f60b710sewardj                   && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL);
1513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1515b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1517b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1519b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
15275706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
15285706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
15295706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
15305706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
15315706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
15325706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
15335706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
15345706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
15355706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
15365706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
15375706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1550eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1552eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1553eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1554eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1560eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
15655706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1574eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1575eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
15826b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
15836b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
15846b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
15886b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
15896b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
15901636d33c13958b9c0e7d3059cdd5005746418eb2florian                    Addr a, HChar* buf, Int nbuf,
1591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1592c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1595f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1596c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1597eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1600eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
16016882443ef154bca367bc591287de641e43a9e108njn
1602a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
16036b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
1604a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   di->symtab[sno].pri_name, buf, nbuf );
16056b7611bf42a0fbb62e047d8c43b008205bd21e75njn
16066b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
16076b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
16086b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
16096b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
16106b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
16116b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
16126b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
16136b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
16146b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1615eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1617c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
16201636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar    buf2[12];
16211636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   symend = buf + VG_(strlen)(buf);
16221636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   end = buf + nbuf;
1623eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1624eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1625c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1626eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1627eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1628eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1629eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1630eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
16311636d33c13958b9c0e7d3059cdd5005746418eb2florian	 HChar *cp = buf2;
1632eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1633eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1634eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1635eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
16366b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
16376b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1643eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1644eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1645eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1647f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1648eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1652eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1656eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1657eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1658eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
16601636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname) ( Addr a, HChar* buf, Int nbuf )
1661eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
16626b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
16636b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
16646b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1670eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
16731636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_w_offset) ( Addr a, HChar* buf, Int nbuf )
1674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
16756b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
16766b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
16776b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1683eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
16871636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_if_entry) ( Addr a, HChar* buf, Int nbuf )
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
16896b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
16906b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
16916b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
16986b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
16996b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
17006b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
17011636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf )
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
17036b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
17046b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
17056b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
17136b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
17146b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
1715a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeBool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf,
1716a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                       InlIPCursor* iipc )
1717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1718a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
1719a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
1720a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
1721a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*below-main-renaming*/True,
1722a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            a, buf, nbuf,
1723a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*match_anywhere_in_fun*/True,
1724a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*show offset?*/False,
1725a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*text syms only*/True,
1726a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*offsetP*/NULL );
1727a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
1728a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
1729a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
1730a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
1731a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
1732a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
1733a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(snprintf)(buf, nbuf, "%s", next_inl->inlinedfn);
1734a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return True;
1735a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1736eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17385db15403e889d4db339b342bc2a824ef0bfaa654sewardj/* mips-linux only: find the offset of current address. This is needed for
17395db15403e889d4db339b342bc2a824ef0bfaa654sewardj   stack unwinding for MIPS.
17405db15403e889d4db339b342bc2a824ef0bfaa654sewardj*/
17415db15403e889d4db339b342bc2a824ef0bfaa654sewardjBool VG_(get_inst_offset_in_function)( Addr a,
17425db15403e889d4db339b342bc2a824ef0bfaa654sewardj                                       /*OUT*/PtrdiffT* offset )
17435db15403e889d4db339b342bc2a824ef0bfaa654sewardj{
17441636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar fnname[64];
17455db15403e889d4db339b342bc2a824ef0bfaa654sewardj   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
17465db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*below-main-renaming*/False,
17475db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         a, fnname, 64,
17485db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*match_anywhere_in_sym*/True,
17495db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*show offset?*/True,
17505db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*data syms only please*/True,
17515db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         offset );
17525db15403e889d4db339b342bc2a824ef0bfaa654sewardj}
17535db15403e889d4db339b342bc2a824ef0bfaa654sewardj
17541636d33c13958b9c0e7d3059cdd5005746418eb2florianVg_FnNameKind VG_(get_fnname_kind) ( HChar* name )
17556882443ef154bca367bc591287de641e43a9e108njn{
17566882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
17576882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
17586882443ef154bca367bc591287de641e43a9e108njn
17596882443ef154bca367bc591287de641e43a9e108njn   } else if (
17603026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
17616882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
17626882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
17633026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
17663026f71684a930286186aa10fef266c304672e8fsewardj#      else
17673026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
17683026f71684a930286186aa10fef266c304672e8fsewardj#      endif
17696882443ef154bca367bc591287de641e43a9e108njn       0) {
17706882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
17716882443ef154bca367bc591287de641e43a9e108njn
17726882443ef154bca367bc591287de641e43a9e108njn   } else {
17736882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
17746882443ef154bca367bc591287de641e43a9e108njn   }
17756882443ef154bca367bc591287de641e43a9e108njn}
17766882443ef154bca367bc591287de641e43a9e108njn
17776882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
17786882443ef154bca367bc591287de641e43a9e108njn{
17796882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
17806882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
17811636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar buf[50];
17826882443ef154bca367bc591287de641e43a9e108njn
17836882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
17846882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
17856b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
17866882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
17876882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
17886882443ef154bca367bc591287de641e43a9e108njn   } else {
17896882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
17906882443ef154bca367bc591287de641e43a9e108njn   }
17916882443ef154bca367bc591287de641e43a9e108njn}
17926882443ef154bca367bc591287de641e43a9e108njn
1793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
17981636d33c13958b9c0e7d3059cdd5005746418eb2florian                                  /*OUT*/HChar* dname, Int n_dname,
1799c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
18036b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
18046b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
18056b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1815b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
18191636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf )
1820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1822f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1823f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
18244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
18257cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
18267cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
18295706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1832a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
18334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1834eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1835eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
18377cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
18387cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
18397cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
18407cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
18417cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
18427cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
18437cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1844f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1845f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1846f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1848eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1849eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1851eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1852e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1853eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1854e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1856e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
18595706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1862e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1863e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1869eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1870eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
18711636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_filename)( Addr a, HChar* filename, Int n_filename )
1872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1874f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1886f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1887eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1888eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1889eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1890eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1891eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1892eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1893eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1894eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1895eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1896eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1897eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
18991636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* filename, Int n_filename,
19001636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* dirname,  Int n_dirname,
1901eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1905f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1908eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1912c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1913db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1914db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1915db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1916db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1917eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1918c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1919c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1920eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1930eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19424ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
19434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
19444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
19454ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
19464ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
19474ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
19484ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
19496bd9dc18c043927c1196caba20a327238a179c42florianBool VG_(lookup_symbol_SLOW)(const HChar* sopatt, HChar* name,
1950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
19514ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
19524ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
19534ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
19554ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
19564ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
19574ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
19584ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
19604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
19614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
19624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
19634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
19644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
19654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
19664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
19674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
19681636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* pri_name = si->symtab[i].pri_name;
1969a5cace0c2a3e212931badbf6398a0cd98393121asewardj         tl_assert(pri_name);
1970a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
19714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
19724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
19734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
19744ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
19754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
19761636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar** sec_names = si->symtab[i].sec_names;
1977a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
1978a5cace0c2a3e212931badbf6398a0cd98393121asewardj            tl_assert(sec_names[0]);
1979a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
1980a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
1981a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   && (require_pToc ? si->symtab[i].tocptr : True)) {
1982a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pEnt = si->symtab[i].addr;
1983a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pToc = si->symtab[i].tocptr;
1984a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
1985a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
1986a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
1987a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
1988a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
19894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
19904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
19914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
19924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
19934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
19944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1995e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1996e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1997e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1998e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1999e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
2000eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20011636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStr ( Int n, Int n_buf, HChar* buf, const HChar* str )
2002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2003e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
2004e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2005eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
2006eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
2007e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2008eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
2009eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
2010eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2011e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
2012e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
2013e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
2014e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
20151636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStrEsc ( Int n, Int n_buf, Int count, HChar* buf, HChar* str )
2016eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20171636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar alt[2];
2018e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
2019e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
2020e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2021eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
2022e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
2023e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
2024e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
2025eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
2026e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
2027e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
2028e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
2029e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
2030e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2031e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
2032e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
2033e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
2034e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
2035e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2036e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
2037e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
2038e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
2039e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
2040e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2041e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
2042e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
2043e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
2044e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
2045e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
2046e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
2047e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2048eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2049eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2050e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
2051e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
2052e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2053eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
2054eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2055eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2056a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeHChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc)
2057eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2058eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
2059e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
2060e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
2061e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
2062eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
2063eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2064eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
20651636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar ibuf[50];
2066eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
206714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2068a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (!iipc || iipc->eip == eip);
2069a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
20701636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_fn[BUF_LEN];
20711636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_obj[BUF_LEN];
20721636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_srcloc[BUF_LEN];
20731636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_dirname[BUF_LEN];
207414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
207514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2076eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
2077a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_fnname;
2078a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_objname;
2079a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_srcloc;
2080a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2081a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
2082a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
2083a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = VG_(clo_sym_offsets)
2084a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                    ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
2085a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                    : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
2086a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2087a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
2088a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
2089a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2090a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
2091a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
2092a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(snprintf)(buf_fn, BUF_LEN, "%s", next_inl->inlinedfn);
2093a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = True;
2094a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2095a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // INLINED????
2096a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Can we compute an offset for an inlined fn call ?
2097a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Offset from what ? The beginning of the inl info ?
2098a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? But that is not necessarily the beginning of the fn
2099a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? as e.g. an inlined fn call can be in several ranges.
2100a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Currently never showing an offset.
2101a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2102a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2103a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
2104a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2105a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_top(iipc)) {
2106a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The source for the highest level is in the loctab entry.
2107a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc  = VG_(get_filename_linenum)(
2108a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        eip,
2109a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        buf_srcloc,  BUF_LEN,
2110a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        buf_dirname, BUF_LEN, &know_dirinfo,
2111a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        &lineno
2112a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     );
2113a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2114a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *cur_inl = iipc && iipc->cur_inltab >= 0
2115a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->cur_inltab]
2116a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2117a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (cur_inl);
2118a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The filename and lineno for the inlined fn caller is in cur_inl.
2119b152de19f5e0aac996676c262e7a772e16c692f5philippe      VG_(snprintf) (buf_srcloc, BUF_LEN, "%s", cur_inl->filename);
2120a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lineno = cur_inl->lineno;
2121a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2122a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_dirinfo = False; //INLINED TBD
2123a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2124a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc = True;
2125a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2126a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2127a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
212814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
212914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
213014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
213114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
213214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
2134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
21366bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline  = human_readable ? "\n      " : "";
21376bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline2 = human_readable ? "\n    "   : "";
2138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2139e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
2140e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
2141e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
2142e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
2143e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
2144e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
2145eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
2146a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
2147eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
2148eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
2149eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
2150eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2151eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
2152e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
2153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
2154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
2156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
2158e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
2159eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
2160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
2163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
2164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
2165e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
2166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
2167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
2168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
2170e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
2171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
2172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
2174eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
2177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
2179eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
2180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
2182eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2183eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
21845e40abad4504416c59f0b29c1cfc8087201213a9njn      //
21855e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
21865e40abad4504416c59f0b29c1cfc8087201213a9njn      //
21875e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
21885e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
21895e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
21905e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
21915e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
21925e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
21935e40abad4504416c59f0b29c1cfc8087201213a9njn      //
2194a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
2195eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
21965e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
2197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
2198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
2199eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
2200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
220314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
22041636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* dirname = NULL;
220514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
220614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
220714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
220814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
220914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
221014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
221114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
22121636d33c13958b9c0e7d3059cdd5005746418eb2florian               const HChar* prefix = VG_(clo_fullpath_after)[i];
22131636d33c13958b9c0e7d3059cdd5005746418eb2florian               HChar* str    = VG_(strstr)(dirname, prefix);
221414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
221514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
221614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
221714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
221814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
221914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
222014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
222114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
222214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
222314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
222414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
222514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
222614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
222714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
22285dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
2229eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
2230eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
2231eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
22345e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
22355e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
22365e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
22375e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
22385e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
22395e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
22405e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
22415e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
2242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2243eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
2246eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2247eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
2248eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
2249eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
2250eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2251eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
225272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
2257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
225972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
226072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
226172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
226272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
226372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
22643026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
22653026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
22663026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
226772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
226872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
226972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
227072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
227172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
227272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
2273f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
2274f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
227572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
227672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
227772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
227840628facff2285b0fce592381c6e26fdcd2a1252tom   UWord w, wL, wR;
227919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
22803026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
22813026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
22823026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
228372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
228440628facff2285b0fce592381c6e26fdcd2a1252tom      case Cex_Unop:
228540628facff2285b0fce592381c6e26fdcd2a1252tom         w = evalCfiExpr( exprs, e->Cex.Unop.ix, eec, ok );
228640628facff2285b0fce592381c6e26fdcd2a1252tom         if (!(*ok)) return 0;
228740628facff2285b0fce592381c6e26fdcd2a1252tom         switch (e->Cex.Unop.op) {
228840628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Abs: return (Word) w < 0 ? - w : w;
228940628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Neg: return - (Word) w;
229040628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Not: return ~ w;
229140628facff2285b0fce592381c6e26fdcd2a1252tom            default: goto unhandled;
229240628facff2285b0fce592381c6e26fdcd2a1252tom         }
229340628facff2285b0fce592381c6e26fdcd2a1252tom         /*NOTREACHED*/
229472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
229572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
229672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
229772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
229872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
229972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
2300f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Add: return wL + wR;
2301f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Sub: return wL - wR;
2302f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_And: return wL & wR;
2303f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Mul: return wL * wR;
2304f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shl: return wL << wR;
2305f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shr: return wL >> wR;
2306f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Eq: return wL == wR ? 1 : 0;
2307f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2308f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2309f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2310f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
2311f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ne: return wL != wR ? 1 : 0;
231272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
231372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
231472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
231572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
231672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
23173026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
23183026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
23193026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
23203026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
23213026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
23223026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
23233026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2324fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2325fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2326b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2327b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
2328b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
2329b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
2330b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
23314df0bfc0614379192c780c944415dc420d9cfe8epetarj#           elif defined(VGA_mips32) || defined(VGA_mips64)
23325db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_IP: return eec->uregs->pc;
23335db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_SP: return eec->uregs->sp;
23345db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_BP: return eec->uregs->fp;
23355db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_MIPS_RA: return eec->uregs->ra;
23363026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
2337f0c1250e324f6684757c6a15545366447ef1d64fsewardj#           elif defined(VGP_arm64_linux)
2338821283b2110420321fd3f60afcc799b287788c68sewardj            case Creg_ARM64_X30: return eec->uregs->x30;
23393026f71684a930286186aa10fef266c304672e8fsewardj#           else
23403026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
23413026f71684a930286186aa10fef266c304672e8fsewardj#           endif
234272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
234372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
234472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
234572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
234672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
234719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
234819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
234919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
235019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
2351720e6b71b171885281afab634ce4d667c1f262bcsewardj             || a > eec->max_accessible - sizeof(UWord) + 1) {
235219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
235319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
235419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
235519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
235686781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
235772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
235872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
235972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
236072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
236172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
236272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
236372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
236472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
236572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
236672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
236772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
236872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
236972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
237072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
23715c3dba227192de63d86f65ec7d9597c132818c37philippe/* Search all the DebugInfos in the entire system, to find the DiCfSI_m
2372f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2374f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
23755c3dba227192de63d86f65ec7d9597c132818c37philippe   *cfsi_mP to the cfsi_m pointer in that DebugInfo's cfsi_m_pool.
237672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
23775c3dba227192de63d86f65ec7d9597c132818c37philippe   If not found, set *diP to (DebugInfo*)1 and *cfsi_mP to zero.
2378f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2379f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2380f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
23815c3dba227192de63d86f65ec7d9597c132818c37philippe                          /*OUT*/DiCfSI_m** cfsi_mP,
2382f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2383f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2384f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2385f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2386f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2387f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2388f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2391f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2393f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2394f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2395eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2396eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2399f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2400eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2401f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2404f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2405f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2406f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2407f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2408f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2409f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2410f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2412eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2413eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2414f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2415f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2416f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2417f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
24185c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = 0;
2419f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2420f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2421f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24225c3dba227192de63d86f65ec7d9597c132818c37philippe      /* found a di corresponding to ip. */
2423f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2424f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2425f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
24265c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = ML_(get_cfsi_m) (di, i);
24275c3dba227192de63d86f65ec7d9597c132818c37philippe      if (*cfsi_mP == NULL) {
24285c3dba227192de63d86f65ec7d9597c132818c37philippe         // This is a cfsi hole. Report no cfi information found.
24295c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = (DebugInfo*)1;
24305c3dba227192de63d86f65ec7d9597c132818c37philippe         // But we will still perform the hack below.
24315c3dba227192de63d86f65ec7d9597c132818c37philippe      } else {
24325c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = di;
24335c3dba227192de63d86f65ec7d9597c132818c37philippe      }
2434f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2435f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2436f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2437f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2438f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2439f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2440f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2441f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2442f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2443f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2444f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2445f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2446f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2447f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2448f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2449f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2450f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2451f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2452f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2453f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2454f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2455f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2456f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2457f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2458f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2459f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2460f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24615c3dba227192de63d86f65ec7d9597c132818c37philippe   Each cache entry binds an ip value to a (di, cfsi_m*) pair.  Possible
2462f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2463f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24645c3dba227192de63d86f65ec7d9597c132818c37philippe   di is non-null, cfsi_m* >= 0  ==>  cache slot in use, "cfsi_m*"
24655c3dba227192de63d86f65ec7d9597c132818c37philippe   di is (DebugInfo*)1           ==>  cache slot in use, no associated di
24665c3dba227192de63d86f65ec7d9597c132818c37philippe   di is NULL                    ==>  cache slot not in use
2467f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2468f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2469f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2470f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24715c3dba227192de63d86f65ec7d9597c132818c37philippe   We can map an ip value directly to a (di, cfsi_m*) pair as
24725c3dba227192de63d86f65ec7d9597c132818c37philippe   once a DebugInfo is read, adding new DiCfSI_m* is not possible
24735c3dba227192de63d86f65ec7d9597c132818c37philippe   anymore, as the cfsi_m_pool is frozen once the reading is terminated.
24745c3dba227192de63d86f65ec7d9597c132818c37philippe   Also, the cache is invalidated when new debuginfo is read due to
24755c3dba227192de63d86f65ec7d9597c132818c37philippe   an mmap or some debuginfo is discarded due to an munmap. */
2476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24775c3dba227192de63d86f65ec7d9597c132818c37philippe// Prime number, giving about 6Kbytes cache on 32 bits,
24785c3dba227192de63d86f65ec7d9597c132818c37philippe//                           12Kbytes cache on 64 bits.
24795c3dba227192de63d86f65ec7d9597c132818c37philippe#define N_CFSI_M_CACHE 509
2480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2481f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
24825c3dba227192de63d86f65ec7d9597c132818c37philippe   struct { Addr ip; DebugInfo* di; DiCfSI_m* cfsi_m; }
24835c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt;
2484f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24855c3dba227192de63d86f65ec7d9597c132818c37philippestatic CFSI_m_CacheEnt cfsi_m_cache[N_CFSI_M_CACHE];
2486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24875c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void ) {
24885c3dba227192de63d86f65ec7d9597c132818c37philippe   VG_(memset)(&cfsi_m_cache, 0, sizeof(cfsi_m_cache));
248920ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   CF_info_generation++;
2490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
249220ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippeUInt VG_(CF_info_generation) (void)
249320ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe{
249420ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   return CF_info_generation;
249520ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe}
2496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24975c3dba227192de63d86f65ec7d9597c132818c37philippestatic inline CFSI_m_CacheEnt* cfsi_m_cache__find ( Addr ip )
2498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
24995c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord         hash = ip % N_CFSI_M_CACHE;
25005c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce = &cfsi_m_cache[hash];
25013c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25073c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
25083c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
25093c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
25103c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
25113c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
25123c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
25135c3dba227192de63d86f65ec7d9597c132818c37philippe      find_DiCfSI( &ce->di, &ce->cfsi_m, ip );
25143c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25163c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
25173c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
25183c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
25193c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
25203c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
25213c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2522eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
25233c9cf3442185b5891e15450d6e3058aeff6796fetom}
2524eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2526f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
25273026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
25283c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
25295c3dba227192de63d86f65ec7d9597c132818c37philippe                          DebugInfo* di, DiCfSI_m* cfsi_m )
25303c9cf3442185b5891e15450d6e3058aeff6796fetom{
25313c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
25323c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
25333c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25353c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
253672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
25375c3dba227192de63d86f65ec7d9597c132818c37philippe   switch (cfsi_m->cfa_how) {
25383026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
25393026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
25405c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xsp;
25413026f71684a930286186aa10fef266c304672e8fsewardj         break;
25423026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
25435c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xbp;
254472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
25453026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
25463026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
25475c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r13;
254872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
25493026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
25505c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r12;
25513026f71684a930286186aa10fef266c304672e8fsewardj         break;
25523026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
25535c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r11;
25543026f71684a930286186aa10fef266c304672e8fsewardj         break;
2555fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
25565c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r7;
2557fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2558b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2559b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
25605c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2561b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2562b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2563b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
25645c3dba227192de63d86f65ec7d9597c132818c37philippe         Addr a = uregs->sp + cfsi_m->cfa_off;
2565b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2566b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
256786781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2568b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2569b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2570b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2571b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2572b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2573b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
25745c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
2575b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
25764df0bfc0614379192c780c944415dc420d9cfe8epetarj#     elif defined(VGA_mips32) || defined(VGA_mips64)
25775db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_SPREL:
25785c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
25795db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
25805db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIR_SAME:
25815db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = uregs->fp;
25825db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
25835db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_BPREL:
25845c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
25855db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
25863026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
2587f0c1250e324f6684757c6a15545366447ef1d64fsewardj#     elif defined(VGP_arm64_linux)
2588821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_SPREL:
25895c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2590821283b2110420321fd3f60afcc799b287788c68sewardj         break;
2591821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_X29REL:
25925c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->x29;
2593821283b2110420321fd3f60afcc799b287788c68sewardj         break;
25943026f71684a930286186aa10fef266c304672e8fsewardj#     else
25953026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
25963026f71684a930286186aa10fef266c304672e8fsewardj#     endif
25973026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
25987888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
25997888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
26005c3dba227192de63d86f65ec7d9597c132818c37philippe            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi_m->cfa_off);
26017888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
26027888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
26033026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
26047888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
26057888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
26067888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
26075c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = evalCfiExpr(di->cfsi_exprs, cfsi_m->cfa_off, &eec, &ok );
26083c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
260972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
261072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
261172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
261272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
26133c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
26143c9cf3442185b5891e15450d6e3058aeff6796fetom}
26153c9cf3442185b5891e15450d6e3058aeff6796fetom
26163c9cf3442185b5891e15450d6e3058aeff6796fetom
26173c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
26183026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
26193026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
26203c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
26213c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
26223c9cf3442185b5891e15450d6e3058aeff6796fetom{
26235c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce;
26243c9cf3442185b5891e15450d6e3058aeff6796fetom
26255c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ip);
26263c9cf3442185b5891e15450d6e3058aeff6796fetom
26273c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
26283c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
26293c9cf3442185b5891e15450d6e3058aeff6796fetom
26303026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
26313026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
26323026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
26333026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
26343026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
26353026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
26363026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
26373026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
263805c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
26393026f71684a930286186aa10fef266c304672e8fsewardj   }
2640b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2641b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2642b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2643b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2644b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2645b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
264605c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2647b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2648f03d0b76228354fb63eb970a4e6c9fa1337d60a9dejanj#elif defined(VGA_mips32) || defined(VGA_mips64)
2649fe0b43315c344cfd07981a0826bc34614a220169dejanj   { D3UnwindRegs uregs;
2650fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.pc = ip;
2651fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.sp = sp;
2652fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.fp = fp;
2653fe0b43315c344cfd07981a0826bc34614a220169dejanj     return compute_cfa(&uregs,
265405c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2655fe0b43315c344cfd07981a0826bc34614a220169dejanj   }
2656b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
26573026f71684a930286186aa10fef266c304672e8fsewardj#  else
26583026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
26593026f71684a930286186aa10fef266c304672e8fsewardj#  endif
26603c9cf3442185b5891e15450d6e3058aeff6796fetom}
26613c9cf3442185b5891e15450d6e3058aeff6796fetom
26623c9cf3442185b5891e15450d6e3058aeff6796fetom
26633026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
26643026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
26653026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
26663026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
26673026f71684a930286186aa10fef266c304672e8fsewardj
26683026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
26693026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
26703026f71684a930286186aa10fef266c304672e8fsewardj
2671fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
2672821283b2110420321fd3f60afcc799b287788c68sewardj
2673821283b2110420321fd3f60afcc799b287788c68sewardj   For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
26743026f71684a930286186aa10fef266c304672e8fsewardj*/
26753026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
26763c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
26773c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
26783c9cf3442185b5891e15450d6e3058aeff6796fetom{
26793c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
26805c3dba227192de63d86f65ec7d9597c132818c37philippe   DiCfSI_m*          cfsi_m = NULL;
26813026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
26825c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt*   ce;
2683d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
26843026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
26853c9cf3442185b5891e15450d6e3058aeff6796fetom
26863026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
26873026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
26883026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
26893026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2690b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2691b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
26924df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
26935db15403e889d4db339b342bc2a824ef0bfaa654sewardj   ipHere = uregsHere->pc;
26943026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2695f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
2696821283b2110420321fd3f60afcc799b287788c68sewardj   ipHere = uregsHere->pc;
26973026f71684a930286186aa10fef266c304672e8fsewardj#  else
26983026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
26993026f71684a930286186aa10fef266c304672e8fsewardj#  endif
27005c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ipHere);
27013c9cf3442185b5891e15450d6e3058aeff6796fetom
27023c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
27033c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
27043c9cf3442185b5891e15450d6e3058aeff6796fetom
27053c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
27065c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m = ce->cfsi_m;
27073c9cf3442185b5891e15450d6e3058aeff6796fetom
27083c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
27095c3dba227192de63d86f65ec7d9597c132818c37philippe      VG_(printf)("found cfsi_m (but printing fake base/len): ");
27105c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(ppDiCfSI)(di->cfsi_exprs, 0, 0, cfsi_m);
27113c9cf3442185b5891e15450d6e3058aeff6796fetom   }
27123c9cf3442185b5891e15450d6e3058aeff6796fetom
2713f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
27143c9cf3442185b5891e15450d6e3058aeff6796fetom
27153c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
27163026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
27175c3dba227192de63d86f65ec7d9597c132818c37philippe                     min_accessible, max_accessible, di, cfsi_m);
27183c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
27193c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
272072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
272172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
272272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2728eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2732eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2733eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
27349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2735eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
273686781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2739eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2741eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
274272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
274372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2744f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
27453026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
274672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
274772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2748d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2749f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
275072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
275172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
275272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
275372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
27573026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
27585c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi_m->ra_how, cfsi_m->ra_off);
27595c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi_m->sp_how, cfsi_m->sp_off);
27605c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi_m->bp_how, cfsi_m->bp_off);
27613026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
27625c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi_m->ra_how,  cfsi_m->ra_off);
27635c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi_m->r14_how, cfsi_m->r14_off);
27645c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi_m->r13_how, cfsi_m->r13_off);
27655c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi_m->r12_how, cfsi_m->r12_off);
27665c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi_m->r11_how, cfsi_m->r11_off);
27675c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi_m->r7_how,  cfsi_m->r7_off);
2768b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
27695c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi_m->ra_how, cfsi_m->ra_off);
27705c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
27715c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
27724df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
27735c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi_m->ra_how, cfsi_m->ra_off);
27745c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
27755c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
27763026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2777f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
27785c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc,  uregsHere->pc,  cfsi_m->ra_how,  cfsi_m->ra_off);
27795c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp,  uregsHere->sp,  cfsi_m->sp_how,  cfsi_m->sp_off);
27805c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off);
27815c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off);
27823026f71684a930286186aa10fef266c304672e8fsewardj#  else
27833026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
27843026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
27883026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2795c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2796c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2797c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2798c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2799c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2800c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2801c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2802c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2803c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2804c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2805c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2806c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2807c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2808c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2809c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2810c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2811c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2812c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2813c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2814c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2815c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2816c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2817c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2818c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2819c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2820c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2821c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2822c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2823c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2824c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2825c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2826c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2827c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2828c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2829c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2830c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2831c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2832c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2833c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2834c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2835c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2836c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2837c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2838c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2839c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2840c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2841c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2842c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2843c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2844c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2845c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2846c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2847c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2848c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2849c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2850c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2851c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2852c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2853c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2854c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2855c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2856c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2857c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2858c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2859c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2860c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2861c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2862c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2863c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2864c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2865c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2866c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2867c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2868c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2869c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2870c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2871c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2872c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2873c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2874c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2875c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2876c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2877c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2878c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2879c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2880c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2881c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2882c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2883c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2884c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2885c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2886c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2887c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2888c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2889c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2890c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2891c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2892c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2893c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2894c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2895c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2896c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2897c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2898c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2899c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2900c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2901c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2902c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2903c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2904c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2905c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2906c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
290786781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
290886781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
290986781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
291086781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
2911c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2912c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2913c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2914c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2915c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2916c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2922588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2923b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   VG_(xaprintf)(dst, fmt, args) without having to resort to
2924588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2925588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2926738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2927588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2928b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   //   VG_(xaprintf)(dstxa, format, ##args)
2929738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2930b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart#define  p2XA  VG_(xaprintf)
2931738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2932588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2933588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2934738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2935738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2936738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2937738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2938738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2939738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2940738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2946c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
29479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2951588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
295350fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
29579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
296250fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
296350fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
296450fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
296550fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
296650fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
296750fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
296850fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
296950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
297050fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
297150fde23467d92281b32dd537d0d9a590263628c3sewardj
297250fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2975a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
29779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2988588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2995eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29963c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
3001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
3002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3007738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
3008738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
3009738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
3010738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
3011738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
3012738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
3013738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
3014738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
3016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
3017c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
3018c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
3019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
3020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
3021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
3022eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3023738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
3024738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
30251636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* vo_plural = var_offset == 1 ? "" : "s";
30261636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* ro_plural = residual_offset == 1 ? "" : "s";
30271636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* basetag   = "auxwhat"; /* a constant */
30281636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar tagL[32], tagR[32], xagL[32], xagR[32];
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3030d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
3031d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
3032d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3033d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
3034d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
3035d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3036d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
3037d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
3038d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3039d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
3040738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
3043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
3046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3047738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
3048738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
3049738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
3050738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
3051738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
3052738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
3053738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
3054738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3055738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
3056738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
3057738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
3058738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
3059738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
3060738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
3067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3069738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3070738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3071738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3072b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\",",
3073738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3074738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3075738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3076738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3077738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3078738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3079738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3080738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3081738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
3082738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3083738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3084738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3085738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
3089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
3091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
3092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3093738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3094738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3095738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3096b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\"",
3097738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3098738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3099738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3100738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3101738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3102b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
3103738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
3104738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3105738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3106738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3107b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3108738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3109738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3110738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3111738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3112738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
3113738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3114738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3115738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
3116738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
3117738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
3123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3125738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3126738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3127738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3128b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS",
3129738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3130738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3131738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3132738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3133738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3134738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3135738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3136738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3137738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3138738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
3139738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3140738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3141738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3142738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3143738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
3147738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3148738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
3149738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3150738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3151738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3152b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3153738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3154738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3155738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3156738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3157738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3158738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3159b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
3160738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
3161738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3162738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3163738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3164b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3165738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3166738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3167738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3168738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3169738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3170738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3171738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3172738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3173738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
3174738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
3175738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
3179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
3180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3183738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3184738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3185738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3186b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
3187738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3188738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3189738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3190738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3191738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
3192738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3193738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
3200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3201738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3203738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3204b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
3205738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3206738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3207738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3208738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3209738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3210b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d",
3211738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3212738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3213738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3214738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3215b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3216738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3217738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3218738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3219738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3220738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
3221738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3222738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3223738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
3224738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3225738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
3229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
3232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3233738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3234738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3235738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3236b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3237738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3238738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3239738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3240738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3241738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3242738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3243738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3244738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3245738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3246738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3247738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3248738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
3249738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3250738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3251738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
3255738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3256738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
3257738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3258738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3259738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3260b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3261738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3262738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3263738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3264738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3265738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3266738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3267b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "a global variable declared at %pS:%d",
3268738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3269738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3270738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3271738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3272b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3273738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3274738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3275738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3276738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3277738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3278738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3279738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3280738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3281738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
3282738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3283738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
3287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3288738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
3289738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
3290738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
3291738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3292738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
3293738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
3294738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
3295738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
3296738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
3297738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
3298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3300738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
3302738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
3303738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
3304738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
3305738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
3306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
3307738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
3308738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
3309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
3310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
3311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
3312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
3313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
3315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
3317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
3318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
3320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
3321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
3322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
3323a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
3324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
3325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
3326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
3327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
3331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
3332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
3336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
3337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
3338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
3339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
3342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
3343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
3344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
3345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
3346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
3347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
3348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
3349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
3350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
3351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
3352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
3354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
3356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3405c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3407a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
34099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3411588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3412c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
34159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3416738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3426eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3427eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3428738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
342925963376a3669e7f77395d6f884bdf1f6a928966philippe   debug info we have.  This considers all global variables, and 8
3430738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3431738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3432738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3433738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3434738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3435738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3436738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3437738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3438738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3439738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3440738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3441738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
3442738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
3443738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
3444738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3445738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3446eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3457738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
3458738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
3459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3460a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
34679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3486b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3490b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3491b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3492b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3493b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3494b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3495b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3496b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3500b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3508c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3515b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
35179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3519588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3520c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
35229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
35239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3524738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3526d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3527d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3529738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3530738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3534b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3550b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3553738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3554738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3563b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3566738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3568b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3570738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3571738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3588b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3589b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3590b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3591b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3592b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3593738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3594b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3595b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3596b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3597738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3598738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3600b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3604738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3605738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3608eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3609eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
36119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
36129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
36139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
36149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
36159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
36169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
36189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
36199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
36209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
36219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
36229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
36249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
36259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3626588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
36279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
36289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
36299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
36309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
363150fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
36329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
36339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
36349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
36369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
36379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
36389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
364050fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
364150fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
364250fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
364350fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
364450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
364550fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
364650fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
364750fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
364850fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
36499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
36519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
36529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
36539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
36549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
36559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
36569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
36579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
36589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
36599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
36619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
36629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
36649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
36659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
36669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
36679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
36689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
36699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
36709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3671588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
36729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
36749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
36759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3676588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
36779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
36799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
36809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3681588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
36829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
36849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
36859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3686588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
36879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
36899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
36909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
36919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36923c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
36939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
36949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
36959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
36969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
36979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
36989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
36999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
37019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
37029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
37039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
37059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
37069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
37079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3708588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37093c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
37109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
37119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
371250fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
37139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
371450fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
37159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
37169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
37179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
37189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
37199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
37209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
37219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
37229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
37249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
37259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
37269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3727588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37283c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
37299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
37309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
373150fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
37329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
373350fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
37349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
37359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
37369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
37379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
37389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
37399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
37409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
37419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
37439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
37449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
37469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
37479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
37509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
37519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
37529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
37539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
37559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
37569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
37579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
37589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
37599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
37609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
37619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
37639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
37649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
37659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
37679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
37689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
37699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
37709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
37719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
37729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
37739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
37749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
37759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
37769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
37779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
37789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
37799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
37809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
37819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
37839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
37849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
37859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
37869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
37879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
37899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
37909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
37919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
37929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
37939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
37949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
37959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
37969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
37979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
37989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
37999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
38019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
38039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
38049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
38059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
38079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
38089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
38099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
38109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
38119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
38139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
38149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
38159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
38169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
38179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
38189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
38199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
38209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
38219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
38229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
38239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
38249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
38259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
38269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
38279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
38289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
38299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
38309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
38319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
38329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
38339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
38349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
38359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
38369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
38379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
38389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
38399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
38409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
38419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
38429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
38439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
38449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
38459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
38469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
38479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
38489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
38499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
38509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
38519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
38529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3853588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
38549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
38559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
38589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
38599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
38629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
38639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
38649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
38659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
38669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
38679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
38699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
38709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
38719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
38729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
38739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
38759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
38769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
38779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
38799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
38809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
38819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
38829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
38839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
38849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
38879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
38889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
38899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
38909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
38929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
38939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
38949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
38959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
38979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
38989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
38999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
39019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
39029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
39039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
39049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
39059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
39079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
39089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
39099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
39109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
39119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
39129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
39139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
39159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
39169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
39179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
39189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
39199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
39219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
392250fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
39239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
39249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
39259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
39269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
39279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
39289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
39309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
39319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
39329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
39339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
39349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
39359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3936588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
39379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
39393c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
39409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
39419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
39429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
39439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
39459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
39469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
39479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
394950fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
39509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
395150fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
395250fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
395350fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
395450fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
395550fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
395650fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
395750fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
395850fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
39599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
39619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
39629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
39639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
39649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
39659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
39669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
39679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
39689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
39709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
39719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
39739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
39749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
39759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
39769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
39779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
39789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
39799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
398050fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
39819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
39829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
39839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
39849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
39859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
39869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
39889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
39909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
39929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
39949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
39969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
39979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
4001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4003e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
4004eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
4006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
4007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
4008eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4009eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4010e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
4011eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
4013eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4014eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4015e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
4016eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
4018eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4019eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
40203898022a7d74a227d6a35102faaedd420ed3a1c1bartAddr VG_(DebugInfo_get_bss_avma)(const DebugInfo* di)
40213898022a7d74a227d6a35102faaedd420ed3a1c1bart{
40223898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_avma : 0;
40233898022a7d74a227d6a35102faaedd420ed3a1c1bart}
40243898022a7d74a227d6a35102faaedd420ed3a1c1bart
40253898022a7d74a227d6a35102faaedd420ed3a1c1bartSizeT VG_(DebugInfo_get_bss_size)(const DebugInfo* di)
40263898022a7d74a227d6a35102faaedd420ed3a1c1bart{
40273898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_size : 0;
40283898022a7d74a227d6a35102faaedd420ed3a1c1bart}
40293898022a7d74a227d6a35102faaedd420ed3a1c1bart
4030e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
4031092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4032092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
4033092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4034092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4035e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
4036092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4037092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
4038092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4039092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4040e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
4041092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4042092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
4043092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4044092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4045e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
4046092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4047092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
4048092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4049092b6268cc4a38ae9ee41d1e3355937536ddc579bart
405068347837b3d82e48f85daff33ec7ba528891e4e7bartAddr VG_(DebugInfo_get_got_avma)(const DebugInfo* di)
405168347837b3d82e48f85daff33ec7ba528891e4e7bart{
405268347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_avma : 0;
405368347837b3d82e48f85daff33ec7ba528891e4e7bart}
405468347837b3d82e48f85daff33ec7ba528891e4e7bart
405568347837b3d82e48f85daff33ec7ba528891e4e7bartSizeT VG_(DebugInfo_get_got_size)(const DebugInfo* di)
405668347837b3d82e48f85daff33ec7ba528891e4e7bart{
405768347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_size : 0;
405868347837b3d82e48f85daff33ec7ba528891e4e7bart}
405968347837b3d82e48f85daff33ec7ba528891e4e7bart
40601636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
4061eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
4063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4064eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
40651636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
4066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4067a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
4068eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4069eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4070e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
4071bbec7728efefaa650970dd1f0282b77040287133sewardj{
4072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
4073bbec7728efefaa650970dd1f0282b77040287133sewardj}
4074bbec7728efefaa650970dd1f0282b77040287133sewardj
4075e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
4076eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
4078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4079eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4080e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
4081e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
4082a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    avma,
4083a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    tocptr,
4084a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UInt*    size,
408519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar**  pri_name,
408619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar*** sec_names,
4087a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isText,
4088a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isIFunc )
4089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4090eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
4091a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (avma)      *avma      = si->symtab[idx].addr;
4092a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (tocptr)    *tocptr    = si->symtab[idx].tocptr;
4093a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
4094a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
409519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   if (sec_names) *sec_names = (HChar **)si->symtab[idx].sec_names; // FIXME
4096a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
4097a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
4098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
4103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
4106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
4107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
4108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
4110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
4111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
4112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
4113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
4114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
4115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
4116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
41175706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
4118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
4119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
4123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
4124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
4125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
4126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
41271636d33c13958b9c0e7d3059cdd5005746418eb2florianVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/HChar* name, SizeT n_name,
4128e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
4129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
4131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
4132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
4134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
4136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
4137e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
4138e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
4139a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
4140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
4141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
4142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
4143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
4144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
4146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
4147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
4148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
4149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
4152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
4153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
4154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
4158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
4159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
4160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
4164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
4165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
4166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
4167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
41695706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
41705706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
41715706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
41725706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
41735706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
41745706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
4175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
4176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
4177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
4178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
4179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
4182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
4183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
4184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
4185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4187092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
4188092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
4189092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
4190092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
4191092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
4192092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
4193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
4194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
4195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
4196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
4197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
4200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
4203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
4204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
4206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
4208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4209a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
4210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
4211a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         Int fnlen = VG_(strlen)(di->fsm.filename);
4212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
4213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
4214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
4215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
4216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
4217d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
4218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
4219a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            name[j] = di->fsm.filename[i];
4220a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            if (di->fsm.filename[i] == 0) break;
4221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
4222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
4223d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
4224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
4225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
4226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
4229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
4232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4234eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4235eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
4237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4238