forked from google/binexport
-
Notifications
You must be signed in to change notification settings - Fork 2
/
basic_block.cc
110 lines (96 loc) · 3.65 KB
/
basic_block.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2011-2024 Google LLC
//
// 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
//
// https://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 "third_party/zynamics/binexport/basic_block.h"
#include <ostream>
#include <utility>
#include "third_party/zynamics/binexport/call_graph.h"
#include "third_party/zynamics/binexport/util/format.h"
using security::binexport::FormatAddress;
thread_local BasicBlock::Cache BasicBlock::cache_;
void BasicBlockInstructions::AddInstruction(
Instructions::iterator instruction) {
auto last_range = ranges_.end();
if (last_range != ranges_.begin() && instruction == (--last_range)->end()) {
*last_range = InstructionRange(last_range->begin(), last_range->end() + 1);
} else {
ranges_.emplace_back(instruction, instruction + 1);
}
}
BasicBlock* BasicBlock::Create(BasicBlockInstructions* instructions) {
using Iterator = NestedIterator<
typename BasicBlockInstructions::InstructionRanges::const_iterator>;
auto ranges_end = instructions->ranges_.end();
Iterator instruction_first(instructions->ranges_.begin(), ranges_end);
if (instruction_first == Iterator(ranges_end)) {
return nullptr;
}
// Create the BasicBlock later if one does not exist here already.
auto [entry, found] = cache_.emplace(instruction_first->GetAddress(),
nullptr /* no BasicBlock */);
if (!found) {
return nullptr;
}
auto& ptr = entry->second;
ptr.reset(new BasicBlock(instructions));
instructions->Clear();
return ptr.get();
}
void BasicBlock::Render(std::ostream* stream, const CallGraph& call_graph,
const FlowGraph& flow_graph) const {
for (const auto& instruction : *this) {
*stream << FormatAddress(instruction.GetAddress()) << " ";
instruction.Render(stream, flow_graph);
std::pair<Comments::const_iterator, Comments::const_iterator> comments =
call_graph.GetComments(instruction.GetAddress());
if (comments.first != comments.second) {
for (; comments.first != comments.second; ++comments.first) {
*stream << " // " << *comments.first->comment << "\n";
}
} else {
*stream << std::endl;
}
}
}
int BasicBlock::GetInstructionCount() const {
int count = 0;
for (const auto& r : ranges_) {
count += r.size();
}
return count;
}
BasicBlock::InstructionConstIterator BasicBlock::GetInstruction(
Address address) const {
// This is O(n) on ranges, however there should be only one range usually.
for (auto range = ranges_.begin(), ranges_end = ranges_.end();
range != ranges_end; ++range) {
if (address >= range->begin()->GetAddress() &&
address <= (range->end() - 1)->GetAddress()) {
auto it(::GetInstructionFromRange(*range, address));
if (it != range->end()) {
assert(address == it->GetAddress());
return InstructionConstIterator(range, ranges_end, it);
}
}
}
return end();
}
BasicBlock::RangeConstIterator BasicBlock::BeforeEndRange() const {
auto last = ranges_.before_begin();
// This is O(n) on ranges, however there should be only one range usually.
for (auto range(ranges_.begin()), ranges_end(ranges_.end());
range != ranges_end; ++range) {
++last;
}
return last;
}