blob: c3edc13b6be9c82a0e08d269770bf721726fc1f1 [file] [log] [blame]
philippe07c08522014-05-14 20:39:27 +00001
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
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2008-2017 OpenWorks Ltd
philippe07c08522014-05-14 20:39:27 +000012 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"
philipped0da9682014-12-28 17:30:22 +000033#include "pub_core_clientstate.h"
philippe07c08522014-05-14 20:39:27 +000034#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"
philippe7e3b3f22014-08-31 22:27:19 +000044#include "pub_core_threadstate.h"
philippe18d6f4e2014-05-22 23:48:24 +000045#include "pub_core_stacktrace.h"
philippe7e3b3f22014-08-31 22:27:19 +000046#include "pub_core_stacks.h"
47#include "pub_core_aspacemgr.h"
48
49/* Returns the tid whose stack includes the address a.
50 If not found, returns VG_INVALID_THREADID. */
51static ThreadId find_tid_with_stack_containing (Addr a)
52{
53 ThreadId tid;
54 Addr start, end;
55
56 start = 0;
57 end = 0;
58 VG_(stack_limits)(a, &start, &end);
59 if (start == end) {
60 // No stack found
61 vg_assert (start == 0 && end == 0);
62 return VG_INVALID_THREADID;
63 }
64
65 /* Stack limits found. Search the tid to which this stack belongs. */
66 vg_assert (start <= a);
67 vg_assert (a <= end);
68
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) ... */
72 {
73 Addr stack_min, stack_max;
74
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)
78 return tid;
79 }
80 }
81
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;
87}
philippe07c08522014-05-14 20:39:27 +000088
89void VG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai )
90{
philippe07c08522014-05-14 20:39:27 +000091 VgSectKind sect;
92
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) );
100
101 (void) VG_(get_data_description)( ai->Addr.Variable.descr1,
102 ai->Addr.Variable.descr2, a );
florianad4e9792015-07-05 21:53:33 +0000103 /* If there's nothing in descr1/2, free them. Why is it safe to
philippe07c08522014-05-14 20:39:27 +0000104 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
107 after the call.
108 */
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;
112 }
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;
116 }
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;
124 return;
125 }
126 /* -- Have a look at the low level data symbols - perhaps it's in
127 there. -- */
florian46cc0452014-10-25 19:20:38 +0000128 const HChar *name;
philippe07c08522014-05-14 20:39:27 +0000129 if (VG_(get_datasym_and_offset)(
florian46cc0452014-10-25 19:20:38 +0000130 a, &name,
philippe07c08522014-05-14 20:39:27 +0000131 &ai->Addr.DataSym.offset )) {
florian46cc0452014-10-25 19:20:38 +0000132 ai->Addr.DataSym.name = VG_(strdup)("mc.da.dsname", name);
philippe07c08522014-05-14 20:39:27 +0000133 ai->tag = Addr_DataSym;
philippe07c08522014-05-14 20:39:27 +0000134 return;
135 }
136 /* -- Perhaps it's on a thread's stack? -- */
philippe18d6f4e2014-05-22 23:48:24 +0000137 {
philippe7e3b3f22014-08-31 22:27:19 +0000138 ThreadId tid;
philippe18d6f4e2014-05-22 23:48:24 +0000139 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)];
145 UInt n_frames;
146 UInt f;
147
148 ai->tag = Addr_Stack;
philippe0c9ac8d2014-07-18 00:03:58 +0000149 VG_(initThreadInfo)(&ai->Addr.Stack.tinfo);
150 ai->Addr.Stack.tinfo.tid = tid;
philippe18d6f4e2014-05-22 23:48:24 +0000151 ai->Addr.Stack.IP = 0;
152 ai->Addr.Stack.frameNo = -1;
philippe7e3b3f22014-08-31 22:27:19 +0000153 ai->Addr.Stack.stackPos = StackPos_stacked;
154 ai->Addr.Stack.spoffset = 0; // Unused.
philippe18d6f4e2014-05-22 23:48:24 +0000155 /* 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
158 the description.
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,
163 inside the stack.
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];
175 break;
176 }
177 }
178 return;
179 }
philippe07c08522014-05-14 20:39:27 +0000180 }
181 }
182
183 /* -- Maybe it is in one of the m_mallocfree.c arenas. -- */
184 {
185 AddrArenaInfo aai;
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;
192 else
193 ai->Addr.Block.block_kind
194 = aai.free
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)();
philippe0c9ac8d2014-07-18 00:03:58 +0000200 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe07c08522014-05-14 20:39:27 +0000201 ai->Addr.Block.freed_at = VG_(null_ExeContext)();
202 return;
203 }
204 }
205
206 /* -- last ditch attempt at classification -- */
floriane08950b2014-11-13 21:41:28 +0000207 sect = VG_(DebugInfo_sect_kind)( &name, a);
philippe07c08522014-05-14 20:39:27 +0000208 if (sect != Vg_SectUnknown) {
209 ai->tag = Addr_SectKind;
philippedd238202015-03-21 20:55:36 +0000210 ai->Addr.SectKind.objname = VG_(strdup)("mc.da.dsname", name);
philippe07c08522014-05-14 20:39:27 +0000211 ai->Addr.SectKind.kind = sect;
philippe07c08522014-05-14 20:39:27 +0000212 return;
213 }
philippe7e3b3f22014-08-31 22:27:19 +0000214
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
220 too small). */
221 {
222 ThreadId tid;
philipped099e512014-09-02 22:20:14 +0000223 StackPos stackPos = StackPos_stacked;
224 // Default init to StackPos_stacked, to silence gcc warning.
Elliott Hughesed398002017-06-21 14:41:24 -0700225 // We assert this value is overridden if a stack descr is produced.
philippe7e3b3f22014-08-31 22:27:19 +0000226
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;
233 } else {
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;
244 }
245 }
246
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;
philipped099e512014-09-02 22:20:14 +0000253 vg_assert (stackPos != StackPos_stacked);
philippe7e3b3f22014-08-31 22:27:19 +0000254 ai->Addr.Stack.stackPos = stackPos;
255 vg_assert (a < VG_(get_SP)(tid));
256 ai->Addr.Stack.spoffset = a - VG_(get_SP)(tid);
257 return;
258 }
259 }
260
philippef7ec77f2014-11-24 17:46:41 +0000261 /* -- and yet another last ditch attempt at classification -- */
262 /* Try to find a segment belonging to the client. */
263 {
264 const NSegment *seg = VG_(am_find_nsegment) (a);
philipped0da9682014-12-28 17:30:22 +0000265
266 /* Special case to detect the brk data segment. */
267 if (seg != NULL
sewardj8eb8bab2015-07-21 14:44:28 +0000268#if defined(VGO_solaris)
269 && (seg->kind == SkAnonC || seg->kind == SkFileC)
270#else
philipped0da9682014-12-28 17:30:22 +0000271 && seg->kind == SkAnonC
sewardj8eb8bab2015-07-21 14:44:28 +0000272#endif /* VGO_solaris */
philipped0da9682014-12-28 17:30:22 +0000273 && 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);
287 return;
288 }
289
philippef7ec77f2014-11-24 17:46:41 +0000290 if (seg != NULL
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)
floriand3166c42015-01-24 00:02:19 +0000298 ai->Addr.SegmentKind.filename
299 = VG_(strdup)("mc.da.skfname", VG_(am_get_filename)(seg));
philippef7ec77f2014-11-24 17:46:41 +0000300 ai->Addr.SegmentKind.hasR = seg->hasR;
301 ai->Addr.SegmentKind.hasW = seg->hasW;
302 ai->Addr.SegmentKind.hasX = seg->hasX;
303 return;
304 }
305 }
306
philippe07c08522014-05-14 20:39:27 +0000307 /* -- Clueless ... -- */
308 ai->tag = Addr_Unknown;
309 return;
310}
311
philippe0c9ac8d2014-07-18 00:03:58 +0000312void VG_(initThreadInfo) (ThreadInfo *tinfo)
313{
314 tinfo->tid = 0;
315 tinfo->tnr = 0;
316}
317
philippe07c08522014-05-14 20:39:27 +0000318void VG_(clear_addrinfo) ( AddrInfo* ai)
319{
320 switch (ai->tag) {
philippe0af05d42014-09-19 18:58:18 +0000321 case Addr_Undescribed:
322 break;
323
philippe07c08522014-05-14 20:39:27 +0000324 case Addr_Unknown:
philippe0af05d42014-09-19 18:58:18 +0000325 break;
philippe07c08522014-05-14 20:39:27 +0000326
327 case Addr_Stack:
philippe0af05d42014-09-19 18:58:18 +0000328 break;
philippe07c08522014-05-14 20:39:27 +0000329
330 case Addr_Block:
331 break;
332
333 case Addr_DataSym:
florian46cc0452014-10-25 19:20:38 +0000334 VG_(free)(ai->Addr.DataSym.name);
philippe07c08522014-05-14 20:39:27 +0000335 break;
336
337 case Addr_Variable:
338 if (ai->Addr.Variable.descr1 != NULL) {
339 VG_(deleteXA)( ai->Addr.Variable.descr1 );
340 ai->Addr.Variable.descr1 = NULL;
341 }
342 if (ai->Addr.Variable.descr2 != NULL) {
343 VG_(deleteXA)( ai->Addr.Variable.descr2 );
344 ai->Addr.Variable.descr2 = NULL;
345 }
346 break;
347
348 case Addr_SectKind:
floriane08950b2014-11-13 21:41:28 +0000349 VG_(free)(ai->Addr.SectKind.objname);
philippe07c08522014-05-14 20:39:27 +0000350 break;
351
philipped0da9682014-12-28 17:30:22 +0000352 case Addr_BrkSegment:
353 break;
354
philippef7ec77f2014-11-24 17:46:41 +0000355 case Addr_SegmentKind:
356 VG_(free)(ai->Addr.SegmentKind.filename);
357 break;
358
philippe07c08522014-05-14 20:39:27 +0000359 default:
360 VG_(core_panic)("VG_(clear_addrinfo)");
361 }
362
363 ai->tag = Addr_Undescribed;
364}
365
366static Bool is_arena_BlockKind(BlockKind bk)
367{
368 switch (bk) {
369 case Block_Mallocd:
370 case Block_Freed:
371 case Block_MempoolChunk:
372 case Block_UserG: return False;
373
374 case Block_ClientArenaMallocd:
375 case Block_ClientArenaFree:
376 case Block_ValgrindArenaMallocd:
377 case Block_ValgrindArenaFree: return True;
378
379 default: vg_assert (0);
380 }
381}
382
philippe0c9ac8d2014-07-18 00:03:58 +0000383static const HChar* opt_tnr_prefix (ThreadInfo tinfo)
384{
385 if (tinfo.tnr != 0)
386 return "#";
387 else
388 return "";
389}
390
391static UInt tnr_else_tid (ThreadInfo tinfo)
392{
393 if (tinfo.tnr != 0)
394 return tinfo.tnr;
395 else
396 return tinfo.tid;
397}
398
philippef7ec77f2014-11-24 17:46:41 +0000399static const HChar* pp_SegKind ( SegKind sk )
400{
401 switch (sk) {
402 case SkAnonC: return "anonymous";
403 case SkFileC: return "mapped file";
404 case SkShmC: return "shared memory";
405 default: vg_assert(0);
406 }
407}
408
florian518850b2014-10-22 22:25:30 +0000409static void pp_addrinfo_WRK ( Addr a, const AddrInfo* ai, Bool mc,
410 Bool maybe_gcc )
philippe07c08522014-05-14 20:39:27 +0000411{
412 const HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
413 const HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
414
415 vg_assert (!maybe_gcc || mc); // maybe_gcc can only be given in mc mode.
416
417 switch (ai->tag) {
philippe0af05d42014-09-19 18:58:18 +0000418 case Addr_Undescribed:
419 VG_(core_panic)("mc_pp_AddrInfo Addr_Undescribed");
420
philippe07c08522014-05-14 20:39:27 +0000421 case Addr_Unknown:
422 if (maybe_gcc) {
floriana5e06c32015-08-05 21:16:09 +0000423 VG_(emit)( "%sAddress 0x%lx is just below the stack ptr. "
philippe07c08522014-05-14 20:39:27 +0000424 "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
floriana5e06c32015-08-05 21:16:09 +0000425 xpre, a, xpost );
philippe07c08522014-05-14 20:39:27 +0000426 } else {
floriana5e06c32015-08-05 21:16:09 +0000427 VG_(emit)( "%sAddress 0x%lx "
philippe07c08522014-05-14 20:39:27 +0000428 "is not stack'd, malloc'd or %s%s\n",
floriana5e06c32015-08-05 21:16:09 +0000429 xpre, a,
philippe07c08522014-05-14 20:39:27 +0000430 mc ? "(recently) free'd" : "on a free list",
431 xpost );
432 }
433 break;
434
435 case Addr_Stack:
floriana5e06c32015-08-05 21:16:09 +0000436 VG_(emit)( "%sAddress 0x%lx is on thread %s%u's stack%s\n",
437 xpre, a,
philippe0c9ac8d2014-07-18 00:03:58 +0000438 opt_tnr_prefix (ai->Addr.Stack.tinfo),
439 tnr_else_tid (ai->Addr.Stack.tinfo),
440 xpost );
philippe18d6f4e2014-05-22 23:48:24 +0000441 if (ai->Addr.Stack.frameNo != -1 && ai->Addr.Stack.IP != 0) {
florian46cc0452014-10-25 19:20:38 +0000442 const HChar *fn;
philippe18d6f4e2014-05-22 23:48:24 +0000443 Bool hasfn;
florian10ef7252014-10-27 12:06:35 +0000444 const HChar *file;
philippe18d6f4e2014-05-22 23:48:24 +0000445 Bool hasfile;
446 UInt linenum;
447 Bool haslinenum;
448 PtrdiffT offset;
449
philippe18d6f4e2014-05-22 23:48:24 +0000450 if (VG_(get_inst_offset_in_function)( ai->Addr.Stack.IP,
451 &offset))
452 haslinenum = VG_(get_linenum) (ai->Addr.Stack.IP - offset,
453 &linenum);
454 else
455 haslinenum = False;
456
florian10ef7252014-10-27 12:06:35 +0000457 hasfile = VG_(get_filename)(ai->Addr.Stack.IP, &file);
458
459 HChar strlinenum[16] = ""; // large enough
460 if (hasfile && haslinenum)
floriana5e06c32015-08-05 21:16:09 +0000461 VG_(sprintf)(strlinenum, "%u", linenum);
philippe18d6f4e2014-05-22 23:48:24 +0000462
florian46cc0452014-10-25 19:20:38 +0000463 hasfn = VG_(get_fnname)(ai->Addr.Stack.IP, &fn);
464
philippe18d6f4e2014-05-22 23:48:24 +0000465 if (hasfn || hasfile)
Elliott Hughesa0664b92017-04-18 17:46:52 -0700466 VG_(emit)( "%sin frame #%d, created by %ps (%ps:%s)%s\n",
philippe18d6f4e2014-05-22 23:48:24 +0000467 xpre,
468 ai->Addr.Stack.frameNo,
469 hasfn ? fn : "???",
florian10ef7252014-10-27 12:06:35 +0000470 hasfile ? file : "???", strlinenum,
philippe18d6f4e2014-05-22 23:48:24 +0000471 xpost );
philippe18d6f4e2014-05-22 23:48:24 +0000472 }
philippe7e3b3f22014-08-31 22:27:19 +0000473 switch (ai->Addr.Stack.stackPos) {
474 case StackPos_stacked: break; // nothing more to say
475
476 case StackPos_below_stack_ptr:
477 case StackPos_guard_page:
478 VG_(emit)("%s%s%ld bytes below stack pointer%s\n",
479 xpre,
480 ai->Addr.Stack.stackPos == StackPos_guard_page ?
481 "In stack guard protected page, " : "",
482 - ai->Addr.Stack.spoffset,
483 xpost);
484 // Note: we change the sign of spoffset as the message speaks
485 // about the nr of bytes below stack pointer.
486 break;
487
488 default: vg_assert(0);
489 }
philippe07c08522014-05-14 20:39:27 +0000490 break;
491
492 case Addr_Block: {
493 SizeT block_szB = ai->Addr.Block.block_szB;
494 PtrdiffT rwoffset = ai->Addr.Block.rwoffset;
495 SizeT delta;
496 const HChar* relative;
497
498 if (rwoffset < 0) {
499 delta = (SizeT)(-rwoffset);
500 relative = "before";
501 } else if (rwoffset >= block_szB) {
502 delta = rwoffset - block_szB;
503 relative = "after";
504 } else {
505 delta = rwoffset;
506 relative = "inside";
507 }
508 if (is_arena_BlockKind (ai->Addr.Block.block_kind))
509 VG_(emit)(
510 "%sAddress 0x%lx is %'lu bytes %s a%s block of size %'lu"
511 " in arena \"%s\"%s\n",
512 xpre,
513 a, delta,
514 relative,
515 ai->Addr.Block.block_kind==Block_ClientArenaMallocd
516 || ai->Addr.Block.block_kind==Block_ValgrindArenaMallocd
517 ? "" : "n unallocated",
518 block_szB,
519 ai->Addr.Block.block_desc, // arena name
520 xpost
521 );
522 else
523 VG_(emit)(
524 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
525 xpre,
526 a, delta,
527 relative,
528 ai->Addr.Block.block_desc,
529 block_szB,
530 ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
531 : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
532 : "client-defined",
533 xpost
534 );
535 if (ai->Addr.Block.block_kind==Block_Mallocd) {
536 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
floriane2800c92014-09-15 20:57:45 +0000537 vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
philippe07c08522014-05-14 20:39:27 +0000538 }
539 else if (ai->Addr.Block.block_kind==Block_Freed) {
540 VG_(pp_ExeContext)(ai->Addr.Block.freed_at);
541 if (ai->Addr.Block.allocated_at != VG_(null_ExeContext)()) {
542 VG_(emit)(
philippe0c9ac8d2014-07-18 00:03:58 +0000543 "%sBlock was alloc'd at%s\n",
philippe07c08522014-05-14 20:39:27 +0000544 xpre,
545 xpost
546 );
547 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
548 }
549 }
550 else if (ai->Addr.Block.block_kind==Block_MempoolChunk
551 || ai->Addr.Block.block_kind==Block_UserG) {
552 // client-defined
553 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
floriane2800c92014-09-15 20:57:45 +0000554 vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
philippe07c08522014-05-14 20:39:27 +0000555 /* Nb: cannot have a freed_at, as a freed client-defined block
556 has a Block_Freed block_kind. */
557 } else {
558 // Client or Valgrind arena. At least currently, we never
559 // have stacktraces for these.
floriane2800c92014-09-15 20:57:45 +0000560 vg_assert (ai->Addr.Block.allocated_at == VG_(null_ExeContext)());
561 vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
philippe07c08522014-05-14 20:39:27 +0000562 }
philippe0c9ac8d2014-07-18 00:03:58 +0000563 if (ai->Addr.Block.alloc_tinfo.tnr || ai->Addr.Block.alloc_tinfo.tid)
564 VG_(emit)(
floriana5e06c32015-08-05 21:16:09 +0000565 "%sBlock was alloc'd by thread %s%u%s\n",
philippe0c9ac8d2014-07-18 00:03:58 +0000566 xpre,
567 opt_tnr_prefix (ai->Addr.Block.alloc_tinfo),
568 tnr_else_tid (ai->Addr.Block.alloc_tinfo),
569 xpost
570 );
philippe07c08522014-05-14 20:39:27 +0000571 break;
572 }
573
574 case Addr_DataSym:
floriana5e06c32015-08-05 21:16:09 +0000575 VG_(emit)( "%sAddress 0x%lx is %llu bytes "
Elliott Hughesa0664b92017-04-18 17:46:52 -0700576 "inside data symbol \"%ps\"%s\n",
floriana5e06c32015-08-05 21:16:09 +0000577 xpre, a,
philippe07c08522014-05-14 20:39:27 +0000578 (ULong)ai->Addr.DataSym.offset,
579 ai->Addr.DataSym.name,
580 xpost );
581 break;
582
583 case Addr_Variable:
584 /* Note, no need for XML tags here, because descr1/2 will
585 already have <auxwhat> or <xauxwhat>s on them, in XML
586 mode. */
587 if (ai->Addr.Variable.descr1)
588 VG_(emit)( "%s%s\n",
589 VG_(clo_xml) ? " " : " ",
590 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr1, 0) );
591 if (ai->Addr.Variable.descr2)
592 VG_(emit)( "%s%s\n",
593 VG_(clo_xml) ? " " : " ",
594 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr2, 0) );
595 break;
596
597 case Addr_SectKind:
Elliott Hughesa0664b92017-04-18 17:46:52 -0700598 VG_(emit)( "%sAddress 0x%lx is in the %ps segment of %ps%s\n",
floriana5e06c32015-08-05 21:16:09 +0000599 xpre, a,
philippe07c08522014-05-14 20:39:27 +0000600 VG_(pp_SectKind)(ai->Addr.SectKind.kind),
601 ai->Addr.SectKind.objname,
602 xpost );
philippea7cea052014-07-25 20:46:01 +0000603 if (ai->Addr.SectKind.kind == Vg_SectText) {
604 /* To better describe the address in a text segment,
605 pp a dummy stacktrace made of this single address. */
606 VG_(pp_StackTrace)( &a, 1 );
607 }
philippe07c08522014-05-14 20:39:27 +0000608 break;
609
philipped0da9682014-12-28 17:30:22 +0000610 case Addr_BrkSegment:
611 if (a < ai->Addr.BrkSegment.brk_limit)
floriana5e06c32015-08-05 21:16:09 +0000612 VG_(emit)( "%sAddress 0x%lx is in the brk data segment"
613 " 0x%lx-0x%lx%s\n",
614 xpre, a,
615 VG_(brk_base),
616 ai->Addr.BrkSegment.brk_limit - 1,
philipped0da9682014-12-28 17:30:22 +0000617 xpost );
618 else
floriana5e06c32015-08-05 21:16:09 +0000619 VG_(emit)( "%sAddress 0x%lx is %lu bytes after "
philipped0da9682014-12-28 17:30:22 +0000620 "the brk data segment limit"
floriana5e06c32015-08-05 21:16:09 +0000621 " 0x%lx%s\n",
622 xpre, a,
philipped0da9682014-12-28 17:30:22 +0000623 a - ai->Addr.BrkSegment.brk_limit,
floriana5e06c32015-08-05 21:16:09 +0000624 ai->Addr.BrkSegment.brk_limit,
philipped0da9682014-12-28 17:30:22 +0000625 xpost );
626 break;
627
philippef7ec77f2014-11-24 17:46:41 +0000628 case Addr_SegmentKind:
floriana5e06c32015-08-05 21:16:09 +0000629 VG_(emit)( "%sAddress 0x%lx is in "
Elliott Hughesa0664b92017-04-18 17:46:52 -0700630 "a %s%s%s %s%s%ps segment%s\n",
philippef7ec77f2014-11-24 17:46:41 +0000631 xpre,
floriana5e06c32015-08-05 21:16:09 +0000632 a,
philippef7ec77f2014-11-24 17:46:41 +0000633 ai->Addr.SegmentKind.hasR ? "r" : "-",
634 ai->Addr.SegmentKind.hasW ? "w" : "-",
635 ai->Addr.SegmentKind.hasX ? "x" : "-",
636 pp_SegKind(ai->Addr.SegmentKind.segkind),
637 ai->Addr.SegmentKind.filename ?
638 " " : "",
639 ai->Addr.SegmentKind.filename ?
640 ai->Addr.SegmentKind.filename : "",
641 xpost );
642 break;
643
philippe07c08522014-05-14 20:39:27 +0000644 default:
floriana4ca4fe2014-09-16 09:28:12 +0000645 VG_(core_panic)("mc_pp_AddrInfo");
philippe07c08522014-05-14 20:39:27 +0000646 }
647}
648
florian518850b2014-10-22 22:25:30 +0000649void VG_(pp_addrinfo) ( Addr a, const AddrInfo* ai )
philippe07c08522014-05-14 20:39:27 +0000650{
651 pp_addrinfo_WRK (a, ai, False /*mc*/, False /*maybe_gcc*/);
652}
653
florian518850b2014-10-22 22:25:30 +0000654void VG_(pp_addrinfo_mc) ( Addr a, const AddrInfo* ai, Bool maybe_gcc )
philippe07c08522014-05-14 20:39:27 +0000655{
656 pp_addrinfo_WRK (a, ai, True /*mc*/, maybe_gcc);
657}
658
659
660/*--------------------------------------------------------------------*/
661/*--- end m_addrinfo.c ---*/
662/*--------------------------------------------------------------------*/