Exemple #1
0
static bool hasLinearPathInternal(std::set<uint32> &visited, const Block &block1, const Block &block2) {
	/* Checks that a linear path exists between two blocks, by recursively
	 * descending into the children of the earlier block, until we either
	 * reached the later block (which means there is a path), or moved
	 * past the later block (which means there is no path). */

	// Remember which blocks we already visited, so we don't process them twice
	visited.insert(block1.address);

	// The two blocks are the same => we found a path
	if (block1.address == block2.address)
		return true;

	// We moved past the destination => no path
	if (block1.address > block2.address)
		return false;

	// Continue along the children
	assert(block1.children.size() == block1.childrenTypes.size());

	for (size_t i = 0; i < block1.children.size(); i++) {
		const Block        &child = *block1.children[i];
		const BlockEdgeType type  =  block1.childrenTypes[i];

		// Don't follow subroutine calls, don't jump backwards and don't visit blocks twice
		if (!isSubRoutineCall(type) && (child.address > block1.address))
			if (visited.find(child.address) == visited.end())
				if (hasLinearPathInternal(visited, child, block2))
					return true;
	}

	return false;
}
Exemple #2
0
std::vector<const Block *> Block::getLaterParents(bool includeSubRoutines) const {
	std::vector<const Block *> result;

	for (std::vector<const Block *>::const_iterator p = parents.begin(); p != parents.end(); ++p)
		if ((*p)->address >= address)
			if (includeSubRoutines || !isSubRoutineCall(getParentChildEdgeType(**p, *this)))
				result.push_back(*p);

	return result;
}
Exemple #3
0
std::vector<const Block *> Block::getLaterChildren(bool includeSubRoutines) const {
	std::vector<const Block *> result;

	for (std::vector<const Block *>::const_iterator c = children.begin(); c != children.end(); ++c)
		if ((*c)->address >= address)
			if (includeSubRoutines || !isSubRoutineCall(getParentChildEdgeType(*this, **c)))
				result.push_back(*c);

	return result;
}
Exemple #4
0
void Decompiler::writeBlock(Common::WriteStream &out, const Block *block, size_t indent) {
	for (const auto instruction : block->instructions) {
		writeInstruction(out, instruction, indent);
	}

	for (const auto &childType : block->childrenTypes) {
		if (isSubRoutineCall(childType)) {
			writeIndent(out, indent);
			const Instruction *instruction = block->instructions.back();


			out.writeString(formatJumpLabelName(*instruction->branches[0]));
			out.writeString("(");

			for (size_t i = 0; i < instruction->variables.size(); ++i) {
				out.writeString(formatVariableName(instruction->variables[i]));
				if (i < instruction->variables.size() - 1)
					out.writeString(", ");
			}

			out.writeString(");\n");

			writeBlock(out, block->children[1], indent);
		}
	}

	for (const auto &control : block->controls) {
		if (control.type == kControlTypeReturn) {
			writeIndent(out, indent);
			out.writeString("return;\n");
		} else if (control.type == kControlTypeIfCond) {
			writeIfControl(out, control, indent);
		}

		// TODO: while
		// TODO: break
		// TODO: continue
	}
}
Exemple #5
0
bool Block::isSubRoutineChild(const Block &child) const {
	return isSubRoutineCall(getParentChildEdgeType(*this, child));
}
Exemple #6
0
bool Block::isSubRoutineChild(size_t i) const {
	return (i < childrenTypes.size() && isSubRoutineCall(childrenTypes[i]));
}