• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Obtaining information about an address.                      ---*/
4 /*---                                                 m_addrinfo.c ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright (C) 2008-2013 OpenWorks Ltd
12       info@open-works.co.uk
13 
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of the
17    License, or (at your option) any later version.
18 
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27    02111-1307, USA.
28 
29    The GNU General Public License is contained in the file COPYING.
30 */
31 
32 #include "pub_core_basics.h"
33 #include "pub_core_libcassert.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcprint.h"
36 #include "pub_core_xarray.h"
37 #include "pub_core_debuginfo.h"
38 #include "pub_core_execontext.h"
39 #include "pub_core_addrinfo.h"
40 #include "pub_core_mallocfree.h"
41 #include "pub_core_machine.h"
42 #include "pub_core_options.h"
43 
VG_(describe_addr)44 void VG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai )
45 {
46    ThreadId   tid;
47    Addr       stack_min, stack_max;
48    VgSectKind sect;
49 
50    /* -- Perhaps the variable type/location data describes it? -- */
51    ai->Addr.Variable.descr1
52       = VG_(newXA)( VG_(malloc), "mc.da.descr1",
53                     VG_(free), sizeof(HChar) );
54    ai->Addr.Variable.descr2
55       = VG_(newXA)( VG_(malloc), "mc.da.descr2",
56                     VG_(free), sizeof(HChar) );
57 
58    (void) VG_(get_data_description)( ai->Addr.Variable.descr1,
59                                      ai->Addr.Variable.descr2, a );
60    /* If there's nothing in descr1/2, free them.  Why is it safe to to
61       VG_(indexXA) at zero here?  Because VG_(get_data_description)
62       guarantees to zero terminate descr1/2 regardless of the outcome
63       of the call.  So there's always at least one element in each XA
64       after the call.
65    */
66    if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr1, 0 ))) {
67       VG_(deleteXA)( ai->Addr.Variable.descr1 );
68       ai->Addr.Variable.descr1 = NULL;
69    }
70    if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr2, 0 ))) {
71       VG_(deleteXA)( ai->Addr.Variable.descr2 );
72       ai->Addr.Variable.descr2 = NULL;
73    }
74    /* Assume (assert) that VG_(get_data_description) fills in descr1
75       before it fills in descr2 */
76    if (ai->Addr.Variable.descr1 == NULL)
77       vg_assert(ai->Addr.Variable.descr2 == NULL);
78    /* So did we get lucky? */
79    if (ai->Addr.Variable.descr1 != NULL) {
80       ai->tag = Addr_Variable;
81       return;
82    }
83    /* -- Have a look at the low level data symbols - perhaps it's in
84       there. -- */
85    VG_(memset)( &ai->Addr.DataSym.name,
86                 0, sizeof(ai->Addr.DataSym.name));
87    if (VG_(get_datasym_and_offset)(
88              a, &ai->Addr.DataSym.name[0],
89              sizeof(ai->Addr.DataSym.name)-1,
90              &ai->Addr.DataSym.offset )) {
91       ai->tag = Addr_DataSym;
92       vg_assert( ai->Addr.DataSym.name
93                     [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
94       return;
95    }
96    /* -- Perhaps it's on a thread's stack? -- */
97    VG_(thread_stack_reset_iter)(&tid);
98    while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
99       if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
100          ai->tag            = Addr_Stack;
101          ai->Addr.Stack.tid = tid;
102          return;
103       }
104    }
105 
106    /* -- Maybe it is in one of the m_mallocfree.c arenas. --  */
107    {
108       AddrArenaInfo aai;
109       VG_(describe_arena_addr) ( a, &aai );
110       if (aai.name != NULL) {
111          ai->tag = Addr_Block;
112          if (aai.aid == VG_AR_CLIENT)
113             ai->Addr.Block.block_kind
114                = aai.free ? Block_ClientArenaFree : Block_ClientArenaMallocd;
115          else
116             ai->Addr.Block.block_kind
117                = aai.free
118                   ? Block_ValgrindArenaFree :  Block_ValgrindArenaMallocd;
119          ai->Addr.Block.block_desc = aai.name;
120          ai->Addr.Block.block_szB = aai.block_szB;
121          ai->Addr.Block.rwoffset = aai.rwoffset;
122          ai->Addr.Block.allocated_at = VG_(null_ExeContext)();
123          ai->Addr.Block.freed_at = VG_(null_ExeContext)();
124          return;
125       }
126    }
127 
128    /* -- last ditch attempt at classification -- */
129    vg_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
130    VG_(memset)( &ai->Addr.SectKind.objname,
131                 0, sizeof(ai->Addr.SectKind.objname));
132    VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
133    sect = VG_(DebugInfo_sect_kind)( &ai->Addr.SectKind.objname[0],
134                                     sizeof(ai->Addr.SectKind.objname)-1, a);
135    if (sect != Vg_SectUnknown) {
136       ai->tag = Addr_SectKind;
137       ai->Addr.SectKind.kind = sect;
138       vg_assert( ai->Addr.SectKind.objname
139                     [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
140       return;
141    }
142    /* -- Clueless ... -- */
143    ai->tag = Addr_Unknown;
144    return;
145 }
146 
VG_(clear_addrinfo)147 void VG_(clear_addrinfo) ( AddrInfo* ai)
148 {
149    switch (ai->tag) {
150       case Addr_Unknown:
151           break;
152 
153       case Addr_Stack:
154           break;
155 
156       case Addr_Block:
157          break;
158 
159       case Addr_DataSym:
160          break;
161 
162       case Addr_Variable:
163          if (ai->Addr.Variable.descr1 != NULL) {
164             VG_(deleteXA)( ai->Addr.Variable.descr1 );
165             ai->Addr.Variable.descr1 = NULL;
166          }
167          if (ai->Addr.Variable.descr2 != NULL) {
168             VG_(deleteXA)( ai->Addr.Variable.descr2 );
169             ai->Addr.Variable.descr2 = NULL;
170          }
171          break;
172 
173       case Addr_SectKind:
174          break;
175 
176       default:
177          VG_(core_panic)("VG_(clear_addrinfo)");
178    }
179 
180    ai->tag = Addr_Undescribed;
181 }
182 
is_arena_BlockKind(BlockKind bk)183 static Bool is_arena_BlockKind(BlockKind bk)
184 {
185    switch (bk) {
186       case Block_Mallocd:
187       case Block_Freed:
188       case Block_MempoolChunk:
189       case Block_UserG:                return False;
190 
191       case Block_ClientArenaMallocd:
192       case Block_ClientArenaFree:
193       case Block_ValgrindArenaMallocd:
194       case Block_ValgrindArenaFree:    return True;
195 
196       default:                         vg_assert (0);
197    }
198 }
199 
pp_addrinfo_WRK(Addr a,AddrInfo * ai,Bool mc,Bool maybe_gcc)200 static void pp_addrinfo_WRK ( Addr a, AddrInfo* ai, Bool mc, Bool maybe_gcc )
201 {
202    const HChar* xpre  = VG_(clo_xml) ? "  <auxwhat>" : " ";
203    const HChar* xpost = VG_(clo_xml) ? "</auxwhat>"  : "";
204 
205    vg_assert (!maybe_gcc || mc); // maybe_gcc can only be given in mc mode.
206 
207    switch (ai->tag) {
208       case Addr_Unknown:
209          if (maybe_gcc) {
210             VG_(emit)( "%sAddress 0x%llx is just below the stack ptr.  "
211                        "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
212                        xpre, (ULong)a, xpost );
213 	 } else {
214             VG_(emit)( "%sAddress 0x%llx "
215                        "is not stack'd, malloc'd or %s%s\n",
216                        xpre,
217                        (ULong)a,
218                        mc ? "(recently) free'd" : "on a free list",
219                        xpost );
220          }
221          break;
222 
223       case Addr_Stack:
224          VG_(emit)( "%sAddress 0x%llx is on thread %d's stack%s\n",
225                     xpre, (ULong)a, ai->Addr.Stack.tid, xpost );
226          break;
227 
228       case Addr_Block: {
229          SizeT    block_szB = ai->Addr.Block.block_szB;
230          PtrdiffT rwoffset  = ai->Addr.Block.rwoffset;
231          SizeT    delta;
232          const    HChar* relative;
233 
234          if (rwoffset < 0) {
235             delta    = (SizeT)(-rwoffset);
236             relative = "before";
237          } else if (rwoffset >= block_szB) {
238             delta    = rwoffset - block_szB;
239             relative = "after";
240          } else {
241             delta    = rwoffset;
242             relative = "inside";
243          }
244          if (is_arena_BlockKind (ai->Addr.Block.block_kind))
245             VG_(emit)(
246                "%sAddress 0x%lx is %'lu bytes %s a%s block of size %'lu"
247                " in arena \"%s\"%s\n",
248                xpre,
249                a, delta,
250                relative,
251                ai->Addr.Block.block_kind==Block_ClientArenaMallocd
252                  || ai->Addr.Block.block_kind==Block_ValgrindArenaMallocd
253                  ? "" : "n unallocated",
254                block_szB,
255                ai->Addr.Block.block_desc,  // arena name
256                xpost
257             );
258          else
259             VG_(emit)(
260                "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
261                xpre,
262                a, delta,
263                relative,
264                ai->Addr.Block.block_desc,
265                block_szB,
266                ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
267                : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
268                                                         : "client-defined",
269                xpost
270             );
271          if (ai->Addr.Block.block_kind==Block_Mallocd) {
272             VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
273             tl_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
274          }
275          else if (ai->Addr.Block.block_kind==Block_Freed) {
276             VG_(pp_ExeContext)(ai->Addr.Block.freed_at);
277             if (ai->Addr.Block.allocated_at != VG_(null_ExeContext)()) {
278                VG_(emit)(
279                   "%s block was alloc'd at%s\n",
280                   xpre,
281                   xpost
282                );
283                VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
284             }
285          }
286          else if (ai->Addr.Block.block_kind==Block_MempoolChunk
287                   || ai->Addr.Block.block_kind==Block_UserG) {
288             // client-defined
289             VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
290             tl_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
291             /* Nb: cannot have a freed_at, as a freed client-defined block
292                has a Block_Freed block_kind. */
293          } else {
294             // Client or Valgrind arena. At least currently, we never
295             // have stacktraces for these.
296             tl_assert (ai->Addr.Block.allocated_at == VG_(null_ExeContext)());
297             tl_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
298          }
299 
300          break;
301       }
302 
303       case Addr_DataSym:
304          VG_(emit)( "%sAddress 0x%llx is %llu bytes "
305                     "inside data symbol \"%pS\"%s\n",
306                     xpre,
307                     (ULong)a,
308                     (ULong)ai->Addr.DataSym.offset,
309                     ai->Addr.DataSym.name,
310                     xpost );
311          break;
312 
313       case Addr_Variable:
314          /* Note, no need for XML tags here, because descr1/2 will
315             already have <auxwhat> or <xauxwhat>s on them, in XML
316             mode. */
317          if (ai->Addr.Variable.descr1)
318             VG_(emit)( "%s%s\n",
319                        VG_(clo_xml) ? "  " : " ",
320                        (HChar*)VG_(indexXA)(ai->Addr.Variable.descr1, 0) );
321          if (ai->Addr.Variable.descr2)
322             VG_(emit)( "%s%s\n",
323                        VG_(clo_xml) ? "  " : " ",
324                        (HChar*)VG_(indexXA)(ai->Addr.Variable.descr2, 0) );
325          break;
326 
327       case Addr_SectKind:
328          VG_(emit)( "%sAddress 0x%llx is in the %pS segment of %pS%s\n",
329                     xpre,
330                     (ULong)a,
331                     VG_(pp_SectKind)(ai->Addr.SectKind.kind),
332                     ai->Addr.SectKind.objname,
333                     xpost );
334          break;
335 
336       default:
337          VG_(tool_panic)("mc_pp_AddrInfo");
338    }
339 }
340 
VG_(pp_addrinfo)341 void VG_(pp_addrinfo) ( Addr a, AddrInfo* ai )
342 {
343    pp_addrinfo_WRK (a, ai, False /*mc*/, False /*maybe_gcc*/);
344 }
345 
VG_(pp_addrinfo_mc)346 void VG_(pp_addrinfo_mc) ( Addr a, AddrInfo* ai, Bool maybe_gcc )
347 {
348    pp_addrinfo_WRK (a, ai, True /*mc*/, maybe_gcc);
349 }
350 
351 
352 /*--------------------------------------------------------------------*/
353 /*--- end                                             m_addrinfo.c ---*/
354 /*--------------------------------------------------------------------*/
355