-
Notifications
You must be signed in to change notification settings - Fork 17
/
function.cc
120 lines (100 loc) · 2.57 KB
/
function.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
111
112
113
114
115
116
117
118
119
#include <stdio.h>
#include <stdint.h>
#include <list>
#include "cfg.h"
#include "bb.h"
#include "util.h"
#include "function.h"
uint64_t Function::global_id = 0;
void
Function::print(FILE *out)
{
size_t i;
unsigned offset;
if(entry.empty()) {
fprintf(out, "function %ju: start@0x%016jx end@0x%016jx (entry point unknown)\n", id, start, end);
} else {
i = 0;
for(auto entry_bb: entry) {
offset = 0;
for(auto &e: entry_bb->ancestors) {
if(e.type == Edge::EDGE_TYPE_CALL) offset = e.offset;
}
if(i == 0) {
fprintf(out, "function %ju: entry@0x%016jx %ju bytes\n", id, entry_bb->start + offset, (end-entry_bb->start));
if(entry.size() > 1) {
fprintf(out, "/-- alternative entry points:\n");
}
} else {
fprintf(out, "/-- 0x%016jx\n", entry_bb->start + offset);
}
i++;
}
}
for(auto &bb: BBs) {
fprintf(out, " BB@0x%016jx\n", bb->start);
}
}
void
Function::print_summary(FILE *out)
{
BB *entry_bb;
unsigned offset;
if(entry.empty()) {
fprintf(out, "0x0\t\t\t%ju\n", end-start);
} else {
entry_bb = entry.front();
offset = 0;
for(auto &e: entry_bb->ancestors) {
if(e.type == Edge::EDGE_TYPE_CALL) offset = e.offset;
}
fprintf(out, "0x%016jx\t%ju\n", entry_bb->start + offset, (end-entry_bb->start));
}
}
void
Function::find_entry()
{
bool reached_directly;
std::list<BB*> called;
std::list<BB*> headers;
/* Entries are sorted by priority as follows:
* (1) Called BBs in order of increasing address
* (2) Ancestor-less BBs in order of increasing address
* (3) Starting address of the function (only if no other entry found)
*/
for(auto bb: this->BBs) {
if(bb->is_called()) {
called.push_back(bb);
}
}
called.sort(compare_ptr<BB>);
for(auto bb: called) this->entry.push_back(bb);
for(auto bb: this->BBs) {
reached_directly = false;
for(auto &e: bb->ancestors) {
if(e.offset == 0) reached_directly = true;
}
if(!reached_directly) {
headers.push_back(bb);
}
}
headers.sort(compare_ptr<BB>);
for(auto bb: headers) this->entry.push_back(bb);
if(this->entry.empty()) {
if(this->cfg->start2bb.count(start)) {
this->entry.push_back(this->cfg->start2bb[start]);
}
}
}
void
Function::add_bb(BB *bb)
{
this->BBs.push_back(bb);
if(!this->start || (bb->start < this->start)) {
this->start = bb->start;
}
if(!this->end || (bb->end > this->end)) {
if(!(bb->insns.back().flags & Instruction::INS_FLAG_NOP)) this->end = bb->end;
}
bb->function = this;
}