debuginfo.c revision 666ee9df4c2b6d801b199b8168208dbb46573c9d
1eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
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
120f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 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"
356c591e15c1d6402a2a755310f005f795b68e7e38sewardj#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
37b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
41eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
42b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
4313ac96dea734b3933a73524b991ac64fb48a4d57sewardj#include "pub_core_libcproc.h"   // VG_(getenv)
44d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
45eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
46b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
47eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
48b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
50b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
516882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
52f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
555d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj#include "priv_image.h"
56b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
57b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
60eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
63b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
64c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
67f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
69eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
716f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj/* Set this to 1 to enable debug printing for the
726f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   should-we-load-debuginfo-now? finite state machine. */
736f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj#define DEBUG_FSM 0
746f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
756f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
100c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
101f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
102f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
103c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
104c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
105c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
106eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
11020ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippestatic UInt CF_info_generation = 0;
1115c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void );
112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
114f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
116eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
117eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1791636d33c13958b9c0e7d3059cdd5005746418eb2florianDebugInfo* alloc_DebugInfo( const HChar* filename )
180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
183eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
184f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
185f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
187a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
188a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1896b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.maps     = VG_(newXA)(
1906b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_zalloc), "di.debuginfo.aDI.3",
1916b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_free), sizeof(struct _DebugInfoMapping));
192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
193452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
194452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
195f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1960f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
197f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
203f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
204f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
206eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
211eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
21259a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
2139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
21459a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
2176b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.maps)     VG_(deleteXA)(di->fsm.maps);
218a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
219f1e1aa691d7a2f0f2f933daf060bec5ae6938705philippe   if (di->soname)       ML_(dinfo_free)(di->soname);
220a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
22159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (di->loctab_fndn_ix) ML_(dinfo_free)(di->loctab_fndn_ix);
222a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di->inltab)       ML_(dinfo_free)(di->inltab);
2235c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_base)    ML_(dinfo_free)(di->cfsi_base);
2245c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_ix)    ML_(dinfo_free)(di->cfsi_m_ix);
2255c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)      ML_(dinfo_free)(di->cfsi_rd);
2265c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_m_pool)  VG_(deleteDedupPA)(di->cfsi_m_pool);
227a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
228a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
230a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
231a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
232a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
233a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
234a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
235a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
236a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
237a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
238a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
239a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
240a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
241a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
242a5cace0c2a3e212931badbf6398a0cd98393121asewardj
2432352e9843d8a616b9d829aef929d218aea9b4ae0philippe   if (di->strpool)
2442352e9843d8a616b9d829aef929d218aea9b4ae0philippe      VG_(deleteDedupPA) (di->strpool);
24559e1f3c79e870a978d24add86db6d8c5450c8b63philippe   if (di->fndnpool)
24659e1f3c79e870a978d24add86db6d8c5450c8b63philippe      VG_(deleteDedupPA) (di->fndnpool);
247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
25359a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
25759a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
26159a2d18d0ddfa241850017252b0804d469187d79sewardj
26259a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
26359a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
26459a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
26559a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
26659a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
26759a2d18d0ddfa241850017252b0804d469187d79sewardj      }
26859a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
26959a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
2927293d2530f8c60c1060f9f003e214cc341d35266philippe                  .strpool */
293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3136bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* reason = "munmap";
3144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
32133e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
32233e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
324738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
327a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
3281636d33c13958b9c0e7d3059cdd5005746418eb2florian                                            : "???",
3294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
33233e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
33333e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
348f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
350f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
352f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
376f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
379f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
380f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
388eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4046b5625bb609b154766d2e138b61e15655f60b710sewardj/* Do the basic mappings of the two DebugInfos overlap in any way? */
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4076b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
4106b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) {
4116b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i);
4126b5625bb609b154766d2e138b61e15655f60b710sewardj      for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
4136b5625bb609b154766d2e138b61e15655f60b710sewardj         struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
4146b5625bb609b154766d2e138b61e15655f60b710sewardj         if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size))
4156b5625bb609b154766d2e138b61e15655f60b710sewardj            return True;
4166b5625bb609b154766d2e138b61e15655f60b710sewardj      }
4176b5625bb609b154766d2e138b61e15655f60b710sewardj   }
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
4486b5625bb609b154766d2e138b61e15655f60b710sewardj   Clearly diRef must have its mapping information set to something sane. */
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4670f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4680f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4690f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
4701636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic DebugInfo* find_or_create_DebugInfo_for ( HChar* filename )
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
475a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
476a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4800f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
4966b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool has_nonempty_rx = False;
4976b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool cfsi_fits = False;
4986b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
503a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
504a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
5056b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
5066b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
5076b5625bb609b154766d2e138b61e15655f60b710sewardj      /* We are interested in r-x mappings only */
5086b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map->rx)
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5106b5625bb609b154766d2e138b61e15655f60b710sewardj
5116b5625bb609b154766d2e138b61e15655f60b710sewardj      /* degenerate case: r-x section is empty */
5126b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->size == 0)
513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5146b5625bb609b154766d2e138b61e15655f60b710sewardj      has_nonempty_rx = True;
5156b5625bb609b154766d2e138b61e15655f60b710sewardj
5166b5625bb609b154766d2e138b61e15655f60b710sewardj      /* normal case: r-x section is nonempty */
5176b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (0) */
5186b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(map->size > 0);
5196b5625bb609b154766d2e138b61e15655f60b710sewardj
5206b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (1) */
5216b5625bb609b154766d2e138b61e15655f60b710sewardj      for (di2 = debugInfo_list; di2; di2 = di2->next) {
5226b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di2 == di)
5236b5625bb609b154766d2e138b61e15655f60b710sewardj            continue;
5246b5625bb609b154766d2e138b61e15655f60b710sewardj         for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
5256b5625bb609b154766d2e138b61e15655f60b710sewardj            struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
5266b5625bb609b154766d2e138b61e15655f60b710sewardj            if (!map2->rx || map2->size == 0)
5276b5625bb609b154766d2e138b61e15655f60b710sewardj               continue;
5286b5625bb609b154766d2e138b61e15655f60b710sewardj            vg_assert(!ranges_overlap(map->avma,  map->size,
5296b5625bb609b154766d2e138b61e15655f60b710sewardj                                      map2->avma, map2->size));
5306b5625bb609b154766d2e138b61e15655f60b710sewardj         }
5316b5625bb609b154766d2e138b61e15655f60b710sewardj      }
5326b5625bb609b154766d2e138b61e15655f60b710sewardj      di2 = NULL;
5336b5625bb609b154766d2e138b61e15655f60b710sewardj
5346b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (2) */
5355c3dba227192de63d86f65ec7d9597c132818c37philippe      if (di->cfsi_rd) {
5366b5625bb609b154766d2e138b61e15655f60b710sewardj         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
5376b5625bb609b154766d2e138b61e15655f60b710sewardj         /* Assume the csfi fits completely into one individual mapping
5386b5625bb609b154766d2e138b61e15655f60b710sewardj            for now. This might need to be improved/reworked later. */
5396b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di->cfsi_minavma >= map->avma &&
5406b5625bb609b154766d2e138b61e15655f60b710sewardj             di->cfsi_maxavma <  map->avma + map->size)
5416b5625bb609b154766d2e138b61e15655f60b710sewardj            cfsi_fits = True;
5426b5625bb609b154766d2e138b61e15655f60b710sewardj      }
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5446b5625bb609b154766d2e138b61e15655f60b710sewardj
5456b5625bb609b154766d2e138b61e15655f60b710sewardj   /* degenerate case: all r-x sections are empty */
5466b5625bb609b154766d2e138b61e15655f60b710sewardj   if (!has_nonempty_rx) {
5475c3dba227192de63d86f65ec7d9597c132818c37philippe      vg_assert(di->cfsi_rd == NULL);
5486b5625bb609b154766d2e138b61e15655f60b710sewardj      return;
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5506b5625bb609b154766d2e138b61e15655f60b710sewardj
5516b5625bb609b154766d2e138b61e15655f60b710sewardj   /* invariant (2) - cont. */
5525c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd)
5536b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(cfsi_fits);
5546b5625bb609b154766d2e138b61e15655f60b710sewardj
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
5565c3dba227192de63d86f65ec7d9597c132818c37philippe   if (di->cfsi_rd) {
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
5605c3dba227192de63d86f65ec7d9597c132818c37philippe         DiCfSI* cfsi = &di->cfsi_rd[i];
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
5655c3dba227192de63d86f65ec7d9597c132818c37philippe            DiCfSI* cfsip = &di->cfsi_rd[i-1];
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
582f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
583f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
584f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
585f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
586f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
587f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
588f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
589f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
590f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
5915c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
592f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
593f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
594f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
6004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
602eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
603eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
604731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
605731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
606731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
607731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
608731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
609731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
610731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
611731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
612731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
613731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
614731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
615731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
616731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
617731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
618731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
619731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
620731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
621731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
622731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
623731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
624731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
625731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
626731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
627731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
628731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
629731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
630731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
631731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
632731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
6336b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges specified in the _DebugInfoFsm mapping array. First
6346b5625bb609b154766d2e138b61e15655f60b710sewardj      get rid of any other DebugInfos which overlap any of those
6356b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges (to avoid total confusion). */
636731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
637731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
638731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* .. and acquire new info. */
639731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGO_linux)
640731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
641731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
642731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
643731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
644731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
645731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
646731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
647731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
648731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
649731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
650731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
651731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
6525c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
653731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
654731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
6555c3dba227192de63d86f65ec7d9597c132818c37philippe      /* Check invariants listed in
6565c3dba227192de63d86f65ec7d9597c132818c37philippe         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
6575c3dba227192de63d86f65ec7d9597c132818c37philippe         priv_storage.h. */
6585c3dba227192de63d86f65ec7d9597c132818c37philippe      check_CFSI_related_invariants(di);
6595c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(finish_CFSI_arrays)(di);
660731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
661731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
662731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
663731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
664731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
665731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      tl_assert(di->handle > 0);
666731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
667731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
668731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
669731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
670731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
671731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
672731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
673731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
674731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
675731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
676731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
677731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
678731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
679731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
680731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
681731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
682731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
683731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
684731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
685731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
691eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
6929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
6939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
6945f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   If use_fd is not -1, that is used instead of the filename; this
6955f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   avoids perturbing fcntl locks, which are released by simply
6965f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   re-opening and closing the same file (even via different fd!).
6975f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
6989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
6999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
7009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
7019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
7029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
7039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7055f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
7074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
709731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
7115f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   Int        actual_fd, oflags;
7125f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   SysRes     preadres;
713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
7146f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool       debug = (DEBUG_FSM != 0);
715ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
716ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7185f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(use_fd >= -1);
7195f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7266f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug) {
7276f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-0:\n");
728a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
7326f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
733eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
7409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
7433e7986312a0ffc7646b0552d4c4ea3744a870e73florian   filename = VG_(am_get_filename)( seg );
744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
7459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7470ab84fe82d1e25c2e0544d08826df42caa44ded1bart   /*
7480ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * Cannot read from these magic files:
7490ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- WARNING: Serious error when reading debug info
7500ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- When reading debug info from /proc/xen/privcmd:
7510ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- can't read file to inspect ELF header
7520ab84fe82d1e25c2e0544d08826df42caa44ded1bart    */
7530ab84fe82d1e25c2e0544d08826df42caa44ded1bart   if (VG_(strncmp)(filename, "/proc/xen/", 10) == 0)
7540ab84fe82d1e25c2e0544d08826df42caa44ded1bart      return 0;
7550ab84fe82d1e25c2e0544d08826df42caa44ded1bart
756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
759ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
76015728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
761ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
762ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
763ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
7649c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
765ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
766ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
767ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
768cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
769ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
770ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
771e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
772ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
773a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
774ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
775ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
7769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
7772ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
7782ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
779ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
780ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
7819c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
7829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
783ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
784ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
78515728ab41ea41bf731dcc74ac68354550ced2189bart
786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
807eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
808eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
809eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
812eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
813eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
815eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
817eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
819f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
820f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
821f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
822b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
823b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
824b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
825b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
826b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
827b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
828b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
829b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
830b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
831eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
834731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
835731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
8364df0bfc0614379192c780c944415dc420d9cfe8epetarj#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
8374df0bfc0614379192c780c944415dc420d9cfe8epetarj      || defined(VGA_mips64)
838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
840cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le)  \
841cae0cc22b83ffb260ee8379e92099c5a701944cbcarll        || defined(VGA_arm) || defined(VGA_arm64)
842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
844b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
845b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
846b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
849eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
850eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
851588cd4ebce3305d0cf91896c1f6322ef9775d6c1sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS >= DARWIN_10_7
852731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
853731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
854731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
8566f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-3: "
8576f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  "is_rx_map %d, is_rw_map %d, is_ro_map %d\n",
8586f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  (Int)is_rx_map, (Int)is_rw_map, (Int)is_ro_map);
859eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
860731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
861731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
8629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
863eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8645a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
8655a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
8665a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
867cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
868cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
869cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
870cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
8715f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8725f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8735f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      SysRes fd = VG_(open)( filename, oflags, 0 );
8745f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      if (sr_isError(fd)) {
8755f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         if (sr_Err(fd) != VKI_EACCES) {
8765f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            DebugInfo fake_di;
8775f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            VG_(memset)(&fake_di, 0, sizeof(fake_di));
8785f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            fake_di.fsm.filename = filename;
8795f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            ML_(symerr)(&fake_di, True,
8805f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                        "can't open file to inspect ELF header");
8815f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         }
8825f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         return 0;
8835a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
8845f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = sr_Res(fd);
8855f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   } else {
8865f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = use_fd;
8875a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8885a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8895f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   preadres = VG_(pread)( actual_fd, buf1k, sizeof(buf1k), 0 );
8905f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8915f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      VG_(close)( actual_fd );
8925f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   }
8935f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8945f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_isError(preadres)) {
8955a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
8965a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
897a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      fake_di.fsm.filename = filename;
8985a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
8995a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
9005a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
9015f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_Res(preadres) == 0)
9025f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      return 0;
9035f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
9045a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
9058b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
9066e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
907f7c9714ea0cde18daaecb896278e85e780d3bd75sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
9085a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
9096e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
9105f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
911f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
9126e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
9136e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
9146e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
9155a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
9180f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
9216f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
9226f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_mmap-4: "
9236f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  "noting details in DebugInfo* at %p\n", di);
9246f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
9256b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Note the details about the mapping. */
9266b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping map;
9276b5625bb609b154766d2e138b61e15655f60b710sewardj   map.avma = a;
9286b5625bb609b154766d2e138b61e15655f60b710sewardj   map.size = seg->end + 1 - seg->start;
9296b5625bb609b154766d2e138b61e15655f60b710sewardj   map.foff = seg->offset;
9306b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rx   = is_rx_map;
9316b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rw   = is_rw_map;
9326b5625bb609b154766d2e138b61e15655f60b710sewardj   map.ro   = is_ro_map;
9336b5625bb609b154766d2e138b61e15655f60b710sewardj   VG_(addToXA)(di->fsm.maps, &map);
9346b5625bb609b154766d2e138b61e15655f60b710sewardj
9356b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Update flags about what kind of mappings we've already seen. */
9366b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rx_map |= is_rx_map;
9376b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rw_map |= is_rw_map;
9386b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_ro_map |= is_ro_map;
939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
940731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
941731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
942731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
943731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
944731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
9456f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
9466f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_mmap-5: "
9476f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "achieved accept state for %s\n", filename);
948731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
9499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
950731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
951731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
952731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
953731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
9549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
958eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
959eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
961eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
962f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
963a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
964f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
9665c3dba227192de63d86f65ec7d9597c132818c37philippe      cfsi_m_cache__invalidate();
967eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
968eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
969eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
970eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
971eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
972eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
973eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
975eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
976eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
977f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
978eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
979eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
980f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
981f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
982f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
9835c3dba227192de63d86f65ec7d9597c132818c37philippe         cfsi_m_cache__invalidate();
984f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
985eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
986eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
987731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
988588cd4ebce3305d0cf91896c1f6322ef9775d6c1sewardj/* This is a MacOSX >= 10.7 32-bit only special.  See comments on the
989731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
990731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
991731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
9926f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool debug = (DEBUG_FSM != 0);
9936f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
9946f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
9956f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
9966f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
9976f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug) {
9986f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-0:\n");
9996f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-1: %#lx-%#lx %c%c%c\n",
10006f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  a, a + len - 1,
10016f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                  r_ok ? 'r' : '-', w_ok ? 'w' : '-', x_ok ? 'x' : '-' );
10026f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
10036f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
1004731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
1005ec66ad5f33a4d904b1f728935ec6ee29b58a55ecsewardj#  if defined(VGP_x86_darwin) && (DARWIN_VERS >= DARWIN_10_7)
1006731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
1007731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
10086f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (do_nothing /* wrong platform */) {
10096f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
10106f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_vm_protect-2: wrong platform, "
10116f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "doing nothing.\n");
1012731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
10136f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   }
1014731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1015731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
1016731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
1017731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1018731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
1019731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
1020731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
1021731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
10226f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
10236f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      VG_(printf)("di_notify_vm_protect-3: looking for existing DebugInfo*\n");
1024731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
10256b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping *map = NULL;
10266b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
1027731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
1028731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
1029731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
1030731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
1031731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
1032731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
1033731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
1034731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
1035731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
1036731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
10376b5625bb609b154766d2e138b61e15655f60b710sewardj      /* Try to find a mapping matching the memory area. */
10386b5625bb609b154766d2e138b61e15655f60b710sewardj      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10396b5625bb609b154766d2e138b61e15655f60b710sewardj         map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10406b5625bb609b154766d2e138b61e15655f60b710sewardj         if (map->ro && map->avma == a && map->size == len)
10416b5625bb609b154766d2e138b61e15655f60b710sewardj            break;
10426b5625bb609b154766d2e138b61e15655f60b710sewardj         map = NULL;
10436b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10446b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map)
10456b5625bb609b154766d2e138b61e15655f60b710sewardj         continue; /* this isn't an upgrade of an r-- mapping */
1046731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
1047731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
1048731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
1049731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
1050731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
1051731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
10526f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj   if (debug)
10536f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj     VG_(printf)("di_notify_vm_protect-4: found existing DebugInfo* at %p\n",
10546f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                 di);
10556f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj
10566b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Do the upgrade.  Simply update the flags of the mapping
10576b5625bb609b154766d2e138b61e15655f60b710sewardj      and pretend we never saw the RO map at all. */
1058731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
10596b5625bb609b154766d2e138b61e15655f60b710sewardj   map->rx = True;
10606b5625bb609b154766d2e138b61e15655f60b710sewardj   map->ro = False;
1061731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
1062731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
10636b5625bb609b154766d2e138b61e15655f60b710sewardj   /* See if there are any more ro mappings */
10646b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10656b5625bb609b154766d2e138b61e15655f60b710sewardj      map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10666b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->ro) {
10676b5625bb609b154766d2e138b61e15655f60b710sewardj         di->fsm.have_ro_map = True;
10686b5625bb609b154766d2e138b61e15655f60b710sewardj         break;
10696b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10706b5625bb609b154766d2e138b61e15655f60b710sewardj   }
10716b5625bb609b154766d2e138b61e15655f60b710sewardj
10726b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Check if we're now in an accept state and read debuginfo.  Finally. */
10736b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
10746f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj      if (debug)
10756f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj         VG_(printf)("di_notify_vm_protect-5: "
10766f00ae96d4dcab1f35efe4cc875837089e6d8f72sewardj                     "achieved accept state for %s\n", di->fsm.filename);
10776b5625bb609b154766d2e138b61e15655f60b710sewardj      ULong di_handle __attribute__((unused))
10786b5625bb609b154766d2e138b61e15655f60b710sewardj         = di_notify_ACHIEVE_ACCEPT_STATE( di );
10796b5625bb609b154766d2e138b61e15655f60b710sewardj      /* di_handle is ignored. That's not a problem per se -- it just
10806b5625bb609b154766d2e138b61e15655f60b710sewardj         means nobody will ever be able to refer to this debuginfo by
10816b5625bb609b154766d2e138b61e15655f60b710sewardj         handle since nobody will know what the handle value is. */
10826b5625bb609b154766d2e138b61e15655f60b710sewardj   }
1083731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1084731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1085731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1086c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1087c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1088c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1089c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
109054c45db2f978055aeca91aaccb05aac825523e6csewardj                                   SizeT total_size, PtrdiffT bias_obj )
1091c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
109213ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1093c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
109454fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian   HChar  exename[VKI_PATH_MAX];
10951636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* pdbname = NULL;
10961636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* dot;
1097c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1098c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1099c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1100c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1101c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1102c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1103738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1104c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1105cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
110654c45db2f978055aeca91aaccb05aac825523e6csewardj         "bias=%#lx\n",
110754c45db2f978055aeca91aaccb05aac825523e6csewardj         fd_obj, avma_obj, total_size, bias_obj
1108c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1109c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1110c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1111c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1112c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1113c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1114c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1115c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
1116c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
11179c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1118c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1119c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
1120c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
1121c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
1122c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
1123c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
1124c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
1125c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
1126c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
1127c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
1128c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
1129c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
1130c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1131c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1132738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1133c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1134c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
113513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
113613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
113713ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
113813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
113913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
114013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
114113ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
114213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
114313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
114413ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
114513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
114613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
114713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
114813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
114913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
115013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
115113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
115213ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
115313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
115413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
115513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
115613ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
115713ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
115813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
115913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
116013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
116113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
116213ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
116313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
116413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
116513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
116698500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/drive_%c%s",
116798500e2ee5f63f9c0af57835f7620d30848115f4bart                       wpfx, pdbname[0], &pdbname[2]);
116813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
116913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
117013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
117113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
117213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
117313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
117413ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
117513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
117613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
117713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
117898500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/.wine/drive_%c%s",
117998500e2ee5f63f9c0af57835f7620d30848115f4bart		       home, pdbname[0], &pdbname[2]);
118013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
118113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
118213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
118313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
118413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
118513ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
118613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
118713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
118813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
118913ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1190c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
119113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
119213ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
119313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
119413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
119513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
119613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
119713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
119813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
119913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
120013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
120113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
120213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
120313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
120413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
120513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
120613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
120713ac96dea734b3933a73524b991ac64fb48a4d57sewardj
120813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
120913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
121013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
121113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
121213ac96dea734b3933a73524b991ac64fb48a4d57sewardj
121313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
121413ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1215c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1216c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1217c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1218cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1219738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1220c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1221c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1222738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1223c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1224c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
12259c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
12267138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1227ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
12287138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
12297138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
12307138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
12317138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
12327138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
12337138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
12347138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1235738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1236ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1237ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1238ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1239c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1240c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1241c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1242cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1243738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1246c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1247cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1248cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1249cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1250cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1251cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1252cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1253cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1254cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1255cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
12569c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1257cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1258cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1259cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1260cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1261cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1262cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1263cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1264cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1265cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1266cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1267cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1268c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1269c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1270c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1271c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1272cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1273cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1274cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1275cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1276cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1277cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1278cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1279cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1280c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1281738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1282c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1283c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1284c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
12855c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m_cache__invalidate();
1286c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1287c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1288c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12890f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1290c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1291c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1292a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1293c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1294c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1295c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1296c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
129754c45db2f978055aeca91aaccb05aac825523e6csewardj     ML_(read_pdb_debug_info)( di, avma_obj, bias_obj,
1298c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1299c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1300c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1301c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1302c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1303c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1304cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1305cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1306cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1307a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                 "%lu syms, %lu src locs, "
1308a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                 "%lu src locs, %lu fpo recs\n",
1309a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     di->symtab_used, di->loctab_used,
1310a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     di->inltab_used, di->fpo_size);
1311cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1312c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1313c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1314c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1315c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1316c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1317c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
13188b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
13194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
13204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
13279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
13289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
13299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
13309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
13319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
13329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
13339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
13349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
13359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
13369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
13379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
13389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
13399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
13406b5625bb609b154766d2e138b61e15655f60b710sewardjstruct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di,
13416b5625bb609b154766d2e138b61e15655f60b710sewardj                                                 Addr lo, Addr hi )
13426b5625bb609b154766d2e138b61e15655f60b710sewardj{
13436b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
13446b5625bb609b154766d2e138b61e15655f60b710sewardj   vg_assert(lo <= hi);
13456b5625bb609b154766d2e138b61e15655f60b710sewardj
13466b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Optimization: Try to use the last matched rx mapping first */
13476b5625bb609b154766d2e138b61e15655f60b710sewardj   if (   di->last_rx_map
13486b5625bb609b154766d2e138b61e15655f60b710sewardj       && lo >= di->last_rx_map->avma
13496b5625bb609b154766d2e138b61e15655f60b710sewardj       && hi <  di->last_rx_map->avma + di->last_rx_map->size)
13506b5625bb609b154766d2e138b61e15655f60b710sewardj      return di->last_rx_map;
13516b5625bb609b154766d2e138b61e15655f60b710sewardj
13526b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
13536b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
13546b5625bb609b154766d2e138b61e15655f60b710sewardj      if (   map->rx && map->size > 0
13556b5625bb609b154766d2e138b61e15655f60b710sewardj          && lo >= map->avma && hi < map->avma + map->size) {
13566b5625bb609b154766d2e138b61e15655f60b710sewardj         di->last_rx_map = map;
13576b5625bb609b154766d2e138b61e15655f60b710sewardj         return map;
13586b5625bb609b154766d2e138b61e15655f60b710sewardj      }
13596b5625bb609b154766d2e138b61e15655f60b710sewardj   }
13606b5625bb609b154766d2e138b61e15655f60b710sewardj
13616b5625bb609b154766d2e138b61e15655f60b710sewardj   return NULL;
13626b5625bb609b154766d2e138b61e15655f60b710sewardj}
13636b5625bb609b154766d2e138b61e15655f60b710sewardj
1364a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1365a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*--- Types and functions for inlined IP cursor            ---*/
1366a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/*------------------------------------------------------------*/
1367a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestruct _InlIPCursor {
1368a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Addr eip;             // Cursor used to describe calls at eip.
1369a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo* di;        // DebugInfo describing inlined calls at eip
1370a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1371a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_lopos; // The inlined fn calls covering eip are in
1372a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word    inltab_hipos; // di->inltab[inltab_lopos..inltab_hipos].
1373a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // Note that not all inlined fn calls in this range
1374a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // are necessarily covering eip.
1375a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1376a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Int   curlevel;       // Current level to describe.
1377a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // 0 means to describe eip itself.
1378a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  cur_inltab;     // inltab pos for call inlined at current level.
1379a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word  next_inltab;    // inltab pos for call inlined at next (towards main)
1380a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                         // level.
1381a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe};
1382a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1383a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Bool is_top(InlIPCursor *iipc)
1384a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1385a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->cur_inltab == -1;
1386a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1387a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1388a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Bool is_bottom(InlIPCursor *iipc)
1389a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1390a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return !iipc || iipc->next_inltab == -1;
1391a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1392a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1393a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeBool VG_(next_IIPC)(InlIPCursor *iipc)
1394a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1395a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word i;
1396a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DiInlLoc *hinl = NULL;
1397a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word hinl_pos = -1;
1398a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo *di;
1399a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1400a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc == NULL)
1401a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1402a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1403a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->curlevel <= 0) {
1404a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel--;
1405a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return False;
1406a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1407a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1408a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   di = iipc->di;
1409a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = iipc->inltab_lopos; i <= iipc->inltab_hipos; i++) {
1410a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= iipc->eip
1411a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && iipc->eip < di->inltab[i].addr_hi
1412a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && di->inltab[i].level < iipc->curlevel
1413a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe          && (!hinl || hinl->level < di->inltab[i].level)) {
1414a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl = &di->inltab[i];
1415a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         hinl_pos = i;
1416a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1417a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1418a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1419a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->cur_inltab = iipc->next_inltab;
1420a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   iipc->next_inltab = hinl_pos;
1421a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc->next_inltab < 0)
1422a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = 0; // no inlined call anymore, describe eip itself
1423a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   else
1424a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      iipc->curlevel = di->inltab[iipc->next_inltab].level;
1425a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1426a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return True;
1427a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1428a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1429a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Forward */
1430a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1431a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                           /*OUT*/Word* locno );
1432a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1433a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe/* Returns the position after which eip would be inserted in inltab.
1434a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (-1 if eip should be inserted before position 0).
1435a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   This is the highest position with an addr_lo <= eip.
1436a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   As inltab is sorted on addr_lo, dichotomic search can be done
1437a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   (note that inltab might have duplicates addr_lo). */
1438a0a73939b0398b6608fd6dbde49820ce6530d12cphilippestatic Word inltab_insert_pos (DebugInfo *di, Addr eip)
1439a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1440a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word mid,
1441a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        lo = 0,
1442a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        hi = di->inltab_used-1;
1443a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= hi) {
1444a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      mid      = (lo + hi) / 2;
1445a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo) { hi = mid-1; continue; }
1446a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip > di->inltab[mid].addr_lo) { lo = mid+1; continue; }
1447a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo = mid; break;
1448a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1449a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1450a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   while (lo <= di->inltab_used-1 && di->inltab[lo].addr_lo <= eip)
1451a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      lo++;
1452a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#if 0
1453a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (mid = 0; mid <= di->inltab_used-1; mid++)
1454a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (eip < di->inltab[mid].addr_lo)
1455a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1456a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (lo - 1 == mid - 1);
1457a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe#endif
1458a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return lo - 1;
1459a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1460a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1461a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeInlIPCursor* VG_(new_IIPC)(Addr eip)
1462a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1463a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   DebugInfo*  di;
1464a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        locno;
1465a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Word        i;
1466a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   InlIPCursor *ret;
1467a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool        avail;
1468a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1469a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (!VG_(clo_read_inline_info))
1470a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No way we can find inlined calls.
1471a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1472a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the DebugInfo for eip */
1473a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   search_all_loctabs ( eip, &di, &locno );
1474a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (di == NULL || di->inltab_used == 0)
1475a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No di (with inltab) containing eip.
1476a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1477a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* Search the entry in di->inltab with the highest addr_lo that
1478a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      contains eip. */
1479a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We start from the highest pos in inltab after which eip would
1480a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      be inserted. */
1481a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = inltab_insert_pos (di, eip); i >= 0; i--) {
1482a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo <= eip && eip < di->inltab[i].addr_hi) {
1483a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break;
1484a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      }
1485a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      /* Stop the backward scan when reaching an addr_lo which
1486a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         cannot anymore contain eip : we know that all ranges before
1487a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         i also cannot contain eip. */
1488a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1489a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         return NULL;
1490a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1491a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1492a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (i < 0)
1493a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return NULL; // No entry containing eip.
1494a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1495a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* We have found the highest entry containing eip.
1496a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      Build a cursor. */
1497a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret = ML_(dinfo_zalloc) ("dinfo.new_IIPC", sizeof(*ret));
1498a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->eip = eip;
1499a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->di = di;
1500a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_hipos = i;
1501a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   for (i = ret->inltab_hipos - 1; i >= 0; i--) {
1502a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1503a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      if (di->inltab[i].addr_lo < eip - di->maxinl_codesz)
1504a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         break; /* Similar stop backward scan logic as above. */
1505a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1506a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->inltab_lopos = i + 1;
1507a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->curlevel = MAX_LEVEL;
1508a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->cur_inltab = -1;
1509a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   ret->next_inltab = -1;
1510a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1511a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   /* MAX_LEVEL is higher than any stored level. We can use
1512a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(next_IIPC) to get to the 'real' first highest call level. */
1513a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   avail = VG_(next_IIPC) (ret);
1514a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (avail);
1515a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1516a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   return ret;
1517a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1518a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
1519a0a73939b0398b6608fd6dbde49820ce6530d12cphilippevoid VG_(delete_IIPC)(InlIPCursor *iipc)
1520a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe{
1521a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (iipc)
1522a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      ML_(dinfo_free)( iipc );
1523a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe}
1524a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
15256b5625bb609b154766d2e138b61e15655f60b710sewardj
1526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1527eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1534b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1541eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
154951c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
155051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
155151c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1552a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
15536b5625bb609b154766d2e138b61e15655f60b710sewardj                   && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL);
1554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
15685706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
15695706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
15705706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
15715706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
15725706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
15735706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
15745706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
15755706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
15765706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
15775706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
15785706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1588b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1589b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1594eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1595eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1596eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1600f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1602f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16065706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1610eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1611eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1613eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1614eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1615eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1616eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1618eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1620eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1621eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1622eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
16236b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
16246b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
16256b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1628eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
16296b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
16306b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
16311636d33c13958b9c0e7d3059cdd5005746418eb2florian                    Addr a, HChar* buf, Int nbuf,
1632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1633c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1634eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1636f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1637c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
16426882443ef154bca367bc591287de641e43a9e108njn
1643a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
16446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
1645a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   di->symtab[sno].pri_name, buf, nbuf );
16466b7611bf42a0fbb62e047d8c43b008205bd21e75njn
16476b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
16486b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
16496b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
16506b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
16516b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
16526b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
16536b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
16546b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
16556b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1656eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1658c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1660eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
16611636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar    buf2[12];
16621636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   symend = buf + VG_(strlen)(buf);
16631636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   end = buf + nbuf;
1664eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1665eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1666c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1667eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1670eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
16721636d33c13958b9c0e7d3059cdd5005746418eb2florian	 HChar *cp = buf2;
1673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
16776b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
16786b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1682cae0cc22b83ffb260ee8379e92099c5a701944cbcarll/* ppc64be-linux only: find the TOC pointer (R2 value) that should be in
1683eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1688f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1693eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
17011636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname) ( Addr a, HChar* buf, Int nbuf )
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
17036b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
17046b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
17056b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
17141636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_w_offset) ( Addr a, HChar* buf, Int nbuf )
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
17166b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
17176b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
17186b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
17281636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_if_entry) ( Addr a, HChar* buf, Int nbuf )
1729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
17306b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
17316b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
17326b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17396b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
17406b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
17416b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
17421636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf )
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
17446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
17456b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
17466b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
17546b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
17556b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
1756a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeBool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf,
1757a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                       InlIPCursor* iipc )
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1759a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
1760a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
1761a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
1762a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*below-main-renaming*/True,
1763a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            a, buf, nbuf,
1764a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*match_anywhere_in_fun*/True,
1765a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*show offset?*/False,
1766a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*text syms only*/True,
1767a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                            /*offsetP*/NULL );
1768a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
1769a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
1770a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
1771a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
1772a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
1773a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
1774a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(snprintf)(buf, nbuf, "%s", next_inl->inlinedfn);
1775a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      return True;
1776a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
1777eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1778eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17795db15403e889d4db339b342bc2a824ef0bfaa654sewardj/* mips-linux only: find the offset of current address. This is needed for
17805db15403e889d4db339b342bc2a824ef0bfaa654sewardj   stack unwinding for MIPS.
17815db15403e889d4db339b342bc2a824ef0bfaa654sewardj*/
17825db15403e889d4db339b342bc2a824ef0bfaa654sewardjBool VG_(get_inst_offset_in_function)( Addr a,
17835db15403e889d4db339b342bc2a824ef0bfaa654sewardj                                       /*OUT*/PtrdiffT* offset )
17845db15403e889d4db339b342bc2a824ef0bfaa654sewardj{
17851636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar fnname[64];
17865db15403e889d4db339b342bc2a824ef0bfaa654sewardj   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
17875db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*below-main-renaming*/False,
17885db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         a, fnname, 64,
17895db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*match_anywhere_in_sym*/True,
179081208182df4e8b9c8642affd6754996777ee7556florian                         /*show offset?*/False,
17914afac5b6f637d1cea82e62b3a280fa4e81101c05petarj                         /*text syms only*/True,
17925db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         offset );
17935db15403e889d4db339b342bc2a824ef0bfaa654sewardj}
17945db15403e889d4db339b342bc2a824ef0bfaa654sewardj
17951636d33c13958b9c0e7d3059cdd5005746418eb2florianVg_FnNameKind VG_(get_fnname_kind) ( HChar* name )
17966882443ef154bca367bc591287de641e43a9e108njn{
17976882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
17986882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
17996882443ef154bca367bc591287de641e43a9e108njn
18006882443ef154bca367bc591287de641e43a9e108njn   } else if (
18013026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
18026882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
18036882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
18043026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1805f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1806f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
18073026f71684a930286186aa10fef266c304672e8fsewardj#      else
18083026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
18093026f71684a930286186aa10fef266c304672e8fsewardj#      endif
18106882443ef154bca367bc591287de641e43a9e108njn       0) {
18116882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
18126882443ef154bca367bc591287de641e43a9e108njn
18136882443ef154bca367bc591287de641e43a9e108njn   } else {
18146882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
18156882443ef154bca367bc591287de641e43a9e108njn   }
18166882443ef154bca367bc591287de641e43a9e108njn}
18176882443ef154bca367bc591287de641e43a9e108njn
18186882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
18196882443ef154bca367bc591287de641e43a9e108njn{
18206882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
18216882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
18221636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar buf[50];
18236882443ef154bca367bc591287de641e43a9e108njn
18246882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
18257d995792542cf8e7f5a81248589445adfffeae30florian   // we're looking for won't be mangled.
18266b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
18276882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
18286882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
18296882443ef154bca367bc591287de641e43a9e108njn   } else {
18306882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
18316882443ef154bca367bc591287de641e43a9e108njn   }
18326882443ef154bca367bc591287de641e43a9e108njn}
18336882443ef154bca367bc591287de641e43a9e108njn
1834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1835b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1836b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
18391636d33c13958b9c0e7d3059cdd5005746418eb2florian                                  /*OUT*/HChar* dname, Int n_dname,
1840c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
18446b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
18456b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
18466b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
18601636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf )
1861eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1863f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1864f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
18654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
18667cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
18677cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
18705706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1873a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
18746625f7115ce012b84712770af22765c01f96ba44florian         buf[nbuf-1] = 0;
1875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
18787cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
18797cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
18807cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
18817cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
18827cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
18837cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
18847cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1885f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1886f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1887f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1888eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1889eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1890eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1892eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1893e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1894eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1895e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1897e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
19005706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1903e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1904e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1908eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
19121636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_filename)( Addr a, HChar* filename, Int n_filename )
1913eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1915f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
191659e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt       fndn_ix;
191759e1f3c79e870a978d24add86db6d8c5450c8b63philippe
1918eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1919eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1920eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
192159e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn_ix = ML_(fndn_ix) (si, locno);
1922666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   VG_(strncpy_safely)(filename,
1923666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                       ML_(fndn_ix2filename) (si, fndn_ix),
1924666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                       n_filename);
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1930eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1932f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
19451636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* filename, Int n_filename,
19461636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* dirname,  Int n_dirname,
1947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1951f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
195259e1f3c79e870a978d24add86db6d8c5450c8b63philippe   UInt       fndn_ix;
1953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1958eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1959c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1960db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1961db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1962db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1963db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1964eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1965c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1966c1b1d421216369aec58867ce1c5b99cfb1703c36njn
196759e1f3c79e870a978d24add86db6d8c5450c8b63philippe   fndn_ix = ML_(fndn_ix)(si, locno);
1968666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   VG_(strncpy_safely)(filename,
1969666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                       ML_(fndn_ix2filename) (si, fndn_ix),
1970666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                       n_filename);
1971eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1972eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1973eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1975eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1976666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      VG_(strncpy_safely)(dirname,
1977666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                          ML_(fndn_ix2dirname) (si, fndn_ix),
1978666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                          n_dirname);
1979666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      *dirname_available = *dirname != 0;
1980eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1981eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1982eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1984eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1985eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
19874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
19884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
19894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
19904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
19914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
19924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
19936bd9dc18c043927c1196caba20a327238a179c42florianBool VG_(lookup_symbol_SLOW)(const HChar* sopatt, HChar* name,
1994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
19954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
19964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
19974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
19994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
20004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
20014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
20024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
2003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
20044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
20054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
20064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
20074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
20084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
20094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
20104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
20114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
20121636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* pri_name = si->symtab[i].pri_name;
2013a5cace0c2a3e212931badbf6398a0cd98393121asewardj         tl_assert(pri_name);
2014a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
20154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
20164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
20174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
20184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
20194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
20201636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar** sec_names = si->symtab[i].sec_names;
2021a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
2022a5cace0c2a3e212931badbf6398a0cd98393121asewardj            tl_assert(sec_names[0]);
2023a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
2024a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
2025a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   && (require_pToc ? si->symtab[i].tocptr : True)) {
2026a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pEnt = si->symtab[i].addr;
2027a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pToc = si->symtab[i].tocptr;
2028a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
2029a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
2030a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
2031a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
2032a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
20334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
20344ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
20354ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
20364ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
20374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
20384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
2039e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
2040e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
2041e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
2042e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
2043e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
2044eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
20451636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStr ( Int n, Int n_buf, HChar* buf, const HChar* str )
2046eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2047e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
2048e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2049eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
2050eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
2051e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2052eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
2053eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
2054eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2055e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
2056e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
2057e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
2058e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
20591636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStrEsc ( Int n, Int n_buf, Int count, HChar* buf, HChar* str )
2060eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20611636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar alt[2];
2062e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
2063e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
2064e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2065eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
2066e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
2067e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
2068e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
2069eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
2070e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
2071e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
2072e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
2073e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
2074e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2075e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
2076e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
2077e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
2078e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
2079e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2080e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
2081e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
2082e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
2083e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
2084e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2085e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
2086e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
2087e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
2088e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
2089e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
2090e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
2091e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
2092eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2093eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2094e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
2095e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
2096e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
2097eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
2098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2099eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2100a0a73939b0398b6608fd6dbde49820ce6530d12cphilippeHChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf, InlIPCursor *iipc)
2101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
2103e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
2104e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
2105e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
2106eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
2107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2108eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
21091636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar ibuf[50];
2110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
211114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2112a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert (!iipc || iipc->eip == eip);
2113a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
21141636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_fn[BUF_LEN];
21151636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_obj[BUF_LEN];
21161636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_srcloc[BUF_LEN];
21171636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_dirname[BUF_LEN];
211814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
211914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2120eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
2121a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_fnname;
2122a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_objname;
2123a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   Bool  know_srcloc;
2124a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2125a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_bottom(iipc)) {
2126a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // At the bottom (towards main), we describe the fn at eip.
2127a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = VG_(clo_sym_offsets)
2128a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                    ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
2129a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                    : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
2130a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2131a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *next_inl = iipc && iipc->next_inltab >= 0
2132a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->next_inltab]
2133a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2134a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (next_inl);
2135a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The function we are in is called by next_inl.
2136a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      VG_(snprintf)(buf_fn, BUF_LEN, "%s", next_inl->inlinedfn);
2137a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_fnname = True;
2138a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2139a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // INLINED????
2140a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Can we compute an offset for an inlined fn call ?
2141a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Offset from what ? The beginning of the inl info ?
2142a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? But that is not necessarily the beginning of the fn
2143a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? as e.g. an inlined fn call can be in several ranges.
2144a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // ??? Currently never showing an offset.
2145a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2146a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2147a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
2148a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2149a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   if (is_top(iipc)) {
2150a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      // The source for the highest level is in the loctab entry.
2151a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc  = VG_(get_filename_linenum)(
2152a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        eip,
2153a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        buf_srcloc,  BUF_LEN,
2154a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        buf_dirname, BUF_LEN, &know_dirinfo,
2155a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                        &lineno
2156a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                     );
2157a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   } else {
2158a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      const DiInlLoc *cur_inl = iipc && iipc->cur_inltab >= 0
2159a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         ? & iipc->di->inltab[iipc->cur_inltab]
2160a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe         : NULL;
2161a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      vg_assert (cur_inl);
2162a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
216359e1f3c79e870a978d24add86db6d8c5450c8b63philippe      know_dirinfo = False;
2164666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      // The fndn_ix and lineno for the caller of the inlined fn is in cur_inl.
2165666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      if (cur_inl->fndn_ix == 0) {
2166666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         VG_(snprintf) (buf_srcloc, BUF_LEN, "???");
2167666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      } else {
2168666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         FnDn *fndn = VG_(indexEltNumber) (iipc->di->fndnpool,
2169666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                                           cur_inl->fndn_ix);
2170666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         if (fndn->dirname) {
2171666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe            VG_(snprintf) (buf_dirname, BUF_LEN, "%s", fndn->dirname);
2172666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe            know_dirinfo = True;
2173666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         }
2174666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe         VG_(snprintf) (buf_srcloc, BUF_LEN, "%s", fndn->filename);
2175666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      }
2176666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe      lineno = cur_inl->lineno;
2177a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      know_srcloc = True;
2178a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   }
2179a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
2180a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe
218114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
218214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
218314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
218414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
218514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
2186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
2187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2188eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
21896bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline  = human_readable ? "\n      " : "";
21906bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline2 = human_readable ? "\n    "   : "";
2191eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2192e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
2193e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
2194e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
2195e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
2196e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
2197e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
2198eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
2199a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
2200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
2201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
2202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
2203eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
2205e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
2206eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
2207eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
2209eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2210eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
2211e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
2212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
2213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2214eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
2216eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
2217eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
2218e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
2219eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
2220eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
2221eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2222eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
2223e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
2224eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
2225eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
2226eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
2227eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2228eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2229eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
2230eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2231eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
2232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
2233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2234eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
2235eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
22375e40abad4504416c59f0b29c1cfc8087201213a9njn      //
22385e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
22395e40abad4504416c59f0b29c1cfc8087201213a9njn      //
22405e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
22415e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
22425e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
22435e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
22445e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
22455e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
22465e40abad4504416c59f0b29c1cfc8087201213a9njn      //
2247a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
2248eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
22495e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
2250eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
2251eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
2252eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
2253eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2254eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
2255eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
225614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
22571636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* dirname = NULL;
225814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
225914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
226014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
226114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
226214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
226314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
226414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
22651636d33c13958b9c0e7d3059cdd5005746418eb2florian               const HChar* prefix = VG_(clo_fullpath_after)[i];
22661636d33c13958b9c0e7d3059cdd5005746418eb2florian               HChar* str    = VG_(strstr)(dirname, prefix);
226714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
226814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
226914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
227014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
227114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
227214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
227314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
227414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
227514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
227614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
227714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
227814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
227914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
228014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
22815dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
2282eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
2283eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
2284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
22875e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
22885e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
22895e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
22905e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
22915e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
22925e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
22935e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
22945e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
2295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
2299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
2301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
2302eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
2303eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
230572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
2310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
231272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
231372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
231472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
231572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
231672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
23173026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
23183026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
23193026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
232072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
232172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
232272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
232372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
232472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
232572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
2326f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
2327f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
232872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
232972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
233072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
233140628facff2285b0fce592381c6e26fdcd2a1252tom   UWord w, wL, wR;
233219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
23333026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
23343026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
23353026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
233672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
233740628facff2285b0fce592381c6e26fdcd2a1252tom      case Cex_Unop:
233840628facff2285b0fce592381c6e26fdcd2a1252tom         w = evalCfiExpr( exprs, e->Cex.Unop.ix, eec, ok );
233940628facff2285b0fce592381c6e26fdcd2a1252tom         if (!(*ok)) return 0;
234040628facff2285b0fce592381c6e26fdcd2a1252tom         switch (e->Cex.Unop.op) {
234140628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Abs: return (Word) w < 0 ? - w : w;
234240628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Neg: return - (Word) w;
234340628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Not: return ~ w;
234440628facff2285b0fce592381c6e26fdcd2a1252tom            default: goto unhandled;
234540628facff2285b0fce592381c6e26fdcd2a1252tom         }
234640628facff2285b0fce592381c6e26fdcd2a1252tom         /*NOTREACHED*/
234772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
234872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
234972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
235072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
235172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
235272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
2353f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Add: return wL + wR;
2354f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Sub: return wL - wR;
2355f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_And: return wL & wR;
2356f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Mul: return wL * wR;
2357f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shl: return wL << wR;
2358f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shr: return wL >> wR;
2359f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Eq: return wL == wR ? 1 : 0;
2360f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2361f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2362f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2363f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
2364f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ne: return wL != wR ? 1 : 0;
236572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
236672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
236772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
236872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
236972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
23703026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
23713026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
23723026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
23733026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
23743026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
23753026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
23763026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2377fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2378fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2379ade2eddf567a868bafad9110ed92acf7373a972bsewardj            case Creg_ARM_R7:  return eec->uregs->r7;
2380b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2381b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
2382b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
2383b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
2384b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
23854df0bfc0614379192c780c944415dc420d9cfe8epetarj#           elif defined(VGA_mips32) || defined(VGA_mips64)
23865db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_IP: return eec->uregs->pc;
23875db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_SP: return eec->uregs->sp;
23885db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_BP: return eec->uregs->fp;
23895db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_MIPS_RA: return eec->uregs->ra;
2390cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#           elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
2391cae0cc22b83ffb260ee8379e92099c5a701944cbcarll               || defined(VGA_ppc64le)
2392f0c1250e324f6684757c6a15545366447ef1d64fsewardj#           elif defined(VGP_arm64_linux)
2393821283b2110420321fd3f60afcc799b287788c68sewardj            case Creg_ARM64_X30: return eec->uregs->x30;
23943026f71684a930286186aa10fef266c304672e8fsewardj#           else
23953026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
23963026f71684a930286186aa10fef266c304672e8fsewardj#           endif
239772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
239872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
239972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
240072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
240172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
240219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
240319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
240419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
240519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
2406720e6b71b171885281afab634ce4d667c1f262bcsewardj             || a > eec->max_accessible - sizeof(UWord) + 1) {
240719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
240819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
240919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
241019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
241186781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
241272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
241372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
241472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
241572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
241672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
241772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
241872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
241972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
242072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
242172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
242272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
242372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
242472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
242572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
24265c3dba227192de63d86f65ec7d9597c132818c37philippe/* Search all the DebugInfos in the entire system, to find the DiCfSI_m
2427f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2428eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2429f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
24305c3dba227192de63d86f65ec7d9597c132818c37philippe   *cfsi_mP to the cfsi_m pointer in that DebugInfo's cfsi_m_pool.
243172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
24325c3dba227192de63d86f65ec7d9597c132818c37philippe   If not found, set *diP to (DebugInfo*)1 and *cfsi_mP to zero.
2433f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2434f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2435f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
24365c3dba227192de63d86f65ec7d9597c132818c37philippe                          /*OUT*/DiCfSI_m** cfsi_mP,
2437f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2438f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2439f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2440f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2441f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2442f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2443f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2444eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2445eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2446f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2447eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2448f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2449f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2450eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2451eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2454f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2455eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2456f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2457eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2459f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2460f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2461f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2462f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2463f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2464f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2465f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2467eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2468eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2469f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2470f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2471f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2472f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
24735c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = 0;
2474f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2475f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2476f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24775c3dba227192de63d86f65ec7d9597c132818c37philippe      /* found a di corresponding to ip. */
2478f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2479f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
24815c3dba227192de63d86f65ec7d9597c132818c37philippe      *cfsi_mP = ML_(get_cfsi_m) (di, i);
24825c3dba227192de63d86f65ec7d9597c132818c37philippe      if (*cfsi_mP == NULL) {
24835c3dba227192de63d86f65ec7d9597c132818c37philippe         // This is a cfsi hole. Report no cfi information found.
24845c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = (DebugInfo*)1;
24855c3dba227192de63d86f65ec7d9597c132818c37philippe         // But we will still perform the hack below.
24865c3dba227192de63d86f65ec7d9597c132818c37philippe      } else {
24875c3dba227192de63d86f65ec7d9597c132818c37philippe         *diP = di;
24885c3dba227192de63d86f65ec7d9597c132818c37philippe      }
2489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2505f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2510f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2512f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2513f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2514f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2515f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25165c3dba227192de63d86f65ec7d9597c132818c37philippe   Each cache entry binds an ip value to a (di, cfsi_m*) pair.  Possible
2517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25195c3dba227192de63d86f65ec7d9597c132818c37philippe   di is non-null, cfsi_m* >= 0  ==>  cache slot in use, "cfsi_m*"
25205c3dba227192de63d86f65ec7d9597c132818c37philippe   di is (DebugInfo*)1           ==>  cache slot in use, no associated di
25215c3dba227192de63d86f65ec7d9597c132818c37philippe   di is NULL                    ==>  cache slot not in use
2522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25265c3dba227192de63d86f65ec7d9597c132818c37philippe   We can map an ip value directly to a (di, cfsi_m*) pair as
25275c3dba227192de63d86f65ec7d9597c132818c37philippe   once a DebugInfo is read, adding new DiCfSI_m* is not possible
25285c3dba227192de63d86f65ec7d9597c132818c37philippe   anymore, as the cfsi_m_pool is frozen once the reading is terminated.
25295c3dba227192de63d86f65ec7d9597c132818c37philippe   Also, the cache is invalidated when new debuginfo is read due to
25305c3dba227192de63d86f65ec7d9597c132818c37philippe   an mmap or some debuginfo is discarded due to an munmap. */
2531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25325c3dba227192de63d86f65ec7d9597c132818c37philippe// Prime number, giving about 6Kbytes cache on 32 bits,
25335c3dba227192de63d86f65ec7d9597c132818c37philippe//                           12Kbytes cache on 64 bits.
25345c3dba227192de63d86f65ec7d9597c132818c37philippe#define N_CFSI_M_CACHE 509
2535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
25375c3dba227192de63d86f65ec7d9597c132818c37philippe   struct { Addr ip; DebugInfo* di; DiCfSI_m* cfsi_m; }
25385c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt;
2539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25405c3dba227192de63d86f65ec7d9597c132818c37philippestatic CFSI_m_CacheEnt cfsi_m_cache[N_CFSI_M_CACHE];
2541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25425c3dba227192de63d86f65ec7d9597c132818c37philippestatic void cfsi_m_cache__invalidate ( void ) {
25435c3dba227192de63d86f65ec7d9597c132818c37philippe   VG_(memset)(&cfsi_m_cache, 0, sizeof(cfsi_m_cache));
254420ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   CF_info_generation++;
2545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
254720ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippeUInt VG_(CF_info_generation) (void)
254820ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe{
254920ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   return CF_info_generation;
255020ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe}
2551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25525c3dba227192de63d86f65ec7d9597c132818c37philippestatic inline CFSI_m_CacheEnt* cfsi_m_cache__find ( Addr ip )
2553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
25545c3dba227192de63d86f65ec7d9597c132818c37philippe   UWord         hash = ip % N_CFSI_M_CACHE;
25555c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce = &cfsi_m_cache[hash];
25563c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
25623c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
25633c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
25643c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
25653c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
25663c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
25673c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
25685c3dba227192de63d86f65ec7d9597c132818c37philippe      find_DiCfSI( &ce->di, &ce->cfsi_m, ip );
25693c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25713c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
25723c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
25733c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
25743c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
25753c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
25763c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2577eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
25783c9cf3442185b5891e15450d6e3058aeff6796fetom}
2579eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2581f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
25823026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
25833c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
25845c3dba227192de63d86f65ec7d9597c132818c37philippe                          DebugInfo* di, DiCfSI_m* cfsi_m )
25853c9cf3442185b5891e15450d6e3058aeff6796fetom{
25863c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
25873c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
25883c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25903c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
259172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
25925c3dba227192de63d86f65ec7d9597c132818c37philippe   switch (cfsi_m->cfa_how) {
25933026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
25943026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
25955c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xsp;
25963026f71684a930286186aa10fef266c304672e8fsewardj         break;
25973026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
25985c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->xbp;
259972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
26003026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
26013026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
26025c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r13;
260372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
26043026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
26055c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r12;
26063026f71684a930286186aa10fef266c304672e8fsewardj         break;
26073026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
26085c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r11;
26093026f71684a930286186aa10fef266c304672e8fsewardj         break;
2610fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
26115c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->r7;
2612fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2613b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2614b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
26155c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2616b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2617b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2618b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
26195c3dba227192de63d86f65ec7d9597c132818c37philippe         Addr a = uregs->sp + cfsi_m->cfa_off;
2620b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2621b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
262286781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2623b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2624b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2625b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2626b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2627b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2628b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
26295c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
2630b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
26314df0bfc0614379192c780c944415dc420d9cfe8epetarj#     elif defined(VGA_mips32) || defined(VGA_mips64)
26325db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_SPREL:
26335c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
26345db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
26355db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIR_SAME:
26365db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = uregs->fp;
26375db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
26385db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_BPREL:
26395c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->fp;
26405db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
2641cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#     elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2642f0c1250e324f6684757c6a15545366447ef1d64fsewardj#     elif defined(VGP_arm64_linux)
2643821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_SPREL:
26445c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->sp;
2645821283b2110420321fd3f60afcc799b287788c68sewardj         break;
2646821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_X29REL:
26475c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = cfsi_m->cfa_off + uregs->x29;
2648821283b2110420321fd3f60afcc799b287788c68sewardj         break;
26493026f71684a930286186aa10fef266c304672e8fsewardj#     else
26503026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
26513026f71684a930286186aa10fef266c304672e8fsewardj#     endif
26523026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
26537888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
26547888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
26555c3dba227192de63d86f65ec7d9597c132818c37philippe            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi_m->cfa_off);
26567888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
26577888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
26583026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
26597888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
26607888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
26617888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
26625c3dba227192de63d86f65ec7d9597c132818c37philippe         cfa = evalCfiExpr(di->cfsi_exprs, cfsi_m->cfa_off, &eec, &ok );
26633c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
266472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
266572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
266672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
266772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
26683c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
26693c9cf3442185b5891e15450d6e3058aeff6796fetom}
26703c9cf3442185b5891e15450d6e3058aeff6796fetom
26713c9cf3442185b5891e15450d6e3058aeff6796fetom
26723c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
26733026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
26743026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
26753c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
26763c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
26773c9cf3442185b5891e15450d6e3058aeff6796fetom{
26785c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt* ce;
26793c9cf3442185b5891e15450d6e3058aeff6796fetom
26805c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ip);
26813c9cf3442185b5891e15450d6e3058aeff6796fetom
26823c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
26833c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
26843c9cf3442185b5891e15450d6e3058aeff6796fetom
26853026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
26863026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
26873026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
26883026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
26893026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
26903026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
26913026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
26923026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
269305c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
26943026f71684a930286186aa10fef266c304672e8fsewardj   }
2695b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2696b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2697b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2698b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2699b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2700b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
270105c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2702b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2703f03d0b76228354fb63eb970a4e6c9fa1337d60a9dejanj#elif defined(VGA_mips32) || defined(VGA_mips64)
2704fe0b43315c344cfd07981a0826bc34614a220169dejanj   { D3UnwindRegs uregs;
2705fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.pc = ip;
2706fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.sp = sp;
2707fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.fp = fp;
2708fe0b43315c344cfd07981a0826bc34614a220169dejanj     return compute_cfa(&uregs,
270905c459ea63c50a072cf1eb0868590e9c0b362f30philippe                        min_accessible,  max_accessible, ce->di, ce->cfsi_m);
2710fe0b43315c344cfd07981a0826bc34614a220169dejanj   }
2711b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
27123026f71684a930286186aa10fef266c304672e8fsewardj#  else
27133026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
27143026f71684a930286186aa10fef266c304672e8fsewardj#  endif
27153c9cf3442185b5891e15450d6e3058aeff6796fetom}
27163c9cf3442185b5891e15450d6e3058aeff6796fetom
27173c9cf3442185b5891e15450d6e3058aeff6796fetom
27183026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
27193026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
27203026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
27213026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
27223026f71684a930286186aa10fef266c304672e8fsewardj
27233026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
27243026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
27253026f71684a930286186aa10fef266c304672e8fsewardj
2726fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
2727821283b2110420321fd3f60afcc799b287788c68sewardj
2728821283b2110420321fd3f60afcc799b287788c68sewardj   For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
27293026f71684a930286186aa10fef266c304672e8fsewardj*/
27303026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
27313c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
27323c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
27333c9cf3442185b5891e15450d6e3058aeff6796fetom{
27343c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
27355c3dba227192de63d86f65ec7d9597c132818c37philippe   DiCfSI_m*          cfsi_m = NULL;
27363026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
27375c3dba227192de63d86f65ec7d9597c132818c37philippe   CFSI_m_CacheEnt*   ce;
2738d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
27393026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
27403c9cf3442185b5891e15450d6e3058aeff6796fetom
27413026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
27423026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
27433026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
27443026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2745b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2746b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
27474df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
27485db15403e889d4db339b342bc2a824ef0bfaa654sewardj   ipHere = uregsHere->pc;
2749cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2750f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
2751821283b2110420321fd3f60afcc799b287788c68sewardj   ipHere = uregsHere->pc;
27523026f71684a930286186aa10fef266c304672e8fsewardj#  else
27533026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
27543026f71684a930286186aa10fef266c304672e8fsewardj#  endif
27555c3dba227192de63d86f65ec7d9597c132818c37philippe   ce = cfsi_m_cache__find(ipHere);
27563c9cf3442185b5891e15450d6e3058aeff6796fetom
27573c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
27583c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
27593c9cf3442185b5891e15450d6e3058aeff6796fetom
27603c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
27615c3dba227192de63d86f65ec7d9597c132818c37philippe   cfsi_m = ce->cfsi_m;
27623c9cf3442185b5891e15450d6e3058aeff6796fetom
27633c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
27645c3dba227192de63d86f65ec7d9597c132818c37philippe      VG_(printf)("found cfsi_m (but printing fake base/len): ");
27655c3dba227192de63d86f65ec7d9597c132818c37philippe      ML_(ppDiCfSI)(di->cfsi_exprs, 0, 0, cfsi_m);
27663c9cf3442185b5891e15450d6e3058aeff6796fetom   }
27673c9cf3442185b5891e15450d6e3058aeff6796fetom
2768f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
27693c9cf3442185b5891e15450d6e3058aeff6796fetom
27703c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
27713026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
27725c3dba227192de63d86f65ec7d9597c132818c37philippe                     min_accessible, max_accessible, di, cfsi_m);
27733c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
27743c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
277572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
277672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
277772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2778eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2779eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2780eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
27899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
279186781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2795eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
279772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
279872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2799f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
28003026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
280172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
280272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2803d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2804f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
280572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
280672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
280772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
280872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2809eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
28123026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
28135c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi_m->ra_how, cfsi_m->ra_off);
28145c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi_m->sp_how, cfsi_m->sp_off);
28155c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi_m->bp_how, cfsi_m->bp_off);
28163026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
28175c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi_m->ra_how,  cfsi_m->ra_off);
28185c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi_m->r14_how, cfsi_m->r14_off);
28195c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi_m->r13_how, cfsi_m->r13_off);
28205c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi_m->r12_how, cfsi_m->r12_off);
28215c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi_m->r11_how, cfsi_m->r11_off);
28225c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi_m->r7_how,  cfsi_m->r7_off);
2823b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
28245c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi_m->ra_how, cfsi_m->ra_off);
28255c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
28265c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
28274df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
28285c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi_m->ra_how, cfsi_m->ra_off);
28295c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
28305c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
2831cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#  elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
2832f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
28335c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.pc,  uregsHere->pc,  cfsi_m->ra_how,  cfsi_m->ra_off);
28345c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.sp,  uregsHere->sp,  cfsi_m->sp_how,  cfsi_m->sp_off);
28355c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off);
28365c3dba227192de63d86f65ec7d9597c132818c37philippe   COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off);
28373026f71684a930286186aa10fef266c304672e8fsewardj#  else
28383026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
28393026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2841eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
28433026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2844eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2845eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2846eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2850c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2851c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2852c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2853c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2854c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2855c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2856c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2857c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2858c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2859c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2860c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2861c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2862c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2863c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2864c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2865c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2866c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2867c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2868c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2869c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2870c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2871c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2872c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2873c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2874c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2875c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2876c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2877c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2878c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2879c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2880c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2881c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2882c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2883c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2884c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2885c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2886c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2887c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2888c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2889c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2890c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2891c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2892c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2893c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2894c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2895c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2896c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2897c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2898c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2899c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2900c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2901c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2902c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2903c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2904c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2905c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2906c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2907c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2908c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2909c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2910c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2911c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2912c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2913c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2914c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2915c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2916c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2917c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2918c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2919c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2920c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2921c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2922c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2923c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2924c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2925c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2926c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2927c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2928c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2929c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2930c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2931c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2932c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2933c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2934c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2935c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2936c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2937c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2938c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2939c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2940c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2941c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2942c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2943c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2944c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2945c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2946c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2947c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2948c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2949c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2950c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2951c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2952c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2953c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2954c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2955c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2956c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2957c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2958c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2959c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2960c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2961c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
296286781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
296386781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
296486781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
296586781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
2966c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2967c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2968c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2969c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2970c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2971c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2977588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2978b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   VG_(xaprintf)(dst, fmt, args) without having to resort to
2979588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2980588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2981738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2982588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2983b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   //   VG_(xaprintf)(dstxa, format, ##args)
2984738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2985b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart#define  p2XA  VG_(xaprintf)
2986738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2987588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2988588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2989738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2990738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2991738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2992738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2993738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2994738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2995738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
3001c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
30029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
3006588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
300850fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
3011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
30129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
3014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
301750fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
301850fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
301950fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
302050fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
302150fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
302250fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
302350fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
302450fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
302550fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
302650fde23467d92281b32dd537d0d9a590263628c3sewardj
302750fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
3028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
3030a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
30329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
3033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
3034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
3037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
3038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
3039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
3040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3043588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
3046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
3047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
3048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
3049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3050eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
30513c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
3052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
3053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
3054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
3055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
3056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
3057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3062738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
3063738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
3064738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
3065738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
3066738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
3067738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
3068738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
3069738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
3070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
3071666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                             DebugInfo* di,
3072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
3073c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
3074c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
3075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
3076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
3077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
3078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3079738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
3080738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
30811636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* vo_plural = var_offset == 1 ? "" : "s";
30821636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* ro_plural = residual_offset == 1 ? "" : "s";
30831636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* basetag   = "auxwhat"; /* a constant */
30841636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar tagL[32], tagR[32], xagL[32], xagR[32];
3085666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   const HChar *fileName = ML_(fndn_ix2filename)(di, var->fndn_ix);
3086666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   // fileName will be "???" if var->fndn_ix == 0.
3087666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   // fileName will only be used if have_descr is True.
3088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3089d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
3090d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
3091d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3092d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
3093d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
3094d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3095d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
3096d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
3097d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
3098d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
3099738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
3100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
3101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
3102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
3103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
3104666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe   have_srcloc = var->fndn_ix > 0 && var->lineNo > 0;
3105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3106738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
3107738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
3108738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
3109738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
3110738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
3111738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
3112738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
3113738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3114738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
3115738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
3116738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
3117738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
3118738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
3119738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
3120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
3122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
3126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3128738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3129738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3130738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3131b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\",",
3132738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3133738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3134738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3135738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3136738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3137738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3138738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3139738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3140738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
3141738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3142738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3143738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3144738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
3148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
3150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
3151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3152738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3153738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3154738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3155b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\"",
3156738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3157738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3158738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3159738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3160738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3161b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
3162666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo, frameNo, (Int)tid );
3163738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3164738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3165738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3166b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3167666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3168738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3169738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3170738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3171738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
3172738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3173738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3174738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
3175666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo, frameNo, (Int)tid );
3176738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
3180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
3183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3184738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3185738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3186738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3187b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS",
3188738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3189738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3190738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3191738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3192738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3193738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3194738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3195738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3196738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3197738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
3198738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3199738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3200738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3201738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
3202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
3206738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3207738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
3208738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3209738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3210738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3211b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3212738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3213738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3214738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3215738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3216738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3217738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3218b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
3219666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo, frameNo, (Int)tid );
3220738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3221738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3222738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3223b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3224666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3225738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3226738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3227738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3228738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3229738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3230738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3231738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3232738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
3233666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo, frameNo, (Int)tid );
3234738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
3238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
3239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
3240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3242738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3243738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3244738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3245b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
3246738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3247738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3248738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3249738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3250738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
3251738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3252738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
3256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
3257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
3258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
3259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3260738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3261738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3262738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3263b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
3264738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3265738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3266738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3267738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3268738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3269b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d",
3270666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3271738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3272738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3273738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3274b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3275666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3276738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3277738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3278738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3279738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
3280738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3281738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3282738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
3283666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3284738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
3288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
3291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3292738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3293738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3294738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3295b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3296738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3297738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3298738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3299738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3300738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3301738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3302738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3303738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3304738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3305738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3306738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3307738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
3308738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3309738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3310738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
3314738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3315738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
3316738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3317738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3318738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3319b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3320738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3321738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3322738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3323738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3324738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3325738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3326b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "a global variable declared at %pS:%d",
3327666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3328738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3329738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3330738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3331b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3332666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo );
3333738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3334738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3335738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3336738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3337738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3338738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3339738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3340738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
3341666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe               fileName, var->lineNo);
3342738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
3346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3347738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
3348738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
3349738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
3350738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3351738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
3352738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
3353738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
3354738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
3355738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
3356738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
3357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3359738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
3361738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
3362738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
3363738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
3364738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
3365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
3366738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
3367738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
3368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
3369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
3370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
3371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
3372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
3374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
3376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
3377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
3379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
3380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
3381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
3382a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
3383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
3384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
3385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
3386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
3390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
3391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
3395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
3396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
3397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
3398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
3401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
3402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
3403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
3404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
3405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
3406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
3407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
3408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
3409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
3410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
3411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
3413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
3415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3462b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3463b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3464c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3466a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
34689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
34699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3470588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3471c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
34739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
34749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3475738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3476666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                            data_addr, di, var, offset, residual_offset,
3477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3487738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
348825963376a3669e7f77395d6f884bdf1f6a928966philippe   debug info we have.  This considers all global variables, and 8
3489738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3490738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3491738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3492738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3493738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3494738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3495738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3496738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3497738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3498738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3499738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3500738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
3501738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
3502738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
3503738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3504738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3505eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3506b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3515b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3516738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
3517738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
3518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3519a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
35269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3528b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3530b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3531b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3534b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3536b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3537b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3547b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3550b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3551b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3567c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
35769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3578588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3579c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
35819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
35829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3583738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3584666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                            data_addr, di, var, offset, residual_offset,
3585d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3586d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3588738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3589738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3590b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3594b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3596b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3600b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3607b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3612738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3613738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3622b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3625738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3627b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3629738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3630738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3647b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3648b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3649b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3650b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3651b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3652738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3653b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3654b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3655b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3656738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3657738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3663738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3664738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3667eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
36709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
36719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
36729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
36739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
36749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
36759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
36779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
36789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
36799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
36809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
36819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
36839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
36849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3685588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
36869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
36879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
36889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
36899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
369050fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
36919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
36929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
36939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
36959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
36969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
36979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
369950fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
370050fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
370150fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
370250fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
370350fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
370450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
370550fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
370650fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
370750fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
37089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
37109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
37119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
37129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
37139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
37149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
37159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
37169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
37179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
37189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
37209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
37219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
37239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
37249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
37259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
37269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
37279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
37289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
37299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3730588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
37339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
37349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3735588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
37389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
37399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3740588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
37439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
37449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3745588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
37489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
37499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
37509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37513c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
37529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
37539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
37549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
37559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
37569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
37579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
37589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
37609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
37619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
37629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
37649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
37659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
37669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3767588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37683c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
37699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
37709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
377150fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
37729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
377350fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
37749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
37759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
37769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
37779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
37789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
37799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
37809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
37819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
37829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
37839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
37849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
37859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3786588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
37873c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
37889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
37899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
379050fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
37919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
379250fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
37939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
37949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
37959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
37969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
37979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
37989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
37999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
38009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
38019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
38029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
38039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
38049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
38069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
38099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
38109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
38119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
38129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
38149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
38159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
38169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
38179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
38189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
38199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
38209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
38229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
38239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
38249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
38269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
38279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
38289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
38299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
38309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
38319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
38329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
38339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
38349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
38359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
38369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
38379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
38389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
38399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
38429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
38439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
38449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
38459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
38469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
38489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
38499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
38509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
38519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
38529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
38539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
38549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
38559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
38569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
38579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
38589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
38599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
38609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
38629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
38639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
38649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
38669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
38679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
38689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
38699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
38709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
38719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
38729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
38739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
38749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
38759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
38769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
38779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
38789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
38799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
38809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
38819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
38829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
38839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
38849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
38859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
38869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
38879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
38889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
38899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
38909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
38919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
38929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
38939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
38949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
38959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
38969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
38979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
38989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
38999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
39009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
39019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
39029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
39039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
39049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
39059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
39069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
39079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
39089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
39099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
39109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
39119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3912588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
39139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
39149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
39159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
39179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
39189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
39219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
39229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
39239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
39249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
39259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
39269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
39289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
39299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
39309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
39319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
39329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
39349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
39359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
39369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
39389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
39399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
39409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
39419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
39429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
39439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
39449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
39469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
39479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
39489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
39499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
39519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
39529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
39539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
39549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
39569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
39579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
39589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
39609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
39619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
39629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
39639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
39649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
39669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
39679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
39689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
39699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
39709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
39719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
39729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
39749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
39759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
39769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
39779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
39789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
39809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
398150fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
39829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
39839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
39849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
39859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
39869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
39879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
39899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
39909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
39919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
39929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
39939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
39949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3995588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
39969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
39979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
39983c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
39999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
40009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
40019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
40029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
40049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
40059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
40069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
400850fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
40099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
401050fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
401150fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
401250fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
401350fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
401450fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
401550fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
401650fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
401750fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
40189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
40209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
40219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
40229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
40239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
40249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
40259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
40269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
40279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
40299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
40309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
40329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
40339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
40349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
4035666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                               ML_(fndn_ix2filename)(di, var->fndn_ix),
4036666ee9df4c2b6d801b199b8168208dbb46573c9dphilippe                               var->lineNo);
40379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
40389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
403950fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
40409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
40419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
40429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
40439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
40449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
40459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
40479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
40499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
40519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
40539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
40559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
40569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
40579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
4058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
4060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4062e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
4063eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
4065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
4066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
4067eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4068eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4069e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
4070eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
4072eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4073eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4074e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
4075eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
4077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
40793898022a7d74a227d6a35102faaedd420ed3a1c1bartAddr VG_(DebugInfo_get_bss_avma)(const DebugInfo* di)
40803898022a7d74a227d6a35102faaedd420ed3a1c1bart{
40813898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_avma : 0;
40823898022a7d74a227d6a35102faaedd420ed3a1c1bart}
40833898022a7d74a227d6a35102faaedd420ed3a1c1bart
40843898022a7d74a227d6a35102faaedd420ed3a1c1bartSizeT VG_(DebugInfo_get_bss_size)(const DebugInfo* di)
40853898022a7d74a227d6a35102faaedd420ed3a1c1bart{
40863898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_size : 0;
40873898022a7d74a227d6a35102faaedd420ed3a1c1bart}
40883898022a7d74a227d6a35102faaedd420ed3a1c1bart
4089e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
4090092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4091092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
4092092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4093092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4094e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
4095092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4096092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
4097092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4098092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4099e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
4100092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4101092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
4102092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4103092b6268cc4a38ae9ee41d1e3355937536ddc579bart
4104e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
4105092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
4106092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
4107092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
4108092b6268cc4a38ae9ee41d1e3355937536ddc579bart
410968347837b3d82e48f85daff33ec7ba528891e4e7bartAddr VG_(DebugInfo_get_got_avma)(const DebugInfo* di)
411068347837b3d82e48f85daff33ec7ba528891e4e7bart{
411168347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_avma : 0;
411268347837b3d82e48f85daff33ec7ba528891e4e7bart}
411368347837b3d82e48f85daff33ec7ba528891e4e7bart
411468347837b3d82e48f85daff33ec7ba528891e4e7bartSizeT VG_(DebugInfo_get_got_size)(const DebugInfo* di)
411568347837b3d82e48f85daff33ec7ba528891e4e7bart{
411668347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_size : 0;
411768347837b3d82e48f85daff33ec7ba528891e4e7bart}
411868347837b3d82e48f85daff33ec7ba528891e4e7bart
41191636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
4120eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
4122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4123eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
41241636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
4125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4126a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
4127eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4129e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
4130bbec7728efefaa650970dd1f0282b77040287133sewardj{
4131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
4132bbec7728efefaa650970dd1f0282b77040287133sewardj}
4133bbec7728efefaa650970dd1f0282b77040287133sewardj
4134e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
4135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
4137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4139e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
4140e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
4141a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    avma,
4142a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    tocptr,
4143582d58245637ab05272d89fb94b12fd0f18fa0f8carll                                  /*OUT*/Addr*    local_ep,
4144a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UInt*    size,
414519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar**  pri_name,
414619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar*** sec_names,
4147a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isText,
4148a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isIFunc )
4149eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4150eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
4151a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (avma)      *avma      = si->symtab[idx].addr;
4152a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (tocptr)    *tocptr    = si->symtab[idx].tocptr;
4153582d58245637ab05272d89fb94b12fd0f18fa0f8carll   if (local_ep)  *local_ep  = si->symtab[idx].local_ep;
4154a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
4155a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
415619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   if (sec_names) *sec_names = (HChar **)si->symtab[idx].sec_names; // FIXME
4157a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
4158a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
4159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
4164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
4165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
4167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
4168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
4169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
4171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
4172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
4173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
4174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
4175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
4176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
4177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
41785706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
4179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
4180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
4182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
4184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
4185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
4186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
4187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
41881636d33c13958b9c0e7d3059cdd5005746418eb2florianVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/HChar* name, SizeT n_name,
4189e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
4190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
4191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
4192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
4193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
4195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
4197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
4198e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
4199e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
4200a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
4201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
4202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
4203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
4204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
4205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
4207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
4208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
4209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
4210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
4213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
4214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
4215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
4219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
4220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
4221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
4222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
4225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
4226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
4227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
4228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
42305706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
42315706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
42325706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
42335706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
42345706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
42355706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
4236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
4237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
4238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
4239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
4240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
4243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
4244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
4245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
4246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4248092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
4249092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
4250092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
4251092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
4252092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
4253092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
4254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
4255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
4256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
4257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
4258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
4259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
4261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
4264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
4265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
4267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
4269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4270a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
4271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
4272a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         Int fnlen = VG_(strlen)(di->fsm.filename);
4273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
4274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
4275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
4276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
4277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
4278d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
4279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
4280a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            name[j] = di->fsm.filename[i];
4281a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            if (di->fsm.filename[i] == 0) break;
4282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
4283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
4284d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
4285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
4286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
4287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
4290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
4293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
4298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4299