Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/agent/src/os/bsd/symtab.c
38833 views
1
/*
2
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include <unistd.h>
26
#include <search.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <db.h>
30
#include <fcntl.h>
31
32
#include "libproc_impl.h"
33
#include "symtab.h"
34
#ifndef __APPLE__
35
#include "salibelf.h"
36
#endif // __APPLE__
37
38
39
// ----------------------------------------------------
40
// functions for symbol lookups
41
// ----------------------------------------------------
42
43
typedef struct symtab_symbol {
44
char *name; // name like __ZThread_...
45
uintptr_t offset; // to loaded address
46
uintptr_t size; // size strlen
47
} symtab_symbol;
48
49
typedef struct symtab {
50
char *strs; // all symbols "__symbol1__'\0'__symbol2__...."
51
size_t num_symbols;
52
DB* hash_table;
53
symtab_symbol* symbols;
54
} symtab_t;
55
56
#ifdef __APPLE__
57
58
void build_search_table(symtab_t *symtab) {
59
int i;
60
for (i = 0; i < symtab->num_symbols; i++) {
61
DBT key, value;
62
key.data = symtab->symbols[i].name;
63
key.size = strlen(key.data) + 1;
64
value.data = &(symtab->symbols[i]);
65
value.size = sizeof(symtab_symbol);
66
(*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
67
68
// check result
69
if (is_debug()) {
70
DBT rkey, rvalue;
71
char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1);
72
strcpy(tmp, symtab->symbols[i].name);
73
rkey.data = tmp;
74
rkey.size = strlen(tmp) + 1;
75
(*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0);
76
// we may get a copy back so compare contents
77
symtab_symbol *res = (symtab_symbol *)rvalue.data;
78
if (strcmp(res->name, symtab->symbols[i].name) ||
79
res->offset != symtab->symbols[i].offset ||
80
res->size != symtab->symbols[i].size) {
81
print_debug("error to get hash_table value!\n");
82
}
83
free(tmp);
84
}
85
}
86
}
87
88
// read symbol table from given fd.
89
struct symtab* build_symtab(int fd) {
90
symtab_t* symtab = NULL;
91
int i;
92
mach_header_64 header;
93
off_t image_start;
94
95
if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
96
print_debug("failed in get fat header\n");
97
return NULL;
98
}
99
lseek(fd, image_start, SEEK_SET);
100
if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
101
print_debug("reading header failed!\n");
102
return NULL;
103
}
104
// header
105
if (header.magic != MH_MAGIC_64) {
106
print_debug("not a valid .dylib file\n");
107
return NULL;
108
}
109
110
load_command lcmd;
111
symtab_command symtabcmd;
112
nlist_64 lentry;
113
114
bool lcsymtab_exist = false;
115
116
long filepos = ltell(fd);
117
for (i = 0; i < header.ncmds; i++) {
118
lseek(fd, filepos, SEEK_SET);
119
if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
120
print_debug("read load_command failed for file\n");
121
return NULL;
122
}
123
filepos += lcmd.cmdsize; // next command position
124
if (lcmd.cmd == LC_SYMTAB) {
125
lseek(fd, -sizeof(load_command), SEEK_CUR);
126
lcsymtab_exist = true;
127
break;
128
}
129
}
130
if (!lcsymtab_exist) {
131
print_debug("No symtab command found!\n");
132
return NULL;
133
}
134
if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) {
135
print_debug("read symtab_command failed for file");
136
return NULL;
137
}
138
symtab = (symtab_t *)malloc(sizeof(symtab_t));
139
if (symtab == NULL) {
140
print_debug("out of memory: allocating symtab\n");
141
return NULL;
142
}
143
144
// create hash table, we use berkeley db to
145
// manipulate the hash table.
146
symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
147
if (symtab->hash_table == NULL)
148
goto quit;
149
150
symtab->num_symbols = symtabcmd.nsyms;
151
symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols);
152
symtab->strs = (char *)malloc(sizeof(char) * symtabcmd.strsize);
153
if (symtab->symbols == NULL || symtab->strs == NULL) {
154
print_debug("out of memory: allocating symtab.symbol or symtab.strs\n");
155
goto quit;
156
}
157
lseek(fd, image_start + symtabcmd.symoff, SEEK_SET);
158
for (i = 0; i < symtab->num_symbols; i++) {
159
if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) {
160
print_debug("read nlist_64 failed at %i\n", i);
161
goto quit;
162
}
163
symtab->symbols[i].offset = lentry.n_value;
164
symtab->symbols[i].size = lentry.n_un.n_strx; // index
165
}
166
167
// string table
168
lseek(fd, image_start + symtabcmd.stroff, SEEK_SET);
169
int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char));
170
if (size != symtabcmd.strsize * sizeof(char)) {
171
print_debug("reading string table failed\n");
172
goto quit;
173
}
174
175
for (i = 0; i < symtab->num_symbols; i++) {
176
symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size;
177
if (i > 0) {
178
// fix size
179
symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size;
180
print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size);
181
182
}
183
184
if (i == symtab->num_symbols - 1) {
185
// last index
186
symtab->symbols[i].size =
187
symtabcmd.strsize - symtab->symbols[i].size;
188
print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size);
189
}
190
}
191
192
// build a hashtable for fast query
193
build_search_table(symtab);
194
return symtab;
195
quit:
196
if (symtab) destroy_symtab(symtab);
197
return NULL;
198
}
199
200
#else // __APPLE__
201
202
struct elf_section {
203
ELF_SHDR *c_shdr;
204
void *c_data;
205
};
206
207
// read symbol table from given fd.
208
struct symtab* build_symtab(int fd) {
209
ELF_EHDR ehdr;
210
struct symtab* symtab = NULL;
211
212
// Reading of elf header
213
struct elf_section *scn_cache = NULL;
214
int cnt = 0;
215
ELF_SHDR* shbuf = NULL;
216
ELF_SHDR* cursct = NULL;
217
ELF_PHDR* phbuf = NULL;
218
int symtab_found = 0;
219
int dynsym_found = 0;
220
uint32_t symsection = SHT_SYMTAB;
221
222
uintptr_t baseaddr = (uintptr_t)-1;
223
224
lseek(fd, (off_t)0L, SEEK_SET);
225
if (! read_elf_header(fd, &ehdr)) {
226
// not an elf
227
return NULL;
228
}
229
230
// read ELF header
231
if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
232
goto quit;
233
}
234
235
baseaddr = find_base_address(fd, &ehdr);
236
237
scn_cache = calloc(ehdr.e_shnum, sizeof(*scn_cache));
238
if (scn_cache == NULL) {
239
goto quit;
240
}
241
242
for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
243
scn_cache[cnt].c_shdr = cursct;
244
if (cursct->sh_type == SHT_SYMTAB ||
245
cursct->sh_type == SHT_STRTAB ||
246
cursct->sh_type == SHT_DYNSYM) {
247
if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
248
goto quit;
249
}
250
}
251
252
if (cursct->sh_type == SHT_SYMTAB)
253
symtab_found++;
254
255
if (cursct->sh_type == SHT_DYNSYM)
256
dynsym_found++;
257
258
cursct++;
259
}
260
261
if (!symtab_found && dynsym_found)
262
symsection = SHT_DYNSYM;
263
264
for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
265
ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
266
267
if (shdr->sh_type == symsection) {
268
ELF_SYM *syms;
269
int j, n;
270
size_t size;
271
272
// FIXME: there could be multiple data buffers associated with the
273
// same ELF section. Here we can handle only one buffer. See man page
274
// for elf_getdata on Solaris.
275
276
// guarantee(symtab == NULL, "multiple symtab");
277
symtab = calloc(1, sizeof(*symtab));
278
if (symtab == NULL) {
279
goto quit;
280
}
281
// the symbol table
282
syms = (ELF_SYM *)scn_cache[cnt].c_data;
283
284
// number of symbols
285
n = shdr->sh_size / shdr->sh_entsize;
286
287
// create hash table, we use berkeley db to
288
// manipulate the hash table.
289
symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
290
// guarantee(symtab->hash_table, "unexpected failure: dbopen");
291
if (symtab->hash_table == NULL)
292
goto bad;
293
294
// shdr->sh_link points to the section that contains the actual strings
295
// for symbol names. the st_name field in ELF_SYM is just the
296
// string table index. we make a copy of the string table so the
297
// strings will not be destroyed by elf_end.
298
size = scn_cache[shdr->sh_link].c_shdr->sh_size;
299
symtab->strs = malloc(size);
300
if (symtab->strs == NULL)
301
goto bad;
302
memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
303
304
// allocate memory for storing symbol offset and size;
305
symtab->num_symbols = n;
306
symtab->symbols = calloc(n , sizeof(*symtab->symbols));
307
if (symtab->symbols == NULL)
308
goto bad;
309
310
// copy symbols info our symtab and enter them info the hash table
311
for (j = 0; j < n; j++, syms++) {
312
DBT key, value;
313
char *sym_name = symtab->strs + syms->st_name;
314
315
// skip non-object and non-function symbols
316
int st_type = ELF_ST_TYPE(syms->st_info);
317
if ( st_type != STT_FUNC && st_type != STT_OBJECT)
318
continue;
319
// skip empty strings and undefined symbols
320
if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
321
322
symtab->symbols[j].name = sym_name;
323
symtab->symbols[j].offset = syms->st_value - baseaddr;
324
symtab->symbols[j].size = syms->st_size;
325
326
key.data = sym_name;
327
key.size = strlen(sym_name) + 1;
328
value.data = &(symtab->symbols[j]);
329
value.size = sizeof(symtab_symbol);
330
(*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
331
}
332
}
333
}
334
goto quit;
335
336
bad:
337
destroy_symtab(symtab);
338
symtab = NULL;
339
340
quit:
341
if (shbuf) free(shbuf);
342
if (phbuf) free(phbuf);
343
if (scn_cache) {
344
for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
345
if (scn_cache[cnt].c_data != NULL) {
346
free(scn_cache[cnt].c_data);
347
}
348
}
349
free(scn_cache);
350
}
351
return symtab;
352
}
353
354
#endif // __APPLE__
355
356
void destroy_symtab(symtab_t* symtab) {
357
if (!symtab) return;
358
free(symtab->strs);
359
free(symtab->symbols);
360
free(symtab);
361
}
362
363
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) {
364
DBT key, value;
365
int ret;
366
367
// library does not have symbol table
368
if (!symtab || !symtab->hash_table) {
369
return 0;
370
}
371
372
key.data = (char*)(uintptr_t)sym_name;
373
key.size = strlen(sym_name) + 1;
374
ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
375
if (ret == 0) {
376
symtab_symbol *sym = value.data;
377
uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
378
if (sym_size) *sym_size = sym->size;
379
return rslt;
380
}
381
382
return 0;
383
}
384
385
const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
386
uintptr_t* poffset) {
387
int n = 0;
388
if (!symtab) return NULL;
389
for (; n < symtab->num_symbols; n++) {
390
symtab_symbol* sym = &(symtab->symbols[n]);
391
if (sym->name != NULL &&
392
offset >= sym->offset && offset < sym->offset + sym->size) {
393
if (poffset) *poffset = (offset - sym->offset);
394
return sym->name;
395
}
396
}
397
return NULL;
398
}
399
400