Example #1
0
BasicBlockCoverage::BasicBlockCoverage(const std::string &basicBlockListFile,
           const std::string &moduleName)
{
    FILE *fp = fopen(basicBlockListFile.c_str(), "r");
    if (!fp) {
        std::cerr << "Could not open file " << basicBlockListFile << std::endl;
        return;
    }

    char buffer[512];
    while (fgets(buffer, sizeof(buffer), fp)) {
        uint64_t start, end;
        char name[512];
        sscanf(buffer, "0x%"PRIx64" 0x%"PRIx64" %[^\r\t\n]s", &start, &end, name);
        //std::cout << "Read 0x" << std::hex << start << " 0x" << end << " " << name << std::endl;

        BasicBlocks &bbs = m_functions[name];
        //XXX: the +1 is here to compensate the broken extraction script, which
        //does not take into account the whole size of the last instruction.
        bbs.insert(BasicBlock(start, end));
        m_allBbs.insert(BasicBlock(start, end));

    }

    Functions::iterator fit;
    unsigned fcnBbCount = 0;
    for (fit = m_functions.begin(); fit != m_functions.end() ; ++fit) {
        fcnBbCount += (*fit).second.size();
    }
    assert(fcnBbCount == m_allBbs.size());

    if (m_allBbs.size() == 0) {
        std::cerr << "No basic blocks found in the list for " << moduleName << ". Check the format of the file." << std::endl;
    }

}
Example #2
0
void Function::RegisterBlockEnd(std::vector<uint32_t> next_list,
                                SpvOp branch_instruction) {
  assert(
      current_block_ &&
      "RegisterBlockEnd can only be called when parsing a binary in a block");
  std::vector<BasicBlock*> next_blocks;
  next_blocks.reserve(next_list.size());

  std::unordered_map<uint32_t, BasicBlock>::iterator inserted_block;
  bool success;
  for (uint32_t successor_id : next_list) {
    tie(inserted_block, success) =
        blocks_.insert({successor_id, BasicBlock(successor_id)});
    if (success) {
      undefined_blocks_.insert(successor_id);
    }
    next_blocks.push_back(&inserted_block->second);
  }

  if (current_block_->is_type(kBlockTypeLoop)) {
    // For each loop header, record the set of its successors, and include
    // its continue target if the continue target is not the loop header
    // itself.
    std::vector<BasicBlock*>& next_blocks_plus_continue_target =
        loop_header_successors_plus_continue_target_map_[current_block_];
    next_blocks_plus_continue_target = next_blocks;
    auto continue_target =
        FindConstructForEntryBlock(current_block_, ConstructType::kLoop)
            .corresponding_constructs()
            .back()
            ->entry_block();
    if (continue_target != current_block_) {
      next_blocks_plus_continue_target.push_back(continue_target);
    }
  }

  current_block_->RegisterBranchInstruction(branch_instruction);
  current_block_->RegisterSuccessors(next_blocks);
  current_block_ = nullptr;
  return;
}
Example #3
0
spv_result_t Function::RegisterBlock(uint32_t block_id, bool is_definition) {
  assert(
      declaration_type_ == FunctionDecl::kFunctionDeclDefinition &&
      "RegisterBlocks can only be called after declaration_type_ is defined");

  std::unordered_map<uint32_t, BasicBlock>::iterator inserted_block;
  bool success = false;
  tie(inserted_block, success) =
      blocks_.insert({block_id, BasicBlock(block_id)});
  if (is_definition) {  // new block definition
    assert(current_block_ == nullptr &&
           "Register Block can only be called when parsing a binary outside of "
           "a BasicBlock");

    undefined_blocks_.erase(block_id);
    current_block_ = &inserted_block->second;
    ordered_blocks_.push_back(current_block_);
    if (IsFirstBlock(block_id)) current_block_->set_reachable(true);
  } else if (success) {  // Block doesn't exsist but this is not a definition
    undefined_blocks_.insert(block_id);
  }

  return SPV_SUCCESS;
}
Example #4
0
//------------------------------------------------------------------------------
// Name: operator=
//------------------------------------------------------------------------------
BasicBlock &BasicBlock::operator=(const BasicBlock &rhs) {
	BasicBlock(rhs).swap(*this);
	return *this;
}
Example #5
0
void ControlFlowAnalysis::BasicBlocks()
{
    for(auto i = _blockStarts.begin(); i != _blockStarts.end(); ++i)
    {
        uint start = *i;
        if(!IsValidAddress(start))
            continue;
        uint nextStart = _base + _size;
        auto next = std::next(i);
        if(next != _blockStarts.end())
            nextStart = *next;
        for(uint addr = start, prevaddr = 0; addr < _base + _size;)
        {
            prevaddr = addr;
            if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
            {
                if(_cp.InGroup(CS_GRP_RET) || _cp.GetId() == X86_INS_INT3)
                {
                    insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
                    break;
                }
                else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
                {
                    uint dest1 = GetReferenceOperand();
                    uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
                    insertBlock(BasicBlock(start, addr, dest1, dest2));
                    insertParent(dest1, start);
                    insertParent(dest2, start);
                    break;
                }
                addr += _cp.Size();
            }
            else
                addr++;
            if(addr == nextStart)   //special case handling overlapping blocks
            {
                insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
                insertParent(nextStart, start);
                break;
            }
        }
    }
    _blockStarts.clear();

#ifdef _WIN64
    int count = 0;
    EnumerateFunctionRuntimeEntries64([&](PRUNTIME_FUNCTION Function)
    {
        const uint funcAddr = _moduleBase + Function->BeginAddress;
        const uint funcEnd = _moduleBase + Function->EndAddress;

        // If within limits...
        if(funcAddr >= _base && funcAddr < _base + _size)
            _functionStarts.insert(funcAddr);
        count++;
        return true;
    });
    dprintf("%u functions from the exception directory...\n", count);
#endif // _WIN64

    dprintf("%u basic blocks, %u function starts detected...\n", _blocks.size(), _functionStarts.size());
}