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