-
Notifications
You must be signed in to change notification settings - Fork 846
Expand file tree
/
Copy pathkernel_symbol_parser.cpp
More file actions
139 lines (129 loc) · 4.94 KB
/
kernel_symbol_parser.cpp
File metadata and controls
139 lines (129 loc) · 4.94 KB
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
#include "kernel_symbol_parser.h"
#include <sstream>
#include <algorithm>
#include <unordered_map>
#include "3rdparty/aarch64_asm_helper.h"
#include "aarch64_simulate_insn.h"
#include "aarch64_insn.h"
#ifndef MIN
#define MIN(x, y)(x < y) ? (x) : (y)
#endif // !MIN
KernelSymbolParser::KernelSymbolParser(const std::vector<char>& file_buf) : m_file_buf(file_buf), m_kernel_ver_parser(file_buf)
, m_kallsyms_lookup_name_6_12_0(file_buf)
, m_kallsyms_lookup_name_6_4_0(file_buf)
, m_kallsyms_lookup_name_6_1_60(file_buf)
, m_kallsyms_lookup_name_6_1_42(file_buf)
, m_kallsyms_lookup_name_6_1_0(file_buf)
, m_kallsyms_lookup_name_4_6_0(file_buf)
, m_kallsyms_lookup_name(file_buf)
{
}
KernelSymbolParser::~KernelSymbolParser()
{
}
bool KernelSymbolParser::init_kallsyms_lookup_name() {
std::string current_version = m_kernel_ver_parser.get_kernel_version();
if (current_version.empty()) {
std::cout << "Failed to read Linux kernel version" << std::endl;
return false;
}
std::cout << "Find the current Linux kernel version: " << current_version << std::endl;
std::cout << std::endl;
if (m_kernel_ver_parser.is_kernel_version_less("4.4.0")) { // android special
if (!try_init_lookup(m_kallsyms_lookup_name)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else if (m_kernel_ver_parser.is_kernel_version_less("4.6.0")) {
if (!try_init_lookup(m_kallsyms_lookup_name)) {
if (!try_init_lookup(m_kallsyms_lookup_name_4_6_0)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
}
} else if (m_kernel_ver_parser.is_kernel_version_less("6.1.0")) {
if (!try_init_lookup(m_kallsyms_lookup_name_4_6_0)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else if (m_kernel_ver_parser.is_kernel_version_less("6.1.42")) {
if (!try_init_lookup(m_kallsyms_lookup_name_6_1_0)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else if (m_kernel_ver_parser.is_kernel_version_less("6.1.60")) {
if (!try_init_lookup(m_kallsyms_lookup_name_6_1_42)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else if (m_kernel_ver_parser.is_kernel_version_less("6.4.0")) {
if (!try_init_lookup(m_kallsyms_lookup_name_6_1_60)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else if(m_kernel_ver_parser.is_kernel_version_less("6.12.0")) {
if (!try_init_lookup(m_kallsyms_lookup_name_6_4_0)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
} else {
if (!try_init_lookup(m_kallsyms_lookup_name_6_12_0)) {
std::cout << "Failed to analyze kernel kallsyms lookup name information" << std::endl;
return false;
}
}
return true;
}
uint64_t KernelSymbolParser::kallsyms_lookup_name(const char* name) {
if (!m_active_lookup || !m_active_lookup->is_inited()) return 0;
uint64_t symbol = m_active_lookup->kallsyms_lookup_name(name);
symbol = check_convert_b_insn(symbol);
return symbol;
}
uint64_t KernelSymbolParser::kallsyms_symbol_size(uint64_t cur_addr) {
if (!m_active_lookup || !m_active_lookup->is_inited()) return 0;
return m_active_lookup->kallsyms_symbol_size(cur_addr);
}
std::unordered_map<std::string, uint64_t> KernelSymbolParser::kallsyms_lookup_names_like(const char* name) {
if (!m_active_lookup || !m_active_lookup->is_inited()) return {};
static const std::vector<std::string> skip_suffixes = {
".cfi_jt",
};
std::unordered_map<std::string, uint64_t> all_symbols = m_active_lookup->kallsyms_on_each_symbol();
std::unordered_map<std::string, uint64_t> result;
for (const auto& [sym_name, addr] : all_symbols) {
if (sym_name.find(name) == std::string::npos) {
continue;
}
bool skip = std::any_of(
skip_suffixes.begin(), skip_suffixes.end(),
[&](const std::string& suf) {
return sym_name.size() >= suf.size()
&& sym_name.compare(
sym_name.size() - suf.size(),
suf.size(), suf) == 0;
});
if (skip) {
continue;
}
uint64_t new_addr = check_convert_b_insn(addr);
result[sym_name] = new_addr;
}
return result;
}
bool KernelSymbolParser::try_init_lookup(IKallsymsLookup& lookup) {
if (!lookup.init()) return false;
m_active_lookup = &lookup;
return true;
}
uint64_t KernelSymbolParser::check_convert_b_insn(uint64_t symbol_offset) {
if (symbol_offset > m_file_buf.size() - sizeof(uint32_t)) {
return symbol_offset;
}
uint32_t cmd = *(uint32_t*)&m_file_buf[symbol_offset];
if (!symbol_offset || !aarch64_insn_is_b(cmd)) {
return symbol_offset;
}
int32_t jump_offset = bbl_displacement(cmd);
return symbol_offset + jump_offset;
}