// read a binary tag value from the specified buffer and get whatever // hash object it represents from the buffer, returning a reference // on that object. we will just match against the types of values that // can appear at the top level of a database entry. HashObject* ReadSingleValue(Buffer *buf) { switch (PeekOpenTag(buf)) { case TAG_BlockCFG: return BlockCFG::Read(buf); case TAG_CompositeCSU: return CompositeCSU::Read(buf); case TAG_EscapeEdgeSet: return EscapeEdgeSet::Read(buf); case TAG_EscapeAccessSet: return EscapeAccessSet::Read(buf); case TAG_CallEdgeSet: return CallEdgeSet::Read(buf); case TAG_BlockModset: return BlockModset::Read(buf); case TAG_BlockSummary: return BlockSummary::Read(buf); // special case: get the CFG too. case TAG_BlockMemory: { BlockMemory *mcfg = BlockMemory::Read(buf); BlockCFG *cfg = GetBlockCFG(mcfg->GetId()); if (cfg) mcfg->SetCFG(cfg); return mcfg; } default: logout << "ERROR: Unknown top-level tag in entry: " << PeekOpenTag(buf) << endl; Assert(false); } }
void BlockSummary::ComputeAssertNames() { BlockCFG *cfg = GetBlockCFG(m_id); Assert(cfg); // the assertion names need the filename of the containing function. Location *loc = cfg->GetPointLocation(cfg->GetEntryPoint()); // keep track of the last kind/index to be generated for an assertion. // the index space should be different for each assertion kind so that // different assertions do not interfere with one another. we can get this // with a simple counter because the assertions are sorted by kind. AssertKind last_kind = ASK_None; size_t last_index = 0; for (size_t ind = 0; m_assert_list && ind < m_assert_list->Size(); ind++) { AssertInfo &info = m_assert_list->At(ind); Assert(!info.name_buf); // only compute indexes for assertions which need to be checked. if (info.cls != ASC_Check) continue; // reset the index if this is a new kind of assertion. if (info.kind != last_kind) { last_kind = info.kind; last_index = 0; } last_index++; info.name_buf = new Buffer(256); BufferOutStream out(info.name_buf); out << AssertKindString(last_kind) << "$" << loc->FileName()->Value() << "$" << m_id->Function()->Value() << "$" << (m_id->Kind() == B_Loop ? m_id->Loop()->Value() : "func") << "$" << last_index << '\0'; } cfg->DecRef(); }
// consumes a reference on callee. bool CheckSingleCallee(CheckerState *state, CheckerFrame *frame, PPoint point, WherePostcondition *postcondition, BlockId *callee, bool direct) { Assert(postcondition); Assert(postcondition->GetPoint() == point); BlockCFG *cfg = frame->Memory()->GetCFG(); bool is_call = cfg->PointEdgeIsCall(point); CheckerFrame *callee_frame; if (is_call) callee_frame = frame->GetCalleeFrame(point); else callee_frame = frame->GetLoopTailFrame(point); // we should be going strictly backwards, and thus should never be // able to visit the exit point of a callee more than once. Assert(!callee_frame); callee_frame = state->MakeFrame(callee); callee->DecRef(); if (callee_frame == NULL) { // there are two ways we can get here: // 1. we saw the definition but timed out generating the memory. // emit a warning. // 2. we never saw a definition. emit a warning in the indirect call case, // make a report in the direct call case. we should really make a report // in all cases, but the indirect callgraph needs some more work. BlockCFG *cfg = GetBlockCFG(callee); if (!cfg) { const char *kind = direct ? "direct" : "indirect"; logout << "WARNING: Missing " << kind << " callee: '" << callee << "'" << endl; if (!direct) return false; // make an empty propagation for before the call. CheckerPropagate propagate(frame, point, false); state->m_stack.PushBack(&propagate); state->SetReport(RK_NoCallee); return true; } cfg->DecRef(); logout << "WARNING: Missing memory: '" << callee << "'" << endl; return false; } PPoint exit_point = callee_frame->Memory()->GetCFG()->GetExitPoint(); callee_frame->AssertPointGuard(exit_point, true); if (is_call) { frame->ConnectCallee(callee_frame, point, true); } else { // we are getting the last iteration of the loop so there is no direct // callee to connect yet. frame->ConnectLoopTail(callee_frame, point); } // add the exit equalities for any callee_expand in frame and caller_expand // in callee_frame. frame->ExpandPendingExps(); callee_frame->ExpandPendingExps(); // get the safe bits for the callee frame. Bit *callee_base_bit; GuardBitVector callee_safe_list; postcondition->GetCalleeBits(callee_frame, &callee_base_bit, &callee_safe_list); if (CheckFrameList(state, callee_frame, exit_point, false, false, callee_base_bit, callee_safe_list)) { callee_base_bit->DecRef(); return true; } callee_base_bit->DecRef(); if (is_call) frame->DisconnectCallee(callee_frame, point); else frame->DisconnectLoopTail(callee_frame, point); state->DeleteFrame(callee_frame); return false; }