void HG_(describe_addr) ( Addr a, /*OUT*/AddrInfo* ai ) { tl_assert(ai->tag == Addr_Undescribed); /* hctxt/tnr/haddr/hszB describe the addr if it is a heap block. */ ExeContext* hctxt; UInt tnr; Addr haddr; SizeT hszB; /* First, see if it's in any heap block. Unfortunately this means a linear search through all allocated heap blocks. The assertion says that if it's detected as a heap block, then we must have an allocation context for it, since all heap blocks should have an allocation context. */ Bool is_heapblock = HG_(mm_find_containing_block)( &hctxt, &tnr, &haddr, &hszB, a ); if (is_heapblock) { tl_assert(is_heapblock == (hctxt != NULL)); ai->tag = Addr_Block; ai->Addr.Block.block_kind = Block_Mallocd; ai->Addr.Block.block_desc = "block"; ai->Addr.Block.block_szB = hszB; ai->Addr.Block.rwoffset = (Word)(a) - (Word)(haddr); ai->Addr.Block.allocated_at = hctxt; VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo); ai->Addr.Block.alloc_tinfo.tnr = tnr; ai->Addr.Block.freed_at = VG_(null_ExeContext)();; } else { /* No block found. Search a non-heap block description. */ VG_(describe_addr) (a, ai); /* In case ai contains a tid, set tnr to the corresponding helgrind thread number. */ if (ai->tag == Addr_Stack) { Thread* thr = get_admin_threads(); tl_assert(ai->Addr.Stack.tinfo.tid); while (thr) { if (thr->coretid == ai->Addr.Stack.tinfo.tid) { ai->Addr.Stack.tinfo.tnr = thr->errmsg_index; break; } thr = thr->admin; } } } }
/* This is the "this error is due to be printed shortly; so have a look at it any print any preamble you want" function. We use it to announce any previously un-announced threads in the upcoming error message. */ void HG_(before_pp_Error) ( const Error* err ) { XError* xe; tl_assert(err); xe = (XError*)VG_(get_error_extra)(err); tl_assert(xe); switch (VG_(get_error_kind)(err)) { case XE_Misc: announce_one_thread( xe->XE.Misc.thr ); break; case XE_LockOrder: announce_one_thread( xe->XE.LockOrder.thr ); break; case XE_PthAPIerror: announce_one_thread( xe->XE.PthAPIerror.thr ); break; case XE_UnlockBogus: announce_one_thread( xe->XE.UnlockBogus.thr ); break; case XE_UnlockForeign: announce_one_thread( xe->XE.UnlockForeign.thr ); announce_one_thread( xe->XE.UnlockForeign.owner ); break; case XE_UnlockUnlocked: announce_one_thread( xe->XE.UnlockUnlocked.thr ); break; case XE_Race: announce_one_thread( xe->XE.Race.thr ); if (xe->XE.Race.h2_ct) announce_one_thread( xe->XE.Race.h2_ct ); if (xe->XE.Race.h1_ct) announce_one_thread( xe->XE.Race.h1_ct ); if (xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) { Thread* thr = get_admin_threads(); while (thr) { if (thr->errmsg_index == xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) { announce_one_thread (thr); break; } thr = thr->admin; } } break; default: tl_assert(0); } }