Home | History | Annotate | Download | only in coregrind
      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 (at) 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 
     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 
    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 
    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 
    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 
    341 void VG_(pp_addrinfo) ( Addr a, AddrInfo* ai )
    342 {
    343    pp_addrinfo_WRK (a, ai, False /*mc*/, False /*maybe_gcc*/);
    344 }
    345 
    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