-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsym2addr_linux.cc
145 lines (132 loc) · 5.55 KB
/
sym2addr_linux.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "fuzz.h"
#include "cpu/cpu.h"
#include "memory/memory-bochs.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include <regex>
#include <cstdlib>
#include <cstdio>
#include <set>
static std::set<std::string> bins;
static std::map<size_t, std::vector<std::pair<std::string, std::string>>> addr2sym;
static std::map<std::pair<std::string, std::string>, uint64_t> sym2addr;
// todo: dynamic libc symbols for stuff like exit etc
// Strategy: Run objdump on the binary. Load the
bx_address sym_to_addr(std::string bin, std::string name) {
for(auto it: bins) {
if(it.find(bin) != std::string::npos){
return sym2addr[std::make_pair(std::string(it), name)];
}
}
return NULL;
}
std::pair<std::string, std::string> addr_to_sym(size_t addr) {
if(addr2sym.find(addr) != addr2sym.end())
return addr2sym[addr][0];
for(int i =0; i<0x1000; i++){
if(addr2sym.find(addr-i) != addr2sym.end()){
return std::make_pair(addr2sym[addr-i][0].first, addr2sym[addr-i][0].second + " +"+std::to_string(i));
}
}
return std::make_pair("", "");
}
static std::string executeCommand(const char* cmd) {
std::string result, line;
char buf[1000];
FILE* pipe = popen(cmd, "r");
if (!pipe) return result;
while (fgets(buf, 1000, pipe) != nullptr) {
result += std::string(buf);
}
pclose(pipe);
return result;
}
// Function to parse the output of 'nm' command and construct map of addresses to symbol names
static std::map<std::string, size_t> get_symbol_map(const std::string& binaryPath) {
std::map<std::string, size_t> symbolMap;
std::string nmOutput = executeCommand(("nm -n -C -a " + binaryPath + "| grep -e ' t ' -e ' T '").c_str());
size_t pos = 0;
while ((pos = nmOutput.find("\n")) != std::string::npos) {
std::string line = nmOutput.substr(0, pos);
nmOutput.erase(0, pos + 1);
size_t addrEnd = line.find(' ');
size_t nameStart = line.find(' ', addrEnd + 1);
if (addrEnd != std::string::npos && nameStart != std::string::npos) {
std::string address = line.substr(0, addrEnd);
std::string name = line.substr(nameStart + 1);
symbolMap.emplace(name, strtoull(address.c_str(), NULL, 16));
}
}
nmOutput = executeCommand(("nm -n -C -a -D " + binaryPath + "| grep -e ' t ' -e ' T '").c_str());
pos = 0;
while ((pos = nmOutput.find("\n")) != std::string::npos) {
std::string line = nmOutput.substr(0, pos);
nmOutput.erase(0, pos + 1);
size_t addrEnd = line.find(' ');
size_t nameStart = line.find(' ', addrEnd + 1);
if (addrEnd != std::string::npos && nameStart != std::string::npos) {
std::string address = line.substr(0, addrEnd);
std::string name = line.substr(nameStart + 1);
symbolMap.emplace(name, strtoull(address.c_str(), NULL, 16));
}
}
return symbolMap;
}
void load_symbol_map(char *path) {
uint64_t start, size, sh_addr;
std::string binfile, section;
int log = 0;
std::ifstream file(path);
std::string str;
std::stringstream ss;
std::regex reg_regex("Symbolization Range: (\\w+) - (\\w+) size: (\\w+) file: ([^\\s]+) section: ([^\\s]+) sh_addr: (\\w+)");
char linkpath[100];
readlink("/proc/self/fd/1", linkpath, 100);
linkpath[99] = 0;
log = (strstr(linkpath, "fuzz-0.log") != NULL);
printf(".loading symbolization ranges from %s\n", path);
while (std::getline(file, str))
{
std::smatch match;
std::regex_search(str, match, reg_regex);
if(match.size() < 1){
printf("Unexpected line: %s\n", str.c_str());
continue;
}
ss.clear();
ss << std::hex << match[1].str();
ss >> start;
ss.clear();
ss << std::hex << match[3].str();
ss >> size;
ss.clear();
ss << std::hex << match[6].str();
ss >> sh_addr;
binfile = match[4].str();
section = match[5].str();
verbose_printf(":: loaded range: %s %s 0x%lx +0x%lx\n", binfile.c_str(), section.c_str(), start, size);
bins.insert(binfile);
if(section == ".text") {
auto m = get_symbol_map(binfile);
auto offset = start - sh_addr;
for(auto it: m) {
if(it.second) {
std::string name = it.first;
name.erase(std::find(name.begin(), name.end(), '('), name.end());
/* std::replace(name.begin(), name.end(), '(', '\0'); */
addr2sym[it.second + offset].push_back(std::make_pair(binfile, name));
if(log)
printf(".info Symbol Name added: %s@%s %lx\n", name.c_str(), binfile.c_str(), it.second+offset);
sym2addr[std::make_pair(binfile, name)] = it.second + offset;
printf("Looking up %s@%s %lx\n", name.c_str(), binfile.c_str(), sym2addr[std::make_pair(binfile, name)]);
/* if(!sym2addr.emplace(std::make_pair(binfile, name), it.second + offset).second) */
/* printf(".warning Symbol Name Collision: %s@%s %lx %lx\n", name.c_str(), binfile.c_str(), it.second+offset, sym2addr[std::make_pair(binfile, name)]); */
}
}
}
}
printf("sym2addr: vmlinux, init_task %lx\n", sym_to_addr("vmlinux", "init_task"));
printf("sym2addr: vmlinux, dump_stack %lx\n", sym_to_addr("vmlinux", "dump_stack"));
printf("sym2addr: vmlinux, do_idle %lx\n", sym_to_addr("vmlinux", "do_idle"));
}