debuginfo.c revision 2352e9843d8a616b9d829aef929d218aea9b4ae0
1eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
3eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Top level management of symbols and debugging information.   ---*/
4eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                  debuginfo.c ---*/
5eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
6eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*
8eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This file is part of Valgrind, a dynamic binary instrumentation
9eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   framework.
10eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
12eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      jseward@acm.org
13eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is free software; you can redistribute it and/or
15eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   modify it under the terms of the GNU General Public License as
16eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   published by the Free Software Foundation; either version 2 of the
17eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   License, or (at your option) any later version.
18eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
19eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This program is distributed in the hope that it will be useful, but
20eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   General Public License for more details.
23eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
24eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   You should have received a copy of the GNU General Public License
25eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   along with this program; if not, write to the Free Software
26eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   02111-1307, USA.
28eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
29eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   The GNU General Public License is contained in the file COPYING.
30eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
31eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
32eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
334cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
346c591e15c1d6402a2a755310f005f795b68e7e38sewardj#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
36b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
38eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
40eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
41b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
4213ac96dea734b3933a73524b991ac64fb48a4d57sewardj#include "pub_core_libcproc.h"   // VG_(getenv)
43d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
4872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
506882443ef154bca367bc591287de641e43a9e108njn#include "pub_core_stacktrace.h" // VG_(get_StackTrace) XXX: circular dependency
51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
545d616dfbb8439dfd51a40ddf1dba970938baa1ebsewardj#include "priv_image.h"
55b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_d3basics.h"       /* ML_(pp_GX) */
56b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_tytypes.h"
57eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_storage.h"
58eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readdwarf.h"
59eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "priv_readstabs.h"
604ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
614ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readelf.h"
62b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj# include "priv_readdwarf3.h"
63c8259b85b701d25d72aabe9dc0a8154517f96913sewardj# include "priv_readpdb.h"
64f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
65f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readmacho.h"
66f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# include "priv_readpdb.h"
674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
68eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
69c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
95f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
96f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
97c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- fwdses                                               ---*/
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
10420ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippestatic UInt CF_info_generation = 0;
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void );
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*------------------------------------------------------------*/
109eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
110eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
161eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
162eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
164eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
165eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Gives out unique abstract handles for allocated DebugInfos.  See
1679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   comment in priv_storage.h, declaration of struct _DebugInfo, for
1689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   details. */
1699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic ULong handle_counter = 1;
1709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
1731636d33c13958b9c0e7d3059cdd5005746418eb2florianDebugInfo* alloc_DebugInfo( const HChar* filename )
174eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
178f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
179f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
1809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo));
181a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->handle       = handle_counter++;
182a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename);
1836b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.maps     = VG_(newXA)(
1846b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_zalloc), "di.debuginfo.aDI.3",
1856b5625bb609b154766d2e138b61e15655f60b710sewardj                         ML_(dinfo_free), sizeof(struct _DebugInfoMapping));
186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
187452e89a9f847975609b3ad318943830f2cce841csewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by
188452e89a9f847975609b3ad318943830f2cce841csewardj      ML_(dinfo_zalloc).  Now set up the debugging-output flags. */
189f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
1900f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename );
191f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
194b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
197f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
198f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
201eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
202eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
20659a2d18d0ddfa241850017252b0804d469187d79sewardj   Word i, j, n;
2079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt* ent;
20859a2d18d0ddfa241850017252b0804d469187d79sewardj   GExpr* gexpr;
209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
2116b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.maps)     VG_(deleteXA)(di->fsm.maps);
212a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename);
213f1e1aa691d7a2f0f2f933daf060bec5ae6938705philippe   if (di->soname)       ML_(dinfo_free)(di->soname);
214a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->loctab)       ML_(dinfo_free)(di->loctab);
215a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi)         ML_(dinfo_free)(di->cfsi);
216a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->cfsi_exprs)   VG_(deleteXA)(di->cfsi_exprs);
217a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   if (di->fpo)          ML_(dinfo_free)(di->fpo);
218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
219a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (di->symtab) {
220a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* We have to visit all the entries so as to free up any
221a5cace0c2a3e212931badbf6398a0cd98393121asewardj         sec_names arrays that might exist. */
222a5cace0c2a3e212931badbf6398a0cd98393121asewardj      n = di->symtab_used;
223a5cace0c2a3e212931badbf6398a0cd98393121asewardj      for (i = 0; i < n; i++) {
224a5cace0c2a3e212931badbf6398a0cd98393121asewardj         DiSym* sym = &di->symtab[i];
225a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sym->sec_names)
226a5cace0c2a3e212931badbf6398a0cd98393121asewardj            ML_(dinfo_free)(sym->sec_names);
227a5cace0c2a3e212931badbf6398a0cd98393121asewardj      }
228a5cace0c2a3e212931badbf6398a0cd98393121asewardj      /* and finally .. */
229a5cace0c2a3e212931badbf6398a0cd98393121asewardj      ML_(dinfo_free)(di->symtab);
230a5cace0c2a3e212931badbf6398a0cd98393121asewardj   }
231a5cace0c2a3e212931badbf6398a0cd98393121asewardj
2322352e9843d8a616b9d829aef929d218aea9b4ae0philippe   if (di->strpool)
2332352e9843d8a616b9d829aef929d218aea9b4ae0philippe      VG_(deleteDedupPA) (di->strpool);
234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Delete the two admin arrays.  These lists exist primarily so
2369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      that we can visit each object exactly once when we need to
2379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      delete them. */
2389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (di->admin_tyents) {
2399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n = VG_(sizeXA)(di->admin_tyents);
24059a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
2419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ent = (TyEnt*)VG_(indexXA)(di->admin_tyents, i);
2429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Dump anything hanging off this ent */
2439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(TyEnt__make_EMPTY)(ent);
24459a2d18d0ddfa241850017252b0804d469187d79sewardj      }
2459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(deleteXA)(di->admin_tyents);
2469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di->admin_tyents = NULL;
247eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
24859a2d18d0ddfa241850017252b0804d469187d79sewardj
24959a2d18d0ddfa241850017252b0804d469187d79sewardj   if (di->admin_gexprs) {
25059a2d18d0ddfa241850017252b0804d469187d79sewardj      n = VG_(sizeXA)(di->admin_gexprs);
25159a2d18d0ddfa241850017252b0804d469187d79sewardj      for (i = 0; i < n; i++) {
25259a2d18d0ddfa241850017252b0804d469187d79sewardj         gexpr = *(GExpr**)VG_(indexXA)(di->admin_gexprs, i);
25359a2d18d0ddfa241850017252b0804d469187d79sewardj         ML_(dinfo_free)(gexpr);
25459a2d18d0ddfa241850017252b0804d469187d79sewardj      }
25559a2d18d0ddfa241850017252b0804d469187d79sewardj      VG_(deleteXA)(di->admin_gexprs);
25659a2d18d0ddfa241850017252b0804d469187d79sewardj      di->admin_gexprs = NULL;
257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
2797293d2530f8c60c1060f9f003e214cc341d35266philippe                  .strpool */
280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
291eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3006bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* reason = "munmap";
3014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
304eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
305eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
30833e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
30933e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
311738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                         "Discarding syms at %#lx-%#lx in %s due to %s()\n",
312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
314a5acac39bf3be7546222b1316faee5ee524be0d1sewardj                         curr->fsm.filename ? curr->fsm.filename
3151636d33c13958b9c0e7d3059cdd5005746418eb2florian                                            : "???",
3164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
31933e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
32033e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
335f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   iterations.  Returns True iff any such DebugInfos were found.
336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
337f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Bool discard_syms_in_range ( Addr start, SizeT length )
338eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
339f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool       anyFound = False;
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
345eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
363f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      anyFound = True;
364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
366f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
367f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return anyFound;
368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3916b5625bb609b154766d2e138b61e15655f60b710sewardj/* Do the basic mappings of the two DebugInfos overlap in any way? */
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3946b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
3976b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) {
3986b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i);
3996b5625bb609b154766d2e138b61e15655f60b710sewardj      for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
4006b5625bb609b154766d2e138b61e15655f60b710sewardj         struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
4016b5625bb609b154766d2e138b61e15655f60b710sewardj         if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size))
4026b5625bb609b154766d2e138b61e15655f60b710sewardj            return True;
4036b5625bb609b154766d2e138b61e15655f60b710sewardj      }
4046b5625bb609b154766d2e138b61e15655f60b710sewardj   }
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
4356b5625bb609b154766d2e138b61e15655f60b710sewardj   Clearly diRef must have its mapping information set to something sane. */
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
449eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
453eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4540f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj/* Find the existing DebugInfo for |filename| or if not found, create
4550f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   one.  In the latter case |filename| is strdup'd into VG_AR_DINFO,
4560f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   and the new DebugInfo is added to debugInfo_list. */
4571636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic DebugInfo* find_or_create_DebugInfo_for ( HChar* filename )
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
460b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
461b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
462a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      vg_assert(di->fsm.filename);
463a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (0==VG_(strcmp)(di->fsm.filename, filename))
464b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
465b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
466b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
4670f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj      di = alloc_DebugInfo(filename);
468b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
469b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
470b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
471b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
472b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
476f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Debuginfo reading for 'di' has just been successfully completed.
477f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Check that the invariants stated in
478f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
479f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   priv_storage.h are observed. */
480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void check_CFSI_related_invariants ( DebugInfo* di )
481f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
482f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di2 = NULL;
4836b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool has_nonempty_rx = False;
4846b5625bb609b154766d2e138b61e15655f60b710sewardj   Bool cfsi_fits = False;
4856b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i, j;
486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(di);
487f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* This fn isn't called until after debuginfo for this object has
488f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      been successfully read.  And that shouldn't happen until we have
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      both a r-x and rw- mapping for the object.  Hence: */
490a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rx_map);
491a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   vg_assert(di->fsm.have_rw_map);
4926b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
4936b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
4946b5625bb609b154766d2e138b61e15655f60b710sewardj      /* We are interested in r-x mappings only */
4956b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map->rx)
496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
4976b5625bb609b154766d2e138b61e15655f60b710sewardj
4986b5625bb609b154766d2e138b61e15655f60b710sewardj      /* degenerate case: r-x section is empty */
4996b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->size == 0)
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         continue;
5016b5625bb609b154766d2e138b61e15655f60b710sewardj      has_nonempty_rx = True;
5026b5625bb609b154766d2e138b61e15655f60b710sewardj
5036b5625bb609b154766d2e138b61e15655f60b710sewardj      /* normal case: r-x section is nonempty */
5046b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (0) */
5056b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(map->size > 0);
5066b5625bb609b154766d2e138b61e15655f60b710sewardj
5076b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (1) */
5086b5625bb609b154766d2e138b61e15655f60b710sewardj      for (di2 = debugInfo_list; di2; di2 = di2->next) {
5096b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di2 == di)
5106b5625bb609b154766d2e138b61e15655f60b710sewardj            continue;
5116b5625bb609b154766d2e138b61e15655f60b710sewardj         for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) {
5126b5625bb609b154766d2e138b61e15655f60b710sewardj            struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
5136b5625bb609b154766d2e138b61e15655f60b710sewardj            if (!map2->rx || map2->size == 0)
5146b5625bb609b154766d2e138b61e15655f60b710sewardj               continue;
5156b5625bb609b154766d2e138b61e15655f60b710sewardj            vg_assert(!ranges_overlap(map->avma,  map->size,
5166b5625bb609b154766d2e138b61e15655f60b710sewardj                                      map2->avma, map2->size));
5176b5625bb609b154766d2e138b61e15655f60b710sewardj         }
5186b5625bb609b154766d2e138b61e15655f60b710sewardj      }
5196b5625bb609b154766d2e138b61e15655f60b710sewardj      di2 = NULL;
5206b5625bb609b154766d2e138b61e15655f60b710sewardj
5216b5625bb609b154766d2e138b61e15655f60b710sewardj      /* invariant (2) */
5226b5625bb609b154766d2e138b61e15655f60b710sewardj      if (di->cfsi) {
5236b5625bb609b154766d2e138b61e15655f60b710sewardj         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
5246b5625bb609b154766d2e138b61e15655f60b710sewardj         /* Assume the csfi fits completely into one individual mapping
5256b5625bb609b154766d2e138b61e15655f60b710sewardj            for now. This might need to be improved/reworked later. */
5266b5625bb609b154766d2e138b61e15655f60b710sewardj         if (di->cfsi_minavma >= map->avma &&
5276b5625bb609b154766d2e138b61e15655f60b710sewardj             di->cfsi_maxavma <  map->avma + map->size)
5286b5625bb609b154766d2e138b61e15655f60b710sewardj            cfsi_fits = True;
5296b5625bb609b154766d2e138b61e15655f60b710sewardj      }
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5316b5625bb609b154766d2e138b61e15655f60b710sewardj
5326b5625bb609b154766d2e138b61e15655f60b710sewardj   /* degenerate case: all r-x sections are empty */
5336b5625bb609b154766d2e138b61e15655f60b710sewardj   if (!has_nonempty_rx) {
5346b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(di->cfsi == NULL);
5356b5625bb609b154766d2e138b61e15655f60b710sewardj      return;
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
5376b5625bb609b154766d2e138b61e15655f60b710sewardj
5386b5625bb609b154766d2e138b61e15655f60b710sewardj   /* invariant (2) - cont. */
5396b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->cfsi)
5406b5625bb609b154766d2e138b61e15655f60b710sewardj      vg_assert(cfsi_fits);
5416b5625bb609b154766d2e138b61e15655f60b710sewardj
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* invariants (3) and (4) */
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (di->cfsi) {
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used > 0);
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size > 0);
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for (i = 0; i < di->cfsi_used; i++) {
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DiCfSI* cfsi = &di->cfsi[i];
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->len > 0);
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base >= di->cfsi_minavma);
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         if (i > 0) {
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            DiCfSI* cfsip = &di->cfsi[i-1];
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            vg_assert(cfsip->base + cfsip->len <= cfsi->base);
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_used == 0);
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di->cfsi_size == 0);
559f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
560f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM             ---*/
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                        ---*/
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------*/
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid VG_(di_initialise) ( void )
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* There's actually very little to do here, since everything
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      centers around the DebugInfos in debugInfo_list, they are
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      created and destroyed on demand, and each one is treated more or
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      less independently. */
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   vg_assert(debugInfo_list == NULL);
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* flush the CFI fast query cache. */
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cfsi_cache__invalidate();
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
5824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
5854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
5864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
5874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)  ||  defined(VGO_darwin)
589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
591731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   segment has been mapped in, or unmapped, or when sections change
592731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   permission.  It's all a bit kludgey and basically means watching
593731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   syscalls, trying to second-guess when the system's dynamic linker
594731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is done with mapping in a new object for execution.  This is all
595731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   tracked using the DebugInfoFSM struct for the object.  Anyway, once
596731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   we finally decide we've got to an accept state, this section then
597731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   will acquire whatever info is available for the corresponding
598731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   object.  This section contains the notification handlers, which
599731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   update the FSM and determine when an accept state has been reached.
600731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
601731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
602731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* When the sequence of observations causes a DebugInfoFSM to move
603731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   into the accept state, call here to actually get the debuginfo read
604731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   in.  Returns a ULong whose purpose is described in comments
605731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   preceding VG_(di_notify_mmap) just below.
606731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj*/
607731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjstatic ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
608731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
609731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ULong di_handle;
610731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool  ok;
611731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
612731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.filename);
613731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
614731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ start ELF OBJECT "
615731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
616731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
617731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
618731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
619731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* We're going to read symbols and debug info for the avma
6206b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges specified in the _DebugInfoFsm mapping array. First
6216b5625bb609b154766d2e138b61e15655f60b710sewardj      get rid of any other DebugInfos which overlap any of those
6226b5625bb609b154766d2e138b61e15655f60b710sewardj      ranges (to avoid total confusion). */
623731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   discard_DebugInfos_which_overlap_with( di );
624731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
625731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* .. and acquire new info. */
626731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGO_linux)
627731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_elf_debug_info)( di );
628731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  elif defined(VGO_darwin)
629731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   ok = ML_(read_macho_debug_info)( di );
630731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  else
631731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#    error "unknown OS"
632731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
633731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
634731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (ok) {
635731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
636731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Canonicalising the "
637731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                   "acquired info ------\n");
638731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* invalidate the CFI unwind cache. */
639731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      cfsi_cache__invalidate();
640731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* prepare read data for use */
641731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      ML_(canonicaliseTables)( di );
642731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* notify m_redir about it */
643731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
644731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      VG_(redir_notify_new_DebugInfo)( di );
645731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Note that we succeeded */
646731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di->have_dinfo = True;
647731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      tl_assert(di->handle > 0);
648731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = di->handle;
649731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Check invariants listed in
650731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
651731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         priv_storage.h. */
652731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      check_CFSI_related_invariants(di);
653731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
654731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   } else {
655731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      TRACE_SYMTAB("\n------ ELF reading failed ------\n");
656731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Something went wrong (eg. bad ELF file).  Should we delete
657731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         this DebugInfo?  No - it contains info on the rw/rx
658731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         mappings, at least. */
659731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      di_handle = 0;
660731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->have_dinfo == False);
661731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
662731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
663731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
664731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ name = %s\n", di->fsm.filename);
665731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("------ end ELF OBJECT "
666731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj                "------------------------------\n");
667731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   TRACE_SYMTAB("\n");
668731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
669731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   return di_handle;
670731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
671731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
672eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
674eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
675eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
676eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
677eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
6789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Valgrind executable itself.
6799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
6805f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   If use_fd is not -1, that is used instead of the filename; this
6815f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   avoids perturbing fcntl locks, which are released by simply
6825f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   re-opening and closing the same file (even via different fd!).
6835f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
6849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   If a call to VG_(di_notify_mmap) causes debug info to be read, then
6859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the returned ULong is an abstract handle which can later be used to
6869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   refer to the debuginfo read as a result of this specific mapping,
6879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   in later queries to m_debuginfo.  In this case the handle value
6889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   will be one or above.  If the returned value is zero, no debug info
6899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   was read. */
690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
6915f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardjULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
6934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
695731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool       is_rx_map, is_rw_map, is_ro_map;
696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
6975f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   Int        actual_fd, oflags;
6985f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   SysRes     preadres;
699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
701ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   SysRes     statres;
702ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   struct vg_stat statbuf;
703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7045f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(use_fd >= -1);
7055f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
710b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
713a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("di_notify_mmap-1: %#lx-%#lx %c%c%c\n",
714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
7249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
7273e7986312a0ffc7646b0552d4c4ea3744a870e73florian   filename = VG_(am_get_filename)( seg );
728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
7299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
7310ab84fe82d1e25c2e0544d08826df42caa44ded1bart   /*
7320ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * Cannot read from these magic files:
7330ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- WARNING: Serious error when reading debug info
7340ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- When reading debug info from /proc/xen/privcmd:
7350ab84fe82d1e25c2e0544d08826df42caa44ded1bart    * --20208-- can't read file to inspect ELF header
7360ab84fe82d1e25c2e0544d08826df42caa44ded1bart    */
7370ab84fe82d1e25c2e0544d08826df42caa44ded1bart   if (VG_(strncmp)(filename, "/proc/xen/", 10) == 0)
7380ab84fe82d1e25c2e0544d08826df42caa44ded1bart      return 0;
7390ab84fe82d1e25c2e0544d08826df42caa44ded1bart
740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
743ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Only try to read debug information from regular files.  */
74415728ab41ea41bf731dcc74ac68354550ced2189bart   statres = VG_(stat)(filename, &statbuf);
745ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
746ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* stat dereferences symlinks, so we don't expect it to succeed and
747ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      yet produce something that is a symlink. */
7489c20ece00e07304f66da5f43b87ec45bc9c04550njn   vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.mode));
749ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
750ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Don't let the stat call fail silently.  Filter out some known
751ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      sources of noise before complaining, though. */
752cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(statres)) {
753ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      DebugInfo fake_di;
754ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
755e025eca1d49cdfe5a8cb58ab495763434280333asewardj      if (!quiet && VG_(clo_verbosity) > 1) {
756ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         VG_(memset)(&fake_di, 0, sizeof(fake_di));
757a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         fake_di.fsm.filename = filename;
758ec61b6509566cf36ab3968d69226cecf177cb0fesewardj         ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
759ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      }
7609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
7612ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
7622ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
763ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* Finally, the point of all this stattery: if it's not a regular file,
764ec61b6509566cf36ab3968d69226cecf177cb0fesewardj      don't try to read debug info from it. */
7659c20ece00e07304f66da5f43b87ec45bc9c04550njn   if (! VKI_S_ISREG(statbuf.mode))
7669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
767ec61b6509566cf36ab3968d69226cecf177cb0fesewardj
768ec61b6509566cf36ab3968d69226cecf177cb0fesewardj   /* no uses of statbuf below here. */
76915728ab41ea41bf731dcc74ac68354550ced2189bart
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
780eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
781eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
783eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
784eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
785eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
788eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
790eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
793eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
795eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
798eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
799eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
801eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
803f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj
804f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      2009 Aug 16: apply similar kludge to ppc32-linux.
805f56d255d644ec9a1bfa970d50a0489a816a4e736sewardj      See http://bugs.kde.org/show_bug.cgi?id=190820
806b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
807b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      There are two modes on s390x: with and without the noexec kernel
808b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      parameter. Together with some older kernels, this leads to several
809b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      variants:
810b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
811b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w and x
812b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      or
813b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      executable: r and x
814b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      data:       r and w
815eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
818731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = False;
819731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
8204df0bfc0614379192c780c944415dc420d9cfe8epetarj#  if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
8214df0bfc0614379192c780c944415dc420d9cfe8epetarj      || defined(VGA_mips64)
822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
824f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm) \
825f0c1250e324f6684757c6a15545366447ef1d64fsewardj        || defined(VGA_arm64)
826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
828b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGP_s390x_linux)
829b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
830b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   is_rw_map = seg->hasR && seg->hasW;
831eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
834eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
835731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  if defined(VGP_x86_darwin) && DARWIN_VERS == DARWIN_10_7
836731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   is_ro_map = seg->hasR && !seg->hasW && !seg->hasX;
837731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
838731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
843731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Ignore mappings with permissions we can't possibly be interested in. */
844731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (!(is_rx_map || is_rw_map || is_ro_map))
8459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return 0;
846eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
8475a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF */
8485a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   /* object file. Ignore the file if we do not have read permission. */
8495a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
850cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags = VKI_O_RDONLY;
851cec083d9a254e92623ed44e9dca080d224693c82sewardj#  if defined(VKI_O_LARGEFILE)
852cec083d9a254e92623ed44e9dca080d224693c82sewardj   oflags |= VKI_O_LARGEFILE;
853cec083d9a254e92623ed44e9dca080d224693c82sewardj#  endif
8545f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8555f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8565f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      SysRes fd = VG_(open)( filename, oflags, 0 );
8575f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      if (sr_isError(fd)) {
8585f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         if (sr_Err(fd) != VKI_EACCES) {
8595f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            DebugInfo fake_di;
8605f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            VG_(memset)(&fake_di, 0, sizeof(fake_di));
8615f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            fake_di.fsm.filename = filename;
8625f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj            ML_(symerr)(&fake_di, True,
8635f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                        "can't open file to inspect ELF header");
8645f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         }
8655f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj         return 0;
8665a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      }
8675f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = sr_Res(fd);
8685f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   } else {
8695f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      actual_fd = use_fd;
8705a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8715a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8725f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   preadres = VG_(pread)( actual_fd, buf1k, sizeof(buf1k), 0 );
8735f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (use_fd == -1) {
8745f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      VG_(close)( actual_fd );
8755f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   }
8765f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj
8775f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_isError(preadres)) {
8785a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      DebugInfo fake_di;
8795a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
880a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      fake_di.fsm.filename = filename;
8815a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header");
8825a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8835a5eec0923d55afc94165721d25125d5fc8f24d8sewardj   }
8845f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (sr_Res(preadres) == 0)
8855f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj      return 0;
8865f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
8875a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
8888b68b64759254d514d98328c496cbd88cde4c9a5njn   /* We're only interested in mappings of object files. */
8896e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  if defined(VGO_linux)
890f7c9714ea0cde18daaecb896278e85e780d3bd75sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
8915a5eec0923d55afc94165721d25125d5fc8f24d8sewardj      return 0;
8926e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  elif defined(VGO_darwin)
8935f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj   if (!ML_(is_macho_object_file)( buf1k, (SizeT)sr_Res(preadres) ))
894f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return 0;
8956e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  else
8966e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#    error "unknown OS"
8976e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#  endif
8985a5eec0923d55afc94165721d25125d5fc8f24d8sewardj
899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
9010f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   di = find_or_create_DebugInfo_for( filename );
902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
9046b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Note the details about the mapping. */
9056b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping map;
9066b5625bb609b154766d2e138b61e15655f60b710sewardj   map.avma = a;
9076b5625bb609b154766d2e138b61e15655f60b710sewardj   map.size = seg->end + 1 - seg->start;
9086b5625bb609b154766d2e138b61e15655f60b710sewardj   map.foff = seg->offset;
9096b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rx   = is_rx_map;
9106b5625bb609b154766d2e138b61e15655f60b710sewardj   map.rw   = is_rw_map;
9116b5625bb609b154766d2e138b61e15655f60b710sewardj   map.ro   = is_ro_map;
9126b5625bb609b154766d2e138b61e15655f60b710sewardj   VG_(addToXA)(di->fsm.maps, &map);
9136b5625bb609b154766d2e138b61e15655f60b710sewardj
9146b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Update flags about what kind of mappings we've already seen. */
9156b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rx_map |= is_rx_map;
9166b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_rw_map |= is_rw_map;
9176b5625bb609b154766d2e138b61e15655f60b710sewardj   di->fsm.have_ro_map |= is_ro_map;
918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
919731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* So, finally, are we in an accept state? */
920731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
921731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* Ok, so, finally, we found what we need, and we haven't
922731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         already read debuginfo for this object.  So let's do so now.
923731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         Yee-ha! */
924731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return di_notify_ACHIEVE_ACCEPT_STATE ( di );
9259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } else {
926731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* If we don't have an rx and rw mapping, or if we already have
927731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         debuginfo for this mapping for whatever reason, go no
928731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         further. */
929731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return 0;
9309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
938f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Bool anyFound;
939a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
940f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   anyFound = discard_syms_in_range(a, len);
941f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (anyFound)
942f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      cfsi_cache__invalidate();
943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
946eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
953f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  if defined(VGA_x86)
954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
956f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && !exe_ok) {
957f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Bool anyFound = discard_syms_in_range(a, len);
958f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (anyFound)
959f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfsi_cache__invalidate();
960f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
961eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
962eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
963731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
964731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj/* This is a MacOSX 10.7 32-bit only special.  See comments on the
965731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   declaration of struct _DebugInfoFSM for details. */
966731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardjvoid VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot )
967731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj{
968731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool do_nothing = True;
969ae284e5cc0830afcdec7b436564ea9f18bbedff8sewardj#  if defined(VGP_x86_darwin) && (DARWIN_VERS == DARWIN_10_7 || DARWIN_VERS == DARWIN_10_8)
970731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   do_nothing = False;
971731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj#  endif
972731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (do_nothing /* wrong platform */)
973731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return;
974731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
975731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool r_ok = toBool(prot & VKI_PROT_READ);
976731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool w_ok = toBool(prot & VKI_PROT_WRITE);
977731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   Bool x_ok = toBool(prot & VKI_PROT_EXEC);
978731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (! (r_ok && !w_ok && x_ok))
979731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* not an upgrade to r-x */
980731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
981731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   /* Find a DebugInfo containing a FSM that has [a, +len) previously
982731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      observed as a r-- mapping, plus some other rw- mapping.  If such
983731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      is found, conclude we're in an accept state and read debuginfo
984731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      accordingly. */
985731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   DebugInfo* di;
9866b5625bb609b154766d2e138b61e15655f60b710sewardj   struct _DebugInfoMapping *map = NULL;
9876b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
988731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   for (di = debugInfo_list; di; di = di->next) {
989731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      vg_assert(di->fsm.filename);
990731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->have_dinfo)
991731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* already have debuginfo for this object */
992731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_ro_map)
993731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a r-- mapping for this object */
994731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (di->fsm.have_rx_map)
995731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* rx- mapping already exists */
996731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      if (!di->fsm.have_rw_map)
997731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj         continue; /* need to have a rw- mapping */
9986b5625bb609b154766d2e138b61e15655f60b710sewardj      /* Try to find a mapping matching the memory area. */
9996b5625bb609b154766d2e138b61e15655f60b710sewardj      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10006b5625bb609b154766d2e138b61e15655f60b710sewardj         map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10016b5625bb609b154766d2e138b61e15655f60b710sewardj         if (map->ro && map->avma == a && map->size == len)
10026b5625bb609b154766d2e138b61e15655f60b710sewardj            break;
10036b5625bb609b154766d2e138b61e15655f60b710sewardj         map = NULL;
10046b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10056b5625bb609b154766d2e138b61e15655f60b710sewardj      if (!map)
10066b5625bb609b154766d2e138b61e15655f60b710sewardj         continue; /* this isn't an upgrade of an r-- mapping */
1007731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      /* looks like we're in luck! */
1008731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      break;
1009731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   }
1010731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   if (di == NULL)
1011731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj      return; /* didn't find anything */
1012731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
10136b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Do the upgrade.  Simply update the flags of the mapping
10146b5625bb609b154766d2e138b61e15655f60b710sewardj      and pretend we never saw the RO map at all. */
1015731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   vg_assert(di->fsm.have_ro_map);
10166b5625bb609b154766d2e138b61e15655f60b710sewardj   map->rx = True;
10176b5625bb609b154766d2e138b61e15655f60b710sewardj   map->ro = False;
1018731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_rx_map = True;
1019731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj   di->fsm.have_ro_map = False;
10206b5625bb609b154766d2e138b61e15655f60b710sewardj   /* See if there are any more ro mappings */
10216b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
10226b5625bb609b154766d2e138b61e15655f60b710sewardj      map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i);
10236b5625bb609b154766d2e138b61e15655f60b710sewardj      if (map->ro) {
10246b5625bb609b154766d2e138b61e15655f60b710sewardj         di->fsm.have_ro_map = True;
10256b5625bb609b154766d2e138b61e15655f60b710sewardj         break;
10266b5625bb609b154766d2e138b61e15655f60b710sewardj      }
10276b5625bb609b154766d2e138b61e15655f60b710sewardj   }
10286b5625bb609b154766d2e138b61e15655f60b710sewardj
10296b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Check if we're now in an accept state and read debuginfo.  Finally. */
10306b5625bb609b154766d2e138b61e15655f60b710sewardj   if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) {
10316b5625bb609b154766d2e138b61e15655f60b710sewardj      ULong di_handle __attribute__((unused))
10326b5625bb609b154766d2e138b61e15655f60b710sewardj         = di_notify_ACHIEVE_ACCEPT_STATE( di );
10336b5625bb609b154766d2e138b61e15655f60b710sewardj      /* di_handle is ignored. That's not a problem per se -- it just
10346b5625bb609b154766d2e138b61e15655f60b710sewardj         means nobody will ever be able to refer to this debuginfo by
10356b5625bb609b154766d2e138b61e15655f60b710sewardj         handle since nobody will know what the handle value is. */
10366b5625bb609b154766d2e138b61e15655f60b710sewardj   }
1037731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj}
1038731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1039731f9cf9fd4d507b44f1a0fdc2d3b8e8efae02e3sewardj
1040c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------- PDB (windows debug info) reading --------- */
1041c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1042c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/* this should really return ULong, as per VG_(di_notify_mmap). */
1043c8259b85b701d25d72aabe9dc0a8154517f96913sewardjvoid VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
104454c45db2f978055aeca91aaccb05aac825523e6csewardj                                   SizeT total_size, PtrdiffT bias_obj )
1045c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
104613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   Int    i, r, sz_exename;
1047c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   ULong  obj_mtime, pdb_mtime;
104854fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorian   HChar  exename[VKI_PATH_MAX];
10491636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* pdbname = NULL;
10501636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar* dot;
1051c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SysRes sres;
1052c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Int    fd_pdbimage;
1053c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   SizeT  n_pdbimage;
1054c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   struct vg_stat stat_buf;
1055c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1056c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1057738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "\n");
1058c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(message)(Vg_UserMsg,
1059cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj         "LOAD_PDB_DEBUGINFO: clreq:   fd=%d, avma=%#lx, total_size=%lu, "
106054c45db2f978055aeca91aaccb05aac825523e6csewardj         "bias=%#lx\n",
106154c45db2f978055aeca91aaccb05aac825523e6csewardj         fd_obj, avma_obj, total_size, bias_obj
1062c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      );
1063c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1064c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1065c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* 'fd' refers to the .exe/.dll we're dealing with.  Get its modification
1066c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      time into obj_mtime. */
1067c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   r = VG_(fstat)(fd_obj, &stat_buf);
1068c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (r == -1)
1069c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* stat failed ?! */
1070c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(r == 0);
10719c20ece00e07304f66da5f43b87ec45bc9c04550njn   obj_mtime = stat_buf.mtime;
1072c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1073c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* and get its name into exename[]. */
1074c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(VKI_PATH_MAX > 100); /* to ensure /proc/self/fd/%d is safe */
1075c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(memset)(exename, 0, sizeof(exename));
1076c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   VG_(sprintf)(exename, "/proc/self/fd/%d", fd_obj);
1077c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* convert exename from a symlink to real name .. overwrites the
1078c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      old contents of the buffer.  Ick. */
1079c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sz_exename = VG_(readlink)(exename, exename, sizeof(exename)-2 );
1080c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (sz_exename == -1)
1081c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out; /* readlink failed ?! */
1082c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(sz_exename >= 0 && sz_exename < sizeof(exename));
1083c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   vg_assert(exename[sizeof(exename)-1] == 0);
1084c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1085c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0) {
1086738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: objname: %s\n", exename);
1087c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1088c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
108913ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try to get the PDB file name from the executable. */
109013ac96dea734b3933a73524b991ac64fb48a4d57sewardj   pdbname = ML_(find_name_of_pdb_file)(exename);
109113ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (pdbname) {
109213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(VG_(strlen)(pdbname) >= 5); /* 5 = strlen("X.pdb") */
109313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* So we successfully extracted a name from the PE file.  But it's
109413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         likely to be of the form
109513ac96dea734b3933a73524b991ac64fb48a4d57sewardj            e:\foo\bar\xyzzy\wibble.pdb
109613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         and we need to change it into something we can actually open
109713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         in Wine-world, which basically means turning it into
109813ac96dea734b3933a73524b991ac64fb48a4d57sewardj            $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
109913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         We also take into account $WINEPREFIX, if it is set.
110013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         For the moment, if the name isn't fully qualified, just forget it
110113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         (we'd have to root around to find where the pdb actually is)
110213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      */
110313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Change all the backslashes to forward slashes */
110413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      for (i = 0; pdbname[i]; i++) {
110513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         if (pdbname[i] == '\\')
110613ac96dea734b3933a73524b991ac64fb48a4d57sewardj            pdbname[i] = '/';
110713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
110813ac96dea734b3933a73524b991ac64fb48a4d57sewardj      Bool is_quald
110913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         = ('a' <= VG_(tolower)(pdbname[0]) && VG_(tolower)(pdbname[0]) <= 'z')
111013ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[1] == ':'
111113ac96dea734b3933a73524b991ac64fb48a4d57sewardj           && pdbname[2] == '/';
111213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* home = VG_(getenv)("HOME");
111313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      HChar* wpfx = VG_(getenv)("WINEPREFIX");
111413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (is_quald && wpfx) {
111513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
111613ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $WINEPREFIX/drive_e/foo/bar/xyzzy/wibble.pdb
111713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
111813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(wpfx) + 50/*misc*/;
111913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.1", mashedSzB);
112098500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/drive_%c%s",
112198500e2ee5f63f9c0af57835f7620d30848115f4bart                       wpfx, pdbname[0], &pdbname[2]);
112213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
112313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
112413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
112513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
112613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else if (is_quald && home && !wpfx) {
112713ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* Change e:/foo/bar/xyzzy/wibble.pdb
112813ac96dea734b3933a73524b991ac64fb48a4d57sewardj                to $HOME/.wine/drive_e/foo/bar/xyzzy/wibble.pdb
112913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         */
113013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Int mashedSzB = VG_(strlen)(pdbname) + VG_(strlen)(home) + 50/*misc*/;
113113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         HChar* mashed = ML_(dinfo_zalloc)("di.debuginfo.dnpdi.2", mashedSzB);
113298500e2ee5f63f9c0af57835f7620d30848115f4bart         VG_(snprintf)(mashed, mashedSzB, "%s/.wine/drive_%c%s",
113398500e2ee5f63f9c0af57835f7620d30848115f4bart		       home, pdbname[0], &pdbname[2]);
113413ac96dea734b3933a73524b991ac64fb48a4d57sewardj         vg_assert(mashed[mashedSzB-1] == 0);
113513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
113613ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = mashed;
113713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      } else {
113813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         /* It's not a fully qualified path, or neither $HOME nor $WINE
113913ac96dea734b3933a73524b991ac64fb48a4d57sewardj            are set (strange).  Give up. */
114013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         ML_(dinfo_free)(pdbname);
114113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         pdbname = NULL;
114213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      }
114313ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1144c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
114513ac96dea734b3933a73524b991ac64fb48a4d57sewardj   /* Try s/exe/pdb/ if we don't have a valid pdbname. */
114613ac96dea734b3933a73524b991ac64fb48a4d57sewardj   if (!pdbname) {
114713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Try to find a matching PDB file from which to read debuginfo.
114813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         Windows PE files have symbol tables and line number information,
114913ac96dea734b3933a73524b991ac64fb48a4d57sewardj         but MSVC doesn't seem to use them. */
115013ac96dea734b3933a73524b991ac64fb48a4d57sewardj      /* Why +5 ?  Because in the worst case, we could find a dot as the
115113ac96dea734b3933a73524b991ac64fb48a4d57sewardj         last character of pdbname, and we'd then put "pdb" right after
115213ac96dea734b3933a73524b991ac64fb48a4d57sewardj         it, hence extending it a bit. */
115313ac96dea734b3933a73524b991ac64fb48a4d57sewardj      pdbname = ML_(dinfo_zalloc)("di.debuginfo.lpd1", sz_exename+5);
115413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      VG_(strcpy)(pdbname, exename);
115513ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
115613ac96dea734b3933a73524b991ac64fb48a4d57sewardj      dot = VG_(strrchr)(pdbname, '.');
115713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (!dot)
115813ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* there's no dot in the exe's name ?! */
115913ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if (dot[1] == 0)
116013ac96dea734b3933a73524b991ac64fb48a4d57sewardj         goto out; /* hmm, path ends in "." */
116113ac96dea734b3933a73524b991ac64fb48a4d57sewardj
116213ac96dea734b3933a73524b991ac64fb48a4d57sewardj      if ('A' <= dot[1] && dot[1] <= 'Z')
116313ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".PDB");
116413ac96dea734b3933a73524b991ac64fb48a4d57sewardj      else
116513ac96dea734b3933a73524b991ac64fb48a4d57sewardj         VG_(strcpy)(dot, ".pdb");
116613ac96dea734b3933a73524b991ac64fb48a4d57sewardj
116713ac96dea734b3933a73524b991ac64fb48a4d57sewardj      vg_assert(pdbname[sz_exename+5-1] == 0);
116813ac96dea734b3933a73524b991ac64fb48a4d57sewardj   }
1169c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1170c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* See if we can find it, and check it's in-dateness. */
1171c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(stat)(pdbname, &stat_buf);
1172cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1173738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s\n",
1174c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbname);
1175c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1176738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: missing: %s\n", pdbname);
1177c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1178c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
11799c20ece00e07304f66da5f43b87ec45bc9c04550njn   pdb_mtime = stat_buf.mtime;
11807138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj
1181ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj   if (obj_mtime > pdb_mtime + 60ULL) {
11827138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      /* PDB file is older than PE file.  Really, the PDB should be
11837138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         newer than the PE, but that doesn't always seem to be the
11847138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         case.  Allow the PDB to be up to one minute older.
11857138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         Otherwise, it's probably out of date, in which case ignore it
11867138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         or we will either (a) print wrong stack traces or more likely
11877138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj         (b) crash.
11887138ef060dce6c67500c5cb16daa503b6ce71dc6sewardj      */
1189738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg,
1190ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   "Warning:       %s (mtime = %llu)\n"
1191ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   " is older than %s (mtime = %llu)\n",
1192ced85060ebfd32f26de8e6a6f11567c9ac2b096asewardj                   pdbname, pdb_mtime, exename, obj_mtime);
1193c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1194c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1195c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   sres = VG_(open)(pdbname, VKI_O_RDONLY, 0);
1196cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1197738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "Warning: Can't open %s\n", pdbname);
1198c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1199c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1200c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1201cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   /* Looks promising; go on to try and read stuff from it.  But don't
1202cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      mmap the file.  Instead mmap free space and read the file into
1203cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      it.  This is because files on CIFS filesystems that are mounted
1204cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      '-o directio' can't be mmap'd, and that mount option is needed
1205cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      to make CIFS work reliably.  (See
1206cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      http://www.nabble.com/Corrupted-data-on-write-to-
1207cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                            Windows-2003-Server-t2782623.html)
1208cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      This is slower, but at least it works reliably. */
1209cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   fd_pdbimage = sr_Res(sres);
12109c20ece00e07304f66da5f43b87ec45bc9c04550njn   n_pdbimage  = stat_buf.size;
1211cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (n_pdbimage == 0 || n_pdbimage > 0x7FFFFFFF) {
1212cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // 0x7FFFFFFF: why?  Because the VG_(read) just below only
1213cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // can deal with a signed int as the size of data to read,
1214cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // so we can't reliably check for read failure for files
1215cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // greater than that size.  Hence just skip them; we're
1216cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      // unlikely to encounter a PDB that large anyway.
1217cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1218cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1219cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1220cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   sres = VG_(am_mmap_anon_float_valgrind)( n_pdbimage );
1221cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
1222c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(close)(fd_pdbimage);
1223c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      goto out;
1224c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1225c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1226cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   void* pdbimage = (void*)sr_Res(sres);
1227cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   r = VG_(read)( fd_pdbimage, pdbimage, (Int)n_pdbimage );
1228cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   if (r < 0 || r != (Int)n_pdbimage) {
1229cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1230cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      VG_(close)(fd_pdbimage);
1231cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj      goto out;
1232cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj   }
1233cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1234c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (VG_(clo_verbosity) > 0)
1235738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: pdbname: %s\n", pdbname);
1236c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1237c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* play safe; always invalidate the CFI cache.  I don't know if
1238c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      this is necessary, but anyway .. */
1239c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   cfsi_cache__invalidate();
1240c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* dump old info for this range, if any */
1241c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   discard_syms_in_range( avma_obj, total_size );
1242c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12430f4126c9b5898dde89473d5993c98dd4d41ee8b7sewardj   { DebugInfo* di = find_or_create_DebugInfo_for(exename);
1244c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1245c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* this di must be new, since we just nuked any old stuff in the range */
1246a5acac39bf3be7546222b1316faee5ee524be0d1sewardj     vg_assert(di && !di->fsm.have_rx_map && !di->fsm.have_rw_map);
1247c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(!di->have_dinfo);
1248c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1249c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     /* don't set up any of the di-> fields; let
1250c8259b85b701d25d72aabe9dc0a8154517f96913sewardj        ML_(read_pdb_debug_info) do it. */
125154c45db2f978055aeca91aaccb05aac825523e6csewardj     ML_(read_pdb_debug_info)( di, avma_obj, bias_obj,
1252c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                               pdbimage, n_pdbimage, pdbname, pdb_mtime );
1253c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // JRS fixme: take notice of return value from read_pdb_debug_info,
1254c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     // and handle failure
1255c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     vg_assert(di->have_dinfo); // fails if PDB read failed
1256c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(am_munmap_valgrind)( (Addr)pdbimage, n_pdbimage );
1257c8259b85b701d25d72aabe9dc0a8154517f96913sewardj     VG_(close)(fd_pdbimage);
1258cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj
1259cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     if (VG_(clo_verbosity) > 0) {
1260cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj        VG_(message)(Vg_UserMsg, "LOAD_PDB_DEBUGINFO: done:    "
1261cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                                 "%lu syms, %lu src locs, %lu fpo recs\n",
1262cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj                     di->symtab_used, di->loctab_used, di->fpo_size);
1263cd458d28a6a18ab7e1516ae0c05eeaaaa2512f47sewardj     }
1264c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
1265c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
1266c8259b85b701d25d72aabe9dc0a8154517f96913sewardj  out:
1267c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (pdbname) ML_(dinfo_free)(pdbname);
1268c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
1269c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
12708b68b64759254d514d98328c496cbd88cde4c9a5njn#endif /* defined(VGO_linux) || defined(VGO_darwin) */
12714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
12724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1273eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1274eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1275eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
1276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
1277eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1278eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
12799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid VG_(di_discard_ALL_debuginfo)( void )
12809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
12819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo *di, *di2;
12829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   di = debugInfo_list;
12839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   while (di) {
12849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di2 = di->next;
12859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("XXX rm %p\n", di);
12869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      free_DebugInfo( di );
12879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      di = di2;
12889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
12899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
12909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
12926b5625bb609b154766d2e138b61e15655f60b710sewardjstruct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di,
12936b5625bb609b154766d2e138b61e15655f60b710sewardj                                                 Addr lo, Addr hi )
12946b5625bb609b154766d2e138b61e15655f60b710sewardj{
12956b5625bb609b154766d2e138b61e15655f60b710sewardj   Word i;
12966b5625bb609b154766d2e138b61e15655f60b710sewardj   vg_assert(lo <= hi);
12976b5625bb609b154766d2e138b61e15655f60b710sewardj
12986b5625bb609b154766d2e138b61e15655f60b710sewardj   /* Optimization: Try to use the last matched rx mapping first */
12996b5625bb609b154766d2e138b61e15655f60b710sewardj   if (   di->last_rx_map
13006b5625bb609b154766d2e138b61e15655f60b710sewardj       && lo >= di->last_rx_map->avma
13016b5625bb609b154766d2e138b61e15655f60b710sewardj       && hi <  di->last_rx_map->avma + di->last_rx_map->size)
13026b5625bb609b154766d2e138b61e15655f60b710sewardj      return di->last_rx_map;
13036b5625bb609b154766d2e138b61e15655f60b710sewardj
13046b5625bb609b154766d2e138b61e15655f60b710sewardj   for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
13056b5625bb609b154766d2e138b61e15655f60b710sewardj      struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
13066b5625bb609b154766d2e138b61e15655f60b710sewardj      if (   map->rx && map->size > 0
13076b5625bb609b154766d2e138b61e15655f60b710sewardj          && lo >= map->avma && hi < map->avma + map->size) {
13086b5625bb609b154766d2e138b61e15655f60b710sewardj         di->last_rx_map = map;
13096b5625bb609b154766d2e138b61e15655f60b710sewardj         return map;
13106b5625bb609b154766d2e138b61e15655f60b710sewardj      }
13116b5625bb609b154766d2e138b61e15655f60b710sewardj   }
13126b5625bb609b154766d2e138b61e15655f60b710sewardj
13136b5625bb609b154766d2e138b61e15655f60b710sewardj   return NULL;
13146b5625bb609b154766d2e138b61e15655f60b710sewardj}
13156b5625bb609b154766d2e138b61e15655f60b710sewardj
13166b5625bb609b154766d2e138b61e15655f60b710sewardj
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
1319eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
1320eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
1321eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1322eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
1323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
1324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
1325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
1326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
1327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
1328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1329f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* symno,
1330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
1331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
1332eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1333f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
1336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
134051c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj         /* Consider any symbol in the r-x mapped area to be text.
134151c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            See Comment_Regarding_Text_Range_Checks in storage.c for
134251c9d3750448a4f2c95d22879e2f9f4bbd22bcfesewardj            details. */
1343a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         inRange = di->fsm.have_rx_map
13446b5625bb609b154766d2e138b61e15655f60b710sewardj                   && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL);
1345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
1346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
1347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
1348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
1349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
1350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
1352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
1353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
1354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
1355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
1356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
1357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
1358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
13595706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->bss_avma + di->bss_size)
13605706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13615706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->sbss_present
13625706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_size > 0
13635706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->sbss_avma <= ptr
13645706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->sbss_avma + di->sbss_size)
13655706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   ||
13665706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                   (di->rodata_present
13675706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_size > 0
13685706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && di->rodata_avma <= ptr
13695706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj                    && ptr < di->rodata_avma + di->rodata_size);
1370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
1373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
1375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
1376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
1377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
1378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
1379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
1380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
1388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
1389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
1390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
1391f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                           /*OUT*/Word* locno )
1392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1393f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       lno;
1394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
13975706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
1399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
1400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
1401eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
1402eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
1403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
1404eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
1405eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1406eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1407eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
1408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
1409eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1410eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1411eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1412eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
1413eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
14146b7611bf42a0fbb62e047d8c43b008205bd21e75njn   Caller supplies buf and nbuf.  If do_cxx_demangling is False, don't do
14156b7611bf42a0fbb62e047d8c43b008205bd21e75njn   C++ demangling, regardless of VG_(clo_demangle) -- probably because the
14166b7611bf42a0fbb62e047d8c43b008205bd21e75njn   call has come from VG_(get_fnname_raw)().  findText
1417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
1418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
1419eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
14206b7611bf42a0fbb62e047d8c43b008205bd21e75njnBool get_sym_name ( Bool do_cxx_demangling, Bool do_z_demangling,
14216b7611bf42a0fbb62e047d8c43b008205bd21e75njn                    Bool do_below_main_renaming,
14221636d33c13958b9c0e7d3059cdd5005746418eb2florian                    Addr a, HChar* buf, Int nbuf,
1423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
1424c4431bfe04c7490ea2d74939d222d87f13f30960njn                    Bool findText, /*OUT*/PtrdiffT* offsetP )
1425eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1427f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1428c4431bfe04c7490ea2d74939d222d87f13f30960njn   PtrdiffT   offset;
1429eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
1431b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
1432eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
14336882443ef154bca367bc591287de641e43a9e108njn
1434a5cace0c2a3e212931badbf6398a0cd98393121asewardj   vg_assert(di->symtab[sno].pri_name);
14356b7611bf42a0fbb62e047d8c43b008205bd21e75njn   VG_(demangle) ( do_cxx_demangling, do_z_demangling,
1436a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   di->symtab[sno].pri_name, buf, nbuf );
14376b7611bf42a0fbb62e047d8c43b008205bd21e75njn
14386b7611bf42a0fbb62e047d8c43b008205bd21e75njn   /* Do the below-main hack */
14396b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // To reduce the endless nuisance of multiple different names
14406b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // for "the frame below main()" screwing up the testsuite, change all
14416b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // known incarnations of said into a single name, "(below main)", if
14426b7611bf42a0fbb62e047d8c43b008205bd21e75njn   // --show-below-main=yes.
14436b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if ( do_below_main_renaming && ! VG_(clo_show_below_main) &&
14446b7611bf42a0fbb62e047d8c43b008205bd21e75njn        Vg_FnNameBelowMain == VG_(get_fnname_kind)(buf) )
14456b7611bf42a0fbb62e047d8c43b008205bd21e75njn   {
14466b7611bf42a0fbb62e047d8c43b008205bd21e75njn      VG_(strncpy_safely)(buf, "(below main)", nbuf);
1447eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
1449c4431bfe04c7490ea2d74939d222d87f13f30960njn   if (offsetP) *offsetP = offset;
1450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1451eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
14521636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar    buf2[12];
14531636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   symend = buf + VG_(strlen)(buf);
14541636d33c13958b9c0e7d3059cdd5005746418eb2florian      HChar*   end = buf + nbuf;
1455eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
1456eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1457c4431bfe04c7490ea2d74939d222d87f13f30960njn      len = VG_(sprintf)(buf2, "%c%ld",
1458eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
1459eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
1460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
1461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
14631636d33c13958b9c0e7d3059cdd5005746418eb2florian	 HChar *cp = buf2;
1464eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
1465eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1466eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1467eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
14686b7611bf42a0fbb62e047d8c43b008205bd21e75njn   buf[nbuf-1] = 0; /* paranoia */
14696b7611bf42a0fbb62e047d8c43b008205bd21e75njn
1470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
1474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
1475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
1476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
1477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1478b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1479f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       sno;
1480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
1481b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
1482b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
1483b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
1484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
1487eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1489eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
14921636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname) ( Addr a, HChar* buf, Int nbuf )
1493eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
14946b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
14956b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
14966b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1500b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1501eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1504eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
15051636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_w_offset) ( Addr a, HChar* buf, Int nbuf )
1506eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15076b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
15086b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15096b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
1512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
15191636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_if_entry) ( Addr a, HChar* buf, Int nbuf )
1520eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15216b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/True, /*Z-demangle*/True,
15226b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15236b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1526b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1528eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1529eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15306b7611bf42a0fbb62e047d8c43b008205bd21e75njn/* This is only available to core... don't C++-demangle, don't Z-demangle,
15316b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't rename below-main, match anywhere in function, and don't show
15326b7611bf42a0fbb62e047d8c43b008205bd21e75njn   offsets. */
15331636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_raw) ( Addr a, HChar* buf, Int nbuf )
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15356b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
15366b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/False,
15376b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
1538b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1539b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1540b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1541b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
15456b7611bf42a0fbb62e047d8c43b008205bd21e75njn   do Z-demangling and below-main-renaming, match anywhere in function, and
15466b7611bf42a0fbb62e047d8c43b008205bd21e75njn   don't show offsets. */
15471636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_fnname_no_cxx_demangle) ( Addr a, HChar* buf, Int nbuf )
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
15496b7611bf42a0fbb62e047d8c43b008205bd21e75njn   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/True,
15506b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*below-main-renaming*/True,
15516b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         a, buf, nbuf,
15526b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*match_anywhere_in_fun*/True,
15536b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*show offset?*/False,
15546b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*text syms only*/True,
15556b7611bf42a0fbb62e047d8c43b008205bd21e75njn                         /*offsetP*/NULL );
1556eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1557eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
15585db15403e889d4db339b342bc2a824ef0bfaa654sewardj/* mips-linux only: find the offset of current address. This is needed for
15595db15403e889d4db339b342bc2a824ef0bfaa654sewardj   stack unwinding for MIPS.
15605db15403e889d4db339b342bc2a824ef0bfaa654sewardj*/
15615db15403e889d4db339b342bc2a824ef0bfaa654sewardjBool VG_(get_inst_offset_in_function)( Addr a,
15625db15403e889d4db339b342bc2a824ef0bfaa654sewardj                                       /*OUT*/PtrdiffT* offset )
15635db15403e889d4db339b342bc2a824ef0bfaa654sewardj{
15641636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar fnname[64];
15655db15403e889d4db339b342bc2a824ef0bfaa654sewardj   return get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
15665db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*below-main-renaming*/False,
15675db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         a, fnname, 64,
15685db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*match_anywhere_in_sym*/True,
15695db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*show offset?*/True,
15705db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         /*data syms only please*/True,
15715db15403e889d4db339b342bc2a824ef0bfaa654sewardj                         offset );
15725db15403e889d4db339b342bc2a824ef0bfaa654sewardj}
15735db15403e889d4db339b342bc2a824ef0bfaa654sewardj
15741636d33c13958b9c0e7d3059cdd5005746418eb2florianVg_FnNameKind VG_(get_fnname_kind) ( HChar* name )
15756882443ef154bca367bc591287de641e43a9e108njn{
15766882443ef154bca367bc591287de641e43a9e108njn   if (VG_STREQ("main", name)) {
15776882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameMain;
15786882443ef154bca367bc591287de641e43a9e108njn
15796882443ef154bca367bc591287de641e43a9e108njn   } else if (
15803026f71684a930286186aa10fef266c304672e8fsewardj#      if defined(VGO_linux)
15816882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("__libc_start_main",  name) ||  // glibc glibness
15826882443ef154bca367bc591287de641e43a9e108njn       VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
15833026f71684a930286186aa10fef266c304672e8fsewardj#      elif defined(VGO_darwin)
1584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       // See readmacho.c for an explanation of this.
1585f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
15863026f71684a930286186aa10fef266c304672e8fsewardj#      else
15873026f71684a930286186aa10fef266c304672e8fsewardj#        error "Unknown OS"
15883026f71684a930286186aa10fef266c304672e8fsewardj#      endif
15896882443ef154bca367bc591287de641e43a9e108njn       0) {
15906882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameBelowMain;
15916882443ef154bca367bc591287de641e43a9e108njn
15926882443ef154bca367bc591287de641e43a9e108njn   } else {
15936882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;
15946882443ef154bca367bc591287de641e43a9e108njn   }
15956882443ef154bca367bc591287de641e43a9e108njn}
15966882443ef154bca367bc591287de641e43a9e108njn
15976882443ef154bca367bc591287de641e43a9e108njnVg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip )
15986882443ef154bca367bc591287de641e43a9e108njn{
15996882443ef154bca367bc591287de641e43a9e108njn   // We don't need a big buffer;  all the special names are small.
16006882443ef154bca367bc591287de641e43a9e108njn   #define BUFLEN 50
16011636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar buf[50];
16026882443ef154bca367bc591287de641e43a9e108njn
16036882443ef154bca367bc591287de641e43a9e108njn   // We don't demangle, because it's faster not to, and the special names
16046882443ef154bca367bc591287de641e43a9e108njn   // we're looking for won't be demangled.
16056b7611bf42a0fbb62e047d8c43b008205bd21e75njn   if (VG_(get_fnname_raw) ( ip, buf, BUFLEN )) {
16066882443ef154bca367bc591287de641e43a9e108njn      buf[BUFLEN-1] = '\0';      // paranoia
16076882443ef154bca367bc591287de641e43a9e108njn      return VG_(get_fnname_kind)(buf);
16086882443ef154bca367bc591287de641e43a9e108njn   } else {
16096882443ef154bca367bc591287de641e43a9e108njn      return Vg_FnNameNormal;    // Don't know the name, treat it as normal.
16106882443ef154bca367bc591287de641e43a9e108njn   }
16116882443ef154bca367bc591287de641e43a9e108njn}
16126882443ef154bca367bc591287de641e43a9e108njn
1613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
16181636d33c13958b9c0e7d3059cdd5005746418eb2florian                                  /*OUT*/HChar* dname, Int n_dname,
1619c4431bfe04c7490ea2d74939d222d87f13f30960njn                                  /*OUT*/PtrdiffT* offset )
1620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1621b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1622b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
16236b7611bf42a0fbb62e047d8c43b008205bd21e75njn   ok = get_sym_name ( /*C++-demangle*/False, /*Z-demangle*/False,
16246b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       /*below-main-renaming*/False,
16256b7611bf42a0fbb62e047d8c43b008205bd21e75njn                       data_addr, dname, n_dname,
1626b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
16391636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_objname) ( Addr a, HChar* buf, Int nbuf )
1640eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1642f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1643f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
16444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
16457cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Look in the debugInfo_list to find the name.  In most cases we
16467cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      expect this to produce a result. */
1647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16495706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1652a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         VG_(strncpy_safely)(buf, di->fsm.filename, nbuf);
16534ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1654eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1655eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1656eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
16577cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   /* Last-ditch fallback position: if we don't find the address in
16587cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      the debugInfo_list, ask the address space manager whether it
16597cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      knows the name of the file associated with this mapping.  This
16607cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      allows us to print the names of exe/dll files in the stack trace
16617cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj      when running programs under wine. */
16627cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj   if ( (seg = VG_(am_find_nsegment(a))) != NULL
16637cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj        && (filename = VG_(am_get_filename)(seg)) != NULL ) {
1664f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1665f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1666f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1667eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1668eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1669eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1671eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1672e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjDebugInfo* VG_(find_DebugInfo) ( Addr a )
1673eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1674e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   static UWord n_search = 0;
1675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1676e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj   n_search++;
1677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
16795706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->text_size > 0
1680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1682e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj         if (0 == (n_search & 0xF))
1683e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            move_DebugInfo_one_step_forward( di );
1684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1685eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1686eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1687eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1688eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1689eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1690eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
16911636d33c13958b9c0e7d3059cdd5005746418eb2florianBool VG_(get_filename)( Addr a, HChar* filename, Int n_filename )
1692eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1694f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1695eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1696eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1697eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1698eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1699eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1701eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1706f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1708eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1709eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
17191636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* filename, Int n_filename,
17201636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 /*OUT*/HChar* dirname,  Int n_dirname,
1721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1725f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       locno;
1726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1728eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1729eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1730eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1731eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1732c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1733db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1734db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1735db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1736db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1737eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1738c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1739c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1740eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1741eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1742eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1743eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1744eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1745eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1746eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1747eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1748eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1749eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1750eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1751eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1752eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1753eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1754eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1755eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1756eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1757eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1758eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1759eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1760eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1761eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
17624ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
17634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
17644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
17654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
17664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
17674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
17684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
17696bd9dc18c043927c1196caba20a327238a179c42florianBool VG_(lookup_symbol_SLOW)(const HChar* sopatt, HChar* name,
1770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
17714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
17724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
17734ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
17754ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
17764ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
17774ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
17784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
17804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
17814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
17824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
17834ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
17844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
17854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
17864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
17874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
17881636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* pri_name = si->symtab[i].pri_name;
1789a5cace0c2a3e212931badbf6398a0cd98393121asewardj         tl_assert(pri_name);
1790a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (0==VG_(strcmp)(name, pri_name)
17914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
17924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
17934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
17944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
17954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
17961636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar** sec_names = si->symtab[i].sec_names;
1797a5cace0c2a3e212931badbf6398a0cd98393121asewardj         if (sec_names) {
1798a5cace0c2a3e212931badbf6398a0cd98393121asewardj            tl_assert(sec_names[0]);
1799a5cace0c2a3e212931badbf6398a0cd98393121asewardj            while (*sec_names) {
1800a5cace0c2a3e212931badbf6398a0cd98393121asewardj               if (0==VG_(strcmp)(name, *sec_names)
1801a5cace0c2a3e212931badbf6398a0cd98393121asewardj                   && (require_pToc ? si->symtab[i].tocptr : True)) {
1802a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pEnt = si->symtab[i].addr;
1803a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  *pToc = si->symtab[i].tocptr;
1804a5cace0c2a3e212931badbf6398a0cd98393121asewardj                  return True;
1805a5cace0c2a3e212931badbf6398a0cd98393121asewardj               }
1806a5cace0c2a3e212931badbf6398a0cd98393121asewardj               sec_names++;
1807a5cace0c2a3e212931badbf6398a0cd98393121asewardj            }
1808a5cace0c2a3e212931badbf6398a0cd98393121asewardj         }
18094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
18104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
18114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
18124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
18134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
18144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1815e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1816e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1817e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1818e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1819e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
18211636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStr ( Int n, Int n_buf, HChar* buf, const HChar* str )
1822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1823e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1824e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1825eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1827e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1828eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1829eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1830eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1831e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1832e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1833e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1834e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
18351636d33c13958b9c0e7d3059cdd5005746418eb2florianstatic Int putStrEsc ( Int n, Int n_buf, Int count, HChar* buf, HChar* str )
1836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
18371636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar alt[2];
1838e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1839e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1840e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1841eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1842e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1843e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1844e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1845eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1846e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1847e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1848e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1849e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1850e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1851e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1852e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1853e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1854e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1855e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1856e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1857e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1858e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1859e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1860e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1861e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1862e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1863e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1864e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1865e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1866e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1867e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1869eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1870e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1871e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1872e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1873eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
18761636d33c13958b9c0e7d3059cdd5005746418eb2florianHChar* VG_(describe_IP)(Addr eip, HChar* buf, Int n_buf)
1877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1879e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1880e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1881e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1882eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1883eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
18851636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar ibuf[50];
1886eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
188714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
18881636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_fn[BUF_LEN];
18891636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_obj[BUF_LEN];
18901636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_srcloc[BUF_LEN];
18911636d33c13958b9c0e7d3059cdd5005746418eb2florian   static HChar buf_dirname[BUF_LEN];
189214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn[0] = buf_obj[0] = buf_srcloc[0] = buf_dirname[0] = 0;
189314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1894eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
18954ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
18964ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
18974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1899eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1900eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1901eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1904eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
190514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_fn     [ sizeof(buf_fn)-1      ]  = 0;
190614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_obj    [ sizeof(buf_obj)-1     ]  = 0;
190714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_srcloc [ sizeof(buf_srcloc)-1  ]  = 0;
190814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj   buf_dirname[ sizeof(buf_dirname)-1 ]  = 0;
190914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj
1910eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1912eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
19136bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline  = human_readable ? "\n      " : "";
19146bd9dc18c043927c1196caba20a327238a179c42florian      const HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1915eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1916e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1917e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1918e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1919e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1920e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1921e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1923a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1925eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1927eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1929e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1930eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1931eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1932eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1935e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1942e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1946eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1947e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1958eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1959eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
19615e40abad4504416c59f0b29c1cfc8087201213a9njn      //
19625e40abad4504416c59f0b29c1cfc8087201213a9njn      // Possible forms:
19635e40abad4504416c59f0b29c1cfc8087201213a9njn      //
19645e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (a.c:20)
19655e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in /foo/a.out)
19665e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: really (in ???)
19675e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (in /foo/a.out)
19685e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ??? (a.c:20)
19695e40abad4504416c59f0b29c1cfc8087201213a9njn      //   0x80483BF: ???
19705e40abad4504416c59f0b29c1cfc8087201213a9njn      //
1971a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1972eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
19735e40abad4504416c59f0b29c1cfc8087201213a9njn      if (know_fnname) {
1974eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1975eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1976eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1977eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1978eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1979eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
198014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // Get the directory name, if any, possibly pruned, into dirname.
19811636d33c13958b9c0e7d3059cdd5005746418eb2florian         HChar* dirname = NULL;
198214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (VG_(clo_n_fullpath_after) > 0) {
198314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            Int i;
198414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            dirname = buf_dirname;
198514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // Remove leading prefixes from the dirname.
198614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // If user supplied --fullpath-after=foo, this will remove
198714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            // a leading string which matches '.*foo' (not greedy).
198814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            for (i = 0; i < VG_(clo_n_fullpath_after); i++) {
19891636d33c13958b9c0e7d3059cdd5005746418eb2florian               const HChar* prefix = VG_(clo_fullpath_after)[i];
19901636d33c13958b9c0e7d3059cdd5005746418eb2florian               HChar* str    = VG_(strstr)(dirname, prefix);
199114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               if (str) {
199214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  dirname = str + VG_(strlen)(prefix);
199314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj                  break;
199414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               }
199514cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            }
199614cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            /* remove leading "./" */
199714cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            if (dirname[0] == '.' && dirname[1] == '/')
199814cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj               dirname += 2;
199914cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         }
200014cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // do we have any interesting directory name to show?  If so
200114cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         // add it in.
200214cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj         if (dirname && dirname[0] != 0) {
200314cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND(dirname);
200414cdbf8f4ac7e49de2bced6546f7867b2e0655f0sewardj            APPEND("/");
20055dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30bart         }
2006eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
2007eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
2008eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
2009eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
2010eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
20115e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_objname) {
20125e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ");
20135e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(buf_obj);
20145e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
20155e40abad4504416c59f0b29c1cfc8087201213a9njn      } else if (know_fnname) {
20165e40abad4504416c59f0b29c1cfc8087201213a9njn         // Nb: do this in two steps because "??)" is a trigraph!
20175e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(" (in ???");
20185e40abad4504416c59f0b29c1cfc8087201213a9njn         APPEND(")");
2019eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2020eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2021eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2022eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
2023eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2024eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
2025eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
2026eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
2027eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2028eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
202972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
2034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
203672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
203772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
203872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
203972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
204072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
20413026f71684a930286186aa10fef266c304672e8fsewardj      D3UnwindRegs* uregs;
20423026f71684a930286186aa10fef266c304672e8fsewardj      Addr          min_accessible;
20433026f71684a930286186aa10fef266c304672e8fsewardj      Addr          max_accessible;
204472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
204572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
204672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
204772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
204872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
204972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
2050f7183e38d6215e98043ed014cb947cf5262bdc4asewardj__attribute__((noinline))
2051f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic
205272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
205372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
205472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
205540628facff2285b0fce592381c6e26fdcd2a1252tom   UWord w, wL, wR;
205619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
20573026f71684a930286186aa10fef266c304672e8fsewardj   CfiExpr* e;
20583026f71684a930286186aa10fef266c304672e8fsewardj   vg_assert(sizeof(Addr) == sizeof(UWord));
20593026f71684a930286186aa10fef266c304672e8fsewardj   e = VG_(indexXA)( exprs, ix );
206072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
206140628facff2285b0fce592381c6e26fdcd2a1252tom      case Cex_Unop:
206240628facff2285b0fce592381c6e26fdcd2a1252tom         w = evalCfiExpr( exprs, e->Cex.Unop.ix, eec, ok );
206340628facff2285b0fce592381c6e26fdcd2a1252tom         if (!(*ok)) return 0;
206440628facff2285b0fce592381c6e26fdcd2a1252tom         switch (e->Cex.Unop.op) {
206540628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Abs: return (Word) w < 0 ? - w : w;
206640628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Neg: return - (Word) w;
206740628facff2285b0fce592381c6e26fdcd2a1252tom            case Cunop_Not: return ~ w;
206840628facff2285b0fce592381c6e26fdcd2a1252tom            default: goto unhandled;
206940628facff2285b0fce592381c6e26fdcd2a1252tom         }
207040628facff2285b0fce592381c6e26fdcd2a1252tom         /*NOTREACHED*/
207172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
207272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
207372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
207472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
207572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
207672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
2077f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Add: return wL + wR;
2078f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Sub: return wL - wR;
2079f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_And: return wL & wR;
2080f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Mul: return wL * wR;
2081f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shl: return wL << wR;
2082f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Shr: return wL >> wR;
2083f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Eq: return wL == wR ? 1 : 0;
2084f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ge: return (Word) wL >= (Word) wR ? 1 : 0;
2085f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Gt: return (Word) wL > (Word) wR ? 1 : 0;
2086f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Le: return (Word) wL <= (Word) wR ? 1 : 0;
2087f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Lt: return (Word) wL < (Word) wR ? 1 : 0;
2088f6716dd8f025c9ace67541f3360d7f4523496d8atom            case Cbinop_Ne: return wL != wR ? 1 : 0;
208972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
209072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
209172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
209272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
209372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
20943026f71684a930286186aa10fef266c304672e8fsewardj#           if defined(VGA_x86) || defined(VGA_amd64)
20953026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_IP: return eec->uregs->xip;
20963026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_SP: return eec->uregs->xsp;
20973026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_IA_BP: return eec->uregs->xbp;
20983026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_arm)
20993026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R15: return eec->uregs->r15;
21003026f71684a930286186aa10fef266c304672e8fsewardj            case Creg_ARM_R14: return eec->uregs->r14;
2101fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R13: return eec->uregs->r13;
2102fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj            case Creg_ARM_R12: return eec->uregs->r12;
2103b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#           elif defined(VGA_s390x)
2104b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_IP: return eec->uregs->ia;
2105b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_SP: return eec->uregs->sp;
2106b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_IA_BP: return eec->uregs->fp;
2107b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            case Creg_S390_R14: return eec->uregs->lr;
21084df0bfc0614379192c780c944415dc420d9cfe8epetarj#           elif defined(VGA_mips32) || defined(VGA_mips64)
21095db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_IP: return eec->uregs->pc;
21105db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_SP: return eec->uregs->sp;
21115db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_IA_BP: return eec->uregs->fp;
21125db15403e889d4db339b342bc2a824ef0bfaa654sewardj            case Creg_MIPS_RA: return eec->uregs->ra;
21133026f71684a930286186aa10fef266c304672e8fsewardj#           elif defined(VGA_ppc32) || defined(VGA_ppc64)
2114f0c1250e324f6684757c6a15545366447ef1d64fsewardj#           elif defined(VGP_arm64_linux)
2115821283b2110420321fd3f60afcc799b287788c68sewardj            case Creg_ARM64_X30: return eec->uregs->x30;
21163026f71684a930286186aa10fef266c304672e8fsewardj#           else
21173026f71684a930286186aa10fef266c304672e8fsewardj#             error "Unsupported arch"
21183026f71684a930286186aa10fef266c304672e8fsewardj#           endif
211972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
212072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
212172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
212272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
212372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
212419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
212519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
212619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
212719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
2128720e6b71b171885281afab634ce4d667c1f262bcsewardj             || a > eec->max_accessible - sizeof(UWord) + 1) {
212919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
213019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
213119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
213219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
213386781fabbfc019b752f9605e487cfce77b2a592atom         return ML_(read_UWord)((void *)a);
213472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
213572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
213672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
213772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
213872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
213972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
214072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
214172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
214272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
214372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
214472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
214572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
214672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
214772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2148f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Search all the DebugInfos in the entire system, to find the DiCfSI
2149f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   that pertains to 'ip'.
2150eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2151f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If found, set *diP to the DebugInfo in which it resides, and
2152f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   *ixP to the index in that DebugInfo's cfsi array.
215372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
2154f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
2155f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
2156f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj__attribute__((noinline))
2157f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void find_DiCfSI ( /*OUT*/DebugInfo** diP,
2158f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          /*OUT*/Word* ixP,
2159f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                          Addr ip )
2160f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
2161f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   DebugInfo* di;
2162f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Word       i = -1;
2163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2164f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_search = 0;
2165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   static UWord n_steps = 0;
2166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
2167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2168f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0) VG_(printf)("search for %#lx\n", ip);
2169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2170f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2171f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Word j;
2172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
2173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
2175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
2176f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (di->cfsi_used == 0)
2177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2178f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
2179eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
2180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2181f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* It might be in this DebugInfo.  Search it. */
2182f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      j = ML_(search_one_cfitab)( di, ip );
2183f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(j >= -1 && j < (Word)di->cfsi_used);
2184f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2185f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (j != -1) {
2186f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         i = j;
2187f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         break; /* found it */
2188eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
2189eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
2190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2191f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (i == -1) {
2192f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2193f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* we didn't find it. */
2194f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = (DebugInfo*)1;
2195f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = 0;
2196f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2197f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
2198f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2199f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* found it. */
2200f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* ensure that di is 4-aligned (at least), so it can't possibly
2201f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         be equal to (DebugInfo*)1. */
2202f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(di && VG_IS_4_ALIGNED(di));
2203f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      vg_assert(i >= 0 && i < di->cfsi_used);
2204f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *diP = di;
2205f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *ixP = i;
2206f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2207f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Start of performance-enhancing hack: once every 64 (chosen
2208f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         hackily after profiling) successful searches, move the found
2209f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         DebugInfo one step closer to the start of the list.  This
2210f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         makes future searches cheaper.  For starting konqueror on
2211f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         amd64, this in fact reduces the total amount of searching
2212f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         done by the above find-the-right-DebugInfo loop by more than
2213f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         a factor of 20. */
2214f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if ((n_search & 0xF) == 0) {
2215f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         /* Move di one step closer to the start of the list. */
2216f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         move_DebugInfo_one_step_forward( di );
2217f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
2218f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* End of performance-enhancing hack. */
2219f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2220f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 && ((n_search & 0x7FFFF) == 0))
2221f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(printf)("find_DiCfSI: %lu searches, "
2222f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     "%lu DebugInfos looked at\n",
2223f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                     n_search, n_steps);
2224f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2225f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
2226f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2227f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2228f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2229f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2230f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Now follows a mechanism for caching queries to find_DiCfSI, since
2231f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   they are extremely frequent on amd64-linux, during stack unwinding.
2232f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2233f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Each cache entry binds an ip value to a (di, ix) pair.  Possible
2234f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   values:
2235f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2236f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is non-null, ix >= 0  ==>  cache slot in use, "di->cfsi[ix]"
2237f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is (DebugInfo*)1      ==>  cache slot in use, no associated di
2238f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   di is NULL               ==>  cache slot not in use
2239f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2240f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Hence simply zeroing out the entire cache invalidates all
2241f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   entries.
2242f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2243f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Why not map ip values directly to DiCfSI*'s?  Because this would
2244f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   cause problems if/when the cfsi array is moved due to resizing.
2245f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Instead we cache .cfsi array index value, which should be invariant
2246f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   across resizing.  (That said, I don't think the current
2247f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   implementation will resize whilst during queries, since the DiCfSI
2248f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   records are added all at once, when the debuginfo for an object is
2249f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   read, and is not changed ever thereafter. */
2250eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
225150863bb3d82fcf9126983e8519cc28f1b78a4715philippe// Prime number, giving about 3K cache on 32 bits, 6K cache on 64 bits.
225250863bb3d82fcf9126983e8519cc28f1b78a4715philippe#define N_CFSI_CACHE 509
2253f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2254f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
2255f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct { Addr ip; DebugInfo* di; Word ix; }
2256f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   CFSICacheEnt;
2257f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2258f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
2259f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2260f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void cfsi_cache__invalidate ( void ) {
2261f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
226220ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   CF_info_generation++;
2263f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
2264f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
226520ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippeUInt VG_(CF_info_generation) (void)
226620ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe{
226720ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe   return CF_info_generation;
226820ede3a4f086d4a4b1e0969b1098dcb244ffb6b4philippe}
2269f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2270f7183e38d6215e98043ed014cb947cf5262bdc4asewardjstatic inline CFSICacheEnt* cfsi_cache__find ( Addr ip )
2271f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
22723c9cf3442185b5891e15450d6e3058aeff6796fetom   UWord         hash = ip % N_CFSI_CACHE;
22733c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce = &cfsi_cache[hash];
22743c9cf3442185b5891e15450d6e3058aeff6796fetom   static UWord  n_q = 0, n_m = 0;
2275f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2276f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   n_q++;
2277f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (0 && 0 == (n_q & 0x1FFFFF))
2278f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
2279f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
22803c9cf3442185b5891e15450d6e3058aeff6796fetom   if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
22813c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found an entry in the cache .. */
22823c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
22833c9cf3442185b5891e15450d6e3058aeff6796fetom      /* not found in cache.  Search and update. */
22843c9cf3442185b5891e15450d6e3058aeff6796fetom      n_m++;
22853c9cf3442185b5891e15450d6e3058aeff6796fetom      ce->ip = ip;
22863c9cf3442185b5891e15450d6e3058aeff6796fetom      find_DiCfSI( &ce->di, &ce->ix, ip );
22873c9cf3442185b5891e15450d6e3058aeff6796fetom   }
2288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
22893c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce->di == (DebugInfo*)1)) {
22903c9cf3442185b5891e15450d6e3058aeff6796fetom      /* no DiCfSI for this address */
22913c9cf3442185b5891e15450d6e3058aeff6796fetom      return NULL;
22923c9cf3442185b5891e15450d6e3058aeff6796fetom   } else {
22933c9cf3442185b5891e15450d6e3058aeff6796fetom      /* found a DiCfSI for this address */
22943c9cf3442185b5891e15450d6e3058aeff6796fetom      return ce;
2295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
22963c9cf3442185b5891e15450d6e3058aeff6796fetom}
2297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2299f7183e38d6215e98043ed014cb947cf5262bdc4asewardjinline
23003026f71684a930286186aa10fef266c304672e8fsewardjstatic Addr compute_cfa ( D3UnwindRegs* uregs,
23013c9cf3442185b5891e15450d6e3058aeff6796fetom                          Addr min_accessible, Addr max_accessible,
23023c9cf3442185b5891e15450d6e3058aeff6796fetom                          DebugInfo* di, DiCfSI* cfsi )
23033c9cf3442185b5891e15450d6e3058aeff6796fetom{
23043c9cf3442185b5891e15450d6e3058aeff6796fetom   CfiExprEvalContext eec;
23053c9cf3442185b5891e15450d6e3058aeff6796fetom   Addr               cfa;
23063c9cf3442185b5891e15450d6e3058aeff6796fetom   Bool               ok;
2307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
23083c9cf3442185b5891e15450d6e3058aeff6796fetom   /* Compute the CFA. */
230972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
231072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
23113026f71684a930286186aa10fef266c304672e8fsewardj#     if defined(VGA_x86) || defined(VGA_amd64)
23123026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_SPREL:
23133026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xsp;
23143026f71684a930286186aa10fef266c304672e8fsewardj         break;
23153026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_IA_BPREL:
23163026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->xbp;
231772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
23183026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_arm)
23193026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R13REL:
23203026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r13;
232172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
23223026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R12REL:
23233026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r12;
23243026f71684a930286186aa10fef266c304672e8fsewardj         break;
23253026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_ARM_R11REL:
23263026f71684a930286186aa10fef266c304672e8fsewardj         cfa = cfsi->cfa_off + uregs->r11;
23273026f71684a930286186aa10fef266c304672e8fsewardj         break;
2328fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj      case CFIC_ARM_R7REL:
2329fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         cfa = cfsi->cfa_off + uregs->r7;
2330fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj         break;
2331b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#     elif defined(VGA_s390x)
2332b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_SPREL:
2333b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->sp;
2334b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2335b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_MEMCFAREL:
2336b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      {
2337b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         Addr a = uregs->sp + cfsi->cfa_off;
2338b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         if (a < min_accessible || a > max_accessible-sizeof(Addr))
2339b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj            break;
234086781fabbfc019b752f9605e487cfce77b2a592atom         cfa = ML_(read_Addr)((void *)a);
2341b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2342b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      }
2343b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIR_SAME:
2344b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = uregs->fp;
2345b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
2346b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      case CFIC_IA_BPREL:
2347b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         cfa = cfsi->cfa_off + uregs->fp;
2348b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj         break;
23494df0bfc0614379192c780c944415dc420d9cfe8epetarj#     elif defined(VGA_mips32) || defined(VGA_mips64)
23505db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_SPREL:
23515db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = cfsi->cfa_off + uregs->sp;
23525db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23535db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIR_SAME:
23545db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = uregs->fp;
23555db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23565db15403e889d4db339b342bc2a824ef0bfaa654sewardj      case CFIC_IA_BPREL:
23575db15403e889d4db339b342bc2a824ef0bfaa654sewardj         cfa = cfsi->cfa_off + uregs->fp;
23585db15403e889d4db339b342bc2a824ef0bfaa654sewardj         break;
23593026f71684a930286186aa10fef266c304672e8fsewardj#     elif defined(VGA_ppc32) || defined(VGA_ppc64)
2360f0c1250e324f6684757c6a15545366447ef1d64fsewardj#     elif defined(VGP_arm64_linux)
2361821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_SPREL:
2362821283b2110420321fd3f60afcc799b287788c68sewardj         cfa = cfsi->cfa_off + uregs->sp;
2363821283b2110420321fd3f60afcc799b287788c68sewardj         break;
2364821283b2110420321fd3f60afcc799b287788c68sewardj      case CFIC_ARM64_X29REL:
2365821283b2110420321fd3f60afcc799b287788c68sewardj         cfa = cfsi->cfa_off + uregs->x29;
2366821283b2110420321fd3f60afcc799b287788c68sewardj         break;
23673026f71684a930286186aa10fef266c304672e8fsewardj#     else
23683026f71684a930286186aa10fef266c304672e8fsewardj#       error "Unsupported arch"
23693026f71684a930286186aa10fef266c304672e8fsewardj#     endif
23703026f71684a930286186aa10fef266c304672e8fsewardj      case CFIC_EXPR: /* available on all archs */
23717888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
23727888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
2373f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
23747888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
23757888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
23763026f71684a930286186aa10fef266c304672e8fsewardj         eec.uregs          = uregs;
23777888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
23787888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
23797888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
2380f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
23813c9cf3442185b5891e15450d6e3058aeff6796fetom         if (!ok) return 0;
238272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
238372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
238472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
238572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
23863c9cf3442185b5891e15450d6e3058aeff6796fetom   return cfa;
23873c9cf3442185b5891e15450d6e3058aeff6796fetom}
23883c9cf3442185b5891e15450d6e3058aeff6796fetom
23893c9cf3442185b5891e15450d6e3058aeff6796fetom
23903c9cf3442185b5891e15450d6e3058aeff6796fetom/* Get the call frame address (CFA) given an IP/SP/FP triple. */
23913026f71684a930286186aa10fef266c304672e8fsewardj/* NOTE: This function may rearrange the order of entries in the
23923026f71684a930286186aa10fef266c304672e8fsewardj   DebugInfo list. */
23933c9cf3442185b5891e15450d6e3058aeff6796fetomAddr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
23943c9cf3442185b5891e15450d6e3058aeff6796fetom                    Addr min_accessible, Addr max_accessible )
23953c9cf3442185b5891e15450d6e3058aeff6796fetom{
23963c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt* ce;
23973c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*    di;
2398d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   DiCfSI*       cfsi __attribute__((unused));
23993c9cf3442185b5891e15450d6e3058aeff6796fetom
24003c9cf3442185b5891e15450d6e3058aeff6796fetom   ce = cfsi_cache__find(ip);
24013c9cf3442185b5891e15450d6e3058aeff6796fetom
24023c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
24033c9cf3442185b5891e15450d6e3058aeff6796fetom      return 0; /* no info.  Nothing we can do. */
24043c9cf3442185b5891e15450d6e3058aeff6796fetom
24053c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
24063c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
24073c9cf3442185b5891e15450d6e3058aeff6796fetom
24083026f71684a930286186aa10fef266c304672e8fsewardj   /* Temporary impedance-matching kludge so that this keeps working
24093026f71684a930286186aa10fef266c304672e8fsewardj      on x86-linux and amd64-linux. */
24103026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
24113026f71684a930286186aa10fef266c304672e8fsewardj   { D3UnwindRegs uregs;
24123026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xip = ip;
24133026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xsp = sp;
24143026f71684a930286186aa10fef266c304672e8fsewardj     uregs.xbp = fp;
24153026f71684a930286186aa10fef266c304672e8fsewardj     return compute_cfa(&uregs,
24163026f71684a930286186aa10fef266c304672e8fsewardj                        min_accessible,  max_accessible, di, cfsi);
24173026f71684a930286186aa10fef266c304672e8fsewardj   }
2418b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#elif defined(VGA_s390x)
2419b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   { D3UnwindRegs uregs;
2420b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.ia = ip;
2421b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.sp = sp;
2422b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     uregs.fp = fp;
2423b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj     return compute_cfa(&uregs,
2424b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj                        min_accessible,  max_accessible, di, cfsi);
2425b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   }
2426f03d0b76228354fb63eb970a4e6c9fa1337d60a9dejanj#elif defined(VGA_mips32) || defined(VGA_mips64)
2427fe0b43315c344cfd07981a0826bc34614a220169dejanj   { D3UnwindRegs uregs;
2428fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.pc = ip;
2429fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.sp = sp;
2430fe0b43315c344cfd07981a0826bc34614a220169dejanj     uregs.fp = fp;
2431fe0b43315c344cfd07981a0826bc34614a220169dejanj     return compute_cfa(&uregs,
2432fe0b43315c344cfd07981a0826bc34614a220169dejanj                        min_accessible,  max_accessible, di, cfsi);
2433fe0b43315c344cfd07981a0826bc34614a220169dejanj   }
2434b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj
24353026f71684a930286186aa10fef266c304672e8fsewardj#  else
24363026f71684a930286186aa10fef266c304672e8fsewardj   return 0; /* indicates failure */
24373026f71684a930286186aa10fef266c304672e8fsewardj#  endif
24383c9cf3442185b5891e15450d6e3058aeff6796fetom}
24393c9cf3442185b5891e15450d6e3058aeff6796fetom
24403c9cf3442185b5891e15450d6e3058aeff6796fetom
24413026f71684a930286186aa10fef266c304672e8fsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.  Given a
24423026f71684a930286186aa10fef266c304672e8fsewardj   set of registers in UREGS, modify it to hold the register values
24433026f71684a930286186aa10fef266c304672e8fsewardj   for the previous frame, if possible.  Returns True if successful.
24443026f71684a930286186aa10fef266c304672e8fsewardj   If not successful, *UREGS is not changed.
24453026f71684a930286186aa10fef266c304672e8fsewardj
24463026f71684a930286186aa10fef266c304672e8fsewardj   For x86 and amd64, the unwound registers are: {E,R}IP,
24473026f71684a930286186aa10fef266c304672e8fsewardj   {E,R}SP, {E,R}BP.
24483026f71684a930286186aa10fef266c304672e8fsewardj
2449fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
2450821283b2110420321fd3f60afcc799b287788c68sewardj
2451821283b2110420321fd3f60afcc799b287788c68sewardj   For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
24523026f71684a930286186aa10fef266c304672e8fsewardj*/
24533026f71684a930286186aa10fef266c304672e8fsewardjBool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
24543c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr min_accessible,
24553c9cf3442185b5891e15450d6e3058aeff6796fetom                        Addr max_accessible )
24563c9cf3442185b5891e15450d6e3058aeff6796fetom{
24573c9cf3442185b5891e15450d6e3058aeff6796fetom   DebugInfo*         di;
24583c9cf3442185b5891e15450d6e3058aeff6796fetom   DiCfSI*            cfsi = NULL;
24593026f71684a930286186aa10fef266c304672e8fsewardj   Addr               cfa, ipHere = 0;
24603c9cf3442185b5891e15450d6e3058aeff6796fetom   CFSICacheEnt*      ce;
2461d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj   CfiExprEvalContext eec __attribute__((unused));
24623026f71684a930286186aa10fef266c304672e8fsewardj   D3UnwindRegs       uregsPrev;
24633c9cf3442185b5891e15450d6e3058aeff6796fetom
24643026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
24653026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->xip;
24663026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
24673026f71684a930286186aa10fef266c304672e8fsewardj   ipHere = uregsHere->r15;
2468b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2469b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   ipHere = uregsHere->ia;
24704df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
24715db15403e889d4db339b342bc2a824ef0bfaa654sewardj   ipHere = uregsHere->pc;
24723026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2473f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
2474821283b2110420321fd3f60afcc799b287788c68sewardj   ipHere = uregsHere->pc;
24753026f71684a930286186aa10fef266c304672e8fsewardj#  else
24763026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
24773026f71684a930286186aa10fef266c304672e8fsewardj#  endif
24783026f71684a930286186aa10fef266c304672e8fsewardj   ce = cfsi_cache__find(ipHere);
24793c9cf3442185b5891e15450d6e3058aeff6796fetom
24803c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(ce == NULL))
24813c9cf3442185b5891e15450d6e3058aeff6796fetom      return False; /* no info.  Nothing we can do. */
24823c9cf3442185b5891e15450d6e3058aeff6796fetom
24833c9cf3442185b5891e15450d6e3058aeff6796fetom   di = ce->di;
24843c9cf3442185b5891e15450d6e3058aeff6796fetom   cfsi = &di->cfsi[ ce->ix ];
24853c9cf3442185b5891e15450d6e3058aeff6796fetom
24863c9cf3442185b5891e15450d6e3058aeff6796fetom   if (0) {
24873c9cf3442185b5891e15450d6e3058aeff6796fetom      VG_(printf)("found cfisi: ");
24883c9cf3442185b5891e15450d6e3058aeff6796fetom      ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
24893c9cf3442185b5891e15450d6e3058aeff6796fetom   }
24903c9cf3442185b5891e15450d6e3058aeff6796fetom
2491f7183e38d6215e98043ed014cb947cf5262bdc4asewardj   VG_(bzero_inline)(&uregsPrev, sizeof(uregsPrev));
24923c9cf3442185b5891e15450d6e3058aeff6796fetom
24933c9cf3442185b5891e15450d6e3058aeff6796fetom   /* First compute the CFA. */
24943026f71684a930286186aa10fef266c304672e8fsewardj   cfa = compute_cfa(uregsHere,
24953026f71684a930286186aa10fef266c304672e8fsewardj                     min_accessible, max_accessible, di, cfsi);
24963c9cf3442185b5891e15450d6e3058aeff6796fetom   if (UNLIKELY(cfa == 0))
24973c9cf3442185b5891e15450d6e3058aeff6796fetom      return False;
249872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
249972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
250072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
2501eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
2503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
2504eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
2505eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
2506eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
2507eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
2508eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
2509eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
2510eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
2511eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
25129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   || a > max_accessible-sizeof(Addr))  \
2513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
251486781fabbfc019b752f9605e487cfce77b2a592atom               _prev = ML_(read_Addr)((void *)a);       \
2515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
2516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
2517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
2518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
2519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
252072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
252172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
2522f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                  ML_(ppCfiExpr)(di->cfsi_exprs,_off);  \
25233026f71684a930286186aa10fef266c304672e8fsewardj               eec.uregs = uregsHere;                   \
252472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
252572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
2526d2be8cc17fed04cbd701e9a2cc1cf365ff45cc44sewardj               Bool ok = True;                          \
2527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj               _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
252872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
252972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
253072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
253172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
2532eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
2533eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
2534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25353026f71684a930286186aa10fef266c304672e8fsewardj#  if defined(VGA_x86) || defined(VGA_amd64)
25363026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.xip, uregsHere->xip, cfsi->ra_how, cfsi->ra_off);
25379365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xsp, uregsHere->xsp, cfsi->sp_how, cfsi->sp_off);
25389365e3f48bc3efe2486bf4bc04111a2d89db5520sewardj   COMPUTE(uregsPrev.xbp, uregsHere->xbp, cfsi->bp_how, cfsi->bp_off);
25393026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_arm)
25403026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r15, uregsHere->r15, cfsi->ra_how,  cfsi->ra_off);
25413026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r14, uregsHere->r14, cfsi->r14_how, cfsi->r14_off);
25423026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r13, uregsHere->r13, cfsi->r13_how, cfsi->r13_off);
25433026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
25443026f71684a930286186aa10fef266c304672e8fsewardj   COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
2545fa5ce5616a17e79828fbc79f30b02b5085151e3csewardj   COMPUTE(uregsPrev.r7,  uregsHere->r7,  cfsi->r7_how,  cfsi->r7_off);
2546b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  elif defined(VGA_s390x)
2547b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
2548b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
2549b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
25504df0bfc0614379192c780c944415dc420d9cfe8epetarj#  elif defined(VGA_mips32) || defined(VGA_mips64)
25515db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off);
25525db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
25535db15403e889d4db339b342bc2a824ef0bfaa654sewardj   COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
25543026f71684a930286186aa10fef266c304672e8fsewardj#  elif defined(VGA_ppc32) || defined(VGA_ppc64)
2555f0c1250e324f6684757c6a15545366447ef1d64fsewardj#  elif defined(VGP_arm64_linux)
2556821283b2110420321fd3f60afcc799b287788c68sewardj   COMPUTE(uregsPrev.pc,  uregsHere->pc,  cfsi->ra_how,  cfsi->ra_off);
2557821283b2110420321fd3f60afcc799b287788c68sewardj   COMPUTE(uregsPrev.sp,  uregsHere->sp,  cfsi->sp_how,  cfsi->sp_off);
2558821283b2110420321fd3f60afcc799b287788c68sewardj   COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi->x30_how, cfsi->x30_off);
2559821283b2110420321fd3f60afcc799b287788c68sewardj   COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi->x29_how, cfsi->x29_off);
25603026f71684a930286186aa10fef266c304672e8fsewardj#  else
25613026f71684a930286186aa10fef266c304672e8fsewardj#    error "Unknown arch"
25623026f71684a930286186aa10fef266c304672e8fsewardj#  endif
2563eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2564eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
2565eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
25663026f71684a930286186aa10fef266c304672e8fsewardj   *uregsHere = uregsPrev;
2567eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
2568eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2569eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2570eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2573c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
2574c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---            MSVC FPO INFO                               ---*/
2575c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2576c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2577c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2578c8259b85b701d25d72aabe9dc0a8154517f96913sewardjBool VG_(use_FPO_info) ( /*MOD*/Addr* ipP,
2579c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* spP,
2580c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         /*MOD*/Addr* fpP,
2581c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr min_accessible,
2582c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                         Addr max_accessible )
2583c8259b85b701d25d72aabe9dc0a8154517f96913sewardj{
2584c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Word       i;
2585c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   DebugInfo* di;
2586c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   FPO_DATA*  fpo = NULL;
2587c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Addr       spHere;
2588c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2589c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_search = 0;
2590c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   static UWord n_steps = 0;
2591c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   n_search++;
2592c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2593c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) VG_(printf)("search FPO for %#lx\n", *ipP);
2594c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2595c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2596c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      n_steps++;
2597c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2598c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Use the per-DebugInfo summary address ranges to skip
2599c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         inapplicable DebugInfos quickly. */
2600c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (di->fpo == NULL)
2601c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2602c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (*ipP < di->fpo_minavma || *ipP > di->fpo_maxavma)
2603c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         continue;
2604c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2605c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      i = ML_(search_one_fpotab)( di, *ipP );
2606c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      if (i != -1) {
2607c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Word j;
2608c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         if (0) {
2609c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            /* debug printing only */
2610c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            VG_(printf)("look for %#lx  size %ld i %ld\n",
2611c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                        *ipP, di->fpo_size, i);
2612c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            for (j = 0; j < di->fpo_size; j++)
2613c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               VG_(printf)("[%02ld] %#x %d\n",
2614c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                            j, di->fpo[j].ulOffStart, di->fpo[j].cbProcSize);
2615c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         }
2616c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         vg_assert(i >= 0 && i < di->fpo_size);
2617c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         fpo = &di->fpo[i];
2618c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         break;
2619c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      }
2620c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2621c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2622c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (fpo == NULL)
2623c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return False;
2624c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2625c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
2626c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("VG_(use_FPO_info): %lu searches, "
2627c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  "%lu DebugInfos looked at\n",
2628c8259b85b701d25d72aabe9dc0a8154517f96913sewardj                  n_search, n_steps);
2629c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2630c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2631c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
2632c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      hackily after profiling) successful searches, move the found
2633c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      DebugInfo one step closer to the start of the list.  This makes
2634c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      future searches cheaper.  For starting konqueror on amd64, this
2635c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      in fact reduces the total amount of searching done by the above
2636c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
2637c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if ((n_search & 0x3F) == 0) {
2638c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      /* Move si one step closer to the start of the list. */
2639c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //move_DebugInfo_one_step_forward( di );
2640c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2641c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /* End of performance-enhancing hack. */
2642c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2643c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   if (0) {
2644c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      VG_(printf)("found fpo: ");
2645c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      //ML_(ppFPO)(fpo);
2646c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   }
2647c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2648c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   /*
2649c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Stack layout is:
2650c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp->
2651c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cbRegs  {%edi, %esi, %ebp, %ebx}
2652c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwLocals
2653c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      return_pc
2654c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      4*.cdwParams
2655c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   prior_%esp->
2656c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2657c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   Typical code looks like:
2658c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      sub $4*.cdwLocals,%esp
2659c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Alternative to above for >=4KB (and sometimes for smaller):
2660c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            mov $size,%eax
2661c8259b85b701d25d72aabe9dc0a8154517f96913sewardj            call __chkstk  # WinNT performs page-by-page probe!
2662c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               __chkstk is much like alloc(), except that on return
2663c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               %eax= 5+ &CALL.  Thus it could be used as part of
2664c8259b85b701d25d72aabe9dc0a8154517f96913sewardj               Position Independent Code to locate the Global Offset Table.
2665c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebx
2666c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %ebp
2667c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %esi
2668c8259b85b701d25d72aabe9dc0a8154517f96913sewardj         Other once-only instructions often scheduled >here<.
2669c8259b85b701d25d72aabe9dc0a8154517f96913sewardj      push %edi
2670c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2671c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   If the pc is within the first .cbProlog bytes of the function,
2672c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   then you must disassemble to see how many registers have been pushed,
2673c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because instructions in the prolog may be scheduled for performance.
2674c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   The order of PUSH is always %ebx, %ebp, %esi, %edi, with trailing
2675c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   registers not pushed when .cbRegs < 4.  This seems somewhat strange
2676c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   because %ebp is the register whose usage you want to minimize,
2677c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   yet it is in the first half of the PUSH list.
2678c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2679c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   I don't know what happens when the compiler constructs an outgoing CALL.
2680c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   %esp could move if outgoing parameters are PUSHed, and this affects
2681c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   traceback for errors during the PUSHes. */
2682c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2683c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   spHere = *spP;
2684c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
268586781fabbfc019b752f9605e487cfce77b2a592atom   *ipP = ML_(read_Addr)((void *)(spHere + 4*(fpo->cbRegs + fpo->cdwLocals)));
268686781fabbfc019b752f9605e487cfce77b2a592atom   *spP =                         spHere + 4*(fpo->cbRegs + fpo->cdwLocals + 1
268786781fabbfc019b752f9605e487cfce77b2a592atom                                                          + fpo->cdwParams);
268886781fabbfc019b752f9605e487cfce77b2a592atom   *fpP = ML_(read_Addr)((void *)(spHere + 4*2));
2689c8259b85b701d25d72aabe9dc0a8154517f96913sewardj   return True;
2690c8259b85b701d25d72aabe9dc0a8154517f96913sewardj}
2691c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2692c8259b85b701d25d72aabe9dc0a8154517f96913sewardj
2693c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*--------------------------------------------------------------*/
2694c8259b85b701d25d72aabe9dc0a8154517f96913sewardj/*---                                                        ---*/
2695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
2696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
2697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
2698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
2699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2700588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Try to make p2XA(dst, fmt, args..) turn into
2701b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   VG_(xaprintf)(dst, fmt, args) without having to resort to
2702588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   vararg macros.  As usual with everything to do with varargs, it's
2703588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   an ugly hack.
2704738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2705588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   //#define p2XA(dstxa, format, args...)
2706b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart   //   VG_(xaprintf)(dstxa, format, ##args)
2707738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
2708b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart#define  p2XA  VG_(xaprintf)
2709738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2710588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj/* Add a zero-terminating byte to DST, which must be an XArray* of
2711588adeffafa8102adcfa7a1c035ae272b35cf86dsewardj   HChar. */
2712738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void zterm_XA ( XArray* dst )
2713738856f99eea33d86ce91dcb1d6cd5b151e307casewardj{
2714738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   HChar zero = 0;
2715738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   (void) VG_(addBytesToXA)( dst, &zero, 1 );
2716738856f99eea33d86ce91dcb1d6cd5b151e307casewardj}
2717738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2718738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
2720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
2721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
2722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
2723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
2724c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic Bool data_address_is_in_var ( /*OUT*/PtrdiffT* offset,
27259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     XArray* /* TyEnt */ tyents,
2726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
2727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
2728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
2729588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     const DebugInfo* di )
2730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
273150fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
2732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
2733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
2734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
27359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
2736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
2737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
2738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
274050fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
274150fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
274250fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
274350fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
274450fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
274550fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
274650fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
274750fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
274850fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
274950fde23467d92281b32dd537d0d9a590263628c3sewardj
275050fde23467d92281b32dd537d0d9a590263628c3sewardj   var_szB = (SizeT)mul.ul; /* NB: truncate to host word */
2751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2753a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("VVVV: data_address_%#lx_is_in_var: %s :: ",
2754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
27559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ML_(pp_TyEnt_C_ishly)( tyents, var->typeR );
2756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
2760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
2761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
2762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
2763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2766588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, di );
2767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
2769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
2770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
2771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
2772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2773eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
27743c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res.kind == GXR_Addr
2775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
2776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
2777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
2778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
2779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
2780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2785738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Format the acquired information into DN(AME)1 and DN(AME)2, which
2786738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   are XArray*s of HChar, that have been initialised by the caller.
2787738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Resulting strings will be zero terminated.  Information is
2788738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   formatted in an understandable way.  Not so easy.  If frameNo is
2789738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   -1, this is assumed to be a global variable; else a local
2790738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   variable. */
2791738856f99eea33d86ce91dcb1d6cd5b151e307casewardjstatic void format_message ( /*MOD*/XArray* /* of HChar */ dn1,
2792738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                             /*MOD*/XArray* /* of HChar */ dn2,
2793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
2794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
2795c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT var_offset,
2796c4431bfe04c7490ea2d74939d222d87f13f30960njn                             PtrdiffT residual_offset,
2797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
2798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
2799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
2800eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2801738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   have_descr, have_srcloc;
2802738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Bool   xml       = VG_(clo_xml);
28031636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* vo_plural = var_offset == 1 ? "" : "s";
28041636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* ro_plural = residual_offset == 1 ? "" : "s";
28051636d33c13958b9c0e7d3059cdd5005746418eb2florian   const HChar* basetag   = "auxwhat"; /* a constant */
28061636d33c13958b9c0e7d3059cdd5005746418eb2florian   HChar tagL[32], tagR[32], xagL[32], xagR[32];
2807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2808d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   if (frameNo < -1) {
2809d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(0); /* Not allowed */
2810d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2811d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else if (frameNo == -1) {
2812d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid == VG_INVALID_THREADID);
2813d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2814d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   else /* (frameNo >= 0) */ {
2815d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj      vg_assert(tid != VG_INVALID_THREADID);
2816d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj   }
2817d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj
2818738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   vg_assert(dn1 && dn2);
2819b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
2820b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
2821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
2822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
2823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
2824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2825738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   tagL[0] = tagR[0] = xagL[0] = xagR[0] = 0;
2826738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (xml) {
2827738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagL, "<%s>",   basetag); // <auxwhat>
2828738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(tagR, "</%s>",  basetag); // </auxwhat>
2829738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagL, "<x%s>",  basetag); // <xauxwhat>
2830738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(sprintf)(xagR, "</x%s>", basetag); // </xauxwhat>
2831738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   }
2832738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
2833738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGL(_xa) p2XA(_xa, "%s", tagL)
2834738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TAGR(_xa) p2XA(_xa, "%s", tagR)
2835738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGL(_xa) p2XA(_xa, "%s", xagL)
2836738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define XAGR(_xa) p2XA(_xa, "%s", xagR)
2837738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTL(_xa) p2XA(_xa, "%s", "<text>")
2838738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  define TXTR(_xa) p2XA(_xa, "%s", "</text>")
2839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
2841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
2843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
2845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2847738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2848738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2849738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2850b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\",",
2851738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2852738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2853738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2854738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2855738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2856738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2857738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2858738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2859738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\",",
2860738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2861738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2862738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2863738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2865b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
2867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
2869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
2870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2871738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2872738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2873738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2874b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside local var \"%pS\"",
2875738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2876738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2877738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2878738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2879738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2880b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
2881738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2882738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2883738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2884738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2885b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2886738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2887738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2888738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2889738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2890738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside local var \"%s\"",
2891738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2892738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2893738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2894738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2895738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
2899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
2900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
2901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
2902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2903738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2904738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2905738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2906b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS",
2907738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2908738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2909738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2910738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
2911738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2912738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2913738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
2914738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2915738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2916738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s",
2917738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2918738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2919738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2920738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "in frame #%d of thread %d", frameNo, (Int)tid );
2921738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
2925738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
2926738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         declared at dsyms7.c:17, in frame #1 of thread 1 */
2927738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2928738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2929738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2930b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
2931738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2932738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2933738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2934738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2935738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2936738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2937b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d, in frame #%d of thread %d",
2938738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2939738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2940738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2941738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2942b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2943738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2944738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2945738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2946738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2947738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
2948738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
2949738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
2950738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2951738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d, in frame #%d of thread %d",
2952738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo, frameNo, (Int)tid );
2953738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
2957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
2958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
2959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2961738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2962738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2963738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2964b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
2965738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2966738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2967738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2968738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2969738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2970738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2971738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
2972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
2974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
2975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
2976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
2977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
2978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
2979738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
2980738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
2981738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2982b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside global var \"%pS\"",
2983738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
2984738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
2985738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
2986738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
2987738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2988b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "declared at %pS:%d",
2989738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
2990738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
2991738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
2992738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
2993b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
2994738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
2995738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
2996738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
2997738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
2998738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside global var \"%s\"",
2999738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, var_offset, vo_plural, var->name );
3000738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3001738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "declared at %s:%d",
3002738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3003738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
3007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
3008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
3010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
3011738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3012738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3013738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3014b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3015738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3016738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3017738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3018738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn2 );
3019738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3020738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3021738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn2 );
3022738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3023738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3024738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3025738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3026738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (char*)(VG_(indexXA)(described,0)) );
3027738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3028738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable");
3029738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
3033738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
3034738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         a global variable declared at dsyms7.c:17 */
3035738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (xml) {
3036738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGL( dn1 );
3037738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3038b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "Location 0x%lx is %lu byte%s inside %pS%pS,",
3039738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3040738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3041738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TAGR( dn1 );
3042738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGL( dn2 );
3043738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTL( dn2 );
3044738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3045b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               "a global variable declared at %pS:%d",
3046738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3047738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         TXTR( dn2 );
3048738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         // FIXME: also do <dir>
3049738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3050b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart               " <file>%pS</file> <line>%d</line> ",
3051738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo );
3052738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         XAGR( dn2 );
3053738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      } else {
3054738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn1,
3055738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Location 0x%lx is %lu byte%s inside %s%s,",
3056738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               data_addr, residual_offset, ro_plural, var->name,
3057738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               (HChar*)(VG_(indexXA)(described,0)) );
3058738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         p2XA( dn2,
3059738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "a global variable declared at %s:%d",
3060738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               var->fileName, var->lineNo);
3061738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
3062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
3064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
3065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3066738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* Zero terminate both strings */
3067738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn1 );
3068738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dn2 );
3069738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3070738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGL
3071738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TAGR
3072738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGL
3073738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef XAGR
3074738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTL
3075738856f99eea33d86ce91dcb1d6cd5b151e307casewardj#  undef TXTR
3076eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3077eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3078738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
3080738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   characterised by (ip,sp,fp), and if so write its description at the
3081738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   ends of DNAME{1,2}, which are XArray*s of HChar, that have been
3082738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, zero terminate both, and return True.
3083738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   If it's not a local variable in said frame, return False. */
3084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
3085738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool consider_vars_in_frame ( /*MOD*/XArray* /* of HChar */ dname1,
3086738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                              /*MOD*/XArray* /* of HChar */ dname2,
3087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
3088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
3089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
3090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
3091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
3093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
3095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
3096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
3098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
3099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
3100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
3101a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("QQQQ: cvif: ip,sp,fp %#lx,%#lx,%#lx\n", ip,sp,fp);
3102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
3103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
3104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
3105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
3109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
3110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
3114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
3115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
3116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
3117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
3120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
3121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
3122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
3123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
3124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
3125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
3126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
3127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
3128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
3129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
3130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
3132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
3134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
3135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
3138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
3139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
3140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
3141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
3143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
3144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
3145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
3147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
3148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
3150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
3151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
3152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
3153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
3154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
3155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
3156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
3158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
3159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
3160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
3161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
3162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
3163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
3164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
3166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
3167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
3168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
3169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
3170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
3171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
3172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
3173b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
3174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
3175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
3176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
3177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
3178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
3179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
3180b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
3181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
3182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
3183c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT    offset;
3184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
3185a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
3186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
31879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents,
31889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                     var, &regs,
3189588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3190c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
31929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
31939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3194738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
3197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3206738856f99eea33d86ce91dcb1d6cd5b151e307casewardj/* Try to form some description of DATA_ADDR by looking at the DWARF3
320725963376a3669e7f77395d6f884bdf1f6a928966philippe   debug info we have.  This considers all global variables, and 8
3208738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   frames in the stacks of all threads.  Result is written at the ends
3209738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   of DNAME{1,2}V, which are XArray*s of HChar, that have been
3210738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   initialised by the caller, and True is returned.  If no description
3211738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   is created, False is returned.  Regardless of the return value,
3212738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   DNAME{1,2}V are guaranteed to be zero terminated after the call.
3213738856f99eea33d86ce91dcb1d6cd5b151e307casewardj
3214738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   Note that after the call, DNAME{1,2} may have more than one
3215738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   trailing zero, so callers should establish the useful text length
3216738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   using VG_(strlen) on the contents, rather than VG_(sizeXA) on the
3217738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray itself.
3218738856f99eea33d86ce91dcb1d6cd5b151e307casewardj*/
3219738856f99eea33d86ce91dcb1d6cd5b151e307casewardjBool VG_(get_data_description)(
3220738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname1v,
3221738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        /*MOD*/ void* /* really, XArray* of HChar */ dname2v,
3222738856f99eea33d86ce91dcb1d6cd5b151e307casewardj        Addr data_addr
3223738856f99eea33d86ce91dcb1d6cd5b151e307casewardj     )
3224eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
3226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
3227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
3228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
3230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
3231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
3232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
3234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3235738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname1 = (XArray*)dname1v;
3236738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   XArray*    dname2 = (XArray*)dname2v;
3237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3238a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("get_data_description: dataaddr %#lx\n", data_addr);
3239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
3240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
3241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
3242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
3243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
32459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         gs_size;
3246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
3247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
3248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
3249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
3250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
3252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
3253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
3255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
3256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
3258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
3259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
3261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
3262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
3263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
3264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
3265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
3266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
3267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
3268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
3269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
3270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
3271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
3272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
3273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
3274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
3275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
3276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
3277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
3278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
3279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
3280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
3281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
3282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
3283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
3284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
3285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
3286c4431bfe04c7490ea2d74939d222d87f13f30960njn         PtrdiffT offset;
3287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
3288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
3289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
3290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
3291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
3292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
3293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
3294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
32959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (data_address_is_in_var( &offset, di->admin_tyents, var,
3296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
3297588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                                     data_addr, di )) {
3298c4431bfe04c7490ea2d74939d222d87f13f30960njn            PtrdiffT residual_offset = 0;
3299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
33009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    di->admin_tyents,
33019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                    var->typeR, offset );
3302738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            format_message( dname1, dname2,
3303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
3304d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            described, -1/*frameNo*/,
3305d7adca740c8309a31c897c1ec6c3bbfe1c26489bsewardj                            VG_INVALID_THREADID );
3306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
3307738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname1 );
3308738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            zterm_XA( dname2 );
3309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
3310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
3311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
3315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
3316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
3317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
3319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
3320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
3321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
3322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
3323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
3324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
3325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
3326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
3327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
3331738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname1 );
3332738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      zterm_XA( dname2 );
3333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
3334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
3337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
3338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
3339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
3340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
3341b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj
3342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
3343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
3344738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (consider_vars_in_frame( dname1, dname2,
3345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
3346b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                  ips[j],
3347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
3348738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3349738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
3353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
3354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
3355b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
3356b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
3357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
3358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
3359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
3360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
3361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
3362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
3363b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
3364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
3365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
3366b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         time, but this time add 1 to the IP.  GDB handles this
3367b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         example with no difficulty, which leads me to believe that
3368b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         either (1) I misunderstood something, or (2) GDB has an
3369b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj         equivalent kludge. */
3370b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj      if (j > 0 /* this is a non-innermost frame */
3371738856f99eea33d86ce91dcb1d6cd5b151e307casewardj          && consider_vars_in_frame( dname1, dname2,
3372b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     data_addr,
3373b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     ips[j] + 1,
3374b1ae15d5c3ca2fb57cf1545debd62fc653ad2abfsewardj                                     sps[j], fps[j], tid, j )) {
3375738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname1 );
3376738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         zterm_XA( dname2 );
3377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
3378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
3382738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname1 );
3383738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   zterm_XA( dname2 );
3384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
3385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
3386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
33899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
33909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
33919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj// Support for other kinds of queries to the Dwarf3 var info    //
33929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//                                                              //
33939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj//////////////////////////////////////////////////////////////////
33949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
33959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Figure out if the variable 'var' has a location that is linearly
33969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   dependent on a stack pointer value, or a frame pointer value, and
33979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if it is, add a description of it to 'blocks'.  Otherwise ignore
33989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   it.  If 'arrays_only' is True, also ignore it unless it has an
33999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array type. */
34009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjstatic
34029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks,
34039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    XArray* /* TyEnt */ tyents,
3404588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                    Addr ip, const DebugInfo* di, DiVariable* var,
34059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                    Bool arrays_only )
34069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
34079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   GXResult   res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k;
34089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   RegSummary regs;
340950fde23467d92281b32dd537d0d9a590263628c3sewardj   MaybeULong mul;
34109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool       isVec;
34119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   TyEnt*     ty;
34129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
34149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0&&debug)
34159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("adeps: var %s\n", var->name );
34169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Figure out how big the variable is. */
341850fde23467d92281b32dd537d0d9a590263628c3sewardj   mul = ML_(sizeOfType)(tyents, var->typeR);
341950fde23467d92281b32dd537d0d9a590263628c3sewardj   /* If this var has a type whose size is unknown, zero, or
342050fde23467d92281b32dd537d0d9a590263628c3sewardj      impossibly large, it should never have been added.  ML_(addVar)
342150fde23467d92281b32dd537d0d9a590263628c3sewardj      should have rejected it. */
342250fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.b == True);
342350fde23467d92281b32dd537d0d9a590263628c3sewardj   vg_assert(mul.ul > 0);
342450fde23467d92281b32dd537d0d9a590263628c3sewardj   if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
342550fde23467d92281b32dd537d0d9a590263628c3sewardj   /* After this point, we assume we can truncate mul.ul to a host word
342650fde23467d92281b32dd537d0d9a590263628c3sewardj      safely (without loss of info). */
34279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* skip if non-array and we're only interested in arrays */
34299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   ty = ML_(TyEnts__index_by_cuOff)( tyents, NULL, var->typeR );
34309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty);
34319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
34329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (ty->tag == Te_UNKNOWN)
34339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return; /* perhaps we should complain in this case? */
34349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   isVec = ty->tag == Te_TyArray;
34359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (arrays_only && !isVec)
34369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return;
34379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0) {ML_(pp_TyEnt_C_ishly)(tyents, var->typeR);
34399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj           VG_(printf)("  %s\n", var->name);}
34409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Do some test evaluations of the variable's location expression,
34429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      in order to guess whether it is sp-relative, fp-relative, or
34439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      none.  A crude hack, which can be interpreted roughly as finding
34449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      the first derivative of the location expression w.r.t. the
34459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      supplied frame and stack pointer values. */
34469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
34479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 6 * 1024;
3449588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 0;
34529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 7 * 1024;
3454588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 6 * 1024;
34579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3459588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.fp   = 7 * 1024;
34629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.ip   = ip;
34639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   regs.sp   = 0;
3464588658b13b5ad77672f323d48fe9da0ca60b0bcbtom   res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_sp_7k.kind);
34679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_6k.kind);
34689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   vg_assert(res_sp_6k.kind == res_fp_7k.kind);
34699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34703c9cf3442185b5891e15450d6e3058aeff6796fetom   if (res_sp_6k.kind == GXR_Addr) {
34719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      StackBlock block;
34729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      GXResult res;
34739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
34749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      UWord fp_delta = res_fp_7k.word - res_fp_6k.word;
34759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(sp_delta == 0 || sp_delta == 1024);
34769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(fp_delta == 0 || fp_delta == 1024);
34779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
34789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 0) {
34799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* depends neither on sp nor fp, so it can't be a stack
34809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            local.  Ignore it. */
34819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
34829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
34839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 1024 && fp_delta == 0) {
34849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
34859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3486588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
34873c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
34889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
34899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (sp) %s\n",
349050fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
34919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
349250fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
34939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = True;
34949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
34959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
34969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
34979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
34989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
34999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
35009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else
35029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (sp_delta == 0 && fp_delta == 1024) {
35039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.sp = regs.fp = 0;
35049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         regs.ip = ip;
3505588658b13b5ad77672f323d48fe9da0ca60b0bcbtom         res = ML_(evaluate_GX)( var->gexpr, var->fbGX, &regs, di );
35063c9cf3442185b5891e15450d6e3058aeff6796fetom         tl_assert(res.kind == GXR_Addr);
35079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
35089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("   %5ld .. %5ld (FP) %s\n",
350950fde23467d92281b32dd537d0d9a590263628c3sewardj                     res.word, res.word + ((UWord)mul.ul) - 1, var->name);
35109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.base  = res.word;
351150fde23467d92281b32dd537d0d9a590263628c3sewardj         block.szB   = (SizeT)mul.ul;
35129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.spRel = False;
35139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.isVec = isVec;
35149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(memset)( &block.name[0], 0, sizeof(block.name) );
35159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (var->name)
35169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 );
35179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         block.name[ sizeof(block.name)-1 ] = 0;
35189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(addToXA)( blocks, &block );
35199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      else {
35219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         vg_assert(0);
35229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
35239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
35259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an XArray of StackBlock which describe the stack (auto) blocks
35289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for this ip.  The caller is expected to free the XArray at some
35299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   point.  If 'arrays_only' is True, only array-typed blocks are
35309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned; otherwise blocks of all types are returned. */
35319c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of StackBlock */
35339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only )
35349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
35359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
35369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word       i;
35379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
35389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Bool debug = False;
35399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* res = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dgsbai.1",
35419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             ML_(dinfo_free),
35429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                             sizeof(StackBlock) );
35439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_search = 0;
35459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   static UInt n_steps = 0;
35469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   n_search++;
35479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (debug)
35489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip);
35499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* first, find the DebugInfo that pertains to 'ip'. */
35509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
35519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      n_steps++;
35529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* text segment missing? unlikely, but handle it .. */
35539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!di->text_present || di->text_size == 0)
35549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
35559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Ok.  So does this text mapping bracket the ip? */
35569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
35579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
35589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Didn't find it.  Strange -- means ip is a code address outside
35619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      of any mapped text segment.  Unlikely but not impossible -- app
35629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      could be generating code to run. */
35639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di)
35649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
35659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (0 && ((n_search & 0x1) == 0))
35679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, "
35689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  "%u DebugInfos looked at\n",
35699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  n_search, n_steps);
35709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Start of performance-enhancing hack: once every ??? (chosen
35719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      hackily after profiling) successful searches, move the found
35729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DebugInfo one step closer to the start of the list.  This makes
35739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      future searches cheaper. */
35749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if ((n_search & 0xFFFF) == 0) {
35759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Move si one step closer to the start of the list. */
35769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      move_DebugInfo_one_step_forward( di );
35779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
35789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* End of performance-enhancing hack. */
35799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
35819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
35829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return res; /* currently empty */
35839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Work through the scopes from most deeply nested outwards,
35859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      looking for code address ranges that bracket 'ip'.  The
35869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      variables on each such address range found are in scope right
35879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      now.  Don't descend to level zero as that is the global
35889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      scope. */
35899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
35909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* "for each scope, working outwards ..." */
35919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
35929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      XArray*      vars;
35939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      Word         j;
35949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* arange;
35959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet*        this_scope
35969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
35979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (debug)
35989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
35999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!this_scope)
36009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
36019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Find the set of variables in this scope that
36029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         bracket the program counter. */
36039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      arange = VG_(OSetGen_LookupWithCmp)(
36049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  this_scope, &ip,
36059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                  ML_(cmp_for_DiAddrRange_range)
36069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               );
36079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (!arange)
36089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         continue;
36099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* stay sane */
36109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= arange->aMax);
36119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must bracket the ip we asked for, else
36129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
36139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
36149c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* It must have an attached XArray of DiVariables. */
36159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vars = arange->vars;
36169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(vars);
36179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* But it mustn't cover the entire address range.  We only
36189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         expect that to happen for the global scope (level 0), which
36199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         we're not looking at here.  Except, it may cover the entire
36209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         address range, but in that case the vars array must be
36219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         empty. */
36229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      vg_assert(! (arange->aMin == (Addr)0
36239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && arange->aMax == ~(Addr)0
36249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                   && VG_(sizeXA)(vars) > 0) );
36259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
36269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
36279c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         if (debug)
36289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(printf)("QQQQ:    var:name=%s %#lx-%#lx %#lx\n",
36299c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                        var->name,arange->aMin,arange->aMax,ip);
36309c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         analyse_deps( res, di->admin_tyents, ip,
3631588658b13b5ad77672f323d48fe9da0ca60b0bcbtom                       di, var, arrays_only );
36329c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      }
36339c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
36349c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return res;
36369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
36379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj/* Get an array of GlobalBlock which describe the global blocks owned
36409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   by the shared object characterised by the given di_handle.  Asserts
36419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if the handle is invalid.  The caller is responsible for freeing
36429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   the array at some point.  If 'arrays_only' is True, only
36439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   array-typed blocks are returned; otherwise blocks of all types are
36449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   returned. */
36459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardjvoid* /* really, XArray* of GlobalBlock */
36479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
36489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                                Bool  arrays_only )
36499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj{
36509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* This is a derivation of consider_vars_in_frame() above. */
36519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   DebugInfo* di;
36539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   XArray* gvars; /* XArray* of GlobalBlock */
36549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   Word nScopes, scopeIx;
36559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* The first thing to do is find the DebugInfo that
36579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      pertains to 'di_handle'. */
36589c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di_handle > 0);
36599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (di = debugInfo_list; di; di = di->next) {
36609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      if (di->handle == di_handle)
36619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         break;
36629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   }
36639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* If this fails, we were unable to find any DebugInfo with the
36659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      given handle.  This is considered an error on the part of the
36669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      caller. */
36679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(di != NULL);
36689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll put the collected variables in here. */
36709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   gvars = VG_(newXA)( ML_(dinfo_zalloc), "di.debuginfo.dggbfd.1",
36719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                       ML_(dinfo_free), sizeof(GlobalBlock) );
36729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   tl_assert(gvars);
36739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* any var info at all? */
36759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   if (!di->varinfo)
36769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      return gvars;
36779c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36789c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* we'll iterate over all the variables we can find, even if
36799c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      it seems senseless to visit stack-allocated variables */
36809c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   /* Iterate over all scopes */
36819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   nScopes = VG_(sizeXA)( di->varinfo );
36829c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   for (scopeIx = 0; scopeIx < nScopes; scopeIx++) {
36839c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36849c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      /* Iterate over each (code) address range at the current scope */
36859c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      DiAddrRange* range;
36869c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      OSet* /* of DiAddrInfo */ scope
36879c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx );
36889c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      tl_assert(scope);
36899c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_(OSetGen_ResetIter)(scope);
36909c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      while ( (range = VG_(OSetGen_Next)(scope)) ) {
36919c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         /* Iterate over each variable in the current address range */
36939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         Word nVars, varIx;
36949c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         tl_assert(range->vars);
36959c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         nVars = VG_(sizeXA)( range->vars );
36969c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         for (varIx = 0; varIx < nVars; varIx++) {
36979c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
36989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            Bool        isVec;
36999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GXResult    res;
370050fde23467d92281b32dd537d0d9a590263628c3sewardj            MaybeULong  mul;
37019c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            GlobalBlock gb;
37029c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            TyEnt*      ty;
37039c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            DiVariable* var = VG_(indexXA)( range->vars, varIx );
37049c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
37059c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name );
37069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37079c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Now figure out if this variable has a constant address
37089c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               (that is, independent of FP, SP, phase of moon, etc),
37099c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               and if so, what the address is.  Any variable with a
37109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               constant address is deemed to be a global so we collect
37119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
37129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr);
37139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                     VG_(printf)("\n"); }
3714588658b13b5ad77672f323d48fe9da0ca60b0bcbtom            res = ML_(evaluate_trivial_GX)( var->gexpr, di );
37159c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37169c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Not a constant address => not interesting */
37173c9cf3442185b5891e15450d6e3058aeff6796fetom            if (res.kind != GXR_Addr) {
37189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               if (0) VG_(printf)("FAIL\n");
37199c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue;
37209c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            }
37219c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37229c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, it's a constant address.  See if we want to collect
37239c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               it. */
37249c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("%#lx\n", res.word);
37259c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37269c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Figure out how big the variable is. */
372750fde23467d92281b32dd537d0d9a590263628c3sewardj            mul = ML_(sizeOfType)(di->admin_tyents, var->typeR);
37289c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
372950fde23467d92281b32dd537d0d9a590263628c3sewardj            /* If this var has a type whose size is unknown, zero, or
373050fde23467d92281b32dd537d0d9a590263628c3sewardj               impossibly large, it should never have been added.
373150fde23467d92281b32dd537d0d9a590263628c3sewardj               ML_(addVar) should have rejected it. */
373250fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.b == True);
373350fde23467d92281b32dd537d0d9a590263628c3sewardj            vg_assert(mul.ul > 0);
373450fde23467d92281b32dd537d0d9a590263628c3sewardj            if (sizeof(void*) == 4) vg_assert(mul.ul < (1ULL << 32));
373550fde23467d92281b32dd537d0d9a590263628c3sewardj            /* After this point, we assume we can truncate mul.ul to a
373650fde23467d92281b32dd537d0d9a590263628c3sewardj               host word safely (without loss of info). */
37379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* skip if non-array and we're only interested in
37399c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               arrays */
37409c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            ty = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL,
37419c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                              var->typeR );
37429c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty);
37439c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            vg_assert(ty->tag == Te_UNKNOWN || ML_(TyEnt__is_type)(ty));
37449c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (ty->tag == Te_UNKNOWN)
37459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj               continue; /* perhaps we should complain in this case? */
37469c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37479c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            isVec = ty->tag == Te_TyArray;
37489c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (arrays_only && !isVec) continue;
37499c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37509c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            /* Ok, so collect it! */
37519c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(var->name);
37529c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(di->soname);
37539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            if (0) VG_(printf)("XXXX %s %s %d\n", var->name,
37549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                var->fileName?(HChar*)var->fileName
37559c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                             :"??",var->lineNo);
37569c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(memset)(&gb, 0, sizeof(gb));
37579c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.addr  = res.word;
375850fde23467d92281b32dd537d0d9a590263628c3sewardj            gb.szB   = (SizeT)mul.ul;
37599c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            gb.isVec = isVec;
37609c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1);
37619c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1);
37629c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0);
37639c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0);
37649c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37659c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj            VG_(addToXA)( gvars, &gb );
37669c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37679c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         } /* for (varIx = 0; varIx < nVars; varIx++) */
37689c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37699c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */
37709c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37719c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */
37729c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37739c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   return gvars;
37749c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj}
37759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
37769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj
3777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
3779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3781e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjconst DebugInfo* VG_(next_DebugInfo)(const DebugInfo* di)
3782eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
3784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
3785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
3786eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3787eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3788e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_text_avma)(const DebugInfo* di)
3789eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
3791eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3792eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3793e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_text_size)(const DebugInfo* di)
3794eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
3796eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3797eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
37983898022a7d74a227d6a35102faaedd420ed3a1c1bartAddr VG_(DebugInfo_get_bss_avma)(const DebugInfo* di)
37993898022a7d74a227d6a35102faaedd420ed3a1c1bart{
38003898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_avma : 0;
38013898022a7d74a227d6a35102faaedd420ed3a1c1bart}
38023898022a7d74a227d6a35102faaedd420ed3a1c1bart
38033898022a7d74a227d6a35102faaedd420ed3a1c1bartSizeT VG_(DebugInfo_get_bss_size)(const DebugInfo* di)
38043898022a7d74a227d6a35102faaedd420ed3a1c1bart{
38053898022a7d74a227d6a35102faaedd420ed3a1c1bart   return di->bss_present ? di->bss_size : 0;
38063898022a7d74a227d6a35102faaedd420ed3a1c1bart}
38073898022a7d74a227d6a35102faaedd420ed3a1c1bart
3808e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_plt_avma)(const DebugInfo* di)
3809092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3810092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_avma : 0;
3811092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3812092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3813e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di)
3814092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3815092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->plt_present ? di->plt_size : 0;
3816092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3817092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3818e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjAddr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di)
3819092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3820092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_avma : 0;
3821092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3822092b6268cc4a38ae9ee41d1e3355937536ddc579bart
3823e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjSizeT VG_(DebugInfo_get_gotplt_size)(const DebugInfo* di)
3824092b6268cc4a38ae9ee41d1e3355937536ddc579bart{
3825092b6268cc4a38ae9ee41d1e3355937536ddc579bart   return di->gotplt_present ? di->gotplt_size : 0;
3826092b6268cc4a38ae9ee41d1e3355937536ddc579bart}
3827092b6268cc4a38ae9ee41d1e3355937536ddc579bart
382868347837b3d82e48f85daff33ec7ba528891e4e7bartAddr VG_(DebugInfo_get_got_avma)(const DebugInfo* di)
382968347837b3d82e48f85daff33ec7ba528891e4e7bart{
383068347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_avma : 0;
383168347837b3d82e48f85daff33ec7ba528891e4e7bart}
383268347837b3d82e48f85daff33ec7ba528891e4e7bart
383368347837b3d82e48f85daff33ec7ba528891e4e7bartSizeT VG_(DebugInfo_get_got_size)(const DebugInfo* di)
383468347837b3d82e48f85daff33ec7ba528891e4e7bart{
383568347837b3d82e48f85daff33ec7ba528891e4e7bart   return di->got_present ? di->got_size : 0;
383668347837b3d82e48f85daff33ec7ba528891e4e7bart}
383768347837b3d82e48f85daff33ec7ba528891e4e7bart
38381636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_soname)(const DebugInfo* di)
3839eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
3841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3842eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
38431636d33c13958b9c0e7d3059cdd5005746418eb2florianconst HChar* VG_(DebugInfo_get_filename)(const DebugInfo* di)
3844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3845a5acac39bf3be7546222b1316faee5ee524be0d1sewardj   return di->fsm.filename;
3846eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3847eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3848e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjPtrdiffT VG_(DebugInfo_get_text_bias)(const DebugInfo* di)
3849bbec7728efefaa650970dd1f0282b77040287133sewardj{
3850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
3851bbec7728efefaa650970dd1f0282b77040287133sewardj}
3852bbec7728efefaa650970dd1f0282b77040287133sewardj
3853e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjInt VG_(DebugInfo_syms_howmany) ( const DebugInfo *si )
3854eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3855eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
3856eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
3857eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
3858e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardjvoid VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
3859e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                        Int idx,
3860a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    avma,
3861a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Addr*    tocptr,
3862a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/UInt*    size,
386319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar**  pri_name,
386419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian                                  /*OUT*/HChar*** sec_names,
3865a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isText,
3866a5cace0c2a3e212931badbf6398a0cd98393121asewardj                                  /*OUT*/Bool*    isIFunc )
3867eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
3868eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
3869a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (avma)      *avma      = si->symtab[idx].addr;
3870a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (tocptr)    *tocptr    = si->symtab[idx].tocptr;
3871a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (size)      *size      = si->symtab[idx].size;
3872a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (pri_name)  *pri_name  = si->symtab[idx].pri_name;
387319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   if (sec_names) *sec_names = (HChar **)si->symtab[idx].sec_names; // FIXME
3874a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isText)    *isText    = si->symtab[idx].isText;
3875a5cace0c2a3e212931badbf6398a0cd98393121asewardj   if (isIFunc)   *isIFunc   = si->symtab[idx].isIFunc;
3876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3877b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3878b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
3881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
3882b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3883b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
3884b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
3885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
3886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
3888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
3889b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
3890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
3891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
3892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
3893b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
3894b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
38955706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      case Vg_SectGOTPLT:  return "GOTPLT";
3896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
3897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
3899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
3901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
3902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
3903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
3904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
39051636d33c13958b9c0e7d3059cdd5005746418eb2florianVgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/HChar* name, SizeT n_name,
3906e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj                                     Addr a)
3907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
3908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
3909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
3910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
3912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
3914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
3915e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "addr=%#lx di=%p %s got=%#lx,%ld plt=%#lx,%ld "
3916e3f1e5988a94af9230f67273ca9236c4d7e8b8dasewardj            "data=%#lx,%ld bss=%#lx,%ld\n",
3917a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            a, di, di->fsm.filename,
3918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
3919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
3920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
3921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
3922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
3924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
3925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
3926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
3927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
3930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
3931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
3932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
3936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
3937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
3938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
3939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
3942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
3943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
3944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
3945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
39475706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      if (di->sbss_present
39485706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && di->sbss_size > 0
39495706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj          && a >= di->sbss_avma && a < di->sbss_avma + di->sbss_size) {
39505706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         res = Vg_SectBSS;
39515706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj         break;
39525706ca98d16b4ed5f455c71c01655fc12f6b9eb9sewardj      }
3953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
3954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
3955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
3956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
3957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
3960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
3961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
3962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
3963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3965092b6268cc4a38ae9ee41d1e3355937536ddc579bart      if (di->gotplt_present
3966092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && di->gotplt_size > 0
3967092b6268cc4a38ae9ee41d1e3355937536ddc579bart          && a >= di->gotplt_avma && a < di->gotplt_avma + di->gotplt_size) {
3968092b6268cc4a38ae9ee41d1e3355937536ddc579bart         res = Vg_SectGOTPLT;
3969092b6268cc4a38ae9ee41d1e3355937536ddc579bart         break;
3970092b6268cc4a38ae9ee41d1e3355937536ddc579bart      }
3971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
3972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
3973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
3974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
3975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
3976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
3977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
3978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
3979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3980b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
3981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
3982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
3984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
3986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
3987a5acac39bf3be7546222b1316faee5ee524be0d1sewardj      if (di && di->fsm.filename) {
3988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
3989a5acac39bf3be7546222b1316faee5ee524be0d1sewardj         Int fnlen = VG_(strlen)(di->fsm.filename);
3990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
3991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
3992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
3993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
3994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
3995d5dea1dabc523d3f96bafd52ae9586abd8797416bart            vg_assert(j >= 0 && j < n_name);
3996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
3997a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            name[j] = di->fsm.filename[i];
3998a5acac39bf3be7546222b1316faee5ee524be0d1sewardj            if (di->fsm.filename[i] == 0) break;
3999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
4000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
4001d5dea1dabc523d3f96bafd52ae9586abd8797416bart         vg_assert(i == fnlen);
4002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
4003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
4004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
4005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
4007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
4008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
4010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
4011eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
4012eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4013eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4014eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
4015eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
4016