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
146
147
148
|
#ifndef __PERF_SYMBOL_H__
#define __PERF_SYMBOL_H__
#include <map>
#include <set>
#include <string>
#define INVALID_ADDR ((size_t)(-1))
enum {
NATIVE_TYPE = 0,
JIT_TYPE = 1,
UNKNOWN = 2,
};
struct elf_file {
unsigned char elf_read_error;
size_t eh_frame_hdr_offset;
size_t fde_count;
size_t table_data;
std::string filename;
int type;
elf_file(const std::string &name) : filename(name), type(NATIVE_TYPE) {
elf_read_error = 0;
eh_frame_hdr_offset = 0;
fde_count = 0;
table_data = 0;
}
elf_file() : type(NATIVE_TYPE) {}
void reset(const std::string &name) {
filename = name;
elf_read_error = 0;
eh_frame_hdr_offset = 0;
fde_count = 0;
table_data = 0;
}
bool operator<(const elf_file &rhs) const { return filename < rhs.filename; }
};
struct vma {
size_t start;
size_t end;
size_t offset;
size_t pc;
int type;
std::string name;
struct {
unsigned char elf_read_error;
size_t eh_frame_hdr_offset;
size_t fde_count;
size_t table_data;
};
size_t map(size_t pc) {
// printf("pc: %lx, start: %lx, offset: %lx\n", pc, start, offset);
return pc - start + offset;
}
void set_type(int t) { type = t; }
vma(size_t s, size_t e, size_t o, const std::string &n)
: start(s), end(e), offset(o), pc(0), type(NATIVE_TYPE), name(n) {}
vma() : start(0), end(0), offset(0), pc(0), type(NATIVE_TYPE) {}
vma(size_t addr) : start(0), end(0), offset(0), pc(addr), type(NATIVE_TYPE) {}
bool operator<(const vma &vm) { return vm.start < vm.pc; }
vma &operator=(const vma &vm) {
if (this == &vm) {
return *this;
}
start = vm.start;
end = vm.end;
offset = vm.offset;
name = vm.name;
return *this;
}
};
struct symbol {
size_t start;
size_t end;
size_t ip;
size_t base;
std::string name;
symbol() : start(0), end(0), ip(0), base(0) {}
symbol(size_t pc) : start(0), end(0), ip(pc) {}
void reset(size_t va) {
start = end = 0;
ip = va;
}
bool operator<(const symbol &sym) const { return sym.ip < start; }
bool operator>(const symbol &sym) const { return sym.ip > end; }
};
class symbol_parser {
private:
typedef std::map<size_t, vma> proc_vma;
std::map<elf_file, std::set<symbol>> file_symbols;
std::map<int, std::set<symbol>> java_symbols;
std::set<symbol> kernel_symbols;
std::map<int, proc_vma> machine_vma;
std::set<int> java_procs;
std::map<int, std::map<unsigned long, std::string>> symbols_cache;
public:
bool load_kernel();
std::set<int> &get_java_procs() { return java_procs; }
bool find_kernel_symbol(symbol &sym);
bool find_elf_symbol(symbol &sym, const elf_file &file, int pid, int pid_ns);
bool find_java_symbol(symbol &sym, int pid, int pid_ns);
bool get_symbol_info(int pid, symbol &sym, elf_file &file);
bool find_vma(pid_t pid, vma &vm);
vma *find_vma(pid_t pid, size_t pc);
void clear_symbol_info(int);
bool add_pid_maps(int pid, size_t start, size_t end, size_t offset,
const char *name);
bool find_symbol_in_cache(int tgid, unsigned long addr, std::string &symbol);
bool putin_symbol_cache(int tgid, unsigned long addr, std::string &symbol);
void dump(void);
private:
bool load_pid_maps(int pid);
bool load_elf(pid_t pid, const elf_file &file, size_t file_base_addr);
bool load_perf_map(int pid, int pid_ns);
public:
int java_only;
int user_symbol;
};
extern symbol_parser g_symbol_parser;
#endif
|