2 /*--------------------------------------------------------------------*/
3 /*--- Obtaining information about an address. ---*/
4 /*--- m_addrinfo.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2008-2013 OpenWorks Ltd
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.
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.
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
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_core_basics.h"
33 #include "pub_core_clientstate.h"
34 #include "pub_core_libcassert.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcprint.h"
37 #include "pub_core_xarray.h"
38 #include "pub_core_debuginfo.h"
39 #include "pub_core_execontext.h"
40 #include "pub_core_addrinfo.h"
41 #include "pub_core_mallocfree.h"
42 #include "pub_core_machine.h"
43 #include "pub_core_options.h"
44 #include "pub_core_threadstate.h"
45 #include "pub_core_stacktrace.h"
46 #include "pub_core_stacks.h"
47 #include "pub_core_aspacemgr.h"
49 /* Returns the tid whose stack includes the address a.
50 If not found, returns VG_INVALID_THREADID. */
51 static ThreadId
find_tid_with_stack_containing (Addr a
)
58 VG_(stack_limits
)(a
, &start
, &end
);
61 vg_assert (start
== 0 && end
== 0);
62 return VG_INVALID_THREADID
;
65 /* Stack limits found. Search the tid to which this stack belongs. */
66 vg_assert (start
<= a
);
69 /* The stack end (highest accessible byte) is for sure inside the 'active'
70 part of the stack of the searched tid.
71 So, scan all 'active' stacks with VG_(thread_stack_reset_iter) ... */
73 Addr stack_min
, stack_max
;
75 VG_(thread_stack_reset_iter
)(&tid
);
76 while ( VG_(thread_stack_next
)(&tid
, &stack_min
, &stack_max
) ) {
77 if (stack_min
<= end
&& end
<= stack_max
)
82 /* We can arrive here if a stack was registered with wrong bounds
83 (e.g. end above the highest addressable byte)
84 and/or if the thread for the registered stack is dead, but
85 the stack was not unregistered. */
86 return VG_INVALID_THREADID
;
89 void VG_(describe_addr
) ( Addr a
, /*OUT*/AddrInfo
* ai
)
93 /* -- Perhaps the variable type/location data describes it? -- */
94 ai
->Addr
.Variable
.descr1
95 = VG_(newXA
)( VG_(malloc
), "mc.da.descr1",
96 VG_(free
), sizeof(HChar
) );
97 ai
->Addr
.Variable
.descr2
98 = VG_(newXA
)( VG_(malloc
), "mc.da.descr2",
99 VG_(free
), sizeof(HChar
) );
101 (void) VG_(get_data_description
)( ai
->Addr
.Variable
.descr1
,
102 ai
->Addr
.Variable
.descr2
, a
);
103 /* If there's nothing in descr1/2, free them. Why is it safe to
104 VG_(indexXA) at zero here? Because VG_(get_data_description)
105 guarantees to zero terminate descr1/2 regardless of the outcome
106 of the call. So there's always at least one element in each XA
109 if (0 == VG_(strlen
)( VG_(indexXA
)( ai
->Addr
.Variable
.descr1
, 0 ))) {
110 VG_(deleteXA
)( ai
->Addr
.Variable
.descr1
);
111 ai
->Addr
.Variable
.descr1
= NULL
;
113 if (0 == VG_(strlen
)( VG_(indexXA
)( ai
->Addr
.Variable
.descr2
, 0 ))) {
114 VG_(deleteXA
)( ai
->Addr
.Variable
.descr2
);
115 ai
->Addr
.Variable
.descr2
= NULL
;
117 /* Assume (assert) that VG_(get_data_description) fills in descr1
118 before it fills in descr2 */
119 if (ai
->Addr
.Variable
.descr1
== NULL
)
120 vg_assert(ai
->Addr
.Variable
.descr2
== NULL
);
121 /* So did we get lucky? */
122 if (ai
->Addr
.Variable
.descr1
!= NULL
) {
123 ai
->tag
= Addr_Variable
;
126 /* -- Have a look at the low level data symbols - perhaps it's in
129 if (VG_(get_datasym_and_offset
)(
131 &ai
->Addr
.DataSym
.offset
)) {
132 ai
->Addr
.DataSym
.name
= VG_(strdup
)("mc.da.dsname", name
);
133 ai
->tag
= Addr_DataSym
;
136 /* -- Perhaps it's on a thread's stack? -- */
139 Addr stack_min
, stack_max
;
140 VG_(thread_stack_reset_iter
)(&tid
);
141 while ( VG_(thread_stack_next
)(&tid
, &stack_min
, &stack_max
) ) {
142 if (stack_min
- VG_STACK_REDZONE_SZB
<= a
&& a
<= stack_max
) {
143 Addr ips
[VG_(clo_backtrace_size
)],
144 sps
[VG_(clo_backtrace_size
)];
148 ai
->tag
= Addr_Stack
;
149 VG_(initThreadInfo
)(&ai
->Addr
.Stack
.tinfo
);
150 ai
->Addr
.Stack
.tinfo
.tid
= tid
;
151 ai
->Addr
.Stack
.IP
= 0;
152 ai
->Addr
.Stack
.frameNo
= -1;
153 ai
->Addr
.Stack
.stackPos
= StackPos_stacked
;
154 ai
->Addr
.Stack
.spoffset
= 0; // Unused.
155 /* It is on thread tid stack. Build a stacktrace, and
156 find the frame sp[f] .. sp[f+1] where the address is.
157 Store the found frameNo and the corresponding IP in
159 When description is printed, IP will be translated to
160 the function name containing IP.
161 Before accepting to describe addr with sp[f] .. sp[f+1],
162 we verify the sp looks sane: reasonably sized frame,
164 We could check the ABI required alignment for sp (what is it?)
165 is respected, except for the innermost stack pointer ? */
166 n_frames
= VG_(get_StackTrace
)( tid
, ips
, VG_(clo_backtrace_size
),
167 sps
, NULL
, 0/*first_ip_delta*/ );
168 for (f
= 0; f
< n_frames
-1; f
++) {
169 if (sps
[f
] <= a
&& a
< sps
[f
+1]
170 && sps
[f
+1] - sps
[f
] <= 0x4000000 // 64 MB, arbitrary
171 && sps
[f
+1] <= stack_max
172 && sps
[f
] >= stack_min
- VG_STACK_REDZONE_SZB
) {
173 ai
->Addr
.Stack
.frameNo
= f
;
174 ai
->Addr
.Stack
.IP
= ips
[f
];
183 /* -- Maybe it is in one of the m_mallocfree.c arenas. -- */
186 VG_(describe_arena_addr
) ( a
, &aai
);
187 if (aai
.name
!= NULL
) {
188 ai
->tag
= Addr_Block
;
189 if (aai
.aid
== VG_AR_CLIENT
)
190 ai
->Addr
.Block
.block_kind
191 = aai
.free
? Block_ClientArenaFree
: Block_ClientArenaMallocd
;
193 ai
->Addr
.Block
.block_kind
195 ? Block_ValgrindArenaFree
: Block_ValgrindArenaMallocd
;
196 ai
->Addr
.Block
.block_desc
= aai
.name
;
197 ai
->Addr
.Block
.block_szB
= aai
.block_szB
;
198 ai
->Addr
.Block
.rwoffset
= aai
.rwoffset
;
199 ai
->Addr
.Block
.allocated_at
= VG_(null_ExeContext
)();
200 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
201 ai
->Addr
.Block
.freed_at
= VG_(null_ExeContext
)();
206 /* -- last ditch attempt at classification -- */
207 sect
= VG_(DebugInfo_sect_kind
)( &name
, a
);
208 if (sect
!= Vg_SectUnknown
) {
209 ai
->tag
= Addr_SectKind
;
210 ai
->Addr
.SectKind
.objname
= VG_(strdup
)("mc.da.dsname", name
);
211 ai
->Addr
.SectKind
.kind
= sect
;
215 /* -- and yet another last ditch attempt at classification -- */
216 /* If the address is in a stack between the stack bottom (highest byte)
217 and the current stack ptr, it will have been already described above.
218 But maybe it is in a stack, but below the stack ptr (typical
219 for a 'use after return' or in the stack guard page (thread stack
223 StackPos stackPos
= StackPos_stacked
;
224 // Default init to StackPos_stacked, to silence gcc warning.
225 // We assert this value is overriden if a stack descr is produced.
227 // First try to find a tid with stack containing a
228 tid
= find_tid_with_stack_containing (a
);
229 if (tid
!= VG_INVALID_THREADID
) {
230 /* Should be below stack pointer, as if it is >= SP, it
231 will have been described as StackPos_stacked above. */
232 stackPos
= StackPos_below_stack_ptr
;
234 /* Try to find a stack with guard page containing a.
235 For this, check if a is in a page mapped without r, w and x. */
236 const NSegment
*seg
= VG_(am_find_nsegment
) (a
);
237 if (seg
!= NULL
&& seg
->kind
== SkAnonC
238 && !seg
->hasR
&& !seg
->hasW
&& !seg
->hasX
) {
239 /* This looks a plausible guard page. Check if a is close to
240 the start of stack (lowest byte). */
241 tid
= find_tid_with_stack_containing (VG_PGROUNDUP(a
+1));
242 if (tid
!= VG_INVALID_THREADID
)
243 stackPos
= StackPos_guard_page
;
247 if (tid
!= VG_INVALID_THREADID
) {
248 ai
->tag
= Addr_Stack
;
249 VG_(initThreadInfo
)(&ai
->Addr
.Stack
.tinfo
);
250 ai
->Addr
.Stack
.tinfo
.tid
= tid
;
251 ai
->Addr
.Stack
.IP
= 0;
252 ai
->Addr
.Stack
.frameNo
= -1;
253 vg_assert (stackPos
!= StackPos_stacked
);
254 ai
->Addr
.Stack
.stackPos
= stackPos
;
255 vg_assert (a
< VG_(get_SP
)(tid
));
256 ai
->Addr
.Stack
.spoffset
= a
- VG_(get_SP
)(tid
);
261 /* -- and yet another last ditch attempt at classification -- */
262 /* Try to find a segment belonging to the client. */
264 const NSegment
*seg
= VG_(am_find_nsegment
) (a
);
266 /* Special case to detect the brk data segment. */
268 #if defined(VGO_solaris)
269 && (seg
->kind
== SkAnonC
|| seg
->kind
== SkFileC
)
271 && seg
->kind
== SkAnonC
272 #endif /* VGO_solaris */
273 && VG_(brk_limit
) >= seg
->start
274 && VG_(brk_limit
) <= seg
->end
+1) {
275 /* Address a is in a Anon Client segment which contains
276 VG_(brk_limit). So, this segment is the brk data segment
277 as initimg-linux.c:setup_client_dataseg maps an anonymous
278 segment followed by a reservation, with one reservation
279 page that will never be used by syswrap-generic.c:do_brk,
280 when increasing VG_(brk_limit).
281 So, the brk data segment will never be merged with the
282 next segment, and so an address in that area will
283 either be in the brk data segment, or in the unmapped
284 part of the brk data segment reservation. */
285 ai
->tag
= Addr_BrkSegment
;
286 ai
->Addr
.BrkSegment
.brk_limit
= VG_(brk_limit
);
291 && (seg
->kind
== SkAnonC
292 || seg
->kind
== SkFileC
293 || seg
->kind
== SkShmC
)) {
294 ai
->tag
= Addr_SegmentKind
;
295 ai
->Addr
.SegmentKind
.segkind
= seg
->kind
;
296 ai
->Addr
.SegmentKind
.filename
= NULL
;
297 if (seg
->kind
== SkFileC
)
298 ai
->Addr
.SegmentKind
.filename
299 = VG_(strdup
)("mc.da.skfname", VG_(am_get_filename
)(seg
));
300 ai
->Addr
.SegmentKind
.hasR
= seg
->hasR
;
301 ai
->Addr
.SegmentKind
.hasW
= seg
->hasW
;
302 ai
->Addr
.SegmentKind
.hasX
= seg
->hasX
;
307 /* -- Clueless ... -- */
308 ai
->tag
= Addr_Unknown
;
312 void VG_(initThreadInfo
) (ThreadInfo
*tinfo
)
318 void VG_(clear_addrinfo
) ( AddrInfo
* ai
)
321 case Addr_Undescribed
:
334 VG_(free
)(ai
->Addr
.DataSym
.name
);
338 if (ai
->Addr
.Variable
.descr1
!= NULL
) {
339 VG_(deleteXA
)( ai
->Addr
.Variable
.descr1
);
340 ai
->Addr
.Variable
.descr1
= NULL
;
342 if (ai
->Addr
.Variable
.descr2
!= NULL
) {
343 VG_(deleteXA
)( ai
->Addr
.Variable
.descr2
);
344 ai
->Addr
.Variable
.descr2
= NULL
;
349 VG_(free
)(ai
->Addr
.SectKind
.objname
);
352 case Addr_BrkSegment
:
355 case Addr_SegmentKind
:
356 VG_(free
)(ai
->Addr
.SegmentKind
.filename
);
360 VG_(core_panic
)("VG_(clear_addrinfo)");
363 ai
->tag
= Addr_Undescribed
;
366 static Bool
is_arena_BlockKind(BlockKind bk
)
371 case Block_MempoolChunk
:
372 case Block_UserG
: return False
;
374 case Block_ClientArenaMallocd
:
375 case Block_ClientArenaFree
:
376 case Block_ValgrindArenaMallocd
:
377 case Block_ValgrindArenaFree
: return True
;
379 default: vg_assert (0);
383 static const HChar
* opt_tnr_prefix (ThreadInfo tinfo
)
391 static UInt
tnr_else_tid (ThreadInfo tinfo
)
399 static const HChar
* pp_SegKind ( SegKind sk
)
402 case SkAnonC
: return "anonymous";
403 case SkFileC
: return "mapped file";
404 case SkShmC
: return "shared memory";
405 default: vg_assert(0);
409 static void pp_addrinfo_WRK ( Addr a
, const AddrInfo
* ai
, Bool mc
,
412 const HChar
* xpre
= VG_(clo_xml
) ? " <auxwhat>" : " ";
413 const HChar
* xpost
= VG_(clo_xml
) ? "</auxwhat>" : "";
415 vg_assert (!maybe_gcc
|| mc
); // maybe_gcc can only be given in mc mode.
418 case Addr_Undescribed
:
419 VG_(core_panic
)("mc_pp_AddrInfo Addr_Undescribed");
423 VG_(emit
)( "%sAddress 0x%llx is just below the stack ptr. "
424 "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
425 xpre
, (ULong
)a
, xpost
);
427 VG_(emit
)( "%sAddress 0x%llx "
428 "is not stack'd, malloc'd or %s%s\n",
431 mc
? "(recently) free'd" : "on a free list",
437 VG_(emit
)( "%sAddress 0x%llx is on thread %s%d's stack%s\n",
439 opt_tnr_prefix (ai
->Addr
.Stack
.tinfo
),
440 tnr_else_tid (ai
->Addr
.Stack
.tinfo
),
442 if (ai
->Addr
.Stack
.frameNo
!= -1 && ai
->Addr
.Stack
.IP
!= 0) {
451 if (VG_(get_inst_offset_in_function
)( ai
->Addr
.Stack
.IP
,
453 haslinenum
= VG_(get_linenum
) (ai
->Addr
.Stack
.IP
- offset
,
458 hasfile
= VG_(get_filename
)(ai
->Addr
.Stack
.IP
, &file
);
460 HChar strlinenum
[16] = ""; // large enough
461 if (hasfile
&& haslinenum
)
462 VG_(sprintf
)(strlinenum
, "%d", linenum
);
464 hasfn
= VG_(get_fnname
)(ai
->Addr
.Stack
.IP
, &fn
);
466 if (hasfn
|| hasfile
)
467 VG_(emit
)( "%sin frame #%d, created by %s (%s:%s)%s\n",
469 ai
->Addr
.Stack
.frameNo
,
471 hasfile
? file
: "???", strlinenum
,
474 switch (ai
->Addr
.Stack
.stackPos
) {
475 case StackPos_stacked
: break; // nothing more to say
477 case StackPos_below_stack_ptr
:
478 case StackPos_guard_page
:
479 VG_(emit
)("%s%s%ld bytes below stack pointer%s\n",
481 ai
->Addr
.Stack
.stackPos
== StackPos_guard_page
?
482 "In stack guard protected page, " : "",
483 - ai
->Addr
.Stack
.spoffset
,
485 // Note: we change the sign of spoffset as the message speaks
486 // about the nr of bytes below stack pointer.
489 default: vg_assert(0);
494 SizeT block_szB
= ai
->Addr
.Block
.block_szB
;
495 PtrdiffT rwoffset
= ai
->Addr
.Block
.rwoffset
;
497 const HChar
* relative
;
500 delta
= (SizeT
)(-rwoffset
);
502 } else if (rwoffset
>= block_szB
) {
503 delta
= rwoffset
- block_szB
;
509 if (is_arena_BlockKind (ai
->Addr
.Block
.block_kind
))
511 "%sAddress 0x%lx is %'lu bytes %s a%s block of size %'lu"
512 " in arena \"%s\"%s\n",
516 ai
->Addr
.Block
.block_kind
==Block_ClientArenaMallocd
517 || ai
->Addr
.Block
.block_kind
==Block_ValgrindArenaMallocd
518 ? "" : "n unallocated",
520 ai
->Addr
.Block
.block_desc
, // arena name
525 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
529 ai
->Addr
.Block
.block_desc
,
531 ai
->Addr
.Block
.block_kind
==Block_Mallocd
? "alloc'd"
532 : ai
->Addr
.Block
.block_kind
==Block_Freed
? "free'd"
536 if (ai
->Addr
.Block
.block_kind
==Block_Mallocd
) {
537 VG_(pp_ExeContext
)(ai
->Addr
.Block
.allocated_at
);
538 vg_assert (ai
->Addr
.Block
.freed_at
== VG_(null_ExeContext
)());
540 else if (ai
->Addr
.Block
.block_kind
==Block_Freed
) {
541 VG_(pp_ExeContext
)(ai
->Addr
.Block
.freed_at
);
542 if (ai
->Addr
.Block
.allocated_at
!= VG_(null_ExeContext
)()) {
544 "%sBlock was alloc'd at%s\n",
548 VG_(pp_ExeContext
)(ai
->Addr
.Block
.allocated_at
);
551 else if (ai
->Addr
.Block
.block_kind
==Block_MempoolChunk
552 || ai
->Addr
.Block
.block_kind
==Block_UserG
) {
554 VG_(pp_ExeContext
)(ai
->Addr
.Block
.allocated_at
);
555 vg_assert (ai
->Addr
.Block
.freed_at
== VG_(null_ExeContext
)());
556 /* Nb: cannot have a freed_at, as a freed client-defined block
557 has a Block_Freed block_kind. */
559 // Client or Valgrind arena. At least currently, we never
560 // have stacktraces for these.
561 vg_assert (ai
->Addr
.Block
.allocated_at
== VG_(null_ExeContext
)());
562 vg_assert (ai
->Addr
.Block
.freed_at
== VG_(null_ExeContext
)());
564 if (ai
->Addr
.Block
.alloc_tinfo
.tnr
|| ai
->Addr
.Block
.alloc_tinfo
.tid
)
566 "%sBlock was alloc'd by thread %s%d%s\n",
568 opt_tnr_prefix (ai
->Addr
.Block
.alloc_tinfo
),
569 tnr_else_tid (ai
->Addr
.Block
.alloc_tinfo
),
576 VG_(emit
)( "%sAddress 0x%llx is %llu bytes "
577 "inside data symbol \"%pS\"%s\n",
580 (ULong
)ai
->Addr
.DataSym
.offset
,
581 ai
->Addr
.DataSym
.name
,
586 /* Note, no need for XML tags here, because descr1/2 will
587 already have <auxwhat> or <xauxwhat>s on them, in XML
589 if (ai
->Addr
.Variable
.descr1
)
591 VG_(clo_xml
) ? " " : " ",
592 (HChar
*)VG_(indexXA
)(ai
->Addr
.Variable
.descr1
, 0) );
593 if (ai
->Addr
.Variable
.descr2
)
595 VG_(clo_xml
) ? " " : " ",
596 (HChar
*)VG_(indexXA
)(ai
->Addr
.Variable
.descr2
, 0) );
600 VG_(emit
)( "%sAddress 0x%llx is in the %pS segment of %pS%s\n",
603 VG_(pp_SectKind
)(ai
->Addr
.SectKind
.kind
),
604 ai
->Addr
.SectKind
.objname
,
606 if (ai
->Addr
.SectKind
.kind
== Vg_SectText
) {
607 /* To better describe the address in a text segment,
608 pp a dummy stacktrace made of this single address. */
609 VG_(pp_StackTrace
)( &a
, 1 );
613 case Addr_BrkSegment
:
614 if (a
< ai
->Addr
.BrkSegment
.brk_limit
)
615 VG_(emit
)( "%sAddress 0x%llx is in the brk data segment"
616 " 0x%llx-0x%llx%s\n",
619 (ULong
)VG_(brk_base
),
620 (ULong
)ai
->Addr
.BrkSegment
.brk_limit
- 1,
623 VG_(emit
)( "%sAddress 0x%llx is %lu bytes after "
624 "the brk data segment limit"
628 a
- ai
->Addr
.BrkSegment
.brk_limit
,
629 (ULong
)ai
->Addr
.BrkSegment
.brk_limit
,
633 case Addr_SegmentKind
:
634 VG_(emit
)( "%sAddress 0x%llx is in "
635 "a %s%s%s %s%s%pS segment%s\n",
638 ai
->Addr
.SegmentKind
.hasR
? "r" : "-",
639 ai
->Addr
.SegmentKind
.hasW
? "w" : "-",
640 ai
->Addr
.SegmentKind
.hasX
? "x" : "-",
641 pp_SegKind(ai
->Addr
.SegmentKind
.segkind
),
642 ai
->Addr
.SegmentKind
.filename
?
644 ai
->Addr
.SegmentKind
.filename
?
645 ai
->Addr
.SegmentKind
.filename
: "",
650 VG_(core_panic
)("mc_pp_AddrInfo");
654 void VG_(pp_addrinfo
) ( Addr a
, const AddrInfo
* ai
)
656 pp_addrinfo_WRK (a
, ai
, False
/*mc*/, False
/*maybe_gcc*/);
659 void VG_(pp_addrinfo_mc
) ( Addr a
, const AddrInfo
* ai
, Bool maybe_gcc
)
661 pp_addrinfo_WRK (a
, ai
, True
/*mc*/, maybe_gcc
);
665 /*--------------------------------------------------------------------*/
666 /*--- end m_addrinfo.c ---*/
667 /*--------------------------------------------------------------------*/