debuginfo.c revision 86781fabbfc019b752f9605e487cfce77b2a592a
1eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Top level management of symbols and debugging information.   ---*/
4eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                  debuginfo.c ---*/
5eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
6eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*
8eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This file is part of Valgrind, a dynamic binary instrumentation
9eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   framework.
10eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
119eecbbb9a9cbbd30b903c09a9e04d8efc20bda33sewardj   Copyright (C) 2000-2010 Julian Seward
12eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
346c591e15c1d6402a2a755310f005f795b68e7e38sewardj#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
36b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
41b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
4213ac96dea734b3933a73524b991ac64fb48a4d57sewardj#include "pub_core_libcproc.h"   // VG_(getenv)
43d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
506882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
56eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
594ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
61b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
62c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
63f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
67eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
68c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
69c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
94f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
95f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
96c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
99eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
100f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
107eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
108eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
158eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
159eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1710f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardjDebugInfo* alloc_DebugInfo( const UChar* filename )
172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
176f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
177f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
179a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
180a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
182452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
183452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
184f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1850f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
186f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
192f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
193f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
195eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
196eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20159a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
2039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
20459a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
207a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
208a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
209a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi)         ML_(dinfo_free)(di->cfsi);
210a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
211a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
213a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
214a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
215a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
216a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
217a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
218a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
219a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
220a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
221a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
222a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
223a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
224a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
225a5cace0c2a3e212931badbf6398a0cd98393121asewardj
226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
227eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
23659a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
24059a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
243eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24459a2d18d0ddfa241850017252b0804d469187d79sewardj
24559a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
24659a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
24759a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
24859a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
24959a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
25059a2d18d0ddfa241850017252b0804d469187d79sewardj      }
25159a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
25259a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
2974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
30433e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
30533e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
307738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
310a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
311a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                                            : (UChar*)"???",
3124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
31533e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
31633e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
331f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
333f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
335f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
359f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
362f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
363f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
364eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
368b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
394a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di1->fsm.have_rx_map && di2->fsm.have_rx_map
395a5acac39bf3be7546222b1316faee5ee524be0d1sewardj       && ranges_overlap(di1->fsm.rx_map_avma, di1->fsm.rx_map_size,
396a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         di2->fsm.rx_map_avma, di2->fsm.rx_map_size))
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
398eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
399a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di1->fsm.have_rx_map && di2->fsm.have_rw_map
400a5acac39bf3be7546222b1316faee5ee524be0d1sewardj       && ranges_overlap(di1->fsm.rx_map_avma, di1->fsm.rx_map_size,
401a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         di2->fsm.rw_map_avma, di2->fsm.rw_map_size))
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
404a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di1->fsm.have_rw_map && di2->fsm.have_rx_map
405a5acac39bf3be7546222b1316faee5ee524be0d1sewardj       && ranges_overlap(di1->fsm.rw_map_avma, di1->fsm.rw_map_size,
406a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         di2->fsm.rx_map_avma, di2->fsm.rx_map_size))
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
409a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di1->fsm.have_rw_map && di2->fsm.have_rw_map
410a5acac39bf3be7546222b1316faee5ee524be0d1sewardj       && ranges_overlap(di1->fsm.rw_map_avma, di1->fsm.rw_map_size,
411a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         di2->fsm.rw_map_avma, di2->fsm.rw_map_size))
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
435b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4630f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4640f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4650f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
4660f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardjstatic DebugInfo* find_or_create_DebugInfo_for ( UChar* filename )
467b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
471a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
472a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
473b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
474b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
475b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4760f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
477b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
479b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
485f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
487f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
488f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
490f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
491f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
492f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
493f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
496a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
497a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* degenerate case: r-x section is empty */
499a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.rx_map_size == 0) {
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi == NULL);
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return;
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* normal case: r-x section is nonempty */
504f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (0) */
505a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.rx_map_size > 0);
506f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (1) */
507f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di2 = debugInfo_list; di2; di2 = di2->next) {
508f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di2 == di)
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
510a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di2->fsm.rx_map_size == 0)
511f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
512a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(
513a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rx_map_avma + di->fsm.rx_map_size <= di2->fsm.rx_map_avma
514a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         || di2->fsm.rx_map_avma + di2->fsm.rx_map_size <= di->fsm.rx_map_avma
515a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      );
516f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
517f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di2 = NULL;
518f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariant (2) */
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
521a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->cfsi_minavma >= di->fsm.rx_map_avma);
522a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->cfsi_maxavma < di->fsm.rx_map_avma + di->fsm.rx_map_size);
523f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
524f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
525f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word i;
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
537f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
538f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
539f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
540f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
571f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
572eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
573eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
574731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
575731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
576731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
577731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
578731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
579731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
580731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
581731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
582731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
583731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
584731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
585731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
586731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
587731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
588731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
589731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
590731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
591731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
592731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
593731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
594731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
595731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
596731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
597731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
598731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
599731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
600731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
601731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
602731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
603731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
604731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      +rw_map_size).  First get rid of any other DebugInfos which
605731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      overlap either of those ranges (to avoid total confusion). */
606731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
607731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
608731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* .. and acquire new info. */
609731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGO_linux)
610731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
611731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
612731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
613731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
614731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
615731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
616731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
617731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
618731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
619731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
620731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
621731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
622731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      cfsi_cache__invalidate();
623731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
624731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
625731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
626731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
627731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
628731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
629731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
630731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      tl_assert(di->handle > 0);
631731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
632731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Check invariants listed in
633731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
634731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         priv_storage.h. */
635731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      check_CFSI_related_invariants(di);
636731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
637731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
638731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
639731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
640731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
641731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
642731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
643731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
644731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
645731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
646731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
647731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
648731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
649731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
650731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
651731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
652731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
653731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
654731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
656eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
657eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
658eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
660eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
6619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
6629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
6639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
6649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
6659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
6669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
6679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
6689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
674731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
677cec083d9a254e92623ed44e9dca080d224693c82sewardj   Int        nread, oflags;
678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
680ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
681ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
690a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
7019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
7069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
711ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
71215728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
713ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
714ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
715ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
7169c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
717ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
718ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
719ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
720cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
721ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
722ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
723e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
724ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
725a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
726ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
727ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
7289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
7292ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
7302ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
731ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
732ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
7339c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
7349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
735ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
736ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
73715728ab41ea41bf731dcc74ac68354550ced2189bart
738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
762eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
763eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
766eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
767eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
768eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
771f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
772f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
773f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
774b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
775b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
776b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
777b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
778b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
779b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
780b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
781b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
782b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
786731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
787731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
788f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
7913026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
794b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
795b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
796b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
801731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
802731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
803731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
804731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
808eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
809731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
810731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
8119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
812eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8135a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
8145a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
8155a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
816cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
817cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
818cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
819cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
820cec083d9a254e92623ed44e9dca080d224693c82sewardj   fd = VG_(open)( filename, oflags, 0 );
821cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(fd)) {
822cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Err(fd) != VKI_EACCES) {
8235a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         DebugInfo fake_di;
8245a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
825a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
8265a5eec0923d55afc94165721d25125d5fc8f24d8sewardj         ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
8275a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
8285a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8295a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
830cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) );
831cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   VG_(close)( sr_Res(fd) );
8325a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8335a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread == 0)
8345a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8355a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (nread < 0) {
8365a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
8375a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
838a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      fake_di.fsm.filename = filename;
8395a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
8405a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8415a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8425a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
8435a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8448b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
8456e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
8465a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
8475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8486e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
849f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (!ML_(is_macho_object_file)( buf1k, (SizeT)nread ))
850f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
8516e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
8526e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
8536e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
8545a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
8570f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
862a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (!di->fsm.have_rx_map) {
863a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.have_rx_map = True;
864a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rx_map_avma = a;
865a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rx_map_size = seg->end + 1 - seg->start;
866a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rx_map_foff = seg->offset;
867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
871eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
874a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (!di->fsm.have_rw_map) {
875a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.have_rw_map = True;
876a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rw_map_avma = a;
877a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rw_map_size = seg->end + 1 - seg->start;
878a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         di->fsm.rw_map_foff = seg->offset;
879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
884731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (is_ro_map) {
885731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* We have a r-- mapping.  Note the details (OSX 10.7, 32-bit only) */
886731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map) {
887731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         di->fsm.have_ro_map = True;
888731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         di->fsm.ro_map_avma = a;
889731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         di->fsm.ro_map_size = seg->end + 1 - seg->start;
890731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         di->fsm.ro_map_foff = seg->offset;
891731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      } else {
892731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         /* FIXME: complain about a second r-- mapping */
893731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      }
894731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
896731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
897731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
898731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
899731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
900731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
901731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
9029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
903731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
904731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
905731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
906731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
9079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
908eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
909eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
913eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
914eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
915f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
916a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
917f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
918f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
919f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
920eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
921eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
930f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
933f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
934f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
935f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
936f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
937f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
940731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
941731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* This is a MacOSX 10.7 32-bit only special.  See comments on the
942731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
943731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
944731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
945731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
946731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
947731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
948731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
949731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (do_nothing /* wrong platform */)
950731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
951731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
952731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
953731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
954731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
955731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
956731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
957731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
958731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
959731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
960731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
961731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
962731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
963731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
964731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
965731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
966731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
967731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
968731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
969731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
970731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
971731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
972731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
973731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.ro_map_avma != a || di->fsm.ro_map_size != len)
974731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* this isn't an upgrade of the r-- mapping */
975731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
976731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
977731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
978731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
979731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
980731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
981731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Do the upgrade.  Copy the RO map info into the RX map info and
982731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      pretend we never saw the RO map at all. */
983731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_rw_map);
984731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
985731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(!di->fsm.have_rx_map);
986731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
987731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
988731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.rx_map_avma = di->fsm.ro_map_avma;
989731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.rx_map_size = di->fsm.ro_map_size;
990731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.rx_map_foff = di->fsm.ro_map_foff;
991731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
992731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
993731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.ro_map_avma = 0;
994731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.ro_map_size = 0;
995731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.ro_map_foff = 0;
996731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
997731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* And since we're now in an accept state, read debuginfo.  Finally. */
998731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle __attribute__((unused))
999731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      = di_notify_ACHIEVE_ACCEPT_STATE( di );
1000731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* di_handle is ignored. That's not a problem per se -- it just
1001731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      means nobody will ever be able to refer to this debuginfo by
1002731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      handle since nobody will know what the handle value is. */
1003731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1004731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1005731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1006c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1007c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1008c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1009c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
1010c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   SizeT total_size,
1011c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                                   PtrdiffT unknown_purpose__reloc )
1012c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
101313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1014c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
1015c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char   exename[VKI_PATH_MAX];
1016c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  pdbname = NULL;
1017c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Char*  dot;
1018c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1019c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1020c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1021c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1022c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1023c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1024738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1025c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1026cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
1027cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "uu_reloc=%#lx\n",
1028c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fd_obj, avma_obj, total_size, unknown_purpose__reloc
1029c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1030c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1031c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1032c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1033c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1034c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1035c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1036c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
1037c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
10389c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1039c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1040c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
1041c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
1042c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
1043c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
1044c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
1045c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
1046c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
1047c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
1048c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
1049c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
1050c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
1051c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1052c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1053738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1054c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1055c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
105613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
105713ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
105813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
105913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
106013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
106113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
106213ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
106313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
106413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
106513ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
106613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
106713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
106813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
106913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
107013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
107113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
107213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
107313ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
107413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
107513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
107613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
107713ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
107813ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
107913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
108013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
108113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
108213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
108313ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
108413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
108513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
108613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
108713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(sprintf)(mashed, "%s/drive_%c%s",
108813ac96dea734b3933a73524b991ac64fb48a4d57sewardj                      wpfx, pdbname[0], &pdbname[2]);
108913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
109013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
109113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
109213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
109313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
109413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
109513ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
109613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
109713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
109813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
109913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(sprintf)(mashed, "%s/.wine/drive_%c%s",
110013ac96dea734b3933a73524b991ac64fb48a4d57sewardj                      home, pdbname[0], &pdbname[2]);
110113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
110213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
110313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
110413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
110513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
110613ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
110713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
110813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
110913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
111013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1111c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
111213ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
111313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
111413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
111513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
111613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
111713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
111813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
111913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
112013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
112113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
112213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
112313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
112413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
112513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
112613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
112713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
112813ac96dea734b3933a73524b991ac64fb48a4d57sewardj
112913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
113013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
113113ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
113213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
113313ac96dea734b3933a73524b991ac64fb48a4d57sewardj
113413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
113513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1136c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1137c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1138c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1139cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1140738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1141c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1142c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1143738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1144c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1145c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
11469c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
11477138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1148ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
11497138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
11507138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
11517138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
11527138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
11537138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
11547138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
11557138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1156738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1157ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1158ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1159ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1160c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1161c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1162c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1163cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1164738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1165c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1166c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1167c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1168cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1169cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1170cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1171cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1172cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1173cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1174cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1175cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1176cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
11779c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1178cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1179cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1180cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1181cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1182cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1183cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1184cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1185cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1186cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1187cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1188cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1189c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1190c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1191c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1192c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1193cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1194cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1195cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1196cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1197cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1198cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1199cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1200cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1201c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1203c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1204c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1205c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1206c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1207c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1208c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1209c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12100f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1211c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1212c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1213a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1214c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1215c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1216c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1217c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
1218c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     ML_(read_pdb_debug_info)( di, avma_obj, unknown_purpose__reloc,
1219c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1220c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1221c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1222c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1223c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1224c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1225cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1226cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1227cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1228cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                                 "%lu syms, %lu src locs, %lu fpo recs\n",
1229cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                     di->symtab_used, di->loctab_used, di->fpo_size);
1230cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1231c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1232c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1233c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1234c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1235c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1236c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12378b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
12384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
12394ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1242eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1243eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1244eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1245eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
12479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
12489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
12499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
12509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
12519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
12529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
12539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
12549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
12559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
12569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
12579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
1259eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1261eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1262eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1263eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1271f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1274eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1275f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
128251c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
128351c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
128451c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1285a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
1286a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                   && di->fsm.rx_map_size > 0
1287a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                   && di->fsm.rx_map_avma <= ptr
1288a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                   && ptr < di->fsm.rx_map_avma + di->fsm.rx_map_size;
1289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
13035706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
13045706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13055706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
13065706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
13075706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
13085706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
13095706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13105706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
13115706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
13125706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
13135706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1335f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1337f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
13415706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1350eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
13586b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
13596b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
13606b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
13646b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
13656b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
13666b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Addr a, Char* buf, Int nbuf,
1367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1368c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1371f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1372c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
13776882443ef154bca367bc591287de641e43a9e108njn
1378a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
13796b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
1380a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   di->symtab[sno].pri_name, buf, nbuf );
13816b7611bf42a0fbb62e047d8c43b008205bd21e75njn
13826b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
13836b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
13846b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
13856b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
13866b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
13876b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
13886b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
13896b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
13906b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1393c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1395eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
1396eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
1397eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
1398eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
1399eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1400eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1401c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1403eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1405eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
1407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
1408eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1409eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14126b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
14136b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1414eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1415eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1416eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1417eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1418eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1419eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1420eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1421eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1423f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1424eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1428eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1429eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1430eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1431eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1432eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1433eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1435eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
1436eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1437eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14386b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
14396b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14406b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1445eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1446eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1447eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1448eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
1449eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1450eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14516b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
14526b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1459eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
1463eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14656b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
14666b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14676b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14746b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
14756b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
14766b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
14776b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_raw) ( Addr a, Char* buf, Int nbuf )
1478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14796b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
14806b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
14816b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1484b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1485b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
14896b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
14906b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
14916b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool VG_(get_fnname_no_cxx_demangle) ( Addr a, Char* buf, Int nbuf )
1492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14936b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
14946b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14956b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
14966b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
14976b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
14986b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
14996b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1501eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15026882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind) ( Char* name )
15036882443ef154bca367bc591287de641e43a9e108njn{
15046882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
15056882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
15066882443ef154bca367bc591287de641e43a9e108njn
15076882443ef154bca367bc591287de641e43a9e108njn   } else if (
15083026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
15096882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
15106882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
15113026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1512f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1513f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
15143026f71684a930286186aa10fef266c304672e8fsewardj#      else
15153026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
15163026f71684a930286186aa10fef266c304672e8fsewardj#      endif
15176882443ef154bca367bc591287de641e43a9e108njn       0) {
15186882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
15196882443ef154bca367bc591287de641e43a9e108njn
15206882443ef154bca367bc591287de641e43a9e108njn   } else {
15216882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
15226882443ef154bca367bc591287de641e43a9e108njn   }
15236882443ef154bca367bc591287de641e43a9e108njn}
15246882443ef154bca367bc591287de641e43a9e108njn
15256882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
15266882443ef154bca367bc591287de641e43a9e108njn{
15276882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
15286882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
15296882443ef154bca367bc591287de641e43a9e108njn   Char buf[50];
15306882443ef154bca367bc591287de641e43a9e108njn
15316882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
15326882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
15336b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
15346882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
15356882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
15366882443ef154bca367bc591287de641e43a9e108njn   } else {
15376882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
15386882443ef154bca367bc591287de641e43a9e108njn   }
15396882443ef154bca367bc591287de641e43a9e108njn}
15406882443ef154bca367bc591287de641e43a9e108njn
1541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1542b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1543b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1544b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1545b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1546b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1547c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1548b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1549b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1550b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
15516b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
15526b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
15536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1570f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1571f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
15724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
15737cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
15747cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
15775706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1580a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
15814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
15857cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
15867cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
15877cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
15887cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
15897cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
15907cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
15917cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1592f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1593f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1594f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1595eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1596eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1597eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1599eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1600e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1602e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1604e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1605b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1606b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16075706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1609b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1610e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1611e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1612b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1613eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1614eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1615eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1616eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1617eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1618eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1620eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1622f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1623eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1624eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1625eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1626eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1627eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1628eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1629eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1630eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1631eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1632eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1634f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1635eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1636eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1637eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1639eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1641eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1642eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1643eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1644eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1645eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1646eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1647eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1648eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1649eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1650eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1651eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1653f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1656eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1657eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1658eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1660c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1661db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1662db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1663db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1664db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1665eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1666c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1667c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1670eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1678eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1680eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1683eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
16904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
16914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
16924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
16934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
16944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
16954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
16964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
16994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
17004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
17014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
17034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
17044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
17054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
17064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
17084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
17094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
17104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
17114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
17124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
17134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
17144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
17154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
1716a5cace0c2a3e212931badbf6398a0cd98393121asewardj         UChar* pri_name = si->symtab[i].pri_name;
1717a5cace0c2a3e212931badbf6398a0cd98393121asewardj         tl_assert(pri_name);
1718a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
17194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
17204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
17214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
17224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
17234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
1724a5cace0c2a3e212931badbf6398a0cd98393121asewardj         UChar** sec_names = si->symtab[i].sec_names;
1725a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
1726a5cace0c2a3e212931badbf6398a0cd98393121asewardj            tl_assert(sec_names[0]);
1727a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
1728a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
1729a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   && (require_pToc ? si->symtab[i].tocptr : True)) {
1730a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pEnt = si->symtab[i].addr;
1731a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pToc = si->symtab[i].tocptr;
1732a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
1733a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
1734a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
1735a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
1736a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
17374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
17384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
17394ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
17404ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
17414ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
17424ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1743e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1744e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1745e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1746e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1747e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1751e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1752e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1755e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1759e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1760e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1761e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1762e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1763e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1764eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1765eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1766e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1767e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1768e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1769eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1770e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1771e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1772e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1773eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1774e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1775e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1776e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1777e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1778e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1779e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1780e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1781e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1782e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1783e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1784e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1785e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1786e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1787e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1788e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1789e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1790e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1791e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1792e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1793e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1794e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1795e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1798e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1799e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1800e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1802eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1803eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1804eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1805eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1806eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1807e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1808e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1809e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1810eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1811eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1812eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1813eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
181514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1817eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1818eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
182014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
182114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
18234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
18244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
18254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1827eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1829eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1830eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1831eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1832eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
183314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
183414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
183514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
183614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
183714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1838eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1840eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1841eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1843eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1844e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1845e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1846e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1847e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1848e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1849e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1850eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1851a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1852eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1853eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1854eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1855eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1856eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1857e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1858eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1859eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1860eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1861eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1862eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1863e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1864eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1865eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1866eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1869eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1870e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1871eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1872eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1875e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1876eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1885eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1886eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1887eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1888eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
18895e40abad4504416c59f0b29c1cfc8087201213a9njn      //
18905e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
18915e40abad4504416c59f0b29c1cfc8087201213a9njn      //
18925e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
18935e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
18945e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
18955e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
18965e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
18975e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
18985e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1899a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1900eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
19015e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1904eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1905eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
190814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
190914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         UChar* dirname = NULL;
191014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
191114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
191214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
191314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
191414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
191514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
191614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
191714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* prefix = VG_(clo_fullpath_after)[i];
191814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               UChar* str    = VG_(strstr)(dirname, prefix);
191914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
192014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
192114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
192214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
192314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
192414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
192514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
192614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
192714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
192814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
192914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
193014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
193114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
193214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
19335dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
1934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
19395e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
19405e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
19415e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
19425e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
19435e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
19445e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
19455e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
19465e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
1947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
195772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
196472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
196572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
196672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
196772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
196872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
19693026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
19703026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
19713026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
197272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
197372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
197472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
197572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
197672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
197772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
1978f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
1979f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
198072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
198172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
198272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
198372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
198419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
19853026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
19863026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
19873026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
198872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
198972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
199072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
199172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
199272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
199372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
199472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
199572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
199672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
199719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
19987888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
19990b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Shl: return wL << wR;
20000b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Shr: return wL >> wR;
20010b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Eq: return wL == wR ? 1 : 0;
2002130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2003130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2004130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2005130f6f5a47a1557a454b24db6e08431da6c8b9c1tom            case Cop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
20060b98239b3e0abd430dbc913454d63c7e3d8c8b12tom            case Cop_Ne: return wL != wR ? 1 : 0;
200772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
200872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
200972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
201072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
201172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
20123026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
20133026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
20143026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
20153026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
20163026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
20173026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
20183026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2019fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2020fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2021b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2022b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
2023b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
2024b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
2025b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
20263026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
20273026f71684a930286186aa10fef266c304672e8fsewardj#           else
20283026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
20293026f71684a930286186aa10fef266c304672e8fsewardj#           endif
203072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
203172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
203272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
203372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
203472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
203519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
203619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
203719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
203819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
203919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
204019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
204119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
204219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
204319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
204486781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
204572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
204672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
204772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
204872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
204972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
205072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
205172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
205272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
205372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
205472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
205572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
205672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
205772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
205872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2059f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
2060f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2061eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2062f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
2063f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
206472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2065f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
2066f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2067f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2068f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
2069f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
2070f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2071f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2072f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2073f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2074f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2075f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2076f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2078eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2079f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2080eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2081f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2082f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2083eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2084eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2087f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2088eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2089f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2090eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2092f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2093f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2094f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2095f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2096f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2097f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2098f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2099eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
2106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
2107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2110f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
2111f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
2114f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
2115f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
2116f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
2117f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2118f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2119f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2120f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2121f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2122f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2123f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2124f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2125f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2126f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2127f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2128f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2129f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2130f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2131f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2132f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2133f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2134f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2135f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2136f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2137f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2138f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2139f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2140f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2141f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2142f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2143f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2144f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
2145f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2146f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2147f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
2148f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
2149f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
2150f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2151f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2152f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2153f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2154f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
2155f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
2156f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
2157f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
2158f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
2159f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
2160f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
2161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2162f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#define N_CFSI_CACHE 511
2163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2164f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
2165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
2166f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
2167f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2168f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
2169f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2170f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
2171f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
2172f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2173f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2174f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2175f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic inline CFSICacheEnt* cfsi_cache__find ( Addr ip )
2176f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
21773c9cf3442185b5891e15450d6e3058aeff6796fetom   UWord         hash = ip % N_CFSI_CACHE;
21783c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce = &cfsi_cache[hash];
21793c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2180f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2181f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2182f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2183f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2184f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
21853c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
21863c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
21873c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
21883c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
21893c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
21903c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
21913c9cf3442185b5891e15450d6e3058aeff6796fetom      find_DiCfSI( &ce->di, &ce->ix, ip );
21923c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2193eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
21943c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
21953c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
21963c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
21973c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
21983c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
21993c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
22013c9cf3442185b5891e15450d6e3058aeff6796fetom}
2202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2203eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2204f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
22053026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
22063c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
22073c9cf3442185b5891e15450d6e3058aeff6796fetom                          DebugInfo* di, DiCfSI* cfsi )
22083c9cf3442185b5891e15450d6e3058aeff6796fetom{
22093c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
22103c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
22113c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22133c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
221472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
221572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
22163026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
22173026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
22183026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xsp;
22193026f71684a930286186aa10fef266c304672e8fsewardj         break;
22203026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
22213026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xbp;
222272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
22233026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
22243026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
22253026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r13;
222672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
22273026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
22283026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r12;
22293026f71684a930286186aa10fef266c304672e8fsewardj         break;
22303026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
22313026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r11;
22323026f71684a930286186aa10fef266c304672e8fsewardj         break;
2233fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
2234fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         cfa = cfsi->cfa_off + uregs->r7;
2235fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2236b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2237b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
2238b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->sp;
2239b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2240b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2241b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
2242b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         Addr a = uregs->sp + cfsi->cfa_off;
2243b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2244b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
224586781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2246b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2247b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2248b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2249b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2250b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2251b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
2252b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->fp;
2253b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
22543026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
22553026f71684a930286186aa10fef266c304672e8fsewardj#     else
22563026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
22573026f71684a930286186aa10fef266c304672e8fsewardj#     endif
22583026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
22597888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
22607888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2261f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
22627888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
22637888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
22643026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
22657888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
22667888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
22677888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2268f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
22693c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
227072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
227172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
227272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
227372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
22743c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
22753c9cf3442185b5891e15450d6e3058aeff6796fetom}
22763c9cf3442185b5891e15450d6e3058aeff6796fetom
22773c9cf3442185b5891e15450d6e3058aeff6796fetom
22783c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
22793026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
22803026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
22813c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
22823c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
22833c9cf3442185b5891e15450d6e3058aeff6796fetom{
22843c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce;
22853c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*    di;
2286d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   DiCfSI*       cfsi __attribute__((unused));
22873c9cf3442185b5891e15450d6e3058aeff6796fetom
22883c9cf3442185b5891e15450d6e3058aeff6796fetom   ce = cfsi_cache__find(ip);
22893c9cf3442185b5891e15450d6e3058aeff6796fetom
22903c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
22913c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
22923c9cf3442185b5891e15450d6e3058aeff6796fetom
22933c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
22943c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
22953c9cf3442185b5891e15450d6e3058aeff6796fetom
22963026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
22973026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
22983026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
22993026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
23003026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
23013026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
23023026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
23033026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
23043026f71684a930286186aa10fef266c304672e8fsewardj                        min_accessible,  max_accessible, di, cfsi);
23053026f71684a930286186aa10fef266c304672e8fsewardj   }
2306b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2307b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2308b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2309b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2310b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2311b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
2312b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                        min_accessible,  max_accessible, di, cfsi);
2313b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2314b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
23153026f71684a930286186aa10fef266c304672e8fsewardj#  else
23163026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
23173026f71684a930286186aa10fef266c304672e8fsewardj#  endif
23183c9cf3442185b5891e15450d6e3058aeff6796fetom}
23193c9cf3442185b5891e15450d6e3058aeff6796fetom
23203c9cf3442185b5891e15450d6e3058aeff6796fetom
23213026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
23223026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
23233026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
23243026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
23253026f71684a930286186aa10fef266c304672e8fsewardj
23263026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
23273026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
23283026f71684a930286186aa10fef266c304672e8fsewardj
2329fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
23303026f71684a930286186aa10fef266c304672e8fsewardj*/
23313026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
23323c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
23333c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
23343c9cf3442185b5891e15450d6e3058aeff6796fetom{
23353c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
23363c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*            cfsi = NULL;
23373026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
23383c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt*      ce;
2339d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
23403026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
23413c9cf3442185b5891e15450d6e3058aeff6796fetom
23423026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
23433026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
23443026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
23453026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2346b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2347b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
23483026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
23493026f71684a930286186aa10fef266c304672e8fsewardj#  else
23503026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
23513026f71684a930286186aa10fef266c304672e8fsewardj#  endif
23523026f71684a930286186aa10fef266c304672e8fsewardj   ce = cfsi_cache__find(ipHere);
23533c9cf3442185b5891e15450d6e3058aeff6796fetom
23543c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
23553c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
23563c9cf3442185b5891e15450d6e3058aeff6796fetom
23573c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
23583c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
23593c9cf3442185b5891e15450d6e3058aeff6796fetom
23603c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
23613c9cf3442185b5891e15450d6e3058aeff6796fetom      VG_(printf)("found cfisi: ");
23623c9cf3442185b5891e15450d6e3058aeff6796fetom      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
23633c9cf3442185b5891e15450d6e3058aeff6796fetom   }
23643c9cf3442185b5891e15450d6e3058aeff6796fetom
2365f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
23663c9cf3442185b5891e15450d6e3058aeff6796fetom
23673c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
23683026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
23693026f71684a930286186aa10fef266c304672e8fsewardj                     min_accessible, max_accessible, di, cfsi);
23703c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
23713c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
237272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
237372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
237472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2379eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2380eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
23869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
238886781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
239472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
239572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2396f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
23973026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
239872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
239972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2400d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2401f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
240272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
240372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
240472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
240572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2408eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24093026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
24103026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
24119365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
24129365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
24133026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
24143026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how,  cfsi->ra_off);
24153026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
24163026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
24173026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
24183026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
2419fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi->r7_how,  cfsi->r7_off);
2420b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2421b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
2422b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
2423b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
24243026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
24253026f71684a930286186aa10fef266c304672e8fsewardj#  else
24263026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
24273026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2428eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2429eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2430eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24313026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2432eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2433eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2434eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2435eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2438c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2439c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2440c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2441c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2442c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2443c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2444c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2445c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2446c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2447c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2448c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2449c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2450c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2451c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2452c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2453c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2454c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2455c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2456c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2457c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2458c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2459c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2460c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2461c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2462c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2463c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2464c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2465c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2466c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2467c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2468c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2469c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2470c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2471c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2472c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2473c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2474c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2475c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2476c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2477c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2478c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2479c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2480c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2481c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2482c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2483c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2484c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2485c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2486c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2487c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2488c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2489c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2490c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2491c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2492c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2493c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2494c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2495c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2496c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2497c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2498c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2499c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2500c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2501c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2502c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2503c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2504c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2505c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2506c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2507c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2508c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2509c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2510c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2511c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2512c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2513c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2514c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2515c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2516c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2517c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2518c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2519c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2520c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2521c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2522c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2523c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2524c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2525c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2526c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2527c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2528c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2529c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2530c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2531c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2532c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2533c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2534c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2535c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2536c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2537c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2538c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2539c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2540c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2541c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2542c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2543c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2544c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2545c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2546c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2547c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2548c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2549c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
255086781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
255186781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
255286781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
255386781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
2554c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2555c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2556c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2557c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2558c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2559c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2565588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2566588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   VG_(xaprintf_no_f_c)(dst, fmt, args) without having to resort to
2567588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2568588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2569738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2570588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2571588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //   VG_(xaprintf_no_f_c)(dstxa, format, ##args)
2572738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2573588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj#define  p2XA  VG_(xaprintf_no_f_c)
2574738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2575588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2576588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2577738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2578738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2579738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2580738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2581738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2582738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2583738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2586b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2587b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2588b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2589c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
25909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2591b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2592b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2593b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2594588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2595b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
259650fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2597b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2598b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2599b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
26009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2601b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2602b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2603b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2604b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
260550fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
260650fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
260750fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
260850fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
260950fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
261050fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
261150fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
261250fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
261350fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
261450fde23467d92281b32dd537d0d9a590263628c3sewardj
261550fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2618a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2619b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
26209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2631588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2638eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
26393c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2650738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
2651738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
2652738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
2653738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
2654738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
2655738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
2656738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
2657738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
2658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2660c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2661c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2665eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2666738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
2667738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
2668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
2669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
2670738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar* basetag   = "auxwhat"; /* a constant */
2671738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   UChar tagL[32], tagR[32], xagL[32], xagR[32];
2672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2673d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
2674d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
2675d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2676d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
2677d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
2678d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2679d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
2680d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
2681d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2682d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
2683738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
2684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2690738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
2691738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
2692738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
2693738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
2694738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
2695738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
2696738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
2697738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2698738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
2699738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
2700738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
2701738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
2702738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
2703738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
2704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2712738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2713738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2714738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2715738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\",",
2716738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2717738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2718738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2719738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2720738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2721738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2722738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2723738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2724738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2725738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2726738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2727738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2728738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2736738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2737738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2738738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2739738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%t\"",
2740738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2741738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2742738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2743738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2744738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2745738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2746738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2747738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2748738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2749738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2750738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2751738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2752738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2753738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2754738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2755738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2756738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2757738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2758738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2759738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2760738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2768738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2769738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2770738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2771738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t",
2772738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2773738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2774738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2775738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2776738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2777738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2778738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2779738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2780738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2781738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
2782738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2783738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2784738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2785738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2786738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2791738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
2792738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2793738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2794738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2795738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2796738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2797738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2798738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2799738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2800738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2801738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2802738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d, in frame #%d of thread %d",
2803738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2804738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2805738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2806738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2807738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2808738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2809738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2810738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2811738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2812738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2813738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2814738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2815738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2816738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2817738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2818738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2819b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2820b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2826738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2827738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2828738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2829738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2830738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2831738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2832738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2833738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2834738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2835738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2836738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2844738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2845738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2846738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2847738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%t\"",
2848738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2849738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2850738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2851738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2852738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2853738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %t:%d",
2854738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2855738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2856738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2857738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2858738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2859738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2860738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2861738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2862738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2863738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2864738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2865738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2866738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
2867738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2868738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
2872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2874b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
2875b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2876738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2877738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2878738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2879738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2880738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2881738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2882738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2883738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2884738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2885738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2886738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2887738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2888738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2889738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2890738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2891738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
2892738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2893738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
2894738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
2898738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2899738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
2900738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2901738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2902738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2903738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %t%t,",
2904738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2905738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2906738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2907738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2908738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2909738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2910738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %t:%d",
2911738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2912738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2913738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2914738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2915738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               " <file>%t</file> <line>%d</line> ",
2916738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2917738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2918738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2919738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2920738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2921738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2922738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2923738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2924738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
2925738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2926738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
2930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2931738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
2932738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
2933738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
2934738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2935738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
2936738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
2937738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
2938738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
2939738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
2940738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
2941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2943738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
2945738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
2946738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
2947738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
2948738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
2949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
2950738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
2951738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
2952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
2953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
2954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
2955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
2956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
2958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
2960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
2961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
2963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
2964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
2965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
2966a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
2967b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
2968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
2969b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
2970b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
2979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
2980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
2981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
2982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
2985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
2986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
2987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
2988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
2989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
2990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
2991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
2992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
2993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
2994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
2995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
2997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
2999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3048c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3050a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
30529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
30539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3054588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3055c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
30579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
30589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3059738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3069eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3070eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3071738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
3072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
3073738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3074738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3075738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3076738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3077738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3078738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3079738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3080738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3081738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3082738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3083738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3084738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
3085738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
3086738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
3087738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3088738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3100738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
3101738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
3102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3103a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
31109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3151c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
31609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3162588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3163c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
31659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
31669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3167738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3169d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3170d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3172738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3173738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
3184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
3185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
3186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
3187b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
3188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
3189b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3190b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3193738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
3198738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3199738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
3204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3218738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3219738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3228b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
3230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
3231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
3232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3234738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3236b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3238738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3239738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3256b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3257b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3258b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3259b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3260b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3261738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3262b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3263b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3264b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3265738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3266738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3272738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3273738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3277eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
32799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
32809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
32819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
32829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
32839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
32849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
32869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
32879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
32889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
32899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
32909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
32919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
32929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
32939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3294588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
32959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
32969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
32979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
32989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
329950fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
33009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
33019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
33029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
33049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
33059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
33069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
330850fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
330950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
331050fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
331150fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
331250fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
331350fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
331450fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
331550fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
331650fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
33179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
33199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
33209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
33219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
33229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
33239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
33249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
33259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
33269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
33279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
33299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
33309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
33329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
33339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
33349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
33359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
33369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
33379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
33389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3339588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
33429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
33439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3344588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
33479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
33489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3349588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
33529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
33539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3354588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
33579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
33589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
33599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33603c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
33619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
33629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
33639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
33649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
33659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
33669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
33679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
33699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
33709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
33719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
33729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
33739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
33749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
33759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3376588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33773c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
33789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
33799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
338050fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
33819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
338250fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
33839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
33849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
33859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
33869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
33879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
33889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
33899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
33909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
33919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
33929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
33939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
33949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3395588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
33963c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
33979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
33989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
339950fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
34009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
340150fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
34029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
34039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
34049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
34059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
34069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
34079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
34089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
34099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
34119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
34129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
34159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
34189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
34199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
34209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
34219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
34239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
34249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
34259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
34269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
34279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
34289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
34299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
34319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
34329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
34339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
34359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
34369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
34379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
34389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
34399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
34409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
34419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
34429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
34439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
34449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
34459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
34469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
34479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
34489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
34499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
34519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
34529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
34539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
34549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
34559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
34579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
34589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
34599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
34609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
34619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
34629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
34639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
34649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
34659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
34669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
34679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
34689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
34699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
34719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
34729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
34739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
34759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
34769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
34779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
34789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
34799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
34819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
34829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
34839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
34849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
34859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
34869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
34879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
34889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
34899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
34909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
34919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
34929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
34939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
34949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
34959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
34969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
34979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
34989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
34999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
35009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
35019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
35029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
35039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
35049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
35059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
35069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
35079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
35089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
35099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
35109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
35119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
35129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
35139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
35149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
35159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
35169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
35179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
35189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
35199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
35209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3521588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
35229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
35269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
35279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
35309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
35319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
35329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
35339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
35349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
35359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
35379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
35389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
35399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
35409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
35419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
35439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
35449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
35459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
35479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
35489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
35499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
35509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
35519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
35529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
35559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
35569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
35579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
35589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
35609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
35619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
35629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
35639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
35659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
35669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
35679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
35699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
35709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
35719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
35729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
35739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
35759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
35769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
35779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
35789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
35799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
35809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
35819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
35839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
35849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
35859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
35869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
35879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
35899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
359050fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
35919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
35929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
35939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
35949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
35959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
35969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
35989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
35999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
36009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
36019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
36029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
36039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3604588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
36059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
36073c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
36089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
36099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
36109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
36119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
36139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
36149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
36159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
361750fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
36189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
361950fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
362050fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
362150fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
362250fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
362350fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
362450fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
362550fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
362650fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
36279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
36299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
36309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
36319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
36329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
36339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
36349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
36359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
36369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
36389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
36399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
36419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
36429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
36439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
36449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
36459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
36469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
36479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
364850fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
36499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
36509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
36519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
36529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
36539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
36549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
36569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
36589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
36609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
36629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
36649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
36659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3671e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
3672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3678e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
3679eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3681eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3682eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3683e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
3684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3688e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
3689092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3690092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3691092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3692092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3693e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
3694092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3695092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3696092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3697092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3698e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
3699092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3700092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3701092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3702092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3703e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
3704092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3705092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3706092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3707092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3708e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
3709eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3713e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst UChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
3714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3715a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
3716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3718e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
3719bbec7728efefaa650970dd1f0282b77040287133sewardj{
3720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3721bbec7728efefaa650970dd1f0282b77040287133sewardj}
3722bbec7728efefaa650970dd1f0282b77040287133sewardj
3723e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
3724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3728e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
3729e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
3730a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    avma,
3731a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    tocptr,
3732a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UInt*    size,
3733a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UChar**  pri_name,
3734a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UChar*** sec_names,
3735a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isText,
3736a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isIFunc )
3737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3738eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3739a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (avma)      *avma      = si->symtab[idx].addr;
3740a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (tocptr)    *tocptr    = si->symtab[idx].tocptr;
3741a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
3742a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
3743a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (sec_names) *sec_names = si->symtab[idx].sec_names;
3744a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
3745a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
3746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
37655706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3775e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
3776e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
3777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3785e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
3786e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
3787a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
3788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3804b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3815b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
38175706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
38185706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
38195706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
38205706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
38215706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
38225706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3829b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3835092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3836092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3837092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3838092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3839092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3840092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3857a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
3858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3859a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         Int fnlen = VG_(strlen)(di->fsm.filename);
3860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3865d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3867a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            name[j] = di->fsm.filename[i];
3868a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            if (di->fsm.filename[i] == 0) break;
3869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
3870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3871d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
3872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
3873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
3874b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3875b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
3877b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3878b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
3880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3881eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
3885eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3886