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