debuginfo.c revision 2ac79d3f62c0a2d44896a6d7d74a4500f364bbe0
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
114d474d086188fd1f29fa97dbd84d8ea2e589a9b8sewardj   Copyright (C) 2000-2008 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   Stabs reader greatly improved by Nick Nethercote, Apr 02.
33eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   This module was also extensively hacked on by Jeremy Fitzhardinge
34eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and Tom Hughes.
35eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
36eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
37eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_basics.h"
384cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
39eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_threadstate.h"
40b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_debuginfo.h"  /* self */
41eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_demangle.h"
42eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcbase.h"
43eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcassert.h"
44eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_libcprint.h"
45b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_libcfile.h"
46eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_options.h"
47b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_redir.h"      // VG_(redir_notify_{new,delete}_SegInfo)
48eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#include "pub_core_aspacemgr.h"
49b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_machine.h"    // VG_PLAT_USES_PPCTOC
5072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj#include "pub_core_xarray.h"
51b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_oset.h"
52b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "pub_core_stacktrace.h" // VG_(get_StackTrace)
53b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
54b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#include "priv_misc.h"           /* dinfo_zalloc/free */
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"
634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#elif defined(VGO_aix5)
644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_debuglog.h"
654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcproc.h"
664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "pub_core_libcfile.h"
674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj# include "priv_readxcoff.h"
684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif
69eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
70c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
71c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
72c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*--- The _svma / _avma / _image / _bias naming scheme     ---*/
73c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/*------------------------------------------------------------*/
74c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
75c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj/* JRS 11 Jan 07: I find the different kinds of addresses involved in
76c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   debuginfo reading confusing.  Recently I arrived at some
77c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   terminology which makes it clearer (to me, at least).  There are 3
78c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   kinds of address used in the debuginfo reading process:
79c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
80c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   stated VMAs - the address where (eg) a .so says a symbol is, that
81c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 is, what it tells you if you consider the .so in
82c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 isolation
83c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
84c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   actual VMAs - the address where (eg) said symbol really wound up
85c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                 after the .so was mapped into memory
86c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
87c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   image addresses - pointers into the copy of the .so (etc)
88c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj                     transiently mmaped aboard whilst we read its info
89c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
90c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   Additionally I use the term 'bias' to denote the difference
91c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   between stated and actual VMAs for a given entity.
92c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
93c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   This terminology is not used consistently, but a start has been
94c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   made.  readelf.c and the call-frame info reader in readdwarf.c now
95c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj   use it.  Specifically, various variables and structure fields have
96f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   been annotated with _avma / _svma / _image / _bias.  In places _img
97f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   is used instead of _image for the sake of brevity.
98c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj*/
99c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
100c6d3f6f0aec8607dded979fd15a9876a486ec682sewardj
101eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Root structure                                       ---*/
103eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* The root structure for the entire debug info system.  It is a
106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   linked list of DebugInfos. */
107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic DebugInfo* debugInfo_list = NULL;
108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find 'di' in the debugInfo_list and move it one step closer the the
111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   front of the list, so as to make subsequent searches for it
112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   cheaper.  When used in a controlled way, makes a major improvement
113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   in some DebugInfo-search-intensive situations, most notably stack
114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   unwinding on amd64-linux. */
115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void move_DebugInfo_one_step_forward ( DebugInfo* di )
116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo *di0, *di1, *di2;
118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == debugInfo_list)
119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return; /* already at head of list */
120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di0 = debugInfo_list;
122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di1 = NULL;
123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di2 = NULL;
124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di0 == NULL || di0 == di) break;
126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2 = di1;
127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1 = di0;
128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0 = di0->next;
129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di0 == di);
131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 != NULL) {
132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* tmp;
133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* di0 points to di, di1 to its predecessor, and di2 to di1's
134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         predecessor.  Swap di0 and di1, that is, move di0 one step
135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         closer to the start of the list. */
136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di2->next == di1);
137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tmp = di0->next;
139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di2->next = di0;
140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = tmp;
142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di0 != NULL && di1 != NULL && di2 == NULL) {
145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* it's second in the list. */
146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(debugInfo_list == di1);
147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di1->next == di0);
148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di1->next = di0->next;
149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di0->next = di1;
150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di0;
151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Notification (acquire/discard) helpers               ---*/
157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
158eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Allocate and zero out a new DebugInfo record. */
160eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* alloc_DebugInfo( const UChar* filename,
162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            const UChar* memname )
163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       traceme;
165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
167f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   vg_assert(filename);
168f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = ML_(dinfo_zalloc)(sizeof(DebugInfo));
170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->filename  = ML_(dinfo_strdup)(filename);
171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di->memname   = memname ? ML_(dinfo_strdup)(memname)
172b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                           : NULL;
173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
174f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
175f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      Now set up the debugging-output flags. */
176f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   traceme
177f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj      = VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
178f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj        || (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
179f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj                                          memname ));
180f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   if (traceme) {
181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_symtab = VG_(clo_trace_symtab);
182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->trace_cfi    = VG_(clo_trace_cfi);
183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_syms   = VG_(clo_debug_dump_syms);
184b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_line   = VG_(clo_debug_dump_line);
185b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->ddump_frames = VG_(clo_debug_dump_frames);
186f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj   }
187f767d967b9ef331dcd7d0cd4584f6570cd829333sewardj
188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
189eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
191eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
192b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Free a DebugInfo, and also all the stuff hanging off it. */
193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void free_DebugInfo ( DebugInfo* di )
194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word i, j;
196eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   struct strchunk *chunk, *next;
197b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   TyAdmin *admin1, *admin2;
198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GExpr *gexpr1, *gexpr2;
199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di != NULL);
201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->filename)   ML_(dinfo_free)(di->filename);
202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->symtab)     ML_(dinfo_free)(di->symtab);
203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->loctab)     ML_(dinfo_free)(di->loctab);
204b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi)       ML_(dinfo_free)(di->cfsi);
205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->cfsi_exprs) VG_(deleteXA)(di->cfsi_exprs);
206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
207b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (chunk = di->strchunks; chunk != NULL; chunk = next) {
208eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      next = chunk->next;
209b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(chunk);
210b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
212b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Delete the two admin lists.  These lists exist purely so that we
213b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      can visit each object exactly once when we need to delete
214b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      them. */
215b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (admin1 = di->admin_tyadmins; admin1; admin1 = admin2) {
216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      admin2 = admin1->next;
217b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(delete_TyAdmin_and_payload)(admin1);
218eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
219b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (gexpr1 = di->admin_gexprs; gexpr1; gexpr1 = gexpr2) {
220b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gexpr2 = gexpr1->next;
221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(dinfo_free)(gexpr1);
222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
223b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
224b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Dump the variable info.  This is kinda complex: we must take
225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      care not to free items which reside in either the admin lists
226b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      (as we have just freed them) or which reside in the DebugInfo's
227b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      string table. */
228b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->varinfo) {
229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)(di->varinfo); i++) {
230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         OSet* scope = *(OSet**)VG_(indexXA)(di->varinfo, i);
231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!scope) continue;
232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* iterate over all entries in 'scope' */
233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_ResetIter)(scope);
234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            DiAddrRange* arange = VG_(OSetGen_Next)(scope);
236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (!arange) break;
237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* for each var in 'arange' */
238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(arange->vars);
239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            for (j = 0; j < VG_(sizeXA)( arange->vars ); j++) {
240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               DiVariable* var = (DiVariable*)VG_(indexXA)(arange->vars,j);
241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               vg_assert(var);
242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               /* Nothing to free in var: all the pointer fields refer
243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  to stuff either on an admin list, or in
244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  .strchunks */
245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            }
246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)(arange->vars);
247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            /* Don't free arange itself, as OSetGen_Destroy does
248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               that */
249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(OSetGen_Destroy)(scope);
251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(deleteXA)(di->varinfo);
253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ML_(dinfo_free)(di);
256eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
257eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
258eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* 'si' is a member of debugInfo_list.  Find it, remove it from the
260eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   list, notify m_redir that this has happened, and free all storage
261eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   reachable from it.
262eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfo ( DebugInfo* di )
264eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VGP_ppc32_aix5)
2664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "__unload";
2674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  elif defined(VGP_ppc64_aix5)
2684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "kunload64";
2694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  else
2704ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   HChar* reason = "munmap";
2714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
2724ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo** prev_next_ptr = &debugInfo_list;
274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo*  curr          =  debugInfo_list;
275eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
276eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (curr) {
277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (curr == di) {
278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Found it;  remove from list and free it. */
27933e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo
28033e4e7eaab263cea956700f56f007ab26c39eab4sewardj             && (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)))
281eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            VG_(message)(Vg_DebugMsg,
2824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         "Discarding syms at %p-%p in %s due to %s()",
283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma,
284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di->text_avma + di->text_size,
2854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         curr->filename ? curr->filename : (UChar*)"???",
2864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                         reason);
287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(*prev_next_ptr == curr);
288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *prev_next_ptr = curr->next;
28933e4e7eaab263cea956700f56f007ab26c39eab4sewardj         if (curr->have_dinfo)
29033e4e7eaab263cea956700f56f007ab26c39eab4sewardj            VG_(redir_notify_delete_DebugInfo)( curr );
291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         free_DebugInfo(curr);
292eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      prev_next_ptr = &curr->next;
295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      curr          =  curr->next;
296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Not found. */
299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   AVMAs intersecting [start,start+length), and call discard_DebugInfo
304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to get rid of them.  This modifies the list, hence the multiple
305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   iterations.
306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic void discard_syms_in_range ( Addr start, SizeT length )
308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   while (True) {
313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      found = False;
314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      while (True) {
317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (curr == NULL)
318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            break;
319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->text_present
320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && curr->text_size > 0
321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj             && (start+length - 1 < curr->text_avma
322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                 || curr->text_avma + curr->text_size - 1 < start)) {
323eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            /* no overlap */
324eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 } else {
325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    found = True;
326eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	    break;
327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 }
328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 curr = curr->next;
329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (!found) break;
332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Does [s1,+len1) overlap [s2,+len2) ?  Note: does not handle
338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   wraparound at the end of the address space -- just asserts in that
339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   case. */
340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 )
341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr e1, e2;
343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (len1 == 0 || len2 == 0)
344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e1 = s1 + len1 - 1;
346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   e2 = s2 + len2 - 1;
347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Assert that we don't have wraparound.  If we do it would imply
348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      that file sections are getting mapped around the end of the
349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      address space, which sounds unlikely. */
350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s1 <= e1);
351b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(s2 <= e2);
352b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (e1 < s2 || e2 < s1) return False;
353b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
354b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
357b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in
358b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   any way? */
359b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 )
360b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
361b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di1);
362b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di2);
363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
364b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rx_map
365b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
366b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
367b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
369b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rx_map && di2->have_rw_map
370b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rx_map_avma, di1->rx_map_size,
371b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
372b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
373b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
374b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rx_map
375b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
376b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rx_map_avma, di2->rx_map_size))
377b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
378b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
379b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di1->have_rw_map && di2->have_rw_map
380b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && ranges_overlap(di1->rw_map_avma, di1->rw_map_size,
381b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         di2->rw_map_avma, di2->rw_map_size))
382b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
383b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
384b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
385b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
386b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
387b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
388b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard all elements of debugInfo_list whose .mark bit is set.
389b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
390b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_marked_DebugInfos ( void )
391b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
392b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* curr;
393b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
394b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while (True) {
395b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
396b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      curr = debugInfo_list;
397b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      while (True) {
398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (!curr)
399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (curr->mark)
401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            break;
402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj	 curr = curr->next;
403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
404b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
405b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!curr) break;
406b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfo( curr );
407b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
408b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
409b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
410b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
411b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
412b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Discard any elements of debugInfo_list which overlap with diRef.
413b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Clearly diRef must have its rx_ and rw_ mapping information set to
414b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   something sane. */
415b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#if defined(VGO_aix5)
416b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj__attribute__((unused))
417b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#endif
418b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef )
419b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
420b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
421b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Mark all the DebugInfos in debugInfo_list that need to be
422b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      deleted.  First, clear all the mark bits; then set them if they
423b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      overlap with siRef.  Since siRef itself is in this list we at
424b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      least expect its own mark bit to be set. */
425b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
426b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->mark = do_DebugInfos_overlap( di, diRef );
427b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di == diRef) {
428b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(di->mark);
429b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->mark = False;
430b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
431eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
432b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   discard_marked_DebugInfos();
433b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
434b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
435eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
436b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Find the existing DebugInfo for (memname,filename) or if not found,
437b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   create one.  In the latter case memname and filename are strdup'd
438b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   into VG_AR_DINFO, and the new DebugInfo is added to
439b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debugInfo_list. */
440b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
441b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* find_or_create_DebugInfo_for ( UChar* filename, UChar* memname )
442b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
443b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
444b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(filename);
445b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
446b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
447b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0==VG_(strcmp)(di->filename, filename)
448b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ( (memname && di->memname)
449b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ? 0==VG_(strcmp)(memname, di->memname)
450b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  : True ))
451b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
452b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
453b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di) {
454b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = alloc_DebugInfo(filename, memname);
455b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
456b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->next = debugInfo_list;
457b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      debugInfo_list = di;
458b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
459b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di;
460eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
461eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
462eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
4634ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
4644ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
4654ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
4664ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                        ---*/
4674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--------------------------------------------------------------*/
4684ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
4694ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_linux)
470eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
471eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The debug info system is driven by notifications that a text
472eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   segment has been mapped in, or unmapped.  When that happens it
473eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tries to acquire/discard whatever info is available for the
474eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   corresponding object.  This section contains the notification
475eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   handlers. */
476eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
477eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Notify the debuginfo system about a new mapping.  This is the way
478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   new debug information gets loaded.  If allow_SkFileV is True, it
479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   will try load debug info if the mapping at 'a' belongs to Valgrind;
480eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   whereas normally (False) it will not do that.  This allows us to
481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   carefully control when the thing will read symbols from the
482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Valgrind executable itself. */
483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
4864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   NSegment const * seg;
487b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar*     filename;
488b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       ok, is_rx_map, is_rw_map;
489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
490b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SysRes     fd;
491b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        nread;
492b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   HChar      buf1k[1024];
493b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       debug = False;
494b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
495b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* In short, figure out if this mapping is of interest to us, and
496b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if so, try to guess what ld.so is doing and when/if we should
497b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      read debug info. */
498b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   seg = VG_(am_find_nsegment)(a);
499b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg);
500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
502b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-1: %p-%p %c%c%c\n",
503b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->start, seg->end,
504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasR ? 'r' : '-',
505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  seg->hasW ? 'w' : '-',seg->hasX ? 'x' : '-' );
506eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
507b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* guaranteed by aspacemgr-linux.c, sane_NSegment() */
508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(seg->end > seg->start);
509b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
510b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ignore non-file mappings */
511b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( ! (seg->kind == SkFileC
512b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj           || (seg->kind == SkFileV && allow_SkFileV)) )
513b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
514b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
515b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If the file doesn't have a name, we're hosed.  Give up. */
516b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   filename = VG_(am_get_filename)( (NSegment*)seg );
517b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!filename)
518b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
519b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
520b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
521b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-2: %s\n", filename);
522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
5232ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   /* XXXX begin KLUDGE */
5242ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   /* Skip filenames in /dev/.  Don't even bother to try opening them.
5252ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      Why?
5262ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
5272ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      Suppose the client opens and then mmaps the file specified by
5282ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      'filename' and puts some kind of lock on it, so nobody else can
5292ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      open it.  If we now try to open it to peer at the ELF header,
5302ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      the system can hang, because the VG_(open) call blocks.
5312ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      Precisely this happed when running Amarok, which opened and then
5322ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      mmap'd /dev/snd/pcmC0D0c.
5332ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
5342ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      A clean(er) solution is to open the file with VKI_O_NONBLOCK, so
5352ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      that if it is locked, we simply fail immediately and don't hang
5362ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      the whole system.  But "man 2 open" gives only a sketchy
5372ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      description of the resulting file semantics.  So for the
5382ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      meantime, just skip files in /dev/ as (1) they are likely to be
5392ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      subject to wierd-ass locking stuff, and (2) they won't contain
5402ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      useful debug info anyway.
5412ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
5422ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      But that's a kludge; in principle the same problem could occur
5432ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      with *any* file.
5442ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   */
5452ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   if (0 == VG_(strncmp)(filename, "/dev/", 5)) {
5462ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      if (debug)
5472ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj         VG_(printf)("di_notify_mmap-2: skipping %s\n", filename);
5482ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj      return;
5492ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   }
5502ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj   /* XXXX end KLUDGE */
5512ac79d3f62c0a2d44896a6d7d74a4500f364bbe0sewardj
552b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Peer at the first few bytes of the file, to see if it is an ELF
553b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      object file. */
554b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(memset)(buf1k, 0, sizeof(buf1k));
555b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
556b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (fd.isError) {
557b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo fake_di;
558b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(memset)(&fake_di, 0, sizeof(fake_di));
559b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      fake_di.filename = filename;
560b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header");
561b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
562b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
563b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   nread = VG_(read)( fd.res, buf1k, sizeof(buf1k) );
564b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(close)( fd.res );
565b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
566b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (nread <= 0) {
567b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(symerr)(NULL, True, "can't read file to inspect ELF header");
568b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
569b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
570b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(nread > 0 && nread <= sizeof(buf1k) );
571b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
572b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We're only interested in mappings of ELF object files. */
573b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread ))
574b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
575b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
576b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Now we have to guess if this is a text-like mapping, a data-like
577b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      mapping, neither or both.  The rules are:
578b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
579b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        text if:   x86-linux    r and x
580b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and x and not w
581b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
582b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        data if:   x86-linux    r and w
583b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   other-linux  r and w and not x
584b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
585b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Background: On x86-linux, objects are typically mapped twice:
586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8fb000-1b8ff000 r-xp 00000000 08:02 4471477 vgpreload_memcheck.so
588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      1b8ff000-1b900000 rw-p 00004000 08:02 4471477 vgpreload_memcheck.so
589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      whereas ppc32-linux mysteriously does this:
591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
592eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118a6000-118ad000 r-xp 00000000 08:05 14209428 vgpreload_memcheck.so
593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118ad000-118b6000 ---p 00007000 08:05 14209428 vgpreload_memcheck.so
594eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      118b6000-118bd000 rwxp 00000000 08:05 14209428 vgpreload_memcheck.so
595eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
596eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      The third mapping should not be considered to have executable
597eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      code in.  Therefore a test which works for both is: r and x and
598eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      NOT w.  Reading symbols from the rwx segment -- which overlaps
599eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      the r-x segment in the file -- causes the redirection mechanism
600eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      to redirect to addresses in that third segment, which is wrong
601eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      and causes crashes.
602eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
603eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      JRS 28 Dec 05: unfortunately icc 8.1 on x86 has been seen to
604eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      produce executables with a single rwx segment rather than a
605eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      (r-x,rw-) pair. That means the rules have to be modified thusly:
606eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
607eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      x86-linux:   consider if r and x
608b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all others:  consider if r and x and not w
609eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   */
610b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = False;
611b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = False;
612eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  if defined(VGP_x86_linux)
613b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX;
614b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW;
615b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  elif defined(VGP_amd64_linux) \
616b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
617b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
618b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  else
620b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#    error "Unknown platform"
621eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
622eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
623b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
624b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("di_notify_mmap-3: is_rx_map %d, is_rw_map %d\n",
625b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  (Int)is_rx_map, (Int)is_rw_map);
626eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
627b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* If it is neither text-ish nor data-ish, we're not interested. */
628b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!(is_rx_map || is_rw_map))
629eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return;
630eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* See if we have a DebugInfo for this filename.  If not,
632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      create one. */
633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   di = find_or_create_DebugInfo_for( filename, NULL/*membername*/ );
634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(di);
635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rx_map) {
637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a text-like mapping.  Note the details. */
638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rx_map) {
639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rx_map = True;
640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_avma = a;
641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_size = seg->end + 1 - seg->start;
642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rx_map_foff = seg->offset;
643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second text-like mapping */
645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
647eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (is_rw_map) {
649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We have a data-like mapping.  Note the details. */
650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->have_rw_map) {
651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_rw_map = True;
652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_avma = a;
653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_size = seg->end + 1 - seg->start;
654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->rw_map_foff = seg->offset;
655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* FIXME: complain about a second data-like mapping */
657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
658eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
659eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di->have_rx_map && di->have_rw_map && !di->have_dinfo) {
661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di->filename);
663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("\n");
664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("------ start ELF OBJECT "
665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   "------------------------------\n");
666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("------ name = %s\n", di->filename);
667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("\n");
668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* We're going to read symbols and debug info for the avma
670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ranges [rx_map_avma, +rx_map_size) and [rw_map_avma,
671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         +rw_map_size).  First get rid of any other DebugInfos which
672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         overlap either of those ranges (to avoid total confusion). */
673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      discard_DebugInfos_which_overlap_with( di );
674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* .. and acquire new info. */
676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ok = ML_(read_elf_debug_info)( di );
677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ok) {
679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         TRACE_SYMTAB("\n------ Canonicalising the "
680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                      "acquired info ------\n");
681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* prepare read data for use */
682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(canonicaliseTables)( di );
683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* notify m_redir about it */
684b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         TRACE_SYMTAB("\n------ Notifying m_redir ------\n");
685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(redir_notify_new_DebugInfo)( di );
686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note that we succeeded */
687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_dinfo = True;
688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         TRACE_SYMTAB("\n------ ELF reading failed ------\n");
690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Something went wrong (eg. bad ELF file).  Should we delete
691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            this DebugInfo?  No - it contains info on the rw/rx
692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            mappings, at least. */
693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
694eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("\n");
696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("------ name = %s\n", di->filename);
697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("------ end ELF OBJECT "
698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   "------------------------------\n");
699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      TRACE_SYMTAB("\n");
700eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
702eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
703eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
704eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
705eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Unmap is simpler - throw away any SegInfos intersecting
706eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   [a, a+len).  */
707eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_munmap)( Addr a, SizeT len )
708eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0) VG_(printf)("DISCARD %p %p\n", a, a+len);
710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discard_syms_in_range(a, len);
711eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
712eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
713eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
714eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Uh, this doesn't do anything at all.  IIRC glibc (or ld.so, I don't
715eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   remember) does a bunch of mprotects on itself, and if we follow
716eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   through here, it causes the debug info for that object to get
717eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   discarded. */
718eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjvoid VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot )
719eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
720eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool exe_ok = toBool(prot & VKI_PROT_EXEC);
721eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  if defined(VGP_x86_linux)
722eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
723eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  endif
724eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0 && !exe_ok)
725eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      discard_syms_in_range(a, len);
726eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
727eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
7284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_linux) */
7294ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
7304ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
7314ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
7324ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
7334ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/
7344ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*---                                                       ---*/
7354ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/*-------------------------------------------------------------*/
7364ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
7374ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#if defined(VGO_aix5)
7384ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
7394ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* The supplied parameters describe a code segment and its associated
7404ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   data segment, that have recently been mapped in -- so we need to
7414ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   read debug info for it -- or conversely, have recently been dumped,
7424ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   in which case the relevant debug info has to be unloaded. */
7434ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
7444ee4f98c6dd3dd9517954efc628753bf46811d2dsewardjvoid VG_(di_aix5_notify_segchange)(
7454ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   code_start,
7464ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   code_len,
7474ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Addr   data_start,
7484ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Word   data_len,
7494ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* file_name,
7504ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               UChar* mem_name,
7514ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   is_mainexe,
7524ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               Bool   acquire )
7534ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
7544ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (acquire) {
7554ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Bool       ok;
757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo* di;
758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di = find_or_create_DebugInfo_for( file_name, mem_name );
759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(di);
760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0) {
762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_present = True;
763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_svma = 0; /* don't know yet */
764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_bias = 0; /* don't know yet */
765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_avma = code_start;
766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->text_size = code_len;
767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (data_len > 0) {
769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_present = True;
770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_svma = 0; /* don't know yet */
771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_bias = 0; /* don't know yet */
772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_avma = data_start;
773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->data_size = data_len;
774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* These need to be filled in in order to keep various
777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         assertions in storage.c happy.  In particular see
778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Comment_Regarding_Text_Range_Checks" in that file. */
779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rx_map = True;
780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_avma = code_start;
781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rx_map_size = code_len;
782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->have_rw_map = True;
783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_avma = data_start;
784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      di->rw_map_size = data_len;
785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ok = ML_(read_xcoff_debug_info) ( di, is_mainexe );
787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (ok) {
789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* prepare read data for use */
790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(canonicaliseTables)( di );
791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* notify m_redir about it */
792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(redir_notify_new_DebugInfo)( di );
793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note that we succeeded */
794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di->have_dinfo = True;
795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /*  Something went wrong (eg. bad XCOFF file). */
797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         discard_DebugInfo( di );
798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         di = NULL;
799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
8004ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   } else {
8024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Dump all the debugInfos whose text segments intersect
804f7cdfe298805a91a35b8e0495d9034cbf21003f5sewardj         code_start/code_len. */
805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (code_len > 0)
806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         discard_syms_in_range( code_start, code_len );
8074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
8094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
8104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
8124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#endif /* defined(VGO_aix5) */
8134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
814eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
815eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
816eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
817eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO              ---*/
818eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*---                                                      ---*/
819eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
820eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
821eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
822eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- Use of symbol table & location info to create        ---*/
823eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- plausible-looking stack dumps.                       ---*/
824eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*------------------------------------------------------------*/
825eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
826eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all symtabs that we know about to locate ptr.  If found, set
827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *symno to the symtab entry
828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *psi is set to NULL.
829b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==True,  only text symbols are searched for.
830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If findText==False, only data symbols are searched for.
831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj*/
832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
833eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                           /*OUT*/Int* symno,
834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool match_anywhere_in_sym,
835b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                 Bool findText )
836eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        sno;
838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       inRange;
840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
843b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (findText) {
844b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = di->text_present
845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_size > 0
846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && di->text_avma <= ptr
847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && ptr < di->text_avma + di->text_size;
848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inRange = (di->data_present
850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_size > 0
851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->data_avma <= ptr
852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->data_avma + di->data_size)
853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->sdata_present
855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_size > 0
856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->sdata_avma <= ptr
857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->sdata_avma + di->sdata_size)
858b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   ||
859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   (di->bss_present
860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_size > 0
861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && di->bss_avma <= ptr
862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    && ptr < di->bss_avma + di->bss_size);
863eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
865b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!inRange) continue;
866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      sno = ML_(search_one_symtab) (
868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               di, ptr, match_anywhere_in_sym, findText );
869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (sno == -1) goto not_found;
870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *symno = sno;
871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *pdi = di;
872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return;
873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
874eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
875eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
877eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
878eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
879eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
880eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Search all loctabs that we know about to locate ptr.  If found, set
881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi to the relevant DebugInfo, and *locno to the loctab entry
882b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *number within that.  If not found, *pdi is set to NULL. */
883b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void search_all_loctabs ( Addr ptr, /*OUT*/DebugInfo** pdi,
884eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                           /*OUT*/Int* locno )
885eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        lno;
887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
889b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= ptr
891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && ptr < di->text_avma + di->text_size) {
892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         lno = ML_(search_one_loctab) ( di, ptr );
893eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (lno == -1) goto not_found;
894eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *locno = lno;
895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         *pdi = di;
896eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return;
897eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
898eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
899eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj  not_found:
900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   *pdi = NULL;
901eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
902eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
903eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
904eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* The whole point of this whole big deal: map a code address to a
905eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   plausible symbol name.  Returns False if no idea; otherwise True.
906eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Caller supplies buf and nbuf.  If demangle is False, don't do
907eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   demangling, regardless of VG_(clo_demangle) -- probably because the
908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   call has come from VG_(get_fnname_nodemangle)().  findText
909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   indicates whether we're looking for a text symbol or a data symbol
910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   -- caller must choose one kind or the other. */
911eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic
912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool get_sym_name ( Bool demangle, Addr a, Char* buf, Int nbuf,
913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool match_anywhere_in_sym, Bool show_offset,
914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                    Bool findText, /*OUT*/OffT* offsetP )
915eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        sno;
918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        offset;
919eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   search_all_symtabs ( a, &di, &sno, match_anywhere_in_sym, findText );
921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
922eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
923eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (demangle) {
924eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(demangle) ( True/*do C++ demangle*/,
925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                      di->symtab[sno].name, buf, nbuf );
926eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(strncpy_safely) ( buf, di->symtab[sno].name, nbuf );
928eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
929eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset = a - di->symtab[sno].addr;
931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (offsetP) *offsetP = (OffT)offset;
932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
933eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (show_offset && offset != 0) {
934eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char     buf2[12];
935eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    symend = buf + VG_(strlen)(buf);
936eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Char*    end = buf + nbuf;
937eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Int      len;
938eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
939eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      len = VG_(sprintf)(buf2, "%c%d",
940eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? '-' : '+',
941eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj			 offset < 0 ? -offset : offset);
942eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(len < (Int)sizeof(buf2));
943eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
944eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (len < (end - symend)) {
945eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 Char *cp = buf2;
946eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj	 VG_(memcpy)(symend, cp, len+1);
947eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
948eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
949eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
950eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
951eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
952eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
953eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
954eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   force at the entry point address of the function containing
955eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   guest_code_addr.  Returns 0 if not known. */
956eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjAddr VG_(get_tocptr) ( Addr guest_code_addr )
957eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Int        sno;
960eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_symtabs ( guest_code_addr,
961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        &si, &sno,
962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*match_anywhere_in_fun*/,
963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        True/*consider text symbols only*/ );
964eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
965eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return 0;
966eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   else
967eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return si->symtab[sno].tocptr;
968eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
969eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
970eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
971eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, but don't show offsets. */
972eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
973eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
979eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
980eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
981eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
982eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and show offset if nonzero. */
983eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
984eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/True,
988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
990eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
991eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
992eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is available to tools... always demangle C++ names,
993eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   only succeed if 'a' matches first instruction of function,
994eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   and don't show offsets. */
995eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
996eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/True, a, buf, nbuf,
998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/False,
999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1002eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1003eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1004eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names,
1005eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   match anywhere in function, and don't show offsets. */
1006eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
1007eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return get_sym_name ( /*demangle*/False, a, buf, nbuf,
1009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*match_anywhere_in_fun*/True,
1010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*show offset?*/False,
1011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*text syms only*/True,
1012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                         /*offsetP*/NULL );
1013eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1014eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1015eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* This is only available to core... don't demangle C++ names, but do
1016eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   do Z-demangling, match anywhere in function, and don't show
1017eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   offsets. */
1018eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_fnname_Z_demangle_only) ( Addr a, Char* buf, Int nbuf )
1019eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1020eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define N_TMPBUF 4096 /* arbitrary, 4096 == ERRTXT_LEN */
1021eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char tmpbuf[N_TMPBUF];
1022eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool ok;
1023eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(nbuf > 0);
1024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ok = get_sym_name ( /*demangle*/False, a, tmpbuf, N_TMPBUF,
1025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_fun*/True,
1026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*text syms only*/True,
1028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*offsetP*/NULL );
1029eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   tmpbuf[N_TMPBUF-1] = 0; /* paranoia */
1030eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (!ok)
1031eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1032eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1033eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* We have something, at least.  Try to Z-demangle it. */
1034eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(demangle)( False/*don't do C++ demangling*/, tmpbuf, buf, nbuf);
1035eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1036eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[nbuf-1] = 0; /* paranoia */
1037eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1038eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef N_TMPBUF
1039eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1040eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Looks up data_addr in the collection of data symbols, and if found
1042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   puts its name (or as much as will fit) into dname[0 .. n_dname-1],
1043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   which is guaranteed to be zero terminated.  Also data_addr's offset
1044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   from the symbol start is put into *offset. */
1045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_datasym_and_offset)( Addr data_addr,
1046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/Char* dname, Int n_dname,
1047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  /*OUT*/OffT* offset )
1048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool ok;
1050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
1051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ok = get_sym_name ( /*demangle*/False, data_addr, dname, n_dname,
1052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*match_anywhere_in_sym*/True,
1053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*show offset?*/False,
1054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       /*data syms only please*/False,
1055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                       offset );
1056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!ok)
1057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname[n_dname-1] = 0;
1059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return True;
1060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to the name of a shared object file or the
1063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   executable.  Returns False if no idea; otherwise True.  Doesn't
1064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   require debug info.  Caller supplies buf and nbuf. */
1065eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
1066eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
10674ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int used;
1068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1069f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   const NSegment *seg;
1070f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   HChar* filename;
10714ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   vg_assert(nbuf > 0);
1072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
1074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(strncpy_safely)(buf, di->filename, nbuf);
1077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (di->memname) {
10784ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
10794ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
10804ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
10814ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
10824ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
1083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               VG_(strncpy_safely)(&buf[used], di->memname, nbuf-used);
10844ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            used = VG_(strlen)(buf);
10854ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            if (used < nbuf)
10864ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj               VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
10874ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
10884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         buf[nbuf-1] = 0;
1089eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         return True;
1090eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1091eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1092f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   if ((seg = VG_(am_find_nsegment(a))) != NULL &&
1093f32ec7f0de8a651bc16a1b2e448c0106d8669889tom       (filename = VG_(am_get_filename)(seg)) != NULL)
1094f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   {
1095f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      VG_(strncpy_safely)(buf, filename, nbuf);
1096f32ec7f0de8a651bc16a1b2e448c0106d8669889tom      return True;
1097f32ec7f0de8a651bc16a1b2e448c0106d8669889tom   }
1098eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return False;
1099eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1100eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Map a code address to its DebugInfo.  Returns NULL if not found.  Doesn't
1102eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   require debug info. */
1103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjDebugInfo* VG_(find_seginfo) ( Addr a )
1104eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
1107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
1108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_avma <= a
1109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a < di->text_avma + di->text_size) {
1110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return di;
1111eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1112eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1113eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return NULL;
1114eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1115eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1116eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename.  Returns True if successful.  */
1117eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
1118eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1120eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int      locno;
1121eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1122eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1123eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1124eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1125eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1126eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1127eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1128eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a line number.  Returns True if successful. */
1129eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_linenum)( Addr a, UInt* lineno )
1130eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1132eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int      locno;
1133eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1134eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (si == NULL)
1135eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1136eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1137eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1138eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1139eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1140eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1141eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Map a code address to a filename/line number/dir name info.
1142eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   See prototype for detailed description of behaviour.
1143eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj*/
1144eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(get_filename_linenum) ( Addr a,
1145eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* filename, Int n_filename,
1146eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Char* dirname,  Int n_dirname,
1147eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/Bool* dirname_available,
1148eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                 /*OUT*/UInt* lineno )
1149eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1151eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int      locno;
1152eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1153eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert( (dirname == NULL && dirname_available == NULL)
1154eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              ||
1155eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj              (dirname != NULL && dirname_available != NULL) );
1156eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1157eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   search_all_loctabs ( a, &si, &locno );
1158c1b1d421216369aec58867ce1c5b99cfb1703c36njn   if (si == NULL) {
1159db5c6571454c1f647a4c67593805a8e401cd14c5njn      if (dirname_available) {
1160db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname_available = False;
1161db5c6571454c1f647a4c67593805a8e401cd14c5njn         *dirname = 0;
1162db5c6571454c1f647a4c67593805a8e401cd14c5njn      }
1163eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1164c1b1d421216369aec58867ce1c5b99cfb1703c36njn   }
1165c1b1d421216369aec58867ce1c5b99cfb1703c36njn
1166eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
1167eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *lineno = si->loctab[locno].lineno;
1168eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1169eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (dirname) {
1170eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* caller wants directory info too .. */
1171eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      vg_assert(n_dirname > 0);
1172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->loctab[locno].dirname) {
1173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. and we have some */
1174eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = True;
1175eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
1176eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      n_dirname);
1177eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1178eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         /* .. but we don't have any */
1179eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname_available = False;
1180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         *dirname = 0;
1181eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1182eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1183eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1185eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1186eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
11884ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj/* Map a function name to its entry point and toc pointer.  Is done by
11894ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   sequential search of all symbol tables, so is very slow.  To
11904ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   mitigate the worst performance effects, you may specify a soname
11914ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   pattern, and only objects matching that pattern are searched.
11924ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Therefore specify "*" to search all the objects.  On TOC-afflicted
11934ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   platforms, a symbol is deemed to be found only if it has a nonzero
11944ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   TOC pointer.  */
1195b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name,
1196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr* pEnt, Addr* pToc)
11974ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj{
11984ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     require_pToc = False;
11994ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Int      i;
1200b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
12014ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool     debug = False;
12024ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  if defined(VG_PLAT_USES_PPCTOC)
12034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   require_pToc = True;
12044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj#  endif
1205b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si; si = si->next) {
12064ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (debug)
12074ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname);
12084ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      if (!VG_(string_match)(sopatt, si->soname)) {
12094ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (debug)
12104ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            VG_(printf)(" ... skip\n");
12114ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         continue;
12124ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
12134ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      for (i = 0; i < si->symtab_used; i++) {
12144ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         if (0==VG_(strcmp)(name, si->symtab[i].name)
12154ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj             && (require_pToc ? si->symtab[i].tocptr : True)) {
12164ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pEnt = si->symtab[i].addr;
12174ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            *pToc = si->symtab[i].tocptr;
12184ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj            return True;
12194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj         }
12204ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj      }
12214ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   }
12224ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   return False;
12234ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj}
12244ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
12254ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj
1226e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* VG_(describe_IP): print into buf info on code address, function
1227e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   name and filename. */
1228e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1229e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Copy str into buf starting at n, but not going past buf[n_buf-1]
1230e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   and always ensuring that buf is zero-terminated. */
1231eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1232eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjstatic Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
1233eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1234e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1235e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1236eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; n < n_buf-1 && *str != 0; n++,str++)
1237eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      buf[n] = *str;
1238e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1239eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   buf[n] = '\0';
1240eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1241eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1242e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1243e872fec0c1c3b478a399fdba42ac65764b53f470sewardj/* Same as putStr, but escaping chars for XML output, and
1244e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   also not adding more than count chars to n_buf. */
1245e872fec0c1c3b478a399fdba42ac65764b53f470sewardj
1246e872fec0c1c3b478a399fdba42ac65764b53f470sewardjstatic Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
1247eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1248eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Char alt[2];
1249e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n_buf > 0);
1250e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0 && count < n_buf);
1251e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1252eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   for (; *str != 0; str++) {
1253e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      vg_assert(count >= 0);
1254e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      if (count <= 0)
1255e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         goto done;
1256eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      switch (*str) {
1257e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '&':
1258e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 5) goto done;
1259e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&amp;");
1260e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 5;
1261e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1262e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '<':
1263e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1264e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&lt;");
1265e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1266e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1267e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         case '>':
1268e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 4) goto done;
1269e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, "&gt;");
1270e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 4;
1271e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1272e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         default:
1273e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            if (count < 1) goto done;
1274e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[0] = *str;
1275e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            alt[1] = 0;
1276e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            n = putStr( n, n_buf, buf, alt );
1277e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            count -= 1;
1278e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            break;
1279eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1280eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1281e872fec0c1c3b478a399fdba42ac65764b53f470sewardj  done:
1282e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(count >= 0); /* should not go -ve in loop */
1283e872fec0c1c3b478a399fdba42ac65764b53f470sewardj   vg_assert(n >= 0 && n < n_buf);
1284eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return n;
1285eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1286eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1287eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjChar* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
1288eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1289eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define APPEND(_str) \
1290e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStr(n, n_buf, buf, _str)
1291e872fec0c1c3b478a399fdba42ac65764b53f470sewardj#  define APPEND_ESC(_count,_str) \
1292e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      n = putStrEsc(n, n_buf, (_count), buf, (_str))
1293eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define BUF_LEN    4096
1294eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1295eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UInt  lineno;
1296eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   UChar ibuf[50];
1297eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int   n = 0;
1298eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_fn[BUF_LEN];
1299eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_obj[BUF_LEN];
1300eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_srcloc[BUF_LEN];
1301eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UChar buf_dirname[BUF_LEN];
1302eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_dirinfo = False;
13034ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   Bool  know_fnname  = VG_(clo_sym_offsets)
13044ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN)
13054ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                        : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
1306eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
1307eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Bool  know_srcloc  = VG_(get_filename_linenum)(
1308eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           eip,
1309eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_srcloc,  BUF_LEN,
1310eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           buf_dirname, BUF_LEN, &know_dirinfo,
1311eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                           &lineno
1312eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        );
1313eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (VG_(clo_xml)) {
1314eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1315eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      Bool   human_readable = True;
1316eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline  = human_readable ? "\n      " : "";
1317eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      HChar* maybe_newline2 = human_readable ? "\n    "   : "";
1318eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1319e872fec0c1c3b478a399fdba42ac65764b53f470sewardj      /* Print in XML format, dumping in as much info as we know.
1320e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         Ensure all tags are balanced even if the individual strings
1321e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         are too long.  Allocate 1/10 of BUF_LEN to the object name,
1322e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         6/10s to the function name, 1/10 to the directory name and
1323e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         1/10 to the file name, leaving 1/10 for all the fixed-length
1324e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         stuff. */
1325eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("<frame>");
1326a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"<ip>0x%llX</ip>", (ULong)eip);
1327eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline);
1328eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1329eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_objname) {
1330eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1331eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<obj>");
1332e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_obj);
1333eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</obj>");
1334eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1335eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1336eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1337eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<fn>");
1338e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(6*BUF_LEN/10, buf_fn);
1339eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</fn>");
1340eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1341eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1342eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (know_dirinfo) {
1343eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(maybe_newline);
1344eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("<dir>");
1345e872fec0c1c3b478a399fdba42ac65764b53f470sewardj            APPEND_ESC(1*BUF_LEN/10, buf_dirname);
1346eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND("</dir>");
1347eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1348eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1349eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<file>");
1350e872fec0c1c3b478a399fdba42ac65764b53f470sewardj         APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
1351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</file>");
1352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(maybe_newline);
1353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("<line>");
1354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("</line>");
1357eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1358eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(maybe_newline2);
1359eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND("</frame>");
1360eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1361eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   } else {
1362eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1363eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Print for humans to read */
1364a44b15f527bbebfe824a2e68e4bd6ab1e153b486sewardj      VG_(sprintf)(ibuf,"0x%llX: ", (ULong)eip);
1365eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      APPEND(ibuf);
1366eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_fnname) {
1367eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_fn);
1368eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         if (!know_srcloc && know_objname) {
1369eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(" (in ");
1370eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(buf_obj);
1371eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            APPEND(")");
1372eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }
1373eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else if (know_objname && !know_srcloc) {
1374eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("(within ");
1375eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_obj);
1376eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
1377eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } else {
1378eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND("???");
1379eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1380eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (know_srcloc) {
1381eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(" (");
1382eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(buf_srcloc);
1383eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(":");
1384eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         VG_(sprintf)(ibuf,"%d",lineno);
1385eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(ibuf);
1386eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         APPEND(")");
1387eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1388eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1389eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1390eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return buf;
1391eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1392eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND
1393eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef APPEND_ESC
1394eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef BUF_LEN
1395eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1396eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
139772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1398b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1399b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1400b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: FOR UNWINDING THE STACK USING               ---*/
1401b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            DWARF3 .eh_frame INFO                       ---*/
1402b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1403b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
140472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
140572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Gather up all the constant pieces of info needed to evaluate
140672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   a CfiExpr into one convenient struct. */
140772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjtypedef
140872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   struct {
140972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr ipHere;
141072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr spHere;
141172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr fpHere;
141272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr min_accessible;
141372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      Addr max_accessible;
141472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
141572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext;
141672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
141772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* Evaluate the CfiExpr rooted at ix in exprs given the context eec.
141872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   *ok is set to False on failure, but not to True on success.  The
141972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   caller must set it to True before calling. */
142072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjstatic
142172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardjUWord evalCfiExpr ( XArray* exprs, Int ix,
142272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                    CfiExprEvalContext* eec, Bool* ok )
142372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj{
142472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   UWord wL, wR;
142519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj   Addr  a;
142672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExpr* e = VG_(indexXA)( exprs, ix );
142772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (e->tag) {
142872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Binop:
142972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wL = evalCfiExpr( exprs, e->Cex.Binop.ixL, eec, ok );
143072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
143172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         wR = evalCfiExpr( exprs, e->Cex.Binop.ixR, eec, ok );
143272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         if (!(*ok)) return 0;
143372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.Binop.op) {
143472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Add: return wL + wR;
143572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Cop_Sub: return wL - wR;
143619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            case Cop_And: return wL & wR;
14377888e2204fff6e7429236b4227ed16594e7743b9sewardj            case Cop_Mul: return wL * wR;
143872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
143972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
144072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
144172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_CfiReg:
144272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         switch (e->Cex.CfiReg.reg) {
144372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_IP: return (Addr)eec->ipHere;
144472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_SP: return (Addr)eec->spHere;
144572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case Creg_FP: return (Addr)eec->fpHere;
144672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default: goto unhandled;
144772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         }
144872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         /*NOTREACHED*/
144972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case Cex_Const:
145072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         return e->Cex.Const.con;
145119dc88f90d0e19a1463797dd99f6792a42f961d3sewardj      case Cex_Deref:
145219dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         a = evalCfiExpr( exprs, e->Cex.Deref.ixAddr, eec, ok );
145319dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (!(*ok)) return 0;
145419dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         if (a < eec->min_accessible
145519dc88f90d0e19a1463797dd99f6792a42f961d3sewardj             || (a + sizeof(UWord) - 1) > eec->max_accessible) {
145619dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            *ok = False;
145719dc88f90d0e19a1463797dd99f6792a42f961d3sewardj            return 0;
145819dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         }
145919dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         /* let's hope it doesn't trap! */
146019dc88f90d0e19a1463797dd99f6792a42f961d3sewardj         return * ((UWord*)a);
146172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
146272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         goto unhandled;
146372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
146472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
146572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj  unhandled:
146672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n\nevalCfiExpr: unhandled\n");
146772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   ML_(ppCfiExpr)( exprs, ix );
146872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   VG_(printf)("\n");
146972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   vg_assert(0);
147072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /*NOTREACHED*/
147172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   return 0;
147272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj}
147372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
147472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
147572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj/* The main function for DWARF2/3 CFI-based stack unwinding.
147672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   Given an IP/SP/FP triple, produce the IP/SP/FP values for the
147772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   previous frame, if possible. */
1478eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* Returns True if OK.  If not OK, *{ip,sp,fp}P are not changed. */
1479eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/* NOTE: this function may rearrange the order of entries in the
1480b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo list. */
1481eadcd86d1b0f59efed44c162ef4378ccfb528290sewardjBool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
1482eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        /*MOD*/Addr* spP,
1483eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        /*MOD*/Addr* fpP,
1484eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Addr min_accessible,
1485eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                        Addr max_accessible )
1486eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
148772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   Bool     ok;
1488eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Int      i;
1489b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* si;
1490eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   DiCfSI*  cfsi = NULL;
1491eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   Addr     cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
1492eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
149372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   CfiExprEvalContext eec;
149472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
1495eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UInt n_search = 0;
1496eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   static UInt n_steps = 0;
1497eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   n_search++;
1498eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1499eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0) VG_(printf)("search for %p\n", *ipP);
1500eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1501b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (si = debugInfo_list; si != NULL; si = si->next) {
1502eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      n_steps++;
1503eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1504b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Use the per-DebugInfo summary address ranges to skip
1505b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         inapplicable DebugInfos quickly. */
1506eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (si->cfsi_used == 0)
1507eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1508b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (*ipP < si->cfsi_minavma || *ipP > si->cfsi_maxavma)
1509eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         continue;
1510eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1511eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      i = ML_(search_one_cfitab)( si, *ipP );
1512eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      if (i != -1) {
1513eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         vg_assert(i >= 0 && i < si->cfsi_used);
1514eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         cfsi = &si->cfsi[i];
1515eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         break;
1516eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      }
1517eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1518eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1519eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (cfsi == NULL)
1520eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      return False;
1521eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1522b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x7FFFF) == 0))
1523b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VG_(use_CF_info): %u searches, "
1524b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
1525b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
1526eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1527b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every 64 (chosen
152872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      hackily after profiling) successful searches, move the found
1529b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
1530eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      future searches cheaper.  For starting konqueror on amd64, this
1531eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      in fact reduces the total amount of searching done by the above
1532b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      find-the-right-DebugInfo loop by more than a factor of 20. */
1533b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0x3F) == 0) {
1534eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      /* Move si one step closer to the start of the list. */
1535b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( si );
1536eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1537eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   /* End of performance-enhancing hack. */
1538eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1539eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   if (0) {
1540eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      VG_(printf)("found cfisi: ");
154172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      ML_(ppDiCfSI)(si->cfsi_exprs, cfsi);
1542eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   }
1543eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1544eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipPrev = spPrev = fpPrev = 0;
1545eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1546eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   ipHere = *ipP;
1547eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   spHere = *spP;
1548eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   fpHere = *fpP;
1549eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
155072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* First compute the CFA. */
155172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   cfa = 0;
155272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   switch (cfsi->cfa_how) {
155372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_SPREL:
155472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + spHere;
155572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
155672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_FPREL:
155772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         cfa = cfsi->cfa_off + fpHere;
155872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
155972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      case CFIC_EXPR:
15607888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (0) {
15617888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("CFIC_EXPR: ");
15627888e2204fff6e7429236b4227ed16594e7743b9sewardj            ML_(ppCfiExpr)(si->cfsi_exprs, cfsi->cfa_off);
15637888e2204fff6e7429236b4227ed16594e7743b9sewardj            VG_(printf)("\n");
15647888e2204fff6e7429236b4227ed16594e7743b9sewardj         }
15657888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.ipHere = ipHere;
15667888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.spHere = spHere;
15677888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.fpHere = fpHere;
15687888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.min_accessible = min_accessible;
15697888e2204fff6e7429236b4227ed16594e7743b9sewardj         eec.max_accessible = max_accessible;
15707888e2204fff6e7429236b4227ed16594e7743b9sewardj         ok = True;
15717888e2204fff6e7429236b4227ed16594e7743b9sewardj         cfa = evalCfiExpr(si->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
15727888e2204fff6e7429236b4227ed16594e7743b9sewardj         if (!ok) return False;
157372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         break;
157472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      default:
157572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj         vg_assert(0);
157672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   }
157772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj
157872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj   /* Now we know the CFA, use it to roll back the registers we're
157972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj      interested in. */
1580eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1581eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  define COMPUTE(_prev, _here, _how, _off)             \
1582eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      do {                                              \
1583eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         switch (_how) {                                \
1584eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_UNKNOWN:                          \
1585eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               return False;                            \
1586eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_SAME:                             \
1587eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = _here; break;                    \
1588eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_MEMCFAREL: {                      \
1589eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               Addr a = cfa + (Word)_off;               \
1590eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               if (a < min_accessible                   \
1591eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                   || a+sizeof(Addr) > max_accessible)  \
1592eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                  return False;                         \
1593eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = *(Addr*)a;                       \
1594eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
1595eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            }                                           \
1596eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj            case CFIR_CFAREL:                           \
1597eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               _prev = cfa + (Word)_off;                \
1598eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj               break;                                   \
159972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            case CFIR_EXPR:                             \
160072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (0)                                   \
160172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj                  ML_(ppCfiExpr)(si->cfsi_exprs,_off);  \
160272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.ipHere = ipHere;                     \
160372427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.spHere = spHere;                     \
160472427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.fpHere = fpHere;                     \
160572427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.min_accessible = min_accessible;     \
160672427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               eec.max_accessible = max_accessible;     \
160772427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               ok = True;                               \
160872427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               _prev = evalCfiExpr(si->cfsi_exprs, _off, &eec, &ok ); \
160972427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               if (!ok) return False;                   \
161072427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               break;                                   \
161172427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj            default:                                    \
161272427fa91a5e05e3323b5a8a407bd8d7b04c75ccsewardj               vg_assert(0);                            \
1613eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj         }                                              \
1614eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj      } while (0)
1615eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1616eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(ipPrev, ipHere, cfsi->ra_how, cfsi->ra_off);
1617eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(spPrev, spHere, cfsi->sp_how, cfsi->sp_off);
1618eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   COMPUTE(fpPrev, fpHere, cfsi->fp_how, cfsi->fp_off);
1619eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1620eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj#  undef COMPUTE
1621eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1622eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *ipP = ipPrev;
1623eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *spP = spPrev;
1624eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   *fpP = fpPrev;
1625eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return True;
1626eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1627eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1628eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1629b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1630b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1631b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- TOP LEVEL: GENERATE DESCRIPTION OF DATA ADDRESSES      ---*/
1632b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---            FROM DWARF3 DEBUG INFO                      ---*/
1633b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*---                                                        ---*/
1634b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--------------------------------------------------------------*/
1635b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1636b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Evaluate the location expression/list for var, to see whether or
1637b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   not data_addr falls within the variable.  If so also return the
1638b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   offset of data_addr from the start of the variable.  Note that
1639b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs, which supplies ip,sp,fp values, will be NULL for global
1640b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   variables, and non-NULL for local variables. */
1641b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic Bool data_address_is_in_var ( /*OUT*/UWord* offset,
1642b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     DiVariable*   var,
1643b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     RegSummary*   regs,
1644b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_addr,
1645b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     Addr          data_bias )
1646b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
1647b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   MaybeUWord muw;
1648b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   SizeT      var_szB;
1649b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   GXResult   res;
1650b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       show = False;
1651b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->name);
1652b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->type);
1653b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var->gexpr);
1654b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1655b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Figure out how big the variable is. */
1656b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   muw = ML_(sizeOfType)(var->type);
1657b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* if this var has a type whose size is unknown, it should never
1658b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      have been added.  ML_(addVar) should have rejected it. */
1659b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(muw.b == True);
1660b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1661b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   var_szB = muw.w;
1662b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1663b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
1664b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: data_address_%p_is_in_var: %s :: ",
1665b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  data_addr, var->name );
1666b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_Type_C_ishly)( var->type );
1667b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1668b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1669b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1670b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ignore zero-sized vars; they can never match anything. */
1671b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (var_szB == 0) {
1672b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (show)
1673b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
1674b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1675b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1676b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1677b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs, data_bias );
1678b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1679b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (show) {
1680b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("VVVV: -> ");
1681b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      ML_(pp_GXResult)( res );
1682b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("\n");
1683b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1684eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1685b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (res.kind == GXR_Value
1686b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && res.word <= data_addr
1687b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj       && data_addr < res.word + var_szB) {
1688b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      *offset = data_addr - res.word;
1689b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return True;
1690b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   } else {
1691b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1692b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1693b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
1694b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1695b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1696b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Format the acquired information into dname1[0 .. n_dname-1] and
1697b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname2[0 .. n_dname-1] in an understandable way.  Not so easy.
1698b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   If frameNo is -1, this is assumed to be a global variable; else
1699b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   a local variable. */
1700b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic void format_message ( /*OUT*/Char* dname1,
1701b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             /*OUT*/Char* dname2,
1702b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      n_dname,
1703b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Addr     data_addr,
1704b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             DiVariable* var,
1705b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             OffT     var_offset,
1706b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             OffT     residual_offset,
1707b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             XArray* /*UChar*/ described,
1708b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             Int      frameNo,
1709b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                             ThreadId tid )
1710eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1711b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool have_descr, have_srcloc;
1712b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* vo_plural = var_offset == 1 ? "" : "s";
1713b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UChar* ro_plural = residual_offset == 1 ? "" : "s";
1714b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1715b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(frameNo >= -1);
1716b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(dname1 && dname2 && n_dname > 1);
1717b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(described);
1718b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(var && var->name);
1719b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_descr = VG_(sizeXA)(described) > 0
1720b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && *(UChar*)VG_(indexXA)(described,0) != '\0';
1721b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   have_srcloc = var->fileName && var->lineNo > 0;
1722b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1723b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[0] = dname2[0] = '\0';
1724b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1725b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ local cases ------ */
1726b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1727b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && (!have_descr) ) {
1728b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
1729b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a",
1730b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
1731b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1732b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1733b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1734b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\",",
1735b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
1736b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1737b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1738b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
1739b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1740b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1741b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && (!have_descr) ) {
1742b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
1743b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside local var "a"
1744b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17, in frame #1 of thread 1
1745b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1746b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1747b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1748b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside local var \"%s\"",
1749b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
1750b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1751b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1752b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
1753b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
1754b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1755b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1756b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && (!have_srcloc) && have_descr ) {
1757b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
1758b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2
1759b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         in frame #1 of thread 1
1760b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1761b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1762b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1763b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s",
1764b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
1765b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(indexXA)(described,0) );
1766b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1767b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1768b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "in frame #%d of thread %d", frameNo, (Int)tid);
1769b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1770b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1771b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= 0 && have_srcloc && have_descr ) {
1772b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
1773b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        declared at dsyms7.c:17, in frame #1 of thread 1 */
1774b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1775b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1776b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
1777b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
1778b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(indexXA)(described,0) );
1779b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1780b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1781b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d, in frame #%d of thread %d",
1782b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo, frameNo, (Int)tid);
1783b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1784b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1785b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* ------ global cases ------ */
1786b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && (!have_descr) ) {
1787b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc, no description:
1788b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
1789b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1790b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1791b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1792b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
1793b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
1794b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1795b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1796b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && (!have_descr) ) {
1797b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no description:
1798b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 543 bytes inside global var "a"
1799b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         declared at dsyms7.c:17
1800b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1801b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1802b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1803b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside global var \"%s\"",
1804b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, var_offset, vo_plural, var->name );
1805b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1806b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1807b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "declared at %s:%d",
1808b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
1809b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1810b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1811b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && (!have_srcloc) && have_descr ) {
1812b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* no srcloc:
1813b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
1814b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         a global variable
1815b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      */
1816b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1817b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1818b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
1819b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
1820b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(indexXA)(described,0) );
1821b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1822b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1823b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable");
1824b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1825b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1826b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ( frameNo >= -1 && have_srcloc && have_descr ) {
1827b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj     /* Location 0x7fefff6cf is 2 bytes inside a[3].xyzzy[21].c2,
1828b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj        a global variable declared at dsyms7.c:17 */
1829b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1830b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1, n_dname,
1831b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "Location 0x%lx is %lu byte%s inside %s%s,",
1832b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         data_addr, residual_offset, ro_plural, var->name,
1833b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(indexXA)(described,0) );
1834b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(snprintf)(
1835b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname2, n_dname,
1836b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         "a global variable declared at %s:%d",
1837b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         var->fileName, var->lineNo);
1838b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1839b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   else
1840b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(0);
1841b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1842b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
1843eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1844eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1845b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1846b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Determine if data_addr is a local variable in the frame
1847b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characterised by (ip,sp,fp), and if so write its description into
1848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname{1,2}[0..n_dname-1], and return True.  If not, return
1849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   False. */
1850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjstatic
1851b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool consider_vars_in_frame ( /*OUT*/Char* dname1,
1852b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /*OUT*/Char* dname2,
1853b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Int n_dname,
1854b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr data_addr,
1855b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              Addr ip, Addr sp, Addr fp,
1856b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              /* shown to user: */
1857b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                              ThreadId tid, Int frameNo )
1858eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1859b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       i;
1860b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1861b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   RegSummary regs;
1862b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool debug = False;
1863b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1864b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_search = 0;
1865b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   static UInt n_steps = 0;
1866b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_search++;
1867b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (debug)
1868b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("QQQQ: cvif: ip,sp,fp %p,%p,%p\n", ip,sp,fp);
1869b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* first, find the DebugInfo that pertains to 'ip'. */
1870b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di; di = di->next) {
1871b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      n_steps++;
1872b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
1873b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
1874b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
1875b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok.  So does this text mapping bracket the ip? */
1876b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_avma <= ip && ip < di->text_avma + di->text_size)
1877b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
1878b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1879b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1880b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Didn't find it.  Strange -- means ip is a code address outside
1881b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of any mapped text segment.  Unlikely but not impossible -- app
1882b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      could be generating code to run. */
1883b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di)
1884b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1885b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1886b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0 && ((n_search & 0x1) == 0))
1887b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      VG_(printf)("consider_vars_in_frame: %u searches, "
1888b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  "%u DebugInfos looked at\n",
1889b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  n_search, n_steps);
1890b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Start of performance-enhancing hack: once every ??? (chosen
1891b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      hackily after profiling) successful searches, move the found
1892b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DebugInfo one step closer to the start of the list.  This makes
1893b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      future searches cheaper. */
1894b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if ((n_search & 0xFFFF) == 0) {
1895b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Move si one step closer to the start of the list. */
1896b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      move_DebugInfo_one_step_forward( di );
1897b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1898b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* End of performance-enhancing hack. */
1899b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1900b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* any var info at all? */
1901b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!di->varinfo)
1902b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
1903b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1904b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Work through the scopes from most deeply nested outwards,
1905b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      looking for code address ranges that bracket 'ip'.  The
1906b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables on each such address range found are in scope right
1907b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      now.  Don't descend to level zero as that is the global
1908b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
1909b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.ip = ip;
1910b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.sp = sp;
1911b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   regs.fp = fp;
1912b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1913b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* "for each scope, working outwards ..." */
1914b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) {
1915b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
1916b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         j;
1917b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* arange;
1918b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        this_scope
1919b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = *(OSet**)VG_(indexXA)( di->varinfo, i );
1920b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (debug)
1921b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)("QQQQ:   considering scope %ld\n", (Word)i);
1922b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!this_scope)
1923b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
1924b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Find the set of variables in this scope that
1925b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         bracket the program counter. */
1926b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      arange = VG_(OSetGen_LookupWithCmp)(
1927b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  this_scope, &ip,
1928b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                  ML_(cmp_for_DiAddrRange_range)
1929b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj               );
1930b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!arange)
1931b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
1932b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* stay sane */
1933b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= arange->aMax);
1934b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must bracket the ip we asked for, else
1935b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         ML_(cmp_for_DiAddrRange_range) is somehow broken. */
1936b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(arange->aMin <= ip && ip <= arange->aMax);
1937b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* It must have an attached XArray of DiVariables. */
1938b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = arange->vars;
1939b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(vars);
1940b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But it mustn't cover the entire address range.  We only
1941b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         expect that to happen for the global scope (level 0), which
1942b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         we're not looking at here.  Except, it may cover the entire
1943b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         address range, but in that case the vars array must be
1944b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         empty. */
1945b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(! (arange->aMin == (Addr)0
1946b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && arange->aMax == ~(Addr)0
1947b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                   && VG_(sizeXA)(vars) > 0) );
1948b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (j = 0; j < VG_(sizeXA)( vars ); j++) {
1949b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j );
1950b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         SizeT       offset;
1951b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (debug)
1952b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(printf)("QQQQ:    var:name=%s %p-%p %p\n",
1953b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                        var->name,arange->aMin,arange->aMax,ip);
1954b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (data_address_is_in_var( &offset, var, &regs, data_addr,
1955b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     di->data_bias )) {
1956b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            OffT residual_offset = 0;
1957b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
1958b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                                    var->type, offset );
1959b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
1960b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
1961b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, frameNo, tid );
1962b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
1963b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
1964b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
1965b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
1966b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
1967b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1968b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
1969eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
1970eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
1971b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Try to form some description of data_addr by looking at the DWARF3
1972b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   debug info we have.  This considers all global variables, and all
1973b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   frames in the stacks of all threads.  Result (or as much as will
1974b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   fit) is put into into dname{1,2}[0 .. n_dname-1] and is guaranteed
1975b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to be zero terminated. */
1976b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjBool VG_(get_data_description)( /*OUT*/Char* dname1,
1977b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                /*OUT*/Char* dname2,
1978b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Int  n_dname,
1979b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                Addr data_addr )
1980eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
1981b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  define N_FRAMES 8
1982b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr ips[N_FRAMES], sps[N_FRAMES], fps[N_FRAMES];
1983b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   UInt n_frames;
1984b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1985b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Addr       stack_min, stack_max;
1986b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   ThreadId   tid;
1987b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Bool       found;
1988b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
1989b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   Word       j;
1990b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1991b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_dname > 1);
1992b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
1993b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
1994b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (0) VG_(printf)("get_data_description: dataaddr %p\n", data_addr);
1995b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* First, see if data_addr is (or is part of) a global variable.
1996b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Loop over the DebugInfos we have.  Check data_addr against the
1997b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      outermost scope of all of them, as that should be a global
1998b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      scope. */
1999b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2000b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      OSet*        global_scope;
2001b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Int          gs_size;
2002b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Addr         zero;
2003b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      DiAddrRange* global_arange;
2004b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word         i;
2005b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      XArray*      vars;
2006b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2007b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* text segment missing? unlikely, but handle it .. */
2008b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->text_present || di->text_size == 0)
2009b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2010b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* any var info at all? */
2011b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!di->varinfo)
2012b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2013b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* perhaps this object didn't contribute any vars at all? */
2014b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (VG_(sizeXA)( di->varinfo ) == 0)
2015b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2016b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_scope = *(OSet**)VG_(indexXA)( di->varinfo, 0 );
2017b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_scope);
2018b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      gs_size = VG_(OSetGen_Size)( global_scope );
2019b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global scope might be completely empty if this
2020b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         compilation unit declared locals but nothing global. */
2021b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (gs_size == 0)
2022b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          continue;
2023b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* But if it isn't empty, then it must contain exactly one
2024b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         element, which covers the entire address range. */
2025b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(gs_size == 1);
2026b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Fish out the global scope and check it is as expected. */
2027b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      zero = 0;
2028b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      global_arange
2029b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         = VG_(OSetGen_Lookup)( global_scope, &zero );
2030b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* The global range from (Addr)0 to ~(Addr)0 must exist */
2031b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange);
2032b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(global_arange->aMin == (Addr)0
2033b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                && global_arange->aMax == ~(Addr)0);
2034b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Any vars in this range? */
2035b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (!global_arange->vars)
2036b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue;
2037b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Ok, there are some vars in the global scope of this
2038b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DebugInfo.  Wade through them and see if the data addresses
2039b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         of any of them bracket data_addr. */
2040b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vars = global_arange->vars;
2041b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      for (i = 0; i < VG_(sizeXA)( vars ); i++) {
2042b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         SizeT offset;
2043b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         DiVariable* var = (DiVariable*)VG_(indexXA)( vars, i );
2044b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(var->name);
2045b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         /* Note we use a NULL RegSummary* here.  It can't make any
2046b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            sense for a global variable to have a location expression
2047b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            which depends on a SP/FP/IP value.  So don't supply any.
2048b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            This means, if the evaluation of the location
2049b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            expression/list requires a register, we have to let it
2050b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            fail. */
2051b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (data_address_is_in_var( &offset, var,
2052b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     NULL/* RegSummary* */,
2053b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                     data_addr, di->data_bias )) {
2054b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            OffT residual_offset = 0;
2055b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            XArray* described = ML_(describe_type)( &residual_offset,
2056b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                                    var->type, offset );
2057b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            format_message( dname1, dname2, n_dname,
2058b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            data_addr, var, offset, residual_offset,
2059b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                            described, -1/*frameNo*/, tid );
2060b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            VG_(deleteXA)( described );
2061b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            dname1[n_dname-1] = dname2[n_dname-1] = 0;
2062b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            return True;
2063b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2064b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2065b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2066b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2067b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Ok, well it's not a global variable.  So now let's snoop around
2068b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      in the stacks of all the threads.  First try to figure out which
2069b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      thread's stack data_addr is in. */
2070b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2071b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- KLUDGE --- Try examining the top frame of all thread stacks.
2072b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      This finds variables which are not stack allocated but are not
2073b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      globally visible either; specifically it appears to pick up
2074b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      variables which are visible only within a compilation unit.
2075b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      These will have the address range of the compilation unit and
2076b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      tend to live at Scope level 1. */
2077b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2078b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2079b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2080b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2081b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2082b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2083b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_IP)(tid),
2084b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_SP)(tid),
2085b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  VG_(get_FP)(tid), tid, 0 )) {
2086b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2087b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2088b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2089b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2090b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* --- end KLUDGE --- */
2091b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2092b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Perhaps it's on a thread's stack? */
2093b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   found = False;
2094b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VG_(thread_stack_reset_iter)(&tid);
2095b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
2096b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min >= stack_max)
2097b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         continue; /* ignore obviously stupid cases */
2098b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (stack_min - VG_STACK_REDZONE_SZB <= data_addr
2099b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && data_addr <= stack_max) {
2100b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         found = True;
2101b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2102b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2103b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2104b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (!found) {
2105b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      dname1[n_dname-1] = dname2[n_dname-1] = 0;
2106b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return False;
2107b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2108b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2109b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We conclude data_addr is in thread tid's stack.  Unwind the
2110b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack to get a bunch of (ip,sp,fp) triples describing the
2111b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      frames, and for each frame, consider the local variables. */
2112b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
2113b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   sps, fps, 0/*first_ip_delta*/ );
2114b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* Re ip_delta in the next loop: There's a subtlety in the meaning
2115b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      of the IP values in a stack obtained from VG_(get_StackTrace).
2116b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      The innermost value really is simply the thread's program
2117b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      counter at the time the snapshot was taken.  However, all the
2118b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      other values are actually return addresses, and so point just
2119b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      after the call instructions.  Hence they notionally reflect not
2120b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      what the program counters were at the time those calls were
2121b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      made, but what they will be when those calls return.  This can
2122b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      be of significance should an address range happen to end at the
2123b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      end of a call instruction -- we may ignore the range when in
2124b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      fact it should be considered.  Hence, back up the IPs by 1 for
2125b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      all non-innermost IPs.  Note that VG_(get_StackTrace_wrk) itself
2126b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      has to use the same trick in order to use CFI data to unwind the
2127b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      stack (as documented therein in comments). */
2128b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* As a result of KLUDGE above, starting the loop at j = 0
2129b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      duplicates examination of the top frame and so isn't necessary.
2130b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Oh well. */
2131b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
2132b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (j = 0; j < n_frames; j++) {
2133b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      Word ip_delta = j == 0 ? 0 : 1;
2134b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2135b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2136b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  ips[j] - ip_delta,
2137b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
2138b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2139b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2140b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2141b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* Now, it appears that gcc sometimes appears to produce
2142b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         location lists whose ranges don't actually cover the call
2143b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         instruction, even though the address of the variable in
2144b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         question is passed as a parameter in the call.  AFAICS this
2145b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         is simply a bug in gcc - how can the variable be claimed not
2146b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         exist in memory (on the stack) for the duration of a call in
2147b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         which its address is passed?  But anyway, in the particular
2148b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         case I investigated (memcheck/tests/varinfo6.c, call to croak
2149b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         on line 2999, local var budget declared at line 3115
2150b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         appearing not to exist across the call to mainSort on line
2151b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         3143, "gcc.orig (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2)" on
2152b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         amd64), the variable's location list does claim it exists
2153b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         starting at the first byte of the first instruction after the
2154b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         call instruction.  So, call consider_vars_in_frame a second
2155b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         time, but this time don't subtract 1 from the IP.  GDB
2156b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         handles this example with no difficulty, which leads me to
2157b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         believe that either (1) I misunderstood something, or (2) GDB
2158b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         has an equivalent kludge. */
2159b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (consider_vars_in_frame( dname1, dname2, n_dname,
2160b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  data_addr,
2161b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  ips[j],
2162b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                  sps[j], fps[j], tid, j )) {
2163b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         dname1[n_dname-1] = dname2[n_dname-1] = 0;
2164b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         return True;
2165b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2166b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2167b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2168b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   /* We didn't find anything useful. */
2169b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   dname1[n_dname-1] = dname2[n_dname-1] = 0;
2170b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return False;
2171b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj#  undef N_FRAMES
2172eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2173eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2174b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2175b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2176b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- DebugInfo accessor functions                         ---*/
2177b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2178b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2179b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst DebugInfo* VG_(next_seginfo)(const DebugInfo* di)
2180eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2181b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (di == NULL)
2182b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      return debugInfo_list;
2183b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->next;
2184eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2185eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2186b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjAddr VG_(seginfo_get_text_avma)(const DebugInfo* di)
2187eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2188b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_avma : 0;
2189eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2190eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2191b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjSizeT VG_(seginfo_get_text_size)(const DebugInfo* di)
2192eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2193b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_size : 0;
2194eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2195eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2196b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_soname)(const DebugInfo* di)
2197eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2198b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->soname;
2199b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2200eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2201b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst UChar* VG_(seginfo_filename)(const DebugInfo* di)
2202b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2203b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->filename;
2204eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2205eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2206b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjULong VG_(seginfo_get_text_bias)(const DebugInfo* di)
2207bbec7728efefaa650970dd1f0282b77040287133sewardj{
2208b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return di->text_present ? di->text_bias : 0;
2209bbec7728efefaa650970dd1f0282b77040287133sewardj}
2210bbec7728efefaa650970dd1f0282b77040287133sewardj
2211b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjInt VG_(seginfo_syms_howmany) ( const DebugInfo *si )
2212eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2213eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   return si->symtab_used;
2214eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2215eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2216b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjvoid VG_(seginfo_syms_getidx) ( const DebugInfo *si,
2217eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                                      Int idx,
2218b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Addr*   avma,
22194ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj                               /*OUT*/Addr*   tocptr,
2220eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj                               /*OUT*/UInt*   size,
2221b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/HChar** name,
2222b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                               /*OUT*/Bool*   isText )
2223eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj{
2224eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj   vg_assert(idx >= 0 && idx < si->symtab_used);
2225b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (avma)   *avma   = si->symtab[idx].addr;
22264ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (tocptr) *tocptr = si->symtab[idx].tocptr;
22274ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (size)   *size   = si->symtab[idx].size;
22284ee4f98c6dd3dd9517954efc628753bf46811d2dsewardj   if (name)   *name   = (HChar*)si->symtab[idx].name;
2229b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (isText) *isText = si->symtab[idx].isText;
2230b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2231b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2232b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2233b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2234b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*--- SectKind query functions                             ---*/
2235b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/*------------------------------------------------------------*/
2236b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2237b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Convert a VgSectKind to a string, which must be copied if you want
2238b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   to change it. */
2239b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjconst HChar* VG_(pp_SectKind)( VgSectKind kind )
2240b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2241b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   switch (kind) {
2242b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectUnknown: return "Unknown";
2243b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectText:    return "Text";
2244b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectData:    return "Data";
2245b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectBSS:     return "BSS";
2246b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectGOT:     return "GOT";
2247b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectPLT:     return "PLT";
2248b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      case Vg_SectOPD:     return "OPD";
2249b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      default:             vg_assert(0);
2250b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2251b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj}
2252b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2253b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj/* Given an address 'a', make a guess of which section of which object
2254b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   it comes from.  If name is non-NULL, then the last n_name-1
2255b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   characters of the object's name is put in name[0 .. n_name-2], and
2256b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   name[n_name-1] is set to zero (guaranteed zero terminated). */
2257b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2258b8b79addf04dd5d0b558916e26df0b1927cbd758sewardjVgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
2259b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj                                   Addr a)
2260b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj{
2261b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   DebugInfo* di;
2262b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   VgSectKind res = Vg_SectUnknown;
2263b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2264b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   for (di = debugInfo_list; di != NULL; di = di->next) {
2265b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2266b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (0)
2267b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(printf)(
2268b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            "addr=%p di=%p %s got=%p,%ld plt=%p,%ld data=%p,%ld bss=%p,%ld\n",
2269b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            a, di, di->filename,
2270b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->got_avma,  di->got_size,
2271b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->plt_avma,  di->plt_size,
2272b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->data_avma, di->data_size,
2273b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            di->bss_avma,  di->bss_size);
2274b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2275b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->text_present
2276b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->text_size > 0
2277b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->text_avma && a < di->text_avma + di->text_size) {
2278b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectText;
2279b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2280b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2281b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->data_present
2282b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->data_size > 0
2283b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->data_avma && a < di->data_avma + di->data_size) {
2284b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
2285b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2286b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2287b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->sdata_present
2288b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->sdata_size > 0
2289b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->sdata_avma && a < di->sdata_avma + di->sdata_size) {
2290b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectData;
2291b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2292b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2293b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->bss_present
2294b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->bss_size > 0
2295b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->bss_avma && a < di->bss_avma + di->bss_size) {
2296b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectBSS;
2297b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2298b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2299b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->plt_present
2300b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->plt_size > 0
2301b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->plt_avma && a < di->plt_avma + di->plt_size) {
2302b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectPLT;
2303b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2304b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2305b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->got_present
2306b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->got_size > 0
2307b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->got_avma && a < di->got_avma + di->got_size) {
2308b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectGOT;
2309b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2310b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2311b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di->opd_present
2312b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && di->opd_size > 0
2313b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj          && a >= di->opd_avma && a < di->opd_avma + di->opd_size) {
2314b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         res = Vg_SectOPD;
2315b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         break;
2316b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2317b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      /* we could also check for .eh_frame, if anyone really cares */
2318b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2319b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2320b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   vg_assert( (di == NULL && res == Vg_SectUnknown)
2321b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj              || (di != NULL && res != Vg_SectUnknown) );
2322b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2323b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   if (name) {
2324b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2325b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      vg_assert(n_name >= 8);
2326b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2327b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      if (di && di->filename) {
2328b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int i, j;
2329b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int fnlen = VG_(strlen)(di->filename);
2330b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         Int start_at = 1 + fnlen - n_name;
2331b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         if (start_at < 0) start_at = 0;
2332b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         vg_assert(start_at < fnlen);
2333b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         i = start_at; j = 0;
2334b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         while (True) {
2335b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(j >= 0 && j+1 < n_name);
2336b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            vg_assert(i >= 0 && i <= fnlen);
2337b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j] = di->filename[i];
2338b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            name[j+1] = 0;
2339b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            if (di->filename[i] == 0) break;
2340b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj            i++; j++;
2341b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         }
2342b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      } else {
2343b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj         VG_(snprintf)(name, n_name, "%s", "???");
2344b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      }
2345b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2346b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj      name[n_name-1] = 0;
2347b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   }
2348b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2349b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj   return res;
2350b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj
2351eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj}
2352eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2353eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj
2354eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
2355eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--- end                                                          ---*/
2356eadcd86d1b0f59efed44c162ef4378ccfb528290sewardj/*--------------------------------------------------------------------*/
2357