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/linux/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
#ifndef __ANDROID__
26
#include <search.h>
27
#else
28
// The full search.h implementation is on Android API 28, so we backport it.
29
#include "hsearch/search.h"
30
#endif
31
32
#include <unistd.h>
33
#ifndef __ANDROID__
34
#include <sys/procfs.h>
35
#else
36
#include "glibc_procfs.h"
37
#endif
38
#include <stdlib.h>
39
#include <string.h>
40
#include "symtab.h"
41
#include "salibelf.h"
42
43
44
// ----------------------------------------------------
45
// functions for symbol lookups
46
// ----------------------------------------------------
47
48
struct elf_section {
49
ELF_SHDR *c_shdr;
50
void *c_data;
51
};
52
53
struct elf_symbol {
54
char *name;
55
uintptr_t offset;
56
uintptr_t size;
57
};
58
59
typedef struct symtab {
60
char *strs;
61
size_t num_symbols;
62
struct elf_symbol *symbols;
63
struct hsearch_data *hash_table;
64
} symtab_t;
65
66
67
// Directory that contains global debuginfo files. In theory it
68
// should be possible to change this, but in a Java environment there
69
// is no obvious place to put a user interface to do it. Maybe this
70
// could be set with an environment variable.
71
static const char debug_file_directory[] = "/usr/lib/debug";
72
73
/* The CRC used in gnu_debuglink, retrieved from
74
http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files. */
75
unsigned int gnu_debuglink_crc32 (unsigned int crc,
76
unsigned char *buf, size_t len)
77
{
78
static const unsigned int crc32_table[256] =
79
{
80
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
81
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
82
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
83
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
84
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
85
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
86
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
87
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
88
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
89
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
90
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
91
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
92
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
93
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
94
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
95
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
96
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
97
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
98
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
99
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
100
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
101
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
102
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
103
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
104
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
105
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
106
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
107
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
108
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
109
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
110
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
111
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
112
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
113
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
114
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
115
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
116
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
117
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
118
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
119
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
120
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
121
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
122
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
123
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
124
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
125
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
126
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
127
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
128
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
129
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
130
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
131
0x2d02ef8d
132
};
133
unsigned char *end;
134
135
crc = ~crc & 0xffffffff;
136
for (end = buf + len; buf < end; ++buf)
137
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
138
return ~crc & 0xffffffff;
139
}
140
141
/* Open a debuginfo file and check its CRC. If it exists and the CRC
142
matches return its fd. */
143
static int
144
open_debug_file (const char *pathname, unsigned int crc)
145
{
146
unsigned int file_crc = 0;
147
unsigned char buffer[8 * 1024];
148
149
int fd = pathmap_open(pathname);
150
151
if (fd < 0)
152
return -1;
153
154
lseek(fd, 0, SEEK_SET);
155
156
for (;;) {
157
int len = read(fd, buffer, sizeof buffer);
158
if (len <= 0)
159
break;
160
file_crc = gnu_debuglink_crc32(file_crc, buffer, len);
161
}
162
163
if (crc == file_crc)
164
return fd;
165
else {
166
close(fd);
167
return -1;
168
}
169
}
170
171
/* Find an ELF section. */
172
static struct elf_section *find_section_by_name(char *name,
173
int fd,
174
ELF_EHDR *ehdr,
175
ELF_SHDR *shbuf,
176
struct elf_section *scn_cache)
177
{
178
ELF_SHDR* cursct = NULL;
179
char *strtab;
180
int cnt;
181
182
if (scn_cache[ehdr->e_shstrndx].c_data == NULL) {
183
if ((scn_cache[ehdr->e_shstrndx].c_data
184
= read_section_data(fd, ehdr, cursct)) == NULL) {
185
return NULL;
186
}
187
}
188
189
strtab = scn_cache[ehdr->e_shstrndx].c_data;
190
191
for (cursct = shbuf, cnt = 0;
192
cnt < ehdr->e_shnum;
193
cnt++, cursct++) {
194
if (strcmp(cursct->sh_name + strtab, name) == 0) {
195
scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct);
196
return &scn_cache[cnt];
197
}
198
}
199
200
return NULL;
201
}
202
203
/* Look for a ".gnu_debuglink" section. If one exists, try to open a
204
suitable debuginfo file. */
205
static int open_file_from_debug_link(const char *name,
206
int fd,
207
ELF_EHDR *ehdr,
208
ELF_SHDR *shbuf,
209
struct elf_section *scn_cache)
210
{
211
int debug_fd;
212
struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr,
213
shbuf, scn_cache);
214
if (debug_link == NULL)
215
return -1;
216
char *debug_filename = debug_link->c_data;
217
int offset = (strlen(debug_filename) + 4) >> 2;
218
static unsigned int crc;
219
crc = ((unsigned int*)debug_link->c_data)[offset];
220
char *debug_pathname = malloc(strlen(debug_filename)
221
+ strlen(name)
222
+ strlen(".debug/")
223
+ strlen(debug_file_directory)
224
+ 2);
225
strcpy(debug_pathname, name);
226
char *last_slash = strrchr(debug_pathname, '/');
227
if (last_slash == NULL)
228
return -1;
229
230
/* Look in the same directory as the object. */
231
strcpy(last_slash+1, debug_filename);
232
233
debug_fd = open_debug_file(debug_pathname, crc);
234
if (debug_fd >= 0) {
235
free(debug_pathname);
236
return debug_fd;
237
}
238
239
/* Look in a subdirectory named ".debug". */
240
strcpy(last_slash+1, ".debug/");
241
strcat(last_slash, debug_filename);
242
243
debug_fd = open_debug_file(debug_pathname, crc);
244
if (debug_fd >= 0) {
245
free(debug_pathname);
246
return debug_fd;
247
}
248
249
/* Look in /usr/lib/debug + the full pathname. */
250
strcpy(debug_pathname, debug_file_directory);
251
strcat(debug_pathname, name);
252
last_slash = strrchr(debug_pathname, '/');
253
strcpy(last_slash+1, debug_filename);
254
255
debug_fd = open_debug_file(debug_pathname, crc);
256
if (debug_fd >= 0) {
257
free(debug_pathname);
258
return debug_fd;
259
}
260
261
free(debug_pathname);
262
return -1;
263
}
264
265
static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo);
266
267
/* Look for a ".gnu_debuglink" section. If one exists, try to open a
268
suitable debuginfo file and read a symbol table from it. */
269
static struct symtab *build_symtab_from_debug_link(const char *name,
270
int fd,
271
ELF_EHDR *ehdr,
272
ELF_SHDR *shbuf,
273
struct elf_section *scn_cache)
274
{
275
fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache);
276
277
if (fd >= 0) {
278
struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
279
close(fd);
280
return symtab;
281
}
282
283
return NULL;
284
}
285
286
// Given a build_id, find the associated debuginfo file
287
static char *
288
build_id_to_debug_filename (size_t size, unsigned char *data)
289
{
290
char *filename, *s;
291
292
filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
293
+ 2 * size + (sizeof ".debug" - 1) + 1);
294
s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory);
295
if (size > 0)
296
{
297
size--;
298
s += sprintf (s, "%02x", *data++);
299
}
300
if (size > 0)
301
*s++ = '/';
302
while (size-- > 0)
303
s += sprintf (s, "%02x", *data++);
304
strcpy (s, ".debug");
305
306
return filename;
307
}
308
309
// Read a build ID note. Try to open any associated debuginfo file
310
// and return its symtab
311
static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note)
312
{
313
int fd;
314
struct symtab *symtab = NULL;
315
316
unsigned char *bytes
317
= (unsigned char*)(note+1) + note->n_namesz;
318
char *filename
319
= (build_id_to_debug_filename (note->n_descsz, bytes));
320
321
fd = pathmap_open(filename);
322
if (fd >= 0) {
323
symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
324
close(fd);
325
}
326
free(filename);
327
328
return symtab;
329
}
330
331
// read symbol table from given fd. If try_debuginfo) is true, also
332
// try to open an associated debuginfo file
333
static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) {
334
ELF_EHDR ehdr;
335
char *names = NULL;
336
struct symtab* symtab = NULL;
337
338
// Reading of elf header
339
struct elf_section *scn_cache = NULL;
340
int cnt = 0;
341
ELF_SHDR* shbuf = NULL;
342
ELF_SHDR* cursct = NULL;
343
ELF_PHDR* phbuf = NULL;
344
ELF_PHDR* phdr = NULL;
345
int sym_section = SHT_DYNSYM;
346
347
uintptr_t baseaddr = (uintptr_t)-1;
348
349
lseek(fd, (off_t)0L, SEEK_SET);
350
if (! read_elf_header(fd, &ehdr)) {
351
// not an elf
352
return NULL;
353
}
354
355
// read ELF header
356
if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
357
goto quit;
358
}
359
360
baseaddr = find_base_address(fd, &ehdr);
361
362
scn_cache = (struct elf_section *)
363
calloc(ehdr.e_shnum * sizeof(struct elf_section), 1);
364
if (scn_cache == NULL) {
365
goto quit;
366
}
367
368
for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
369
scn_cache[cnt].c_shdr = cursct;
370
if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB
371
|| cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) {
372
if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
373
goto quit;
374
}
375
}
376
if (cursct->sh_type == SHT_SYMTAB) {
377
// Full symbol table available so use that
378
sym_section = cursct->sh_type;
379
}
380
cursct++;
381
}
382
383
for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
384
ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
385
386
if (shdr->sh_type == sym_section) {
387
ELF_SYM *syms;
388
int j, n, rslt;
389
size_t size;
390
391
// FIXME: there could be multiple data buffers associated with the
392
// same ELF section. Here we can handle only one buffer. See man page
393
// for elf_getdata on Solaris.
394
395
// guarantee(symtab == NULL, "multiple symtab");
396
symtab = (struct symtab*)calloc(1, sizeof(struct symtab));
397
if (symtab == NULL) {
398
goto quit;
399
}
400
// the symbol table
401
syms = (ELF_SYM *)scn_cache[cnt].c_data;
402
403
// number of symbols
404
n = shdr->sh_size / shdr->sh_entsize;
405
406
// create hash table, we use hcreate_r, hsearch_r and hdestroy_r to
407
// manipulate the hash table.
408
#ifndef __ANDROID__
409
symtab->hash_table = (struct hsearch_data*) calloc(1, sizeof(struct hsearch_data));
410
#else // __ANDROID__
411
symtab->hash_table = &(struct hsearch_data){0};
412
#endif // !__ANDROID__
413
rslt = hcreate_r(n, symtab->hash_table);
414
// guarantee(rslt, "unexpected failure: hcreate_r");
415
416
// shdr->sh_link points to the section that contains the actual strings
417
// for symbol names. the st_name field in ELF_SYM is just the
418
// string table index. we make a copy of the string table so the
419
// strings will not be destroyed by elf_end.
420
size = scn_cache[shdr->sh_link].c_shdr->sh_size;
421
symtab->strs = (char *)malloc(size);
422
memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
423
424
// allocate memory for storing symbol offset and size;
425
symtab->num_symbols = n;
426
symtab->symbols = (struct elf_symbol *)calloc(n , sizeof(struct elf_symbol));
427
428
// copy symbols info our symtab and enter them info the hash table
429
for (j = 0; j < n; j++, syms++) {
430
ENTRY item, *ret;
431
char *sym_name = symtab->strs + syms->st_name;
432
433
// skip non-object and non-function symbols
434
int st_type = ELF_ST_TYPE(syms->st_info);
435
if ( st_type != STT_FUNC && st_type != STT_OBJECT)
436
continue;
437
// skip empty strings and undefined symbols
438
if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
439
440
symtab->symbols[j].name = sym_name;
441
symtab->symbols[j].offset = syms->st_value - baseaddr;
442
symtab->symbols[j].size = syms->st_size;
443
444
item.key = sym_name;
445
item.data = (void *)&(symtab->symbols[j]);
446
447
hsearch_r(item, ENTER, &ret, symtab->hash_table);
448
}
449
}
450
}
451
452
// Look for a separate debuginfo file.
453
if (try_debuginfo) {
454
455
// We prefer a debug symtab to an object's own symtab, so look in
456
// the debuginfo file. We stash a copy of the old symtab in case
457
// there is no debuginfo.
458
struct symtab* prev_symtab = symtab;
459
symtab = NULL;
460
461
#ifdef NT_GNU_BUILD_ID
462
// First we look for a Build ID
463
for (cursct = shbuf, cnt = 0;
464
symtab == NULL && cnt < ehdr.e_shnum;
465
cnt++) {
466
if (cursct->sh_type == SHT_NOTE) {
467
Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data;
468
if (note->n_type == NT_GNU_BUILD_ID) {
469
symtab = build_symtab_from_build_id(note);
470
}
471
}
472
cursct++;
473
}
474
#endif
475
476
// Then, if that doesn't work, the debug link
477
if (symtab == NULL) {
478
symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf,
479
scn_cache);
480
}
481
482
// If we still haven't found a symtab, use the object's own symtab.
483
if (symtab != NULL) {
484
if (prev_symtab != NULL)
485
destroy_symtab(prev_symtab);
486
} else {
487
symtab = prev_symtab;
488
}
489
}
490
491
quit:
492
if (shbuf) free(shbuf);
493
if (phbuf) free(phbuf);
494
if (scn_cache) {
495
for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
496
if (scn_cache[cnt].c_data != NULL) {
497
free(scn_cache[cnt].c_data);
498
}
499
}
500
free(scn_cache);
501
}
502
return symtab;
503
}
504
505
struct symtab* build_symtab(int fd, const char *filename) {
506
return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
507
}
508
509
510
void destroy_symtab(struct symtab* symtab) {
511
if (!symtab) return;
512
if (symtab->strs) free(symtab->strs);
513
if (symtab->symbols) free(symtab->symbols);
514
if (symtab->hash_table) {
515
hdestroy_r(symtab->hash_table);
516
free(symtab->hash_table);
517
}
518
free(symtab);
519
}
520
521
uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
522
const char *sym_name, int *sym_size) {
523
ENTRY item;
524
ENTRY* ret = NULL;
525
526
// library does not have symbol table
527
if (!symtab || !symtab->hash_table)
528
return (uintptr_t)NULL;
529
530
item.key = (char*) strdup(sym_name);
531
item.data = NULL;
532
hsearch_r(item, FIND, &ret, symtab->hash_table);
533
if (ret) {
534
struct elf_symbol * sym = (struct elf_symbol *)(ret->data);
535
uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
536
if (sym_size) *sym_size = sym->size;
537
free(item.key);
538
return rslt;
539
}
540
541
quit:
542
free(item.key);
543
return (uintptr_t) NULL;
544
}
545
546
const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
547
uintptr_t* poffset) {
548
int n = 0;
549
if (!symtab) return NULL;
550
for (; n < symtab->num_symbols; n++) {
551
struct elf_symbol* sym = &(symtab->symbols[n]);
552
if (sym->name != NULL &&
553
offset >= sym->offset && offset < sym->offset + sym->size) {
554
if (poffset) *poffset = (offset - sym->offset);
555
return sym->name;
556
}
557
}
558
return NULL;
559
}
560
561
#ifdef __ANDROID__
562
# undef _GNU_SOURCE
563
#endif
564
565