control_flow: Correct block breaking algorithm.

This commit is contained in:
Fernando Sahmkow 2019-06-27 09:24:40 -04:00 committed by FernandoS27
parent dc4a93594c
commit e7c6045a03

View File

@ -75,19 +75,17 @@ struct CFGRebuildState {
enum class BlockCollision : u32 { None, Found, Inside }; enum class BlockCollision : u32 { None, Found, Inside };
std::pair<BlockCollision, std::vector<BlockInfo>::iterator> TryGetBlock(CFGRebuildState& state, std::pair<BlockCollision, u32> TryGetBlock(CFGRebuildState& state, u32 address) {
u32 address) { const auto& blocks = state.block_info;
auto it = state.block_info.begin(); for (u32 index = 0; index < blocks.size(); index++) {
while (it != state.block_info.end()) { if (blocks[index].start == address) {
if (it->start == address) { return {BlockCollision::Found, index};
return {BlockCollision::Found, it};
} }
if (it->IsInside(address)) { if (blocks[index].IsInside(address)) {
return {BlockCollision::Inside, it}; return {BlockCollision::Inside, index};
} }
it++;
} }
return {BlockCollision::None, it}; return {BlockCollision::None, -1};
} }
struct ParseInfo { struct ParseInfo {
@ -318,24 +316,26 @@ bool TryInspectAddress(CFGRebuildState& state) {
if (state.inspect_queries.empty()) { if (state.inspect_queries.empty()) {
return false; return false;
} }
const u32 address = state.inspect_queries.front(); const u32 address = state.inspect_queries.front();
state.inspect_queries.pop_front(); state.inspect_queries.pop_front();
const auto search_result = TryGetBlock(state, address); const auto [result, block_index] = TryGetBlock(state, address);
switch (search_result.first) { switch (result) {
case BlockCollision::Found: { case BlockCollision::Found: {
return true; return true;
} }
case BlockCollision::Inside: { case BlockCollision::Inside: {
// This case is the tricky one: // This case is the tricky one:
// We need to Split the block in 2 sepparate blocks // We need to Split the block in 2 sepparate blocks
const auto it = search_result.second; const u32 end = state.block_info[block_index].end;
BlockInfo& block_info = CreateBlockInfo(state, address, it->end); BlockInfo& new_block = CreateBlockInfo(state, address, end);
it->end = address - 1; BlockInfo& current_block = state.block_info[block_index];
block_info.branch = it->branch; current_block.end = address - 1;
new_block.branch = current_block.branch;
BlockBranchInfo forward_branch{}; BlockBranchInfo forward_branch{};
forward_branch.address = address; forward_branch.address = address;
forward_branch.ignore = true; forward_branch.ignore = true;
it->branch = forward_branch; current_block.branch = forward_branch;
return true; return true;
} }
default: default: