1770a8d23e40b980b5745e59ecb8e4037d81af357florian/* -*- mode: C; c-basic-offset: 3; -*- */
2582d58245637ab05272d89fb94b12fd0f18fa0f8carll
3eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Top level management of symbols and debugging information.   ---*/
5eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                  debuginfo.c ---*/
6eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
7eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*
9eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This file is part of Valgrind, a dynamic binary instrumentation
10eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   framework.
11eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12b3a1e4bffbdbbf38304f216af405009868f43628sewardj   Copyright (C) 2000-2015 Julian Seward
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
33eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
344cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
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"
598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_linux) || defined(VGO_solaris)
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
61b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
62c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
63f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
67eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
68c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
696f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj/* Set this to 1 to enable debug printing for the
706f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   should-we-load-debuginfo-now? finite state machine. */
716f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj#define DEBUG_FSM 0
726f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
736f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
99f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
100f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
101c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
102c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
103c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
108f7bbd7982397fb73477bdc21bf236cf9100cee44philippestatic UInt debuginfo_generation = 0;
1095c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void );
110f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
111f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
113eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
114eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
121ad4e979f408239dabbaae955d8ffcb84a51a5c85florian/* Find 'di' in the debugInfo_list and move it one step closer to the
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
165eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1771636d33c13958b9c0e7d3059cdd5005746418eb2florianDebugInfo* alloc_DebugInfo( const HChar* filename )
178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
182f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
183f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
185a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
186a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1876b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.maps     = VG_(newXA)(
1886b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_zalloc), "di.debuginfo.aDI.3",
189518850bf0da07ed3e2244e307268ae0fd80e93a8florian                         ML_(dinfo_free), sizeof(DebugInfoMapping));
190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
191452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
192452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
193f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1940f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
195f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
201f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
202f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
206eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
21059a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
2119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
21259a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
2156b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.maps)     VG_(deleteXA)(di->fsm.maps);
216a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
217c5af2ae7cec426721577d4a249d4a7b7c0eeb65emjw   if (di->fsm.dbgname)  ML_(dinfo_free)(di->fsm.dbgname);
218f1e1aa691d7a2f0f2f933daf060bec5ae6938705philippe   if (di->soname)       ML_(dinfo_free)(di->soname);
219a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
22059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (di->loctab_fndn_ix) ML_(dinfo_free)(di->loctab_fndn_ix);
221a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di->inltab)       ML_(dinfo_free)(di->inltab);
2225c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_base)    ML_(dinfo_free)(di->cfsi_base);
2235c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_ix)    ML_(dinfo_free)(di->cfsi_m_ix);
2245c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)      ML_(dinfo_free)(di->cfsi_rd);
2255c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_pool)  VG_(deleteDedupPA)(di->cfsi_m_pool);
226a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
227a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
229a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
230a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
231a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
232a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
233a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
234a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
235a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
236a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
237a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
238a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
239a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
240a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
241a5cace0c2a3e212931badbf6398a0cd98393121asewardj
2422352e9843d8a616b9d829aef929d218aea9b4ae0philippe   if (di->strpool)
2432352e9843d8a616b9d829aef929d218aea9b4ae0philippe      VG_(deleteDedupPA) (di->strpool);
24459e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (di->fndnpool)
24559e1f3c79e870a978d24add86db6d8c5450c8b63philippe      VG_(deleteDedupPA) (di->fndnpool);
246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
25259a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
25659a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
259eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
26059a2d18d0ddfa241850017252b0804d469187d79sewardj
26159a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
26259a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
26359a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
26459a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
26559a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
26659a2d18d0ddfa241850017252b0804d469187d79sewardj      }
26759a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
26859a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
2917293d2530f8c60c1060f9f003e214cc341d35266philippe                  .strpool */
292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3126bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* reason = "munmap";
3134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
32033e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
32133e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
323738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
326a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
3271636d33c13958b9c0e7d3059cdd5005746418eb2florian                                            : "???",
3284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
33133e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
33233e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
347f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
349f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
351f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
375f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
378f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
379f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
380eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
401eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4036b5625bb609b154766d2e138b61e15655f60b710sewardj/* Do the basic mappings of the two DebugInfos overlap in any way? */
404518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool do_DebugInfos_overlap ( const DebugInfo* di1, const DebugInfo* di2 )
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4066b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
4096b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) {
410518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i);
4116b5625bb609b154766d2e138b61e15655f60b710sewardj      for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
412518850bf0da07ed3e2244e307268ae0fd80e93a8florian         const DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
4136b5625bb609b154766d2e138b61e15655f60b710sewardj         if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size))
4146b5625bb609b154766d2e138b61e15655f60b710sewardj            return True;
4156b5625bb609b154766d2e138b61e15655f60b710sewardj      }
4166b5625bb609b154766d2e138b61e15655f60b710sewardj   }
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
4476b5625bb609b154766d2e138b61e15655f60b710sewardj   Clearly diRef must have its mapping information set to something sane. */
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4660f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4670f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4680f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
469518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic DebugInfo* find_or_create_DebugInfo_for ( const HChar* filename )
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
474a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
475a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
476b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4790f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
488f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
492518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic void check_CFSI_related_invariants ( const DebugInfo* di )
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
4956b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool has_nonempty_rx = False;
4966b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool cfsi_fits = False;
4976b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
502a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
503a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
5046b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
505518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
5066b5625bb609b154766d2e138b61e15655f60b710sewardj      /* We are interested in r-x mappings only */
5076b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map->rx)
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5096b5625bb609b154766d2e138b61e15655f60b710sewardj
5106b5625bb609b154766d2e138b61e15655f60b710sewardj      /* degenerate case: r-x section is empty */
5116b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->size == 0)
512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5136b5625bb609b154766d2e138b61e15655f60b710sewardj      has_nonempty_rx = True;
5146b5625bb609b154766d2e138b61e15655f60b710sewardj
5156b5625bb609b154766d2e138b61e15655f60b710sewardj      /* normal case: r-x section is nonempty */
5166b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (0) */
5176b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(map->size > 0);
5186b5625bb609b154766d2e138b61e15655f60b710sewardj
5196b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (1) */
5206b5625bb609b154766d2e138b61e15655f60b710sewardj      for (di2 = debugInfo_list; di2; di2 = di2->next) {
5216b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di2 == di)
5226b5625bb609b154766d2e138b61e15655f60b710sewardj            continue;
5236b5625bb609b154766d2e138b61e15655f60b710sewardj         for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
524518850bf0da07ed3e2244e307268ae0fd80e93a8florian            const DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
5256b5625bb609b154766d2e138b61e15655f60b710sewardj            if (!map2->rx || map2->size == 0)
5266b5625bb609b154766d2e138b61e15655f60b710sewardj               continue;
5276b5625bb609b154766d2e138b61e15655f60b710sewardj            vg_assert(!ranges_overlap(map->avma,  map->size,
5286b5625bb609b154766d2e138b61e15655f60b710sewardj                                      map2->avma, map2->size));
5296b5625bb609b154766d2e138b61e15655f60b710sewardj         }
5306b5625bb609b154766d2e138b61e15655f60b710sewardj      }
5316b5625bb609b154766d2e138b61e15655f60b710sewardj      di2 = NULL;
5326b5625bb609b154766d2e138b61e15655f60b710sewardj
5336b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (2) */
5345c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd) {
5356b5625bb609b154766d2e138b61e15655f60b710sewardj         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
5366b5625bb609b154766d2e138b61e15655f60b710sewardj         /* Assume the csfi fits completely into one individual mapping
5376b5625bb609b154766d2e138b61e15655f60b710sewardj            for now. This might need to be improved/reworked later. */
5386b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di->cfsi_minavma >= map->avma &&
5396b5625bb609b154766d2e138b61e15655f60b710sewardj             di->cfsi_maxavma <  map->avma + map->size)
5406b5625bb609b154766d2e138b61e15655f60b710sewardj            cfsi_fits = True;
5416b5625bb609b154766d2e138b61e15655f60b710sewardj      }
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5436b5625bb609b154766d2e138b61e15655f60b710sewardj
5446b5625bb609b154766d2e138b61e15655f60b710sewardj   /* degenerate case: all r-x sections are empty */
5456b5625bb609b154766d2e138b61e15655f60b710sewardj   if (!has_nonempty_rx) {
5465c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd == NULL);
5476b5625bb609b154766d2e138b61e15655f60b710sewardj      return;
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5496b5625bb609b154766d2e138b61e15655f60b710sewardj
5506b5625bb609b154766d2e138b61e15655f60b710sewardj   /* invariant (2) - cont. */
5515c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)
5526b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(cfsi_fits);
5536b5625bb609b154766d2e138b61e15655f60b710sewardj
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
5555c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd) {
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
5595c3dba227192de63d86f65ec7d9597c132818c37philippe         DiCfSI* cfsi = &di->cfsi_rd[i];
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
5645c3dba227192de63d86f65ec7d9597c132818c37philippe            DiCfSI* cfsip = &di->cfsi_rd[i-1];
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
582f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
583f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
584f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
585f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
586f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
587f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
588f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
589f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
5905c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
591f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
592f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
593f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
6008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
602d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj/* Helper (indirect) for di_notify_ACHIEVE_ACCEPT_STATE */
603518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool overlaps_DebugInfoMappings ( const DebugInfoMapping* map1,
604518850bf0da07ed3e2244e307268ae0fd80e93a8florian                                         const DebugInfoMapping* map2 )
605d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj{
606d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   vg_assert(map1 && map2 && map1 != map2);
607d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   vg_assert(map1->size != 0 && map2->size != 0);
608d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   if (map1->avma + map1->size <= map2->avma) return False;
609d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   if (map2->avma + map2->size <= map1->avma) return False;
610d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   return True;
611d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj}
612d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
613d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
614d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj/* Helper (indirect) for di_notify_ACHIEVE_ACCEPT_STATE */
615d6845c6e889dd75928e5cdbe5a8ba654881783acsewardjstatic void show_DebugInfoMappings
616518850bf0da07ed3e2244e307268ae0fd80e93a8florian               ( const DebugInfo* di,
617518850bf0da07ed3e2244e307268ae0fd80e93a8florian                 /*MOD*/XArray* maps /* XArray<DebugInfoMapping> */ )
618d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj{
619d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   Word i, n;
620d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   vg_assert(maps);
621d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   n = VG_(sizeXA)(maps);
622d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   for (i = 0; i < n; i++) {
623518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const DebugInfoMapping* map = VG_(indexXA)(maps, i);
624c6e5d76e9eea8625f385ff844545c688c91938daflorian      TRACE_SYMTAB("  [%ld]    avma 0x%-16lx    size %-8lu    "
625e7f48e650ebc8871b185af5efdd986f526d2f460sewardj                   "foff %-8lld    %s %s %s\n",
626e7f48e650ebc8871b185af5efdd986f526d2f460sewardj                   i, map->avma, map->size, (Long)map->foff,
627d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj                   map->rx ? "rx" : "--",
628d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj                   map->rw ? "rw" : "--",
629d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj                   map->ro ? "ro" : "--");
630d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   }
631d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj}
632d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
633d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
634d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj/* Helper for di_notify_ACHIEVE_ACCEPT_STATE.  This removes overlaps
635d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   in |maps|, in a fairly weak way, by truncating overlapping ends.
636d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   This may need to be strengthened in future.  Currently it performs
637d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   a post-fixup check, so as least we can be sure that if this
638d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   function returns (rather than asserts) that |maps| is overlap
639d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   free. */
640d6845c6e889dd75928e5cdbe5a8ba654881783acsewardjstatic void truncate_DebugInfoMapping_overlaps
641518850bf0da07ed3e2244e307268ae0fd80e93a8florian               ( const DebugInfo* di,
642518850bf0da07ed3e2244e307268ae0fd80e93a8florian                 /*MOD*/XArray* maps /* XArray<DebugInfoMapping> */ )
643d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj{
644d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   TRACE_SYMTAB("Un-de-overlapped _DebugInfoMappings:\n");
645d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   show_DebugInfoMappings(di, maps);
646d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   TRACE_SYMTAB("\n");
647d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
648d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   Word i, j, n;
649518850bf0da07ed3e2244e307268ae0fd80e93a8florian   DebugInfoMapping *map_i, *map_j;
650d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
651d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   n = VG_(sizeXA)(maps);
652d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   for (i = 0; i < n; i++) {
653d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
654518850bf0da07ed3e2244e307268ae0fd80e93a8florian      map_i = VG_(indexXA)(maps, i);
655d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      if (map_i->size == 0)
656d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj        continue; // Hmm, mutancy.  Shouldn't happen.
657d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
658d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      for (j = i+1; j < n; j++) {
659d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
660518850bf0da07ed3e2244e307268ae0fd80e93a8florian         map_j = VG_(indexXA)(maps, j);
661d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         if (map_j->size == 0)
662d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj           continue; // Hmm, mutancy.  Shouldn't happen.
663d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
664d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         /* map_j was observed later than map_i, since the entries are
665d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            in the XArray in the order in which they were observed.
666d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            If map_j starts inside map_i, trim map_i's end so it does
667d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            not overlap map_j.  This reflects the reality that when
668d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            two mmaped areas overlap, the later mmap silently
669d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            overwrites the earlier mmap's mapping. */
670d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         if (map_j->avma >= map_i->avma
671d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj             && map_j->avma < map_i->avma + map_i->size) {
672d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            SizeT map_i_newsize = map_j->avma - map_i->avma;
673d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            vg_assert(map_i_newsize < map_i->size);
674d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            map_i->size = map_i_newsize;
675d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         }
676d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
677d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      }
678d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   }
679d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
680518850bf0da07ed3e2244e307268ae0fd80e93a8florian   TRACE_SYMTAB("De-overlapped DebugInfoMappings:\n");
681d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   show_DebugInfoMappings(di, maps);
682d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   TRACE_SYMTAB("\n");
683d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   TRACE_SYMTAB("Checking that there are no remaining overlaps.\n");
684d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
685d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   for (i = 0; i < n; i++) {
686518850bf0da07ed3e2244e307268ae0fd80e93a8florian      map_i = VG_(indexXA)(maps, i);
687d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      if (map_i->size == 0)
688d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj        continue;
689d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      for (j = i+1; j < n; j++) {
690518850bf0da07ed3e2244e307268ae0fd80e93a8florian         map_j = VG_(indexXA)(maps, j);
691d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         if (map_j->size == 0)
692d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj           continue;
693d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         Bool overlap
694d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            = overlaps_DebugInfoMappings( map_i, map_j );
695d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         /* If the following assert ever fails, it means the de-overlapping
696d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj            scheme above is too weak, and needs improvement. */
697d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj         vg_assert(!overlap);
698d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      }
699d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   }
700d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
701d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   TRACE_SYMTAB("Check successful.\n");
702d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj}
703d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
704d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
706731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
707731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
708731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
709731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
710731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
711731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
712731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
713731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
714731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
715731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
716731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
717731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
718731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
719731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
720731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
721731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
722731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
723731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
724731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
725731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
726731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
727731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
728731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
729731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
730d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj                "-------------------------"
731731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
732731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
733731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
734731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
735731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
7366b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges specified in the _DebugInfoFsm mapping array. First
7376b5625bb609b154766d2e138b61e15655f60b710sewardj      get rid of any other DebugInfos which overlap any of those
7386b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges (to avoid total confusion). */
739731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
740731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
741d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   /* The DebugInfoMappings that now exist in the FSM may involve
742d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      overlaps.  This confuses ML_(read_elf_debug_info), and may cause
743d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      it to compute wrong biases.  So de-overlap them now.
744d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj      See http://bugzilla.mozilla.org/show_bug.cgi?id=788974 */
745d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   truncate_DebugInfoMapping_overlaps( di, di->fsm.maps );
746d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj
747d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj   /* And acquire new info. */
7488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGO_linux) || defined(VGO_solaris)
749731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
750731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
751731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
752731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
753731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
754731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
755731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
756731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
757731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
758731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
759731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
760731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
7615c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
762731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
763731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
7645c3dba227192de63d86f65ec7d9597c132818c37philippe      /* Check invariants listed in
7655c3dba227192de63d86f65ec7d9597c132818c37philippe         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
7665c3dba227192de63d86f65ec7d9597c132818c37philippe         priv_storage.h. */
7675c3dba227192de63d86f65ec7d9597c132818c37philippe      check_CFSI_related_invariants(di);
7685c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(finish_CFSI_arrays)(di);
769731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
770731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
771731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
772731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
773731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
774e2800c958044937e72eefa371c10ae47ac40e089florian      vg_assert(di->handle > 0);
775731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
776731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
777731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
778731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
779731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
780731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
781731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
782731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
783731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
784731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
785731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
786731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
787731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
788731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
789d6845c6e889dd75928e5cdbe5a8ba654881783acsewardj                "-------------------------"
790731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
791731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
792731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
793731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
794731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
795731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
8029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
8039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
8045f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   If use_fd is not -1, that is used instead of the filename; this
8055f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   avoids perturbing fcntl locks, which are released by simply
8065f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   re-opening and closing the same file (even via different fd!).
8075f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
8099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
8109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
8119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
8129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
8139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8155f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
8174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
818d3166c4cf9d2545242da71d8baeaaf203b02a09dflorian   const HChar* filename;
819731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
820b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
8215f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   Int        actual_fd, oflags;
8225f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   SysRes     preadres;
823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
8246f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool       debug = (DEBUG_FSM != 0);
825ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
826ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8285f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(use_fd >= -1);
8295f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
835eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8366f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug) {
8376f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-0:\n");
838a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
8426f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
843eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
8509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
8533e7986312a0ffc7646b0552d4c4ea3744a870e73florian   filename = VG_(am_get_filename)( seg );
854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
8559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
8570ab84fe82d1e25c2e0544d08826df42caa44ded1bart   /*
8580ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * Cannot read from these magic files:
8590ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- WARNING: Serious error when reading debug info
8600ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- When reading debug info from /proc/xen/privcmd:
8610ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- can't read file to inspect ELF header
8620ab84fe82d1e25c2e0544d08826df42caa44ded1bart    */
8630ab84fe82d1e25c2e0544d08826df42caa44ded1bart   if (VG_(strncmp)(filename, "/proc/xen/", 10) == 0)
8640ab84fe82d1e25c2e0544d08826df42caa44ded1bart      return 0;
8650ab84fe82d1e25c2e0544d08826df42caa44ded1bart
866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
869ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
87015728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
871ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
872ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
873ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
8749c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
875ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
876ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
877ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
878cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
879ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
880ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
881e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
882ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
883d3166c4cf9d2545242da71d8baeaaf203b02a09dflorian         fake_di.fsm.filename = ML_(dinfo_strdup)("di.debuginfo.nmm", filename);
884ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
885ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
8869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
8872ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
8882ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
889ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
890ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
8919c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
8929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
893ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
894ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
89515728ab41ea41bf731dcc74ac68354550ced2189bart
896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
908eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
913eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
914eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
915eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
916eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
917eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
919eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
920eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
929f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
930f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
931f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
932b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
933b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
934b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
935b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
936b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
937b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
938b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
939b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
940b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
944731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
945731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
9464df0bfc0614379192c780c944415dc420d9cfe8epetarj#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
9474df0bfc0614379192c780c944415dc420d9cfe8epetarj      || defined(VGA_mips64)
948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
950cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le)  \
951cae0cc22b83ffb260ee8379e92099c5a701944cbcarll        || defined(VGA_arm) || defined(VGA_arm64)
952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
954b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
955b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
956b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
957112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  elif defined(VGA_tilegx)
958112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   is_rx_map = seg->hasR && seg->hasX; // && !seg->hasW;
959112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   is_rw_map = seg->hasR && seg->hasW; // && !seg->hasX;
960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
962eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
963eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
964588cd4ebce3305d0cf91896c1f6322ef9775d6c1sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS >= DARWIN_10_7
965731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
966731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
967731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
9688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGO_solaris)
9698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
9708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   is_rw_map = seg->hasR && seg->hasW;
9718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
9728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
9746f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-3: "
9756f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  "is_rx_map %d, is_rw_map %d, is_ro_map %d\n",
9766f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  (Int)is_rx_map, (Int)is_rw_map, (Int)is_ro_map);
977eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
978731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
979731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
9809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
981eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
9825a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
9835a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
9845a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
985cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
986cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
987cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
988cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
9895f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
9905f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
9915f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      SysRes fd = VG_(open)( filename, oflags, 0 );
9925f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      if (sr_isError(fd)) {
9935f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         if (sr_Err(fd) != VKI_EACCES) {
9945f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            DebugInfo fake_di;
9955f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            VG_(memset)(&fake_di, 0, sizeof(fake_di));
996d3166c4cf9d2545242da71d8baeaaf203b02a09dflorian            fake_di.fsm.filename = ML_(dinfo_strdup)("di.debuginfo.nmm",
997d3166c4cf9d2545242da71d8baeaaf203b02a09dflorian                                                     filename);
9985f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            ML_(symerr)(&fake_di, True,
9995f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                        "can't open file to inspect ELF header");
10005f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         }
10015f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         return 0;
10025a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
10035f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = sr_Res(fd);
10045f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   } else {
10055f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = use_fd;
10065a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
10075a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
10085f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   preadres = VG_(pread)( actual_fd, buf1k, sizeof(buf1k), 0 );
10095f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
10105f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      VG_(close)( actual_fd );
10115f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   }
10125f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
10135f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_isError(preadres)) {
10145a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
10155a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
1016d3166c4cf9d2545242da71d8baeaaf203b02a09dflorian      fake_di.fsm.filename = ML_(dinfo_strdup)("di.debuginfo.nmm", filename);
10175a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
10185a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
10195a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
10205f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_Res(preadres) == 0)
10215f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      return 0;
10225f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
10235a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
10248b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
10258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if defined(VGO_linux) || defined(VGO_solaris)
1026f7c9714ea0cde18daaecb896278e85e780d3bd75sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
10275a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
10286e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
10295f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
1030f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
10316e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
10326e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
10336e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
10345a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
1035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
1036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
10370f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
1038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
1039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
10406f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
10416f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-4: "
10426f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  "noting details in DebugInfo* at %p\n", di);
10436f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
10446b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Note the details about the mapping. */
1045518850bf0da07ed3e2244e307268ae0fd80e93a8florian   DebugInfoMapping map;
10468291e31aca3156bef501b4de33a54a23fc404f11mjw   map.avma = seg->start;
10476b5625bb609b154766d2e138b61e15655f60b710sewardj   map.size = seg->end + 1 - seg->start;
10486b5625bb609b154766d2e138b61e15655f60b710sewardj   map.foff = seg->offset;
10496b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rx   = is_rx_map;
10506b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rw   = is_rw_map;
10516b5625bb609b154766d2e138b61e15655f60b710sewardj   map.ro   = is_ro_map;
10526b5625bb609b154766d2e138b61e15655f60b710sewardj   VG_(addToXA)(di->fsm.maps, &map);
10536b5625bb609b154766d2e138b61e15655f60b710sewardj
10546b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Update flags about what kind of mappings we've already seen. */
10556b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rx_map |= is_rx_map;
10566b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rw_map |= is_rw_map;
10576b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_ro_map |= is_ro_map;
1058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1059731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
1060731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
1061731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
1062731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
1063731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
10646f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
10656f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_mmap-5: "
10666f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "achieved accept state for %s\n", filename);
1067731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
10689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
1069731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
1070731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
1071731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
1072731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
10739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
1074eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1075eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1076eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
1078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
1079eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
1080eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1081f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
1082a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
1083f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
1084f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
10855c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
1086eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1087eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1088eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
1090eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
1091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
1092eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
1093eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
1094eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1095eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
1096f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
1097eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
1098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
1099f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
1100f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
1101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
11025c3dba227192de63d86f65ec7d9597c132818c37philippe         cfsi_m_cache__invalidate();
1103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1105eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1106731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1107588cd4ebce3305d0cf91896c1f6322ef9775d6c1sewardj/* This is a MacOSX >= 10.7 32-bit only special.  See comments on the
1108731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
1109731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
1110731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
11116f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool debug = (DEBUG_FSM != 0);
11126f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
11136f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
11146f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
11156f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
11166f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug) {
11176f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-0:\n");
11186f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-1: %#lx-%#lx %c%c%c\n",
11196f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  a, a + len - 1,
11206f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  r_ok ? 'r' : '-', w_ok ? 'w' : '-', x_ok ? 'x' : '-' );
11216f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
11226f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
1123731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
1124ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#  if defined(VGP_x86_darwin) && (DARWIN_VERS >= DARWIN_10_7)
1125731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
1126731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
11276f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (do_nothing /* wrong platform */) {
11286f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
11296f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_vm_protect-2: wrong platform, "
11306f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "doing nothing.\n");
1131731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
11326f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
1133731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1134731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
1135731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
1136731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1137731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
1138731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
1139731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
1140731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
11416f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
11426f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-3: looking for existing DebugInfo*\n");
1143731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
1144518850bf0da07ed3e2244e307268ae0fd80e93a8florian   DebugInfoMapping *map = NULL;
11456b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
1146731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
1147731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
1148731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
1149731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
1150731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
1151731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
1152731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
1153731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
1154731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
1155731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
11566b5625bb609b154766d2e138b61e15655f60b710sewardj      /* Try to find a mapping matching the memory area. */
11576b5625bb609b154766d2e138b61e15655f60b710sewardj      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1158518850bf0da07ed3e2244e307268ae0fd80e93a8florian         map = VG_(indexXA)(di->fsm.maps, i);
11596b5625bb609b154766d2e138b61e15655f60b710sewardj         if (map->ro && map->avma == a && map->size == len)
11606b5625bb609b154766d2e138b61e15655f60b710sewardj            break;
11616b5625bb609b154766d2e138b61e15655f60b710sewardj         map = NULL;
11626b5625bb609b154766d2e138b61e15655f60b710sewardj      }
11636b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map)
11646b5625bb609b154766d2e138b61e15655f60b710sewardj         continue; /* this isn't an upgrade of an r-- mapping */
1165731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
1166731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
1167731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
1168731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
1169731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
1170731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
11716f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
11726f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj     VG_(printf)("di_notify_vm_protect-4: found existing DebugInfo* at %p\n",
11736f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                 di);
11746f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
11756b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Do the upgrade.  Simply update the flags of the mapping
11766b5625bb609b154766d2e138b61e15655f60b710sewardj      and pretend we never saw the RO map at all. */
1177731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
11786b5625bb609b154766d2e138b61e15655f60b710sewardj   map->rx = True;
11796b5625bb609b154766d2e138b61e15655f60b710sewardj   map->ro = False;
1180731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
1181731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
11826b5625bb609b154766d2e138b61e15655f60b710sewardj   /* See if there are any more ro mappings */
11836b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1184518850bf0da07ed3e2244e307268ae0fd80e93a8florian      map = VG_(indexXA)(di->fsm.maps, i);
11856b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->ro) {
11866b5625bb609b154766d2e138b61e15655f60b710sewardj         di->fsm.have_ro_map = True;
11876b5625bb609b154766d2e138b61e15655f60b710sewardj         break;
11886b5625bb609b154766d2e138b61e15655f60b710sewardj      }
11896b5625bb609b154766d2e138b61e15655f60b710sewardj   }
11906b5625bb609b154766d2e138b61e15655f60b710sewardj
11916b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Check if we're now in an accept state and read debuginfo.  Finally. */
11926b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
11936f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
11946f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_vm_protect-5: "
11956f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "achieved accept state for %s\n", di->fsm.filename);
11966b5625bb609b154766d2e138b61e15655f60b710sewardj      ULong di_handle __attribute__((unused))
11976b5625bb609b154766d2e138b61e15655f60b710sewardj         = di_notify_ACHIEVE_ACCEPT_STATE( di );
11986b5625bb609b154766d2e138b61e15655f60b710sewardj      /* di_handle is ignored. That's not a problem per se -- it just
11996b5625bb609b154766d2e138b61e15655f60b710sewardj         means nobody will ever be able to refer to this debuginfo by
12006b5625bb609b154766d2e138b61e15655f60b710sewardj         handle since nobody will know what the handle value is. */
12016b5625bb609b154766d2e138b61e15655f60b710sewardj   }
1202731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1203731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1204731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1205c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1206c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1207c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1208c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
120954c45db2f978055aeca91aaccb05aac825523e6csewardj                                   SizeT total_size, PtrdiffT bias_obj )
1210c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
121113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1212c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
12131636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* pdbname = NULL;
12141636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* dot;
1215c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1216c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1217c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1218c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1219c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1220c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1221738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1222c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1223cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
122454c45db2f978055aeca91aaccb05aac825523e6csewardj         "bias=%#lx\n",
1225c6e5d76e9eea8625f385ff844545c688c91938daflorian         fd_obj, avma_obj, total_size, (UWord)bias_obj
1226c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1227c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1228c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1229c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1230c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1231c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1232c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1233a175ffb9ffa4fd250611582a611333d11c835de2florian      return; /* stat failed ?! */
1234c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
12359c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1236c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1237a175ffb9ffa4fd250611582a611333d11c835de2florian   /* and get its name into exename. */
12383130eab8c67d0c720cb1a86906cc057daa9700ccflorian   const HChar *exe;
1239a175ffb9ffa4fd250611582a611333d11c835de2florian   if (! VG_(resolve_filename)(fd_obj, &exe))
1240a175ffb9ffa4fd250611582a611333d11c835de2florian      return; /*  failed */
1241a175ffb9ffa4fd250611582a611333d11c835de2florian   sz_exename = VG_(strlen)(exe);
1242a175ffb9ffa4fd250611582a611333d11c835de2florian   HChar exename[sz_exename + 1];
1243a175ffb9ffa4fd250611582a611333d11c835de2florian   VG_(strcpy)(exename, exe);  // make a copy on the stack
1244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1246738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1247c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1248c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
124913ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
125013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
125113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
125213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
125313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
125413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
125513ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
125613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
125713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
125813ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
125913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
126013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
126113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
126213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
126313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
126413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
126513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
126613ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
126713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
126813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
126913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
127013ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
127113ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
127213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
127313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
127413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
127513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
127613ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
127713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
127813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
127913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
128098500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/drive_%c%s",
128198500e2ee5f63f9c0af57835f7620d30848115f4bart                       wpfx, pdbname[0], &pdbname[2]);
128213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
128313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
128413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
128513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
128613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
128713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
128813ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
128913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
129013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
129113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
129298500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/.wine/drive_%c%s",
129398500e2ee5f63f9c0af57835f7620d30848115f4bart		       home, pdbname[0], &pdbname[2]);
129413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
129513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
129613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
129713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
129813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
129913ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
130013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
130113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
130213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
130313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1304c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
130513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
130613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
130713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
130813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
130913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
131013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
131113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
131213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
131313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
131413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
131513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
131613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
131713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
131813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
131913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
132013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
132113ac96dea734b3933a73524b991ac64fb48a4d57sewardj
132213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
132313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
132413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
132513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
132613ac96dea734b3933a73524b991ac64fb48a4d57sewardj
132713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
132813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1329c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1330c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1331c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1332cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1333738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1334c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1335c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1336738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1337c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1338c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
13399c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
13407138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1341ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
13427138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
13437138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
13447138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
13457138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
13467138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
13477138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
13487138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1349738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1350ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1351ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1352ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1353c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1354c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1355c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1356cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1357738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1358c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1359c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1360c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1361cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1362cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1363cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1364cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1365cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1366cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1367cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1368cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1369cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
13709c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1371cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1372cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1373cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1374cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1375cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1376cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1377cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1378cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1379cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1380cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1381cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1382c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1383c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1384c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1385c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1386cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1387cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1388cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1389cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1390cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1391cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1392cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1393cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1394c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1395738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1396c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1397c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1398c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
13995c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
1400c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1401c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1402c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
14030f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1404c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1405c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1406a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1407c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1408c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1409c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1410c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
141154c45db2f978055aeca91aaccb05aac825523e6csewardj     ML_(read_pdb_debug_info)( di, avma_obj, bias_obj,
1412c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1413c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1414c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1415c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1416c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1417c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1418cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1419cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1420cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1421a663c8e5b4767efbd870c857076251460992e3edsewardj                                 "%lu syms, %lu src locs, %lu fpo recs\n",
1422a663c8e5b4767efbd870c857076251460992e3edsewardj                     di->symtab_used, di->loctab_used, di->fpo_size);
1423cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1424c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1425c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1426c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1427c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1428c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1429c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
14308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) */
14314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
14324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1433eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1435eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1436eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1437eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1438eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
14409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
14419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
14429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
14439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
14449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
14459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
14469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
14479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
14489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
14499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
14509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
14519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1452518850bf0da07ed3e2244e307268ae0fd80e93a8florianDebugInfoMapping* ML_(find_rx_mapping) ( DebugInfo* di, Addr lo, Addr hi )
14536b5625bb609b154766d2e138b61e15655f60b710sewardj{
14546b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
14556b5625bb609b154766d2e138b61e15655f60b710sewardj   vg_assert(lo <= hi);
14566b5625bb609b154766d2e138b61e15655f60b710sewardj
14576b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Optimization: Try to use the last matched rx mapping first */
14586b5625bb609b154766d2e138b61e15655f60b710sewardj   if (   di->last_rx_map
14596b5625bb609b154766d2e138b61e15655f60b710sewardj       && lo >= di->last_rx_map->avma
14606b5625bb609b154766d2e138b61e15655f60b710sewardj       && hi <  di->last_rx_map->avma + di->last_rx_map->size)
14616b5625bb609b154766d2e138b61e15655f60b710sewardj      return di->last_rx_map;
14626b5625bb609b154766d2e138b61e15655f60b710sewardj
14636b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1464518850bf0da07ed3e2244e307268ae0fd80e93a8florian      DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
14656b5625bb609b154766d2e138b61e15655f60b710sewardj      if (   map->rx && map->size > 0
14666b5625bb609b154766d2e138b61e15655f60b710sewardj          && lo >= map->avma && hi < map->avma + map->size) {
14676b5625bb609b154766d2e138b61e15655f60b710sewardj         di->last_rx_map = map;
14686b5625bb609b154766d2e138b61e15655f60b710sewardj         return map;
14696b5625bb609b154766d2e138b61e15655f60b710sewardj      }
14706b5625bb609b154766d2e138b61e15655f60b710sewardj   }
14716b5625bb609b154766d2e138b61e15655f60b710sewardj
14726b5625bb609b154766d2e138b61e15655f60b710sewardj   return NULL;
14736b5625bb609b154766d2e138b61e15655f60b710sewardj}
14746b5625bb609b154766d2e138b61e15655f60b710sewardj
1475a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1476a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*--- Types and functions for inlined IP cursor            ---*/
1477a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1478a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestruct _InlIPCursor {
1479a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Addr eip;             // Cursor used to describe calls at eip.
1480a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo* di;        // DebugInfo describing inlined calls at eip
1481a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1482a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_lopos; // The inlined fn calls covering eip are in
1483a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_hipos; // di->inltab[inltab_lopos..inltab_hipos].
1484a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // Note that not all inlined fn calls in this range
1485a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // are necessarily covering eip.
1486a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1487a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Int   curlevel;       // Current level to describe.
1488a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // 0 means to describe eip itself.
1489a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  cur_inltab;     // inltab pos for call inlined at current level.
1490a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  next_inltab;    // inltab pos for call inlined at next (towards main)
1491a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // level.
1492a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe};
1493a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1494518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_top(const InlIPCursor *iipc)
1495a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1496a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->cur_inltab == -1;
1497a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1498a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1499518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_bottom(const InlIPCursor *iipc)
1500a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1501a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->next_inltab == -1;
1502a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1503a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1504a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeBool VG_(next_IIPC)(InlIPCursor *iipc)
1505a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1506a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word i;
1507a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DiInlLoc *hinl = NULL;
1508a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word hinl_pos = -1;
1509a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo *di;
1510a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1511a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc == NULL)
1512a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1513a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1514a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->curlevel <= 0) {
1515a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel--;
1516a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1517a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1518a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1519a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di = iipc->di;
1520a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = iipc->inltab_lopos; i <= iipc->inltab_hipos; i++) {
1521a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= iipc->eip
1522a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && iipc->eip < di->inltab[i].addr_hi
1523a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && di->inltab[i].level < iipc->curlevel
1524a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && (!hinl || hinl->level < di->inltab[i].level)) {
1525a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl = &di->inltab[i];
1526a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl_pos = i;
1527a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1528a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1529a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1530a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->cur_inltab = iipc->next_inltab;
1531a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->next_inltab = hinl_pos;
1532a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->next_inltab < 0)
1533a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = 0; // no inlined call anymore, describe eip itself
1534a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   else
1535a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = di->inltab[iipc->next_inltab].level;
1536a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1537a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return True;
1538a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1539a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1540a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Forward */
1541a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1542a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                           /*OUT*/Word* locno );
1543a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1544a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Returns the position after which eip would be inserted in inltab.
1545a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (-1 if eip should be inserted before position 0).
1546a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   This is the highest position with an addr_lo <= eip.
1547a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   As inltab is sorted on addr_lo, dichotomic search can be done
1548a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (note that inltab might have duplicates addr_lo). */
1549a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Word inltab_insert_pos (DebugInfo *di, Addr eip)
1550a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1551a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word mid,
1552a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        lo = 0,
1553a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        hi = di->inltab_used-1;
1554a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= hi) {
1555a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      mid      = (lo + hi) / 2;
1556a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo) { hi = mid-1; continue; }
1557a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip > di->inltab[mid].addr_lo) { lo = mid+1; continue; }
1558a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo = mid; break;
1559a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1560a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1561a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= di->inltab_used-1 && di->inltab[lo].addr_lo <= eip)
1562a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo++;
1563a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#if 0
1564a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (mid = 0; mid <= di->inltab_used-1; mid++)
1565a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo)
1566a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1567a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (lo - 1 == mid - 1);
1568a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#endif
1569a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return lo - 1;
1570a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1571a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1572a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeInlIPCursor* VG_(new_IIPC)(Addr eip)
1573a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1574a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo*  di;
1575a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        locno;
1576a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        i;
1577a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   InlIPCursor *ret;
1578a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool        avail;
1579a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1580a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (!VG_(clo_read_inline_info))
1581a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No way we can find inlined calls.
1582a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1583a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the DebugInfo for eip */
1584a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   search_all_loctabs ( eip, &di, &locno );
1585a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di == NULL || di->inltab_used == 0)
1586a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No di (with inltab) containing eip.
1587a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1588a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the entry in di->inltab with the highest addr_lo that
1589a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      contains eip. */
1590a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We start from the highest pos in inltab after which eip would
1591a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      be inserted. */
1592a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = inltab_insert_pos (di, eip); i >= 0; i--) {
1593a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= eip && eip < di->inltab[i].addr_hi) {
1594a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1595a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1596a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      /* Stop the backward scan when reaching an addr_lo which
1597a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         cannot anymore contain eip : we know that all ranges before
1598a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         i also cannot contain eip. */
1599a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1600a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         return NULL;
1601a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1602a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1603a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (i < 0)
1604a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No entry containing eip.
1605a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1606a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We have found the highest entry containing eip.
1607a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      Build a cursor. */
1608a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret = ML_(dinfo_zalloc) ("dinfo.new_IIPC", sizeof(*ret));
1609a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->eip = eip;
1610a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->di = di;
1611a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_hipos = i;
1612a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = ret->inltab_hipos - 1; i >= 0; i--) {
1613a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1614a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1615a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break; /* Similar stop backward scan logic as above. */
1616a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1617a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_lopos = i + 1;
1618a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->curlevel = MAX_LEVEL;
1619a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->cur_inltab = -1;
1620a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->next_inltab = -1;
1621a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1622a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* MAX_LEVEL is higher than any stored level. We can use
1623a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(next_IIPC) to get to the 'real' first highest call level. */
1624a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   avail = VG_(next_IIPC) (ret);
1625a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (avail);
1626a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1627a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return ret;
1628a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1629a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1630a0a73939b0398b6608fd6dbde49820ce6530d12cphilippevoid VG_(delete_IIPC)(InlIPCursor *iipc)
1631a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1632a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc)
1633a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      ML_(dinfo_free)( iipc );
1634a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1635a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
16366b5625bb609b154766d2e138b61e15655f60b710sewardj
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1649f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1652eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1653f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
166051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
166151c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
166251c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1663a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
16646b5625bb609b154766d2e138b61e15655f60b710sewardj                   && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL);
1665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
16795706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
16805706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
16815706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
16825706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
16835706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
16845706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
16855706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
16865706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
16875706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
16885706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
16895706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1711f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1713f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
17175706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1732eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1733eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
1734dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   Caller supplies buf.  If do_cxx_demangling is False, don't do
17356b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
17366b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
173846cc04521acf2827eb33310fadc119bf2dc039e4florian   -- caller must choose one kind or the other.
173946cc04521acf2827eb33310fadc119bf2dc039e4florian   Note: the string returned in *BUF is persistent as long as
174046cc04521acf2827eb33310fadc119bf2dc039e4florian   (1) the DebugInfo it belongs to is not discarded
174146cc04521acf2827eb33310fadc119bf2dc039e4florian   (2) the segment containing the address is not merged with another segment
174246cc04521acf2827eb33310fadc119bf2dc039e4florian   (3) the demangler is not invoked again
174346cc04521acf2827eb33310fadc119bf2dc039e4florian   In other words: if in doubt, save it away.
174446cc04521acf2827eb33310fadc119bf2dc039e4florian   Also, the returned string is owned by "somebody else". Callers must
174546cc04521acf2827eb33310fadc119bf2dc039e4florian   not free it or modify it. */
1746eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
17476b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
17486b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
174946cc04521acf2827eb33310fadc119bf2dc039e4florian                    Addr a, const HChar** buf,
1750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1751c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1754f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1755c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
175846cc04521acf2827eb33310fadc119bf2dc039e4florian   if (di == NULL) {
175946cc04521acf2827eb33310fadc119bf2dc039e4florian      *buf = "";
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
176146cc04521acf2827eb33310fadc119bf2dc039e4florian   }
17626882443ef154bca367bc591287de641e43a9e108njn
1763a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
17646b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
176546cc04521acf2827eb33310fadc119bf2dc039e4florian                   di->symtab[sno].pri_name, buf );
17666b7611bf42a0fbb62e047d8c43b008205bd21e75njn
17676b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
17686b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
17696b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
17706b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
17716b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
17726b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
177346cc04521acf2827eb33310fadc119bf2dc039e4florian        Vg_FnNameBelowMain == VG_(get_fnname_kind)(*buf) )
17746b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
177546cc04521acf2827eb33310fadc119bf2dc039e4florian     *buf = "(below main)";
1776eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
17774cace66777ca9ee73ea156210c04e9d4cc178395philippe   offset = a - di->symtab[sno].avmas.main;
1778c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1780eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
178146cc04521acf2827eb33310fadc119bf2dc039e4florian      static HChar *bufwo;      // buf with offset
178246cc04521acf2827eb33310fadc119bf2dc039e4florian      static SizeT  bufwo_szB;
178346cc04521acf2827eb33310fadc119bf2dc039e4florian      SizeT  need, len;
178446cc04521acf2827eb33310fadc119bf2dc039e4florian
178546cc04521acf2827eb33310fadc119bf2dc039e4florian      len = VG_(strlen)(*buf);
178646cc04521acf2827eb33310fadc119bf2dc039e4florian      need = len + 1 + 19 + 1;
178746cc04521acf2827eb33310fadc119bf2dc039e4florian      if (need > bufwo_szB) {
178846cc04521acf2827eb33310fadc119bf2dc039e4florian        bufwo = ML_(dinfo_realloc)("get_sym_size", bufwo, need);
178946cc04521acf2827eb33310fadc119bf2dc039e4florian        bufwo_szB = need;
1790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
179246cc04521acf2827eb33310fadc119bf2dc039e4florian      VG_(strcpy)(bufwo, *buf);
179346cc04521acf2827eb33310fadc119bf2dc039e4florian      VG_(sprintf)(bufwo + len, "%c%ld",
179446cc04521acf2827eb33310fadc119bf2dc039e4florian                   offset < 0 ? '-' : '+',
179546cc04521acf2827eb33310fadc119bf2dc039e4florian                   offset < 0 ? -offset : offset);
179646cc04521acf2827eb33310fadc119bf2dc039e4florian      *buf = bufwo;
179746cc04521acf2827eb33310fadc119bf2dc039e4florian   }
17986b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1802cae0cc22b83ffb260ee8379e92099c5a701944cbcarll/* ppc64be-linux only: find the TOC pointer (R2 value) that should be in
1803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
18074cace66777ca9ee73ea156210c04e9d4cc178395philippe#if defined(VGA_ppc64be) || defined(VGA_ppc64le)
1808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1809f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1815eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
18174cace66777ca9ee73ea156210c04e9d4cc178395philippe      return GET_TOCPTR_AVMA(si->symtab[sno].avmas);
18184cace66777ca9ee73ea156210c04e9d4cc178395philippe#else
18194cace66777ca9ee73ea156210c04e9d4cc178395philippe   return 0;
18204cace66777ca9ee73ea156210c04e9d4cc178395philippe#endif
1821eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1823eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
182446cc04521acf2827eb33310fadc119bf2dc039e4florian   match anywhere in function, but don't show offsets.
182546cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
182646cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
182746cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_fnname) ( Addr a, const HChar** buf )
1828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
18296b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
18306b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
183146cc04521acf2827eb33310fadc119bf2dc039e4florian                         a, buf,
1832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1835b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1837eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1838eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
183946cc04521acf2827eb33310fadc119bf2dc039e4florian   match anywhere in function, and show offset if nonzero.
184046cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
184146cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
184246cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_fnname_w_offset) ( Addr a, const HChar** buf )
1843eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
18446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
18456b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
184646cc04521acf2827eb33310fadc119bf2dc039e4florian                         a, buf,
1847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1851eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1852eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1853eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1854eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
185546cc04521acf2827eb33310fadc119bf2dc039e4florian   and don't show offsets.
185646cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
185746cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
185846cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_fnname_if_entry) ( Addr a, const HChar** buf )
1859eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1860dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   const HChar *tmp;
1861dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   Bool res;
1862dc4ff1a019a3e54d3e5517514b7e683cb2071829florian
1863dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   res =  get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
18646b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
1865dc4ff1a019a3e54d3e5517514b7e683cb2071829florian                         a, &tmp,
1866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1870dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   if (res)
1871dc4ff1a019a3e54d3e5517514b7e683cb2071829florian      *buf = tmp;
1872dc4ff1a019a3e54d3e5517514b7e683cb2071829florian   return res;
1873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
18756b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
18766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
187746cc04521acf2827eb33310fadc119bf2dc039e4florian   offsets.
187846cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
187946cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
188046cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_fnname_raw) ( Addr a, const HChar** buf )
1881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
18826b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
18836b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
188446cc04521acf2827eb33310fadc119bf2dc039e4florian                         a, buf,
1885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1889eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1890eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1891eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
18926b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
189346cc04521acf2827eb33310fadc119bf2dc039e4florian   don't show offsets.
189446cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
189546cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
189646cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_fnname_no_cxx_demangle) ( Addr a, const HChar** buf,
189746cc04521acf2827eb33310fadc119bf2dc039e4florian                                       const InlIPCursor* iipc )
1898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1899a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
1900a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
1901a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
1902a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*below-main-renaming*/True,
190346cc04521acf2827eb33310fadc119bf2dc039e4florian                            a, buf,
1904a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*match_anywhere_in_fun*/True,
1905a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*show offset?*/False,
1906a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*text syms only*/True,
1907a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*offsetP*/NULL );
1908a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
1909a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
1910a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
1911a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
1912a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
1913a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
191446cc04521acf2827eb33310fadc119bf2dc039e4florian      *buf = next_inl->inlinedfn;
1915a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return True;
1916a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1917eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19195db15403e889d4db339b342bc2a824ef0bfaa654sewardj/* mips-linux only: find the offset of current address. This is needed for
19205db15403e889d4db339b342bc2a824ef0bfaa654sewardj   stack unwinding for MIPS.
19215db15403e889d4db339b342bc2a824ef0bfaa654sewardj*/
19225db15403e889d4db339b342bc2a824ef0bfaa654sewardjBool VG_(get_inst_offset_in_function)( Addr a,
19235db15403e889d4db339b342bc2a824ef0bfaa654sewardj                                       /*OUT*/PtrdiffT* offset )
19245db15403e889d4db339b342bc2a824ef0bfaa654sewardj{
192546cc04521acf2827eb33310fadc119bf2dc039e4florian   const HChar *fnname;
19265db15403e889d4db339b342bc2a824ef0bfaa654sewardj   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
19275db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*below-main-renaming*/False,
192846cc04521acf2827eb33310fadc119bf2dc039e4florian                         a, &fnname,
19295db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*match_anywhere_in_sym*/True,
193081208182df4e8b9c8642affd6754996777ee7556florian                         /*show offset?*/False,
19314afac5b6f637d1cea82e62b3a280fa4e81101c05petarj                         /*text syms only*/True,
19325db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         offset );
19335db15403e889d4db339b342bc2a824ef0bfaa654sewardj}
19345db15403e889d4db339b342bc2a824ef0bfaa654sewardj
193546cc04521acf2827eb33310fadc119bf2dc039e4florianVg_FnNameKind VG_(get_fnname_kind) ( const HChar* name )
19366882443ef154bca367bc591287de641e43a9e108njn{
19376882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
19386882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
19396882443ef154bca367bc591287de641e43a9e108njn
19406882443ef154bca367bc591287de641e43a9e108njn   } else if (
19413026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
19426882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
19436882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
19443026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1945f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1946f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
19478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#      elif defined(VGO_solaris)
19488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj       VG_STREQ("_start", name) || // main() is called directly from _start
19493026f71684a930286186aa10fef266c304672e8fsewardj#      else
19503026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
19513026f71684a930286186aa10fef266c304672e8fsewardj#      endif
19526882443ef154bca367bc591287de641e43a9e108njn       0) {
19536882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
19546882443ef154bca367bc591287de641e43a9e108njn
19556882443ef154bca367bc591287de641e43a9e108njn   } else {
19566882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
19576882443ef154bca367bc591287de641e43a9e108njn   }
19586882443ef154bca367bc591287de641e43a9e108njn}
19596882443ef154bca367bc591287de641e43a9e108njn
19606882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
19616882443ef154bca367bc591287de641e43a9e108njn{
196246cc04521acf2827eb33310fadc119bf2dc039e4florian   const HChar *buf;
19636882443ef154bca367bc591287de641e43a9e108njn
19646882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
19657d995792542cf8e7f5a81248589445adfffeae30florian   // we're looking for won't be mangled.
196646cc04521acf2827eb33310fadc119bf2dc039e4florian   if (VG_(get_fnname_raw) ( ip, &buf )) {
196746cc04521acf2827eb33310fadc119bf2dc039e4florian
19686882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
19696882443ef154bca367bc591287de641e43a9e108njn   } else {
19706882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
19716882443ef154bca367bc591287de641e43a9e108njn   }
19726882443ef154bca367bc591287de641e43a9e108njn}
19736882443ef154bca367bc591287de641e43a9e108njn
1974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
197546cc04521acf2827eb33310fadc119bf2dc039e4florian   puts a pointer to its name into dname. The name is zero terminated.
197646cc04521acf2827eb33310fadc119bf2dc039e4florian   Also data_addr's offset from the symbol start is put into *offset.
197746cc04521acf2827eb33310fadc119bf2dc039e4florian   NOTE: See important comment about the persistence and memory ownership
197846cc04521acf2827eb33310fadc119bf2dc039e4florian   of the return string at function get_sym_name */
1979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
198046cc04521acf2827eb33310fadc119bf2dc039e4florian                                  /*OUT*/const HChar** dname,
1981c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
198346cc04521acf2827eb33310fadc119bf2dc039e4florian   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
19846b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
198546cc04521acf2827eb33310fadc119bf2dc039e4florian                       data_addr, dname,
1986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
199346cc04521acf2827eb33310fadc119bf2dc039e4florian   executable.  Returns False if no idea; otherwise True.
199446cc04521acf2827eb33310fadc119bf2dc039e4florian   Note: the string returned in *BUF is persistent as long as
199546cc04521acf2827eb33310fadc119bf2dc039e4florian   (1) the DebugInfo it belongs to is not discarded
199646cc04521acf2827eb33310fadc119bf2dc039e4florian   (2) the segment containing the address is not merged with another segment
199746cc04521acf2827eb33310fadc119bf2dc039e4florian*/
199846cc04521acf2827eb33310fadc119bf2dc039e4florianBool VG_(get_objname) ( Addr a, const HChar** buf )
1999eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2001f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
20023297124fa2116737066ac3cd709f18fdd5405163florian   const HChar* filename;
200346cc04521acf2827eb33310fadc119bf2dc039e4florian
20047cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
20057cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
2006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
20085706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
2009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
2010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
201146cc04521acf2827eb33310fadc119bf2dc039e4florian         *buf = di->fsm.filename;
2012eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
2013eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2014eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
20157cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
20167cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
20177cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
20187cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
20197cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
20207cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
20217cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
202246cc04521acf2827eb33310fadc119bf2dc039e4florian     *buf = filename;
2023f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
2024f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
2025eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
2026eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2027eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
2029eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
2030e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
2031eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2032e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
2033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2034e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
2035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
20375706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
2038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
2039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
2040e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
2041e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
2042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
2043eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2044eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2045eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
2046eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2047eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
204810ef725f1e8e9f1615c483555348eb75b69c4713florian/* Map a code address to a filename.  Returns True if successful. The
204910ef725f1e8e9f1615c483555348eb75b69c4713florian   returned string is persistent as long as the DebugInfo to which it
205010ef725f1e8e9f1615c483555348eb75b69c4713florian   belongs is not discarded. */
205110ef725f1e8e9f1615c483555348eb75b69c4713florianBool VG_(get_filename)( Addr a, const HChar** filename )
2052eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
2054f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
205559e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt       fndn_ix;
205659e1f3c79e870a978d24add86db6d8c5450c8b63philippe
2057eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
2058eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
2059eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
206059e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn_ix = ML_(fndn_ix) (si, locno);
206110ef725f1e8e9f1615c483555348eb75b69c4713florian   *filename = ML_(fndn_ix2filename) (si, fndn_ix);
2062eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2063eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2064eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2065eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
2066eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
2067eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
2069f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
2070eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
2071eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
2072eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
2073eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
2074eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2075eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2076eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
2079eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
2080eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
2081eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
208210ef725f1e8e9f1615c483555348eb75b69c4713florian                                 /*OUT*/const HChar** filename,
208310ef725f1e8e9f1615c483555348eb75b69c4713florian                                 /*OUT*/const HChar** dirname,
2084eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
2085eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
2087f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
208859e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt       fndn_ix;
2089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2090eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
2091c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
2092f4384f47ee6b6234dba548a775585c37af712edfflorian      if (dirname) {
209310ef725f1e8e9f1615c483555348eb75b69c4713florian         *dirname = "";
2094db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
209510ef725f1e8e9f1615c483555348eb75b69c4713florian      *filename = "";      // this used to be not initialised....
2096eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
2097c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
2098c1b1d421216369aec58867ce1c5b99cfb1703c36njn
209959e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn_ix = ML_(fndn_ix)(si, locno);
210010ef725f1e8e9f1615c483555348eb75b69c4713florian   *filename = ML_(fndn_ix2filename) (si, fndn_ix);
2101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
2102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2103eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
2104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
210510ef725f1e8e9f1615c483555348eb75b69c4713florian      *dirname = ML_(fndn_ix2dirname) (si, fndn_ix);
2106eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2108eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
21124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
21134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
21144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
21154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
21164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
21174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
21184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
2119518850bf0da07ed3e2244e307268ae0fd80e93a8florianBool VG_(lookup_symbol_SLOW)(const HChar* sopatt, const HChar* name,
2120518850bf0da07ed3e2244e307268ae0fd80e93a8florian                             SymAVMAs* avmas)
21214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
21224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
21234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
2124518850bf0da07ed3e2244e307268ae0fd80e93a8florian   const DebugInfo* si;
21254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
21264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
21274ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
21284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
2129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
21304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
21314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
21324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
21334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
21344ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
21354ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
21364ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
21374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
21381ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian         const HChar* pri_name = si->symtab[i].pri_name;
2139e2800c958044937e72eefa371c10ae47ac40e089florian         vg_assert(pri_name);
2140a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
21414cace66777ca9ee73ea156210c04e9d4cc178395philippe             && (require_pToc ? GET_TOCPTR_AVMA(si->symtab[i].avmas) : True)) {
21424cace66777ca9ee73ea156210c04e9d4cc178395philippe            *avmas = si->symtab[i].avmas;
21434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
21444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
21451ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian         const HChar** sec_names = si->symtab[i].sec_names;
2146a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
2147e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(sec_names[0]);
2148a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
2149a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
21504cace66777ca9ee73ea156210c04e9d4cc178395philippe                   && (require_pToc
21514cace66777ca9ee73ea156210c04e9d4cc178395philippe                       ? GET_TOCPTR_AVMA(si->symtab[i].avmas) : True)) {
21524cace66777ca9ee73ea156210c04e9d4cc178395philippe                  *avmas = si->symtab[i].avmas;
2153a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
2154a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
2155a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
2156a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
2157a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
21584ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
21594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
21604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
21614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
21624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
21634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
2164770a8d23e40b980b5745e59ecb8e4037d81af357florian/* VG_(describe_IP): return info on code address, function name and
2165770a8d23e40b980b5745e59ecb8e4037d81af357florian   filename. The returned string is allocated in a static buffer and will
2166770a8d23e40b980b5745e59ecb8e4037d81af357florian   be overwritten in the next invocation. */
2167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2168770a8d23e40b980b5745e59ecb8e4037d81af357florian/* Copy str into *buf starting at n, ensuring that buf is zero-terminated.
2169770a8d23e40b980b5745e59ecb8e4037d81af357florian   Return the index of the terminating null character. */
2170770a8d23e40b980b5745e59ecb8e4037d81af357florianstatic SizeT
2171770a8d23e40b980b5745e59ecb8e4037d81af357florianputStr( SizeT n, HChar** buf, SizeT *bufsiz, const HChar* str )
2172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2173770a8d23e40b980b5745e59ecb8e4037d81af357florian   SizeT slen = VG_(strlen)(str);
2174770a8d23e40b980b5745e59ecb8e4037d81af357florian   SizeT need = n + slen + 1;
2175e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
2176770a8d23e40b980b5745e59ecb8e4037d81af357florian   if (need > *bufsiz) {
2177770a8d23e40b980b5745e59ecb8e4037d81af357florian      if (need < 256) need = 256;
2178770a8d23e40b980b5745e59ecb8e4037d81af357florian      *bufsiz = need;
2179770a8d23e40b980b5745e59ecb8e4037d81af357florian      *buf = ML_(dinfo_realloc)("putStr", *buf, *bufsiz);
2180770a8d23e40b980b5745e59ecb8e4037d81af357florian   }
2181e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
2182770a8d23e40b980b5745e59ecb8e4037d81af357florian   VG_(strcpy)(*buf + n, str);
2183770a8d23e40b980b5745e59ecb8e4037d81af357florian
2184770a8d23e40b980b5745e59ecb8e4037d81af357florian   return n + slen;
2185770a8d23e40b980b5745e59ecb8e4037d81af357florian}
2186770a8d23e40b980b5745e59ecb8e4037d81af357florian
2187770a8d23e40b980b5745e59ecb8e4037d81af357florian/* Same as putStr, but escaping chars for XML output. */
2188770a8d23e40b980b5745e59ecb8e4037d81af357florianstatic SizeT
2189770a8d23e40b980b5745e59ecb8e4037d81af357florianputStrEsc( SizeT n, HChar** buf, SizeT *bufsiz, const HChar* str )
2190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
21911636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar alt[2];
2192770a8d23e40b980b5745e59ecb8e4037d81af357florian
2193eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
2194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
2195e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
2196770a8d23e40b980b5745e59ecb8e4037d81af357florian            n = putStr( n, buf, bufsiz, "&amp;");
2197e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2198e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
2199770a8d23e40b980b5745e59ecb8e4037d81af357florian            n = putStr( n, buf, bufsiz, "&lt;");
2200e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2201e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
2202770a8d23e40b980b5745e59ecb8e4037d81af357florian            n = putStr( n, buf, bufsiz, "&gt;");
2203e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2204e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
2205e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
2206e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
2207770a8d23e40b980b5745e59ecb8e4037d81af357florian            n = putStr( n, buf, bufsiz, alt );
2208e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2211eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
2212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2214770a8d23e40b980b5745e59ecb8e4037d81af357florianconst HChar* VG_(describe_IP)(Addr eip, const InlIPCursor *iipc)
2215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2216770a8d23e40b980b5745e59ecb8e4037d81af357florian   static HChar *buf = NULL;
2217770a8d23e40b980b5745e59ecb8e4037d81af357florian   static SizeT bufsiz = 0;
2218eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
2219770a8d23e40b980b5745e59ecb8e4037d81af357florian      n = putStr(n, &buf, &bufsiz, _str)
2220770a8d23e40b980b5745e59ecb8e4037d81af357florian#  define APPEND_ESC(_str) \
2221770a8d23e40b980b5745e59ecb8e4037d81af357florian      n = putStrEsc(n, &buf, &bufsiz, _str)
2222eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2223eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
2224770a8d23e40b980b5745e59ecb8e4037d81af357florian   HChar ibuf[50];   // large enough
2225770a8d23e40b980b5745e59ecb8e4037d81af357florian   SizeT n = 0;
222614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2227a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (!iipc || iipc->eip == eip);
2228a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2229770a8d23e40b980b5745e59ecb8e4037d81af357florian   const HChar *buf_fn;
2230770a8d23e40b980b5745e59ecb8e4037d81af357florian   const HChar *buf_obj;
2231770a8d23e40b980b5745e59ecb8e4037d81af357florian   const HChar *buf_srcloc;
2232770a8d23e40b980b5745e59ecb8e4037d81af357florian   const HChar *buf_dirname;
223314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
223425148a6f2d895ee7005a69395427a4c9753f089dflorian   Bool  know_dirinfo;
2235a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_fnname;
2236a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_objname;
2237a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_srcloc;
2238a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2239a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
2240a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
2241a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = VG_(clo_sym_offsets)
224246cc04521acf2827eb33310fadc119bf2dc039e4florian                    ? VG_(get_fnname_w_offset) (eip, &buf_fn)
224346cc04521acf2827eb33310fadc119bf2dc039e4florian                    : VG_(get_fnname) (eip, &buf_fn);
2244a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2245a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
2246a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
2247a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2248a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
2249a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
2250770a8d23e40b980b5745e59ecb8e4037d81af357florian      buf_fn = next_inl->inlinedfn;
2251a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = True;
2252a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2253a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // INLINED????
2254a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Can we compute an offset for an inlined fn call ?
2255a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Offset from what ? The beginning of the inl info ?
2256a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? But that is not necessarily the beginning of the fn
2257a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? as e.g. an inlined fn call can be in several ranges.
2258a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Currently never showing an offset.
2259a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2260a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
226146cc04521acf2827eb33310fadc119bf2dc039e4florian   know_objname = VG_(get_objname)(eip, &buf_obj);
2262a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2263a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_top(iipc)) {
2264a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The source for the highest level is in the loctab entry.
2265a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc  = VG_(get_filename_linenum)(
2266a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        eip,
226710ef725f1e8e9f1615c483555348eb75b69c4713florian                        &buf_srcloc,
2268f4384f47ee6b6234dba548a775585c37af712edfflorian                        &buf_dirname,
2269a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        &lineno
2270a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     );
2271f4384f47ee6b6234dba548a775585c37af712edfflorian      know_dirinfo = buf_dirname[0] != '\0';
2272a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2273a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *cur_inl = iipc && iipc->cur_inltab >= 0
2274a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->cur_inltab]
2275a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2276a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (cur_inl);
2277a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
227859e1f3c79e870a978d24add86db6d8c5450c8b63philippe      know_dirinfo = False;
227925148a6f2d895ee7005a69395427a4c9753f089dflorian      buf_dirname  = "";
2280666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      // The fndn_ix and lineno for the caller of the inlined fn is in cur_inl.
2281666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      if (cur_inl->fndn_ix == 0) {
228210ef725f1e8e9f1615c483555348eb75b69c4713florian         buf_srcloc = "???";
2283666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      } else {
2284666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         FnDn *fndn = VG_(indexEltNumber) (iipc->di->fndnpool,
2285666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                                           cur_inl->fndn_ix);
2286666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         if (fndn->dirname) {
228710ef725f1e8e9f1615c483555348eb75b69c4713florian            buf_dirname = fndn->dirname;
2288666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe            know_dirinfo = True;
2289666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         }
229010ef725f1e8e9f1615c483555348eb75b69c4713florian         buf_srcloc = fndn->filename;
2291666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      }
2292666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      lineno = cur_inl->lineno;
2293a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc = True;
2294a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2295a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
2297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
22996bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline  = human_readable ? "\n      " : "";
23006bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline2 = human_readable ? "\n    "   : "";
2301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2302e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
2303770a8d23e40b980b5745e59ecb8e4037d81af357florian         Ensure all tags are balanced. */
2304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
2305c6e5d76e9eea8625f385ff844545c688c91938daflorian      VG_(sprintf)(ibuf,"<ip>0x%lX</ip>", eip);
2306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
2307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
2308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
2309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
2311770a8d23e40b980b5745e59ecb8e4037d81af357florian         APPEND_ESC(buf_obj);
2312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
2313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
2315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
2317770a8d23e40b980b5745e59ecb8e4037d81af357florian         APPEND_ESC(buf_fn);
2318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
2319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
2322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
2323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
2324770a8d23e40b980b5745e59ecb8e4037d81af357florian            APPEND_ESC(buf_dirname);
2325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
2326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
2327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
2329770a8d23e40b980b5745e59ecb8e4037d81af357florian         APPEND_ESC(buf_srcloc);
2330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
2331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
2333c6e5d76e9eea8625f385ff844545c688c91938daflorian         VG_(sprintf)(ibuf,"%u",lineno);
2334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
2336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
2338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
2339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
2341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
23435e40abad4504416c59f0b29c1cfc8087201213a9njn      //
23445e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
23455e40abad4504416c59f0b29c1cfc8087201213a9njn      //
23465e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
23475e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
23485e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
23495e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
23505e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
23515e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
23525e40abad4504416c59f0b29c1cfc8087201213a9njn      //
2353c6e5d76e9eea8625f385ff844545c688c91938daflorian      VG_(sprintf)(ibuf,"0x%lX: ", eip);
2354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
23555e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
2356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
2357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
2358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
2359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
236214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
236310ef725f1e8e9f1615c483555348eb75b69c4713florian         const HChar* dirname = NULL;
236425148a6f2d895ee7005a69395427a4c9753f089dflorian         if (know_dirinfo && VG_(sizeXA)(VG_(clo_fullpath_after)) > 0) {
236514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
236614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
236714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
236814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
236914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
23707931627282eede4440f3f329b657c3ec68371e8aflorian            for (i = 0; i < VG_(sizeXA)(VG_(clo_fullpath_after)); i++) {
23717931627282eede4440f3f329b657c3ec68371e8aflorian               const HChar* prefix =
23727931627282eede4440f3f329b657c3ec68371e8aflorian                  *(HChar**) VG_(indexXA)( VG_(clo_fullpath_after), i );
23731636d33c13958b9c0e7d3059cdd5005746418eb2florian               HChar* str    = VG_(strstr)(dirname, prefix);
237414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
237514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
237614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
237714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
237814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
237914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
238014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
238114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
238214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
238314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
238414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
238514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
238614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
238714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
23885dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
2389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
2390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
2391c6e5d76e9eea8625f385ff844545c688c91938daflorian         VG_(sprintf)(ibuf,"%u",lineno);
2392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
23945e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
23955e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
23965e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
23975e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
23985e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
23995e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
24005e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
24015e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
2402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2405eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
2406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
2408eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
2409eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
241172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
2416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
241872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
241972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
242072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
242172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
242272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
24233297124fa2116737066ac3cd709f18fdd5405163florian      const D3UnwindRegs* uregs;
24243026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
24253026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
242672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
242772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
242872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
242972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
243072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
243172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
2432f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
2433f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
24343297124fa2116737066ac3cd709f18fdd5405163florianUWord evalCfiExpr ( const XArray* exprs, Int ix,
24353297124fa2116737066ac3cd709f18fdd5405163florian                    const CfiExprEvalContext* eec, Bool* ok )
243672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
243740628facff2285b0fce592381c6e26fdcd2a1252tom   UWord w, wL, wR;
243819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
24393297124fa2116737066ac3cd709f18fdd5405163florian   const CfiExpr* e;
24403026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
24413026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
244272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
244340628facff2285b0fce592381c6e26fdcd2a1252tom      case Cex_Unop:
244440628facff2285b0fce592381c6e26fdcd2a1252tom         w = evalCfiExpr( exprs, e->Cex.Unop.ix, eec, ok );
244540628facff2285b0fce592381c6e26fdcd2a1252tom         if (!(*ok)) return 0;
244640628facff2285b0fce592381c6e26fdcd2a1252tom         switch (e->Cex.Unop.op) {
244740628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Abs: return (Word) w < 0 ? - w : w;
244840628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Neg: return - (Word) w;
244940628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Not: return ~ w;
245040628facff2285b0fce592381c6e26fdcd2a1252tom            default: goto unhandled;
245140628facff2285b0fce592381c6e26fdcd2a1252tom         }
245240628facff2285b0fce592381c6e26fdcd2a1252tom         /*NOTREACHED*/
245372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
245472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
245572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
245672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
245772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
245872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
2459f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Add: return wL + wR;
2460f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Sub: return wL - wR;
2461f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_And: return wL & wR;
2462f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Mul: return wL * wR;
2463f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shl: return wL << wR;
2464f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shr: return wL >> wR;
2465f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Eq: return wL == wR ? 1 : 0;
2466f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2467f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2468f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2469f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
2470f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ne: return wL != wR ? 1 : 0;
247172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
247272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
247372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
247472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
247572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
24763026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
24773026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
24783026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
24793026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
24803026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
24813026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
24823026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2483fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2484fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2485ade2eddf567a868bafad9110ed92acf7373a972bsewardj            case Creg_ARM_R7:  return eec->uregs->r7;
2486b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2487b6ba6d288e6000a8f95fba1dea671e0b53e26043florian            case Creg_S390_IA: return eec->uregs->ia;
2488b6ba6d288e6000a8f95fba1dea671e0b53e26043florian            case Creg_S390_SP: return eec->uregs->sp;
2489b6ba6d288e6000a8f95fba1dea671e0b53e26043florian            case Creg_S390_FP: return eec->uregs->fp;
2490b6ba6d288e6000a8f95fba1dea671e0b53e26043florian            case Creg_S390_LR: return eec->uregs->lr;
24914df0bfc0614379192c780c944415dc420d9cfe8epetarj#           elif defined(VGA_mips32) || defined(VGA_mips64)
24925db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_IP: return eec->uregs->pc;
24935db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_SP: return eec->uregs->sp;
24945db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_BP: return eec->uregs->fp;
24955db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_MIPS_RA: return eec->uregs->ra;
2496cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#           elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
2497cae0cc22b83ffb260ee8379e92099c5a701944cbcarll               || defined(VGA_ppc64le)
2498f0c1250e324f6684757c6a15545366447ef1d64fsewardj#           elif defined(VGP_arm64_linux)
2499821283b2110420321fd3f60afcc799b287788c68sewardj            case Creg_ARM64_X30: return eec->uregs->x30;
2500112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#           elif defined(VGA_tilegx)
2501112711afefcfcd43680c7c4aa8d38ef180e8811esewardj            case Creg_TILEGX_IP: return eec->uregs->pc;
2502112711afefcfcd43680c7c4aa8d38ef180e8811esewardj            case Creg_TILEGX_SP: return eec->uregs->sp;
2503112711afefcfcd43680c7c4aa8d38ef180e8811esewardj            case Creg_TILEGX_BP: return eec->uregs->fp;
2504112711afefcfcd43680c7c4aa8d38ef180e8811esewardj            case Creg_TILEGX_LR: return eec->uregs->lr;
25053026f71684a930286186aa10fef266c304672e8fsewardj#           else
25063026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
25073026f71684a930286186aa10fef266c304672e8fsewardj#           endif
250872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
250972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
251072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
251172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
251272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
251319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
251419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
251519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
251619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
2517720e6b71b171885281afab634ce4d667c1f262bcsewardj             || a > eec->max_accessible - sizeof(UWord) + 1) {
251819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
251919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
252019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
252119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
252286781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
252372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
252472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
252572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
252672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
252772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
252872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
252972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
253072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
253172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
253272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
253372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
253472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
253572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
253672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
25375c3dba227192de63d86f65ec7d9597c132818c37philippe/* Search all the DebugInfos in the entire system, to find the DiCfSI_m
2538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
25415c3dba227192de63d86f65ec7d9597c132818c37philippe   *cfsi_mP to the cfsi_m pointer in that DebugInfo's cfsi_m_pool.
254272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
25435c3dba227192de63d86f65ec7d9597c132818c37philippe   If not found, set *diP to (DebugInfo*)1 and *cfsi_mP to zero.
2544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
25475c3dba227192de63d86f65ec7d9597c132818c37philippe                          /*OUT*/DiCfSI_m** cfsi_mP,
2548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2555eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2558eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2561eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2562eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2566eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2578eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2582f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2583f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
25845c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = 0;
2585f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2586f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2587f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25885c3dba227192de63d86f65ec7d9597c132818c37philippe      /* found a di corresponding to ip. */
2589f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2590f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2591f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
25925c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = ML_(get_cfsi_m) (di, i);
25935c3dba227192de63d86f65ec7d9597c132818c37philippe      if (*cfsi_mP == NULL) {
25945c3dba227192de63d86f65ec7d9597c132818c37philippe         // This is a cfsi hole. Report no cfi information found.
25955c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = (DebugInfo*)1;
25965c3dba227192de63d86f65ec7d9597c132818c37philippe         // But we will still perform the hack below.
25975c3dba227192de63d86f65ec7d9597c132818c37philippe      } else {
25985c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = di;
25995c3dba227192de63d86f65ec7d9597c132818c37philippe      }
2600f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2601f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2602f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2603f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2604f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2605f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2606f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2607f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2608f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2609f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2610f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2611f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2612f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2613f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2614f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2615f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2616f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2617f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2618f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2619f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2620f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2621f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2622f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2623f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2624f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2625f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2626f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26275c3dba227192de63d86f65ec7d9597c132818c37philippe   Each cache entry binds an ip value to a (di, cfsi_m*) pair.  Possible
2628f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2629f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26305c3dba227192de63d86f65ec7d9597c132818c37philippe   di is non-null, cfsi_m* >= 0  ==>  cache slot in use, "cfsi_m*"
26315c3dba227192de63d86f65ec7d9597c132818c37philippe   di is (DebugInfo*)1           ==>  cache slot in use, no associated di
26325c3dba227192de63d86f65ec7d9597c132818c37philippe   di is NULL                    ==>  cache slot not in use
2633f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2634f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2635f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2636f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26375c3dba227192de63d86f65ec7d9597c132818c37philippe   We can map an ip value directly to a (di, cfsi_m*) pair as
26385c3dba227192de63d86f65ec7d9597c132818c37philippe   once a DebugInfo is read, adding new DiCfSI_m* is not possible
26395c3dba227192de63d86f65ec7d9597c132818c37philippe   anymore, as the cfsi_m_pool is frozen once the reading is terminated.
26405c3dba227192de63d86f65ec7d9597c132818c37philippe   Also, the cache is invalidated when new debuginfo is read due to
26415c3dba227192de63d86f65ec7d9597c132818c37philippe   an mmap or some debuginfo is discarded due to an munmap. */
2642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
26435c3dba227192de63d86f65ec7d9597c132818c37philippe// Prime number, giving about 6Kbytes cache on 32 bits,
26445c3dba227192de63d86f65ec7d9597c132818c37philippe//                           12Kbytes cache on 64 bits.
26455c3dba227192de63d86f65ec7d9597c132818c37philippe#define N_CFSI_M_CACHE 509
2646f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2647f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
26485c3dba227192de63d86f65ec7d9597c132818c37philippe   struct { Addr ip; DebugInfo* di; DiCfSI_m* cfsi_m; }
26495c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt;
2650f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26515c3dba227192de63d86f65ec7d9597c132818c37philippestatic CFSI_m_CacheEnt cfsi_m_cache[N_CFSI_M_CACHE];
2652f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26535c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void ) {
26545c3dba227192de63d86f65ec7d9597c132818c37philippe   VG_(memset)(&cfsi_m_cache, 0, sizeof(cfsi_m_cache));
2655f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   debuginfo_generation++;
2656f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2657f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2658f7bbd7982397fb73477bdc21bf236cf9100cee44philippeUInt VG_(debuginfo_generation) (void)
265920ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe{
2660f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   return debuginfo_generation;
266120ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe}
2662f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26635c3dba227192de63d86f65ec7d9597c132818c37philippestatic inline CFSI_m_CacheEnt* cfsi_m_cache__find ( Addr ip )
2664f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
26655c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord         hash = ip % N_CFSI_M_CACHE;
26665c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce = &cfsi_m_cache[hash];
26673c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2668f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2669f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2670f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2671f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2672f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
26733c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
26743c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
26753c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
26763c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
26773c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
26783c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
26795c3dba227192de63d86f65ec7d9597c132818c37philippe      find_DiCfSI( &ce->di, &ce->cfsi_m, ip );
26803c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
26823c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
26833c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
26843c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
26853c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
26863c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
26873c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
26893c9cf3442185b5891e15450d6e3058aeff6796fetom}
2690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2692f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
26933297124fa2116737066ac3cd709f18fdd5405163florianstatic Addr compute_cfa ( const D3UnwindRegs* uregs,
26943c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
26953297124fa2116737066ac3cd709f18fdd5405163florian                          const DebugInfo* di, const DiCfSI_m* cfsi_m )
26963c9cf3442185b5891e15450d6e3058aeff6796fetom{
26973c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
26983c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
26993c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
27013c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
270272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
27035c3dba227192de63d86f65ec7d9597c132818c37philippe   switch (cfsi_m->cfa_how) {
27043026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
27053026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
27065c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xsp;
27073026f71684a930286186aa10fef266c304672e8fsewardj         break;
27083026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
27095c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xbp;
271072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
27113026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
27123026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
27135c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r13;
271472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
27153026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
27165c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r12;
27173026f71684a930286186aa10fef266c304672e8fsewardj         break;
27183026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
27195c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r11;
27203026f71684a930286186aa10fef266c304672e8fsewardj         break;
2721fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
27225c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r7;
2723fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2724b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2725b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
27265c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2727b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2728b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2729b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
27305c3dba227192de63d86f65ec7d9597c132818c37philippe         Addr a = uregs->sp + cfsi_m->cfa_off;
2731b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2732b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
273386781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2734b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2735b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2736b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2737b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2738b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2739b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
27405c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
2741b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
27424df0bfc0614379192c780c944415dc420d9cfe8epetarj#     elif defined(VGA_mips32) || defined(VGA_mips64)
27435db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_SPREL:
27445c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
27455db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
27465db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIR_SAME:
27475db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = uregs->fp;
27485db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
27495db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_BPREL:
27505c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
27515db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
2752cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#     elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2753f0c1250e324f6684757c6a15545366447ef1d64fsewardj#     elif defined(VGP_arm64_linux)
2754821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_SPREL:
27555c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2756821283b2110420321fd3f60afcc799b287788c68sewardj         break;
2757821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_X29REL:
27585c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->x29;
2759821283b2110420321fd3f60afcc799b287788c68sewardj         break;
2760112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#     elif defined(VGA_tilegx)
2761112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case CFIC_IA_SPREL:
2762112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         cfa = cfsi_m->cfa_off + uregs->sp;
2763112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         break;
2764112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case CFIR_SAME:
2765112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         cfa = uregs->fp;
2766112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         break;
2767112711afefcfcd43680c7c4aa8d38ef180e8811esewardj      case CFIC_IA_BPREL:
2768112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         cfa = cfsi_m->cfa_off + uregs->fp;
2769112711afefcfcd43680c7c4aa8d38ef180e8811esewardj         break;
27703026f71684a930286186aa10fef266c304672e8fsewardj#     else
27713026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
27723026f71684a930286186aa10fef266c304672e8fsewardj#     endif
27733026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
27747888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
27757888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
27765c3dba227192de63d86f65ec7d9597c132818c37philippe            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi_m->cfa_off);
27777888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
27787888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
27793026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
27807888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
27817888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
27827888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
27835c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = evalCfiExpr(di->cfsi_exprs, cfsi_m->cfa_off, &eec, &ok );
27843c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
278572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
278672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
278772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
278872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
27893c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
27903c9cf3442185b5891e15450d6e3058aeff6796fetom}
27913c9cf3442185b5891e15450d6e3058aeff6796fetom
27923c9cf3442185b5891e15450d6e3058aeff6796fetom
27933c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
27943026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
27953026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
27963c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
27973c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
27983c9cf3442185b5891e15450d6e3058aeff6796fetom{
27995c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce;
28003c9cf3442185b5891e15450d6e3058aeff6796fetom
28015c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ip);
28023c9cf3442185b5891e15450d6e3058aeff6796fetom
28033c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
28043c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
28053c9cf3442185b5891e15450d6e3058aeff6796fetom
28063026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
28073026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
28083026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
28093026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
28103026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
28113026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
28123026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
28133026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
281405c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
28153026f71684a930286186aa10fef266c304672e8fsewardj   }
2816b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2817b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2818b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2819b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2820b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2821b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
282205c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2823b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2824112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_tilegx)
2825fe0b43315c344cfd07981a0826bc34614a220169dejanj   { D3UnwindRegs uregs;
2826fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.pc = ip;
2827fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.sp = sp;
2828fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.fp = fp;
2829fe0b43315c344cfd07981a0826bc34614a220169dejanj     return compute_cfa(&uregs,
283005c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2831fe0b43315c344cfd07981a0826bc34614a220169dejanj   }
2832b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
28333026f71684a930286186aa10fef266c304672e8fsewardj#  else
28343026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
28353026f71684a930286186aa10fef266c304672e8fsewardj#  endif
28363c9cf3442185b5891e15450d6e3058aeff6796fetom}
28373c9cf3442185b5891e15450d6e3058aeff6796fetom
283897bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippevoid VG_(ppUnwindInfo) (Addr from, Addr to)
283997bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe{
284097bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   DebugInfo*         di;
284197bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   CFSI_m_CacheEnt*   ce;
284297bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   Addr ce_from;
284397bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   CFSI_m_CacheEnt*   next_ce;
284497bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe
284597bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe
284697bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   ce = cfsi_m_cache__find(from);
284797bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   ce_from = from;
284897bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   while (from <= to) {
284997bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe      from++;
285097bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe      next_ce = cfsi_m_cache__find(from);
285197bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe      if ((ce == NULL && next_ce != NULL)
285297bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe          || (ce != NULL && next_ce == NULL)
285397bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe          || (ce != NULL && next_ce != NULL && ce->cfsi_m != next_ce->cfsi_m)
285497bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe          || from > to) {
285597bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe         if (ce == NULL) {
285697bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe            VG_(printf)("[%#lx .. %#lx]: no CFI info\n", ce_from, from-1);
285797bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe         } else {
285897bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe            di = ce->di;
285997bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe            ML_(ppDiCfSI)(di->cfsi_exprs,
286097bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe                          ce_from, from - ce_from,
286197bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe                          ce->cfsi_m);
286297bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe         }
286397bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe         ce = next_ce;
286497bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe         ce_from = from;
286597bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe      }
286697bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe   }
286797bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe}
286897bfa1905b957b46e8426db4a8aed9b4ee7f476ephilippe
28693c9cf3442185b5891e15450d6e3058aeff6796fetom
28703026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
28713026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
28723026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
28733026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
28743026f71684a930286186aa10fef266c304672e8fsewardj
28753026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
28763026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
28773026f71684a930286186aa10fef266c304672e8fsewardj
2878fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
2879821283b2110420321fd3f60afcc799b287788c68sewardj
2880821283b2110420321fd3f60afcc799b287788c68sewardj   For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
28813026f71684a930286186aa10fef266c304672e8fsewardj*/
28823026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
28833c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
28843c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
28853c9cf3442185b5891e15450d6e3058aeff6796fetom{
28863c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
28875c3dba227192de63d86f65ec7d9597c132818c37philippe   DiCfSI_m*          cfsi_m = NULL;
28883026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
28895c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt*   ce;
2890d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
28913026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
28923c9cf3442185b5891e15450d6e3058aeff6796fetom
28933026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
28943026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
28953026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
28963026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2897b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2898b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
28994df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
29005db15403e889d4db339b342bc2a824ef0bfaa654sewardj   ipHere = uregsHere->pc;
2901cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2902f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
2903821283b2110420321fd3f60afcc799b287788c68sewardj   ipHere = uregsHere->pc;
2904112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  elif defined(VGA_tilegx)
2905112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   ipHere = uregsHere->pc;
29063026f71684a930286186aa10fef266c304672e8fsewardj#  else
29073026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
29083026f71684a930286186aa10fef266c304672e8fsewardj#  endif
29095c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ipHere);
29103c9cf3442185b5891e15450d6e3058aeff6796fetom
29113c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
29123c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
29133c9cf3442185b5891e15450d6e3058aeff6796fetom
29143c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
29155c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m = ce->cfsi_m;
29163c9cf3442185b5891e15450d6e3058aeff6796fetom
29173c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
29185c3dba227192de63d86f65ec7d9597c132818c37philippe      VG_(printf)("found cfsi_m (but printing fake base/len): ");
29195c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(ppDiCfSI)(di->cfsi_exprs, 0, 0, cfsi_m);
29203c9cf3442185b5891e15450d6e3058aeff6796fetom   }
29213c9cf3442185b5891e15450d6e3058aeff6796fetom
2922f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
29233c9cf3442185b5891e15450d6e3058aeff6796fetom
29243c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
29253026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
29265c3dba227192de63d86f65ec7d9597c132818c37philippe                     min_accessible, max_accessible, di, cfsi_m);
29273c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
29283c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
292972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
293072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
293172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
29439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
294586781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2946eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
295172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
295272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2953f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
29543026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
295572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
295672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2957d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
295972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
296072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
296172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
296272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2963eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2964eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2965eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29663026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
29675c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi_m->ra_how, cfsi_m->ra_off);
29685c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi_m->sp_how, cfsi_m->sp_off);
29695c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi_m->bp_how, cfsi_m->bp_off);
29703026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
29715c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi_m->ra_how,  cfsi_m->ra_off);
29725c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi_m->r14_how, cfsi_m->r14_off);
29735c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi_m->r13_how, cfsi_m->r13_off);
29745c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi_m->r12_how, cfsi_m->r12_off);
29755c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi_m->r11_how, cfsi_m->r11_off);
29765c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi_m->r7_how,  cfsi_m->r7_off);
2977b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
29785c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi_m->ra_how, cfsi_m->ra_off);
29795c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
29805c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
29814df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
29825c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi_m->ra_how, cfsi_m->ra_off);
29835c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
29845c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
2985cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2986f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
29875c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc,  uregsHere->pc,  cfsi_m->ra_how,  cfsi_m->ra_off);
29885c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp,  uregsHere->sp,  cfsi_m->sp_how,  cfsi_m->sp_off);
29895c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off);
29905c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off);
2991112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#  elif defined(VGA_tilegx)
2992112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi_m->ra_how, cfsi_m->ra_off);
2993112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
2994112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
29953026f71684a930286186aa10fef266c304672e8fsewardj#  else
29963026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
29973026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2998eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2999eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
3000eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
30013026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
3002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
3003eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3004eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3005eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
3008c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
3009c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
3010c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
3011c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
3012c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3013c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
3014c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
3015c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
3016c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
3017c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
3018c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
3019c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
30203297124fa2116737066ac3cd709f18fdd5405163florian   const DebugInfo* di;
3021c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
3022c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
3023c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3024c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
3025c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
3026c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
3027c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3028c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
3029c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3030c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3031c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
3032c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3033c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
3034c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
3035c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
3036c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
3037c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
3038c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
3039c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3040c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
3041c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
3042c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
3043c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
3044c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
3045c6e5d76e9eea8625f385ff844545c688c91938daflorian            VG_(printf)("look for %#lx  size %lu i %ld\n",
3046c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
3047c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
3048c6e5d76e9eea8625f385ff844545c688c91938daflorian               VG_(printf)("[%02ld] %#x %u\n",
3049c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
3050c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
3051c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
3052c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
3053c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
3054c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
3055c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
3056c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3057c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
3058c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
3059c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3060c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
3061c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
3062c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
3063c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
3064c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3065c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3066c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
3067c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
3068c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
3069c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
3070c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
3071c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
3072c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
3073c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
3074c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
3075c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
3076c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
3077c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3078c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
3079c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
3080c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
3081c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
3082c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3083c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
3084c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
3085c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
3086c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
3087c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
3088c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
3089c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
3090c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
3091c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3092c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
3093c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
3094c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
3095c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
3096c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
3097c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
3098c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
3099c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
3100c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
3101c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
3102c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
3103c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
3104c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
3105c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3106c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
3107c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
3108c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
3109c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
3110c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
3111c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
3112c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
3113c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3114c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
3115c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
3116c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
3117c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3118c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
3119c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
312086781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
312186781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
312286781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
312386781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
3124c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
3125c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
3126c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3127f7bbd7982397fb73477bdc21bf236cf9100cee44philippeBool VG_(FPO_info_present)(void)
3128f7bbd7982397fb73477bdc21bf236cf9100cee44philippe{
3129f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   const DebugInfo* di;
3130f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   for (di = debugInfo_list; di != NULL; di = di->next) {
3131f7bbd7982397fb73477bdc21bf236cf9100cee44philippe      if (di->fpo != NULL)
3132f7bbd7982397fb73477bdc21bf236cf9100cee44philippe         return True;
3133f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   }
3134f7bbd7982397fb73477bdc21bf236cf9100cee44philippe   return False;
3135f7bbd7982397fb73477bdc21bf236cf9100cee44philippe}
3136f7bbd7982397fb73477bdc21bf236cf9100cee44philippe
3137c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
3138c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
3139c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
3140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
3141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
3142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
3143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
3144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3145588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
3146b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   VG_(xaprintf)(dst, fmt, args) without having to resort to
3147588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
3148588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
3149738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3150588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
3151b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   //   VG_(xaprintf)(dstxa, format, ##args)
3152738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3153b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart#define  p2XA  VG_(xaprintf)
3154738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3155588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
3156588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
3157738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
3158738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
3159738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
3160738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
3161738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
3162738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3163738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
3165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
3166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
3167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
3168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
3169c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
31703297124fa2116737066ac3cd709f18fdd5405163florian                                     const XArray* /* TyEnt */ tyents,
31713297124fa2116737066ac3cd709f18fdd5405163florian                                     const DiVariable*   var,
31723297124fa2116737066ac3cd709f18fdd5405163florian                                     const RegSummary*   regs,
31733297124fa2116737066ac3cd709f18fdd5405163florian                                     Addr  data_addr,
3174588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
3175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
317650fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
3177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
3178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
3179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
31809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
3183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
318550fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
318650fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
318750fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
318850fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
318950fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
319050fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
319150fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
319250fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
319350fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
319450fde23467d92281b32dd537d0d9a590263628c3sewardj
319550fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
3198a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
3199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
32009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
3201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
3202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
3205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
3206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
3207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
3208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3211588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
3212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
3214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
3215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
3216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
3217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3218eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32193c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
3220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
3221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
3222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
3223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
3224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
3225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3230738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
3231738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
3232738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
3233738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
3234738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
3235738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
3236738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
3237738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
3238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
3239518850bf0da07ed3e2244e307268ae0fd80e93a8florian                             const DebugInfo* di,
3240518850bf0da07ed3e2244e307268ae0fd80e93a8florian                             const DiVariable* var,
3241c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
3242c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
3243518850bf0da07ed3e2244e307268ae0fd80e93a8florian                             const XArray* /*HChar*/ described,
3244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
3245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
3246eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3247738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
3248738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
32491636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* vo_plural = var_offset == 1 ? "" : "s";
32501636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* ro_plural = residual_offset == 1 ? "" : "s";
32511636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* basetag   = "auxwhat"; /* a constant */
32521636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar tagL[32], tagR[32], xagL[32], xagR[32];
3253666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   const HChar *fileName = ML_(fndn_ix2filename)(di, var->fndn_ix);
3254666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   // fileName will be "???" if var->fndn_ix == 0.
3255666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   // fileName will only be used if have_descr is True.
3256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3257d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
3258d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
3259d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3260d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
3261d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
3262d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3263d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
3264d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
3265d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3266d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
3267738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
3268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
3269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
3270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
3271d6b9fcc80e248211dc9cf888a768a49fa1091522florian                && *(HChar*)VG_(indexXA)(described,0) != '\0';
3272666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   have_srcloc = var->fndn_ix > 0 && var->lineNo > 0;
3273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3274738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
3275738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
3276738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
3277738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
3278738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
3279738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
3280738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
3281738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3282738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
3283738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
3284738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
3285738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
3286738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
3287738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
3288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
3290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
3292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
3294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3296738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3297738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3298738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3299c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside local var \"%pS\",",
3300738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3301738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3302738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3303738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3304c6e5d76e9eea8625f385ff844545c688c91938daflorian               "in frame #%d of thread %u", frameNo, tid );
3305738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3306738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3307738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3308c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside local var \"%s\",",
3309738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3310738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3311c6e5d76e9eea8625f385ff844545c688c91938daflorian               "in frame #%d of thread %u", frameNo, tid );
3312738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
3316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
3318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
3319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3320738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3321738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3322738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3323c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside local var \"%pS\"",
3324738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3325738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3326738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3327738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3328738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3329c6e5d76e9eea8625f385ff844545c688c91938daflorian               "declared at %pS:%d, in frame #%d of thread %u",
3330c6e5d76e9eea8625f385ff844545c688c91938daflorian               fileName, var->lineNo, frameNo, tid );
3331738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3332738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3333738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3334b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3335666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3336738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3337738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3338738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3339c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside local var \"%s\"",
3340738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3341738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3342c6e5d76e9eea8625f385ff844545c688c91938daflorian               "declared at %s:%d, in frame #%d of thread %u",
3343c6e5d76e9eea8625f385ff844545c688c91938daflorian               fileName, var->lineNo, frameNo, tid );
3344738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
3348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
3350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3352738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3353738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3354738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3355c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %pS%pS",
3356738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3357738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3358738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3359738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3360738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3361c6e5d76e9eea8625f385ff844545c688c91938daflorian               "in frame #%d of thread %u", frameNo, tid );
3362738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3363738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3364738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3365c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %s%s",
3366738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3367738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3368738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3369c6e5d76e9eea8625f385ff844545c688c91938daflorian               "in frame #%d of thread %u", frameNo, tid );
3370738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
3374738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3375738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
3376738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3377738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3378738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3379c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %pS%pS,",
3380738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3381738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3382738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3383738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3384738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3385738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3386c6e5d76e9eea8625f385ff844545c688c91938daflorian               "declared at %pS:%d, in frame #%d of thread %u",
3387c6e5d76e9eea8625f385ff844545c688c91938daflorian               fileName, var->lineNo, frameNo, tid );
3388738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3389738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3390738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3391b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3392666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3393738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3394738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3395738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3396c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %s%s,",
3397738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3398738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3399738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3400c6e5d76e9eea8625f385ff844545c688c91938daflorian               "declared at %s:%d, in frame #%d of thread %u",
3401c6e5d76e9eea8625f385ff844545c688c91938daflorian               fileName, var->lineNo, frameNo, tid );
3402738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
3406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
3407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3410738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3411738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3412738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3413c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside global var \"%pS\"",
3414738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3415738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3416738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3417738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3418c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside global var \"%s\"",
3419738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3420738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
3424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
3427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3428738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3429738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3430738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3431c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside global var \"%pS\"",
3432738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3433738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3434738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3435738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3436738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3437b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d",
3438666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3439738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3440738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3441738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3442b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3443666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3444738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3445738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3446738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3447c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside global var \"%s\"",
3448738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3449738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3450738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
3451666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3452738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
3456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
3459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3460738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3461738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3462738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3463c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %pS%pS,",
3464738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3465738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3466738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3467738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3468738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3469738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3470738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3471738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3472738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3473c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %s%s,",
3474738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3475c6e5d76e9eea8625f385ff844545c688c91938daflorian               (HChar*)(VG_(indexXA)(described,0)) );
3476738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3477738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3478738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
3482738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3483738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
3484738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3485738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3486738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3487c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %pS%pS,",
3488738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3489738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3490738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3491738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3492738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3493738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3494b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "a global variable declared at %pS:%d",
3495666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3496738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3497738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3498738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3499b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3500666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3501738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3502738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3503738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3504c6e5d76e9eea8625f385ff844545c688c91938daflorian               "Location 0x%lx is %ld byte%s inside %s%s,",
3505738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3506738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3507738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3508738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
3509666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3510738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
3514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3515738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
3516738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
3517738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
3518738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3519738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
3520738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
3521738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
3522738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
3523738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
3524738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
3525eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3527738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
3529738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
3530738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
3531738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
3532738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
3533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
3534738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
3535738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
3536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
3537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
3538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
3539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
3540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
3542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
3544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
3545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
3547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
3548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
3549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
3550a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
3551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
3552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
3553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
3554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
3558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
3559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
3563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
3564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
3565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
3566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
3569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
3570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
3571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
3572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
3573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
3574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
3575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
3576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
3577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
3578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
3579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
3581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
3583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3588b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3589b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3590b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3600b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3632c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3634a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
36369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
36379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3638588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3639c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
36419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
36429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3643738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3644666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                            data_addr, di, var, offset, residual_offset,
3645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3653eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3655738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
365625963376a3669e7f77395d6f884bdf1f6a928966philippe   debug info we have.  This considers all global variables, and 8
3657738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3658738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3659738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3660738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3661738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3662738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3663738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3664738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3665738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3666738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3667738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3668738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
366909a8b1491c62d8e70575eb85da4875d9a07fd20eflorian        /*MOD*/ XArray* /* of HChar */ dname1,
367009a8b1491c62d8e70575eb85da4875d9a07fd20eflorian        /*MOD*/ XArray* /* of HChar */ dname2,
3671738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3672738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3684a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
36919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3732c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
37419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3743588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3744c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
37469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
37479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3748738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3749666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                            data_addr, di, var, offset, residual_offset,
3750d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3751d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3753738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3754738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3777738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3778738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3787b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3792b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3794738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3795738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3804b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3812b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3813b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3814b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3815b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3816b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3817738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3818b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3819b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3820b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3821738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3822738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3828738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3829738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3832eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
38359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
38369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
38379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
38389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
38399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
38409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
38429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
38439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
38449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
38459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
38469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
38489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
38493297124fa2116737066ac3cd709f18fdd5405163florian                    const XArray* /* TyEnt */ tyents,
38503297124fa2116737066ac3cd709f18fdd5405163florian                    Addr ip, const DebugInfo* di, const DiVariable* var,
38519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
38529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
38539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
38549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
385550fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
38569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
38579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
38589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
38609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
38619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
38629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
386450fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
386550fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
386650fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
386750fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
386850fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
386950fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
387050fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
387150fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
387250fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
38739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
38759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
38769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
38779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
38789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
38799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
38809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
38819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
38829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
38839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
38859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
38869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
38889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
38899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
38909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
38919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
38929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
38939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
38949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3895588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
38969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
38989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
38999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3900588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
39019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
39039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
39049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3905588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
39069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
39089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
39099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3910588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
39119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
39139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
39149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
39159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39163c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
39179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
39189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
39199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
39209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
3921e2800c958044937e72eefa371c10ae47ac40e089florian      vg_assert(sp_delta == 0 || sp_delta == 1024);
3922e2800c958044937e72eefa371c10ae47ac40e089florian      vg_assert(fp_delta == 0 || fp_delta == 1024);
39239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
39259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
39269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
39279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
39289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
39299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
39309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
39319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3932588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
3933e2800c958044937e72eefa371c10ae47ac40e089florian         vg_assert(res.kind == GXR_Addr);
39349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
3935c6e5d76e9eea8625f385ff844545c688c91938daflorian         VG_(printf)("   %5lu .. %5llu (sp) %s\n",
3936c6e5d76e9eea8625f385ff844545c688c91938daflorian                     res.word, res.word + mul.ul - 1, var->name);
39379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
393850fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
39399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
39409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
39419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
39429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
39439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
39449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
39459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
39469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
39479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
39489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
39499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
39509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3951588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
3952e2800c958044937e72eefa371c10ae47ac40e089florian         vg_assert(res.kind == GXR_Addr);
39539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
3954c6e5d76e9eea8625f385ff844545c688c91938daflorian         VG_(printf)("   %5lu .. %5llu (FP) %s\n",
3955c6e5d76e9eea8625f385ff844545c688c91938daflorian                     res.word, res.word + mul.ul - 1, var->name);
39569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
395750fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
39589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
39599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
39609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
39619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
39629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
39639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
39649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
39659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
39669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
39679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
39689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
39699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
39709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
39719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
39749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
39759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
39769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
39779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
397809a8b1491c62d8e70575eb85da4875d9a07fd20eflorianXArray* /* of StackBlock */
397909a8b1491c62d8e70575eb85da4875d9a07fd20eflorianVG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
39809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
39819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
39829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
39839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
39849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
39859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
39879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
39889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
39899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
39919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
39929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
39939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
39949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
39959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
39969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
39979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
39989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
39999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
40009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
40019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
40029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
40039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
40049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
40059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
40079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
40089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
40099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
40109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
40119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
40139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
40149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
40159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
40169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
40179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
40189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
40199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
40209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
40219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
40229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
40239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
40249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
40259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
40279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
40289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
40299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
40319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
40329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
40339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
40349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
40359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
40379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
40389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
40399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
40409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
40419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
40429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
40439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
40449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
40459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
40469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
40479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
40489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
40499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
40509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
40519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
40529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
40539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
40549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
40559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
40569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
40579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
40589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
40599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
40609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
40619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
40629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
40639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
40649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
40659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
40669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
40679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
40689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
40699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
40709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
40719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
40729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
40739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
40749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
40759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
40769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
4077588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
40789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
40799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
40809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
40829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
40839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
40869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
40879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
40889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
40899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
40909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
40919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
409209a8b1491c62d8e70575eb85da4875d9a07fd20eflorianXArray* /* of GlobalBlock */
409309a8b1491c62d8e70575eb85da4875d9a07fd20eflorianVG_(di_get_global_blocks_from_dihandle) ( ULong di_handle, Bool  arrays_only )
40949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
40959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
40969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
40989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
40999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
41009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
41029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
4103e2800c958044937e72eefa371c10ae47ac40e089florian   vg_assert(di_handle > 0);
41049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
41059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
41069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
41079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
41089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
41109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
41119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
4112e2800c958044937e72eefa371c10ae47ac40e089florian   vg_assert(di != NULL);
41139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
41159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
41169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
41179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
41199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
41209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
41219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
41239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
41249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
41259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
41269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
41279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
41299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
41309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
41319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
4132e2800c958044937e72eefa371c10ae47ac40e089florian      vg_assert(scope);
41339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
41349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
41359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
41379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
4138e2800c958044937e72eefa371c10ae47ac40e089florian         vg_assert(range->vars);
41399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
41409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
41419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
41439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
414450fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
41459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
41469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
41479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
4148e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(var->name);
41499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
41509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
41529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
41539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
41549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
41559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
41569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
41579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
4158588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
41599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
41613c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
41629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
41639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
41649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
41659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
41679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
41689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
41699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
417150fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
41729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
417350fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
417450fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
417550fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
417650fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
417750fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
417850fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
417950fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
418050fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
41819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
41839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
41849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
41859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
41869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
41879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
41889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
41899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
41909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
41929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
41939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
41949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
4195e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(var->name);
4196e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(di->soname);
41979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
4198666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                               ML_(fndn_ix2filename)(di, var->fndn_ix),
4199666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                               var->lineNo);
42009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
42019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
420250fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
42039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
42049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
42059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
4206e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
4207e2800c958044937e72eefa371c10ae47ac40e089florian            vg_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
42089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
42109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
42129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
42149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
42169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
42189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
42199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
42209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
4221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
4223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4225e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
4226eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
4228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
4229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
4230eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4231eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4232e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
4233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
4235eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4237e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
4238eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
4240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
42423898022a7d74a227d6a35102faaedd420ed3a1c1bartAddr VG_(DebugInfo_get_bss_avma)(const DebugInfo* di)
42433898022a7d74a227d6a35102faaedd420ed3a1c1bart{
42443898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_avma : 0;
42453898022a7d74a227d6a35102faaedd420ed3a1c1bart}
42463898022a7d74a227d6a35102faaedd420ed3a1c1bart
42473898022a7d74a227d6a35102faaedd420ed3a1c1bartSizeT VG_(DebugInfo_get_bss_size)(const DebugInfo* di)
42483898022a7d74a227d6a35102faaedd420ed3a1c1bart{
42493898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_size : 0;
42503898022a7d74a227d6a35102faaedd420ed3a1c1bart}
42513898022a7d74a227d6a35102faaedd420ed3a1c1bart
4252e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
4253092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4254092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
4255092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4256092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4257e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
4258092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4259092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
4260092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4261092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4262e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
4263092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4264092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
4265092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4266092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4267e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
4268092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4269092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
4270092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4271092b6268cc4a38ae9ee41d1e3355937536ddc579bart
427268347837b3d82e48f85daff33ec7ba528891e4e7bartAddr VG_(DebugInfo_get_got_avma)(const DebugInfo* di)
427368347837b3d82e48f85daff33ec7ba528891e4e7bart{
427468347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_avma : 0;
427568347837b3d82e48f85daff33ec7ba528891e4e7bart}
427668347837b3d82e48f85daff33ec7ba528891e4e7bart
427768347837b3d82e48f85daff33ec7ba528891e4e7bartSizeT VG_(DebugInfo_get_got_size)(const DebugInfo* di)
427868347837b3d82e48f85daff33ec7ba528891e4e7bart{
427968347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_size : 0;
428068347837b3d82e48f85daff33ec7ba528891e4e7bart}
428168347837b3d82e48f85daff33ec7ba528891e4e7bart
42821636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
4283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
4285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
42871636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
4288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4289a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
4290eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4292e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
4293bbec7728efefaa650970dd1f0282b77040287133sewardj{
4294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
4295bbec7728efefaa650970dd1f0282b77040287133sewardj}
4296bbec7728efefaa650970dd1f0282b77040287133sewardj
4297e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
4298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
4300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4302e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
4303e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
43044cace66777ca9ee73ea156210c04e9d4cc178395philippe                                  /*OUT*/SymAVMAs* avmas,
43054cace66777ca9ee73ea156210c04e9d4cc178395philippe                                  /*OUT*/UInt*     size,
43061ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                                  /*OUT*/const HChar**   pri_name,
43071ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian                                  /*OUT*/const HChar***  sec_names,
43084cace66777ca9ee73ea156210c04e9d4cc178395philippe                                  /*OUT*/Bool*     isText,
43094cace66777ca9ee73ea156210c04e9d4cc178395philippe                                  /*OUT*/Bool*     isIFunc )
4310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
43124cace66777ca9ee73ea156210c04e9d4cc178395philippe   if (avmas)     *avmas     = si->symtab[idx].avmas;
4313a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
4314a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
43151ef70c6f00ab1b50d1936f77037e9923d8ed8c59florian   if (sec_names) *sec_names = si->symtab[idx].sec_names;
4316a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
4317a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
4318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
4323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
4326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
4327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
4328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
4330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
4331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
4332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
4333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
4334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
4335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
4336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
43375706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
4338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
4339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
4343e08950b4ce5a3f5d75a7279548f975cd6207dc74florian   it comes from.  If name is non-NULL, then the object's name is put
4344e08950b4ce5a3f5d75a7279548f975cd6207dc74florian   in *name. The returned name, if any, should be saved away, if there is
4345e08950b4ce5a3f5d75a7279548f975cd6207dc74florian   a chance that a debug-info will be discarded and the name is being
4346e08950b4ce5a3f5d75a7279548f975cd6207dc74florian   used later on. */
4347e08950b4ce5a3f5d75a7279548f975cd6207dc74florianVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/const HChar** name, Addr a)
4348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
4350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
4351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
4353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
4355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
4356c6e5d76e9eea8625f385ff844545c688c91938daflorian            "addr=%#lx di=%p %s got=%#lx,%lu plt=%#lx,%lu "
4357c6e5d76e9eea8625f385ff844545c688c91938daflorian            "data=%#lx,%lu bss=%#lx,%lu\n",
4358a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
4359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
4360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
4361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
4362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
4363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
4365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
4366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
4367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
4368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
4371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
4372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
4373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
4377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
4378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
4379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
4383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
4384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
4385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
4386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
43885706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
43895706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
43905706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
43915706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
43925706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
43935706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
4394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
4395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
4396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
4397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
4398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
4401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
4402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
4403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
4404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4406092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
4407092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
4408092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
4409092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
4410092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
4411092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
4412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
4413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
4414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
4415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
4416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
4419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
4422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
4423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
4425a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
4426e08950b4ce5a3f5d75a7279548f975cd6207dc74florian         *name = di->fsm.filename;
4427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
4428e08950b4ce5a3f5d75a7279548f975cd6207dc74florian         *name = "???";
4429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
4433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4435eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4436eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4437eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
4438eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4439