blob: c9d7910cae2c3669ed1a66f50a8e7a8d9979636a [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "syzygy/reorder/dead_code_finder.h"
namespace reorder {
DeadCodeFinder::DeadCodeFinder()
: Reorderer::OrderGenerator("Dead Code Finder") {
}
DeadCodeFinder::~DeadCodeFinder() {
}
bool DeadCodeFinder::OnCodeBlockEntry(const Block* block,
RelativeAddress /*address*/,
uint32 /*process_id*/,
uint32 /*thread_id*/,
const UniqueTime& /*time*/) {
visited_blocks_.insert(block);
return true;
}
bool DeadCodeFinder::IsDead(const Block* block) const {
// We don't consider gap blocks as interesting for the purposes of dead code
// identification. We don't have good names for these blocks, so they end up
// just being noise (not easily actionable) for the consumer of the dead code
// finder's output.
return ((block->attributes() & BlockGraph::GAP_BLOCK) == 0)
&& (visited_blocks_.find(block) == visited_blocks_.end());
}
bool DeadCodeFinder::CalculateReordering(const PEFile& pe_file,
const ImageLayout& image,
bool reorder_code,
bool reorder_data,
Order* order) {
DCHECK(order != NULL);
order->comment = "Unvisited blocks per section";
order->sections.clear();
order->sections.resize(image.sections.size());
for (size_t i = 0; i < image.sections.size(); ++i) {
const ImageLayout::SectionInfo& section = image.sections[i];
order->sections[i].id = i;
order->sections[i].name = section.name;
order->sections[i].characteristics = section.characteristics;
if ((section.characteristics & IMAGE_SCN_CNT_CODE) == 0)
continue;
// Prepare to iterate over all block in the section.
BlockGraph::AddressSpace::Range section_range(section.addr, section.size);
AddressSpace::RangeMapConstIterPair section_blocks(
image.blocks.GetIntersectingBlocks(
section_range.start(), section_range.size()));
// Gather up all unvisited blocks within the section in the "order".
AddressSpace::RangeMapConstIter& section_it = section_blocks.first;
const AddressSpace::RangeMapConstIter& section_end = section_blocks.second;
Order::BlockSpecVector& block_vector = order->sections[i].blocks;
for (; section_it != section_end; ++section_it) {
const BlockGraph::Block* block = section_it->second;
if (IsDead(block)) {
block_vector.push_back(Order::BlockSpec(block));
}
}
}
return true;
}
} // namespace reorder