• 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_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"
48 
49 /* Returns the tid whose stack includes the address a.
50    If not found, returns VG_INVALID_THREADID. */
find_tid_with_stack_containing(Addr a)51 static 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 }
88 
VG_(describe_addr)89 void VG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai )
90 {
91    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 );
103    /* If there's nothing in descr1/2, free them.  Why is it safe to 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
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. -- */
128    const HChar *name;
129    if (VG_(get_datasym_and_offset)(
130              a, &name,
131              &ai->Addr.DataSym.offset )) {
132       ai->Addr.DataSym.name = VG_(strdup)("mc.da.dsname", name);
133       ai->tag = Addr_DataSym;
134       return;
135    }
136    /* -- Perhaps it's on a thread's stack? -- */
137    {
138       ThreadId   tid;
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)];
145             UInt n_frames;
146             UInt f;
147 
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
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          }
180       }
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)();
200          VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
201          ai->Addr.Block.freed_at = VG_(null_ExeContext)();
202          return;
203       }
204    }
205 
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;
212       return;
213    }
214 
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;
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.
226 
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;
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);
257          return;
258       }
259    }
260 
261    /* -- 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);
265 
266       /* Special case to detect the brk data segment. */
267       if (seg != NULL
268           && seg->kind == SkAnonC
269           && VG_(brk_limit) >= seg->start
270           && VG_(brk_limit) <= seg->end+1) {
271          /* Address a is in a Anon Client segment which contains
272             VG_(brk_limit). So, this segment is the brk data segment
273             as initimg-linux.c:setup_client_dataseg maps an anonymous
274             segment followed by a reservation, with one reservation
275             page that will never be used by syswrap-generic.c:do_brk,
276             when increasing VG_(brk_limit).
277             So, the brk data segment will never be merged with the
278             next segment, and so an address in that area will
279             either be in the brk data segment, or in the unmapped
280             part of the brk data segment reservation. */
281          ai->tag = Addr_BrkSegment;
282          ai->Addr.BrkSegment.brk_limit = VG_(brk_limit);
283          return;
284       }
285 
286       if (seg != NULL
287           && (seg->kind == SkAnonC
288               || seg->kind == SkFileC
289               || seg->kind == SkShmC)) {
290          ai->tag = Addr_SegmentKind;
291          ai->Addr.SegmentKind.segkind = seg->kind;
292          ai->Addr.SegmentKind.filename = NULL;
293          if (seg->kind == SkFileC)
294             ai->Addr.SegmentKind.filename
295                = VG_(strdup)("mc.da.skfname", VG_(am_get_filename)(seg));
296          ai->Addr.SegmentKind.hasR = seg->hasR;
297          ai->Addr.SegmentKind.hasW = seg->hasW;
298          ai->Addr.SegmentKind.hasX = seg->hasX;
299          return;
300       }
301    }
302 
303    /* -- Clueless ... -- */
304    ai->tag = Addr_Unknown;
305    return;
306 }
307 
VG_(initThreadInfo)308 void VG_(initThreadInfo) (ThreadInfo *tinfo)
309 {
310    tinfo->tid = 0;
311    tinfo->tnr = 0;
312 }
313 
VG_(clear_addrinfo)314 void VG_(clear_addrinfo) ( AddrInfo* ai)
315 {
316    switch (ai->tag) {
317       case Addr_Undescribed:
318          break;
319 
320       case Addr_Unknown:
321          break;
322 
323       case Addr_Stack:
324          break;
325 
326       case Addr_Block:
327          break;
328 
329       case Addr_DataSym:
330          VG_(free)(ai->Addr.DataSym.name);
331          break;
332 
333       case Addr_Variable:
334          if (ai->Addr.Variable.descr1 != NULL) {
335             VG_(deleteXA)( ai->Addr.Variable.descr1 );
336             ai->Addr.Variable.descr1 = NULL;
337          }
338          if (ai->Addr.Variable.descr2 != NULL) {
339             VG_(deleteXA)( ai->Addr.Variable.descr2 );
340             ai->Addr.Variable.descr2 = NULL;
341          }
342          break;
343 
344       case Addr_SectKind:
345          VG_(free)(ai->Addr.SectKind.objname);
346          break;
347 
348       case Addr_BrkSegment:
349          break;
350 
351       case Addr_SegmentKind:
352          VG_(free)(ai->Addr.SegmentKind.filename);
353          break;
354 
355       default:
356          VG_(core_panic)("VG_(clear_addrinfo)");
357    }
358 
359    ai->tag = Addr_Undescribed;
360 }
361 
is_arena_BlockKind(BlockKind bk)362 static Bool is_arena_BlockKind(BlockKind bk)
363 {
364    switch (bk) {
365       case Block_Mallocd:
366       case Block_Freed:
367       case Block_MempoolChunk:
368       case Block_UserG:                return False;
369 
370       case Block_ClientArenaMallocd:
371       case Block_ClientArenaFree:
372       case Block_ValgrindArenaMallocd:
373       case Block_ValgrindArenaFree:    return True;
374 
375       default:                         vg_assert (0);
376    }
377 }
378 
opt_tnr_prefix(ThreadInfo tinfo)379 static const HChar* opt_tnr_prefix (ThreadInfo tinfo)
380 {
381    if (tinfo.tnr != 0)
382       return "#";
383    else
384       return "";
385 }
386 
tnr_else_tid(ThreadInfo tinfo)387 static UInt tnr_else_tid (ThreadInfo tinfo)
388 {
389    if (tinfo.tnr != 0)
390       return tinfo.tnr;
391    else
392       return tinfo.tid;
393 }
394 
pp_SegKind(SegKind sk)395 static const HChar* pp_SegKind ( SegKind sk )
396 {
397    switch (sk) {
398       case SkAnonC: return "anonymous";
399       case SkFileC: return "mapped file";
400       case SkShmC:  return "shared memory";
401       default:      vg_assert(0);
402    }
403 }
404 
pp_addrinfo_WRK(Addr a,const AddrInfo * ai,Bool mc,Bool maybe_gcc)405 static void pp_addrinfo_WRK ( Addr a, const AddrInfo* ai, Bool mc,
406                               Bool maybe_gcc )
407 {
408    const HChar* xpre  = VG_(clo_xml) ? "  <auxwhat>" : " ";
409    const HChar* xpost = VG_(clo_xml) ? "</auxwhat>"  : "";
410 
411    vg_assert (!maybe_gcc || mc); // maybe_gcc can only be given in mc mode.
412 
413    switch (ai->tag) {
414       case Addr_Undescribed:
415          VG_(core_panic)("mc_pp_AddrInfo Addr_Undescribed");
416 
417       case Addr_Unknown:
418          if (maybe_gcc) {
419             VG_(emit)( "%sAddress 0x%llx is just below the stack ptr.  "
420                        "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
421                        xpre, (ULong)a, xpost );
422 	 } else {
423             VG_(emit)( "%sAddress 0x%llx "
424                        "is not stack'd, malloc'd or %s%s\n",
425                        xpre,
426                        (ULong)a,
427                        mc ? "(recently) free'd" : "on a free list",
428                        xpost );
429          }
430          break;
431 
432       case Addr_Stack:
433          VG_(emit)( "%sAddress 0x%llx is on thread %s%d's stack%s\n",
434                     xpre, (ULong)a,
435                     opt_tnr_prefix (ai->Addr.Stack.tinfo),
436                     tnr_else_tid (ai->Addr.Stack.tinfo),
437                     xpost );
438          if (ai->Addr.Stack.frameNo != -1 && ai->Addr.Stack.IP != 0) {
439             const HChar *fn;
440             Bool  hasfn;
441             const HChar *file;
442             Bool  hasfile;
443             UInt linenum;
444             Bool haslinenum;
445             PtrdiffT offset;
446 
447             if (VG_(get_inst_offset_in_function)( ai->Addr.Stack.IP,
448                                                   &offset))
449                haslinenum = VG_(get_linenum) (ai->Addr.Stack.IP - offset,
450                                               &linenum);
451             else
452                haslinenum = False;
453 
454             hasfile = VG_(get_filename)(ai->Addr.Stack.IP, &file);
455 
456             HChar strlinenum[16] = "";   // large enough
457             if (hasfile && haslinenum)
458                VG_(sprintf)(strlinenum, "%d", linenum);
459 
460             hasfn = VG_(get_fnname)(ai->Addr.Stack.IP, &fn);
461 
462             if (hasfn || hasfile)
463                VG_(emit)( "%sin frame #%d, created by %s (%s:%s)%s\n",
464                           xpre,
465                           ai->Addr.Stack.frameNo,
466                           hasfn ? fn : "???",
467                           hasfile ? file : "???", strlinenum,
468                           xpost );
469          }
470          switch (ai->Addr.Stack.stackPos) {
471             case StackPos_stacked: break; // nothing more to say
472 
473             case StackPos_below_stack_ptr:
474             case StackPos_guard_page:
475                 VG_(emit)("%s%s%ld bytes below stack pointer%s\n",
476                           xpre,
477                           ai->Addr.Stack.stackPos == StackPos_guard_page ?
478                           "In stack guard protected page, " : "",
479                           - ai->Addr.Stack.spoffset,
480                           xpost);
481                 // Note: we change the sign of spoffset as the message speaks
482                 // about the nr of bytes below stack pointer.
483                 break;
484 
485             default: vg_assert(0);
486          }
487          break;
488 
489       case Addr_Block: {
490          SizeT    block_szB = ai->Addr.Block.block_szB;
491          PtrdiffT rwoffset  = ai->Addr.Block.rwoffset;
492          SizeT    delta;
493          const    HChar* relative;
494 
495          if (rwoffset < 0) {
496             delta    = (SizeT)(-rwoffset);
497             relative = "before";
498          } else if (rwoffset >= block_szB) {
499             delta    = rwoffset - block_szB;
500             relative = "after";
501          } else {
502             delta    = rwoffset;
503             relative = "inside";
504          }
505          if (is_arena_BlockKind (ai->Addr.Block.block_kind))
506             VG_(emit)(
507                "%sAddress 0x%lx is %'lu bytes %s a%s block of size %'lu"
508                " in arena \"%s\"%s\n",
509                xpre,
510                a, delta,
511                relative,
512                ai->Addr.Block.block_kind==Block_ClientArenaMallocd
513                  || ai->Addr.Block.block_kind==Block_ValgrindArenaMallocd
514                  ? "" : "n unallocated",
515                block_szB,
516                ai->Addr.Block.block_desc,  // arena name
517                xpost
518             );
519          else
520             VG_(emit)(
521                "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
522                xpre,
523                a, delta,
524                relative,
525                ai->Addr.Block.block_desc,
526                block_szB,
527                ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
528                : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
529                                                         : "client-defined",
530                xpost
531             );
532          if (ai->Addr.Block.block_kind==Block_Mallocd) {
533             VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
534             vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
535          }
536          else if (ai->Addr.Block.block_kind==Block_Freed) {
537             VG_(pp_ExeContext)(ai->Addr.Block.freed_at);
538             if (ai->Addr.Block.allocated_at != VG_(null_ExeContext)()) {
539                VG_(emit)(
540                   "%sBlock was alloc'd at%s\n",
541                   xpre,
542                   xpost
543                );
544                VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
545             }
546          }
547          else if (ai->Addr.Block.block_kind==Block_MempoolChunk
548                   || ai->Addr.Block.block_kind==Block_UserG) {
549             // client-defined
550             VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
551             vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
552             /* Nb: cannot have a freed_at, as a freed client-defined block
553                has a Block_Freed block_kind. */
554          } else {
555             // Client or Valgrind arena. At least currently, we never
556             // have stacktraces for these.
557             vg_assert (ai->Addr.Block.allocated_at == VG_(null_ExeContext)());
558             vg_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
559          }
560          if (ai->Addr.Block.alloc_tinfo.tnr || ai->Addr.Block.alloc_tinfo.tid)
561             VG_(emit)(
562                "%sBlock was alloc'd by thread %s%d%s\n",
563                xpre,
564                opt_tnr_prefix (ai->Addr.Block.alloc_tinfo),
565                tnr_else_tid (ai->Addr.Block.alloc_tinfo),
566                xpost
567             );
568          break;
569       }
570 
571       case Addr_DataSym:
572          VG_(emit)( "%sAddress 0x%llx is %llu bytes "
573                     "inside data symbol \"%pS\"%s\n",
574                     xpre,
575                     (ULong)a,
576                     (ULong)ai->Addr.DataSym.offset,
577                     ai->Addr.DataSym.name,
578                     xpost );
579          break;
580 
581       case Addr_Variable:
582          /* Note, no need for XML tags here, because descr1/2 will
583             already have <auxwhat> or <xauxwhat>s on them, in XML
584             mode. */
585          if (ai->Addr.Variable.descr1)
586             VG_(emit)( "%s%s\n",
587                        VG_(clo_xml) ? "  " : " ",
588                        (HChar*)VG_(indexXA)(ai->Addr.Variable.descr1, 0) );
589          if (ai->Addr.Variable.descr2)
590             VG_(emit)( "%s%s\n",
591                        VG_(clo_xml) ? "  " : " ",
592                        (HChar*)VG_(indexXA)(ai->Addr.Variable.descr2, 0) );
593          break;
594 
595       case Addr_SectKind:
596          VG_(emit)( "%sAddress 0x%llx is in the %pS segment of %pS%s\n",
597                     xpre,
598                     (ULong)a,
599                     VG_(pp_SectKind)(ai->Addr.SectKind.kind),
600                     ai->Addr.SectKind.objname,
601                     xpost );
602          if (ai->Addr.SectKind.kind == Vg_SectText) {
603             /* To better describe the address in a text segment,
604                pp a dummy stacktrace made of this single address. */
605             VG_(pp_StackTrace)( &a, 1 );
606          }
607          break;
608 
609       case Addr_BrkSegment:
610          if (a < ai->Addr.BrkSegment.brk_limit)
611             VG_(emit)( "%sAddress 0x%llx is in the brk data segment"
612                        " 0x%llx-0x%llx%s\n",
613                        xpre,
614                        (ULong)a,
615                        (ULong)VG_(brk_base),
616                        (ULong)ai->Addr.BrkSegment.brk_limit - 1,
617                        xpost );
618          else
619             VG_(emit)( "%sAddress 0x%llx is %lu bytes after "
620                        "the brk data segment limit"
621                        " 0x%llx%s\n",
622                        xpre,
623                        (ULong)a,
624                        a - ai->Addr.BrkSegment.brk_limit,
625                        (ULong)ai->Addr.BrkSegment.brk_limit,
626                        xpost );
627          break;
628 
629       case Addr_SegmentKind:
630          VG_(emit)( "%sAddress 0x%llx is in "
631                     "a %s%s%s %s%s%pS segment%s\n",
632                     xpre,
633                     (ULong)a,
634                     ai->Addr.SegmentKind.hasR ? "r" : "-",
635                     ai->Addr.SegmentKind.hasW ? "w" : "-",
636                     ai->Addr.SegmentKind.hasX ? "x" : "-",
637                     pp_SegKind(ai->Addr.SegmentKind.segkind),
638                     ai->Addr.SegmentKind.filename ?
639                     " " : "",
640                     ai->Addr.SegmentKind.filename ?
641                     ai->Addr.SegmentKind.filename : "",
642                     xpost );
643          break;
644 
645       default:
646          VG_(core_panic)("mc_pp_AddrInfo");
647    }
648 }
649 
VG_(pp_addrinfo)650 void VG_(pp_addrinfo) ( Addr a, const AddrInfo* ai )
651 {
652    pp_addrinfo_WRK (a, ai, False /*mc*/, False /*maybe_gcc*/);
653 }
654 
VG_(pp_addrinfo_mc)655 void VG_(pp_addrinfo_mc) ( Addr a, const AddrInfo* ai, Bool maybe_gcc )
656 {
657    pp_addrinfo_WRK (a, ai, True /*mc*/, maybe_gcc);
658 }
659 
660 
661 /*--------------------------------------------------------------------*/
662 /*--- end                                             m_addrinfo.c ---*/
663 /*--------------------------------------------------------------------*/
664