Fri, 25 Jan 2013 16:50:33 -0800
6518907: cleanup IA64 specific code in Hotspot
Summary: removed unused IA64 specific code
Reviewed-by: twisti, kvn, dholmes
1 /*
2 * Copyright (c) 2003, 2010, 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 */
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"
34 // ----------------------------------------------------
35 // functions for symbol lookups
36 // ----------------------------------------------------
38 struct elf_section {
39 ELF_SHDR *c_shdr;
40 void *c_data;
41 };
43 struct elf_symbol {
44 char *name;
45 uintptr_t offset;
46 uintptr_t size;
47 };
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;
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";
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;
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 }
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];
139 int fd = pathmap_open(pathname);
141 if (fd < 0)
142 return -1;
144 lseek(fd, 0, SEEK_SET);
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 }
153 if (crc == file_crc)
154 return fd;
155 else {
156 close(fd);
157 return -1;
158 }
159 }
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;
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 }
179 strtab = scn_cache[ehdr->e_shstrndx].c_data;
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 }
190 return NULL;
191 }
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;
220 /* Look in the same directory as the object. */
221 strcpy(last_slash+1, debug_filename);
223 debug_fd = open_debug_file(debug_pathname, crc);
224 if (debug_fd >= 0) {
225 free(debug_pathname);
226 return debug_fd;
227 }
229 /* Look in a subdirectory named ".debug". */
230 strcpy(last_slash+1, ".debug/");
231 strcat(last_slash, debug_filename);
233 debug_fd = open_debug_file(debug_pathname, crc);
234 if (debug_fd >= 0) {
235 free(debug_pathname);
236 return debug_fd;
237 }
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);
245 debug_fd = open_debug_file(debug_pathname, crc);
246 if (debug_fd >= 0) {
247 free(debug_pathname);
248 return debug_fd;
249 }
251 free(debug_pathname);
252 return -1;
253 }
255 static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo);
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);
267 if (fd >= 0) {
268 struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
269 close(fd);
270 return symtab;
271 }
273 return NULL;
274 }
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;
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");
296 return filename;
297 }
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;
306 unsigned char *bytes
307 = (unsigned char*)(note+1) + note->n_namesz;
308 unsigned char *filename
309 = (build_id_to_debug_filename (note->n_descsz, bytes));
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);
318 return symtab;
319 }
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;
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;
337 uintptr_t baseaddr = (uintptr_t)-1;
339 lseek(fd, (off_t)0L, SEEK_SET);
340 if (! read_elf_header(fd, &ehdr)) {
341 // not an elf
342 return NULL;
343 }
345 // read ELF header
346 if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
347 goto quit;
348 }
350 baseaddr = find_base_address(fd, &ehdr);
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 }
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 }
373 for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
374 ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
376 if (shdr->sh_type == sym_section) {
377 ELF_SYM *syms;
378 int j, n, rslt;
379 size_t size;
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.
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;
393 // number of symbols
394 n = shdr->sh_size / shdr->sh_entsize;
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");
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);
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));
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;
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;
426 symtab->symbols[j].name = sym_name;
427 symtab->symbols[j].offset = syms->st_value - baseaddr;
428 symtab->symbols[j].size = syms->st_size;
430 item.key = sym_name;
431 item.data = (void *)&(symtab->symbols[j]);
433 hsearch_r(item, ENTER, &ret, symtab->hash_table);
434 }
435 }
436 }
438 // Look for a separate debuginfo file.
439 if (try_debuginfo) {
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;
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
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 }
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 }
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 }
491 struct symtab* build_symtab(int fd, const char *filename) {
492 return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
493 }
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 }
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;
512 // library does not have symbol table
513 if (!symtab || !symtab->hash_table)
514 return (uintptr_t)NULL;
516 item.key = (char*) strdup(sym_name);
517 hsearch_r(item, FIND, &ret, symtab->hash_table);
518 if (ret) {
519 struct elf_symbol * sym = (struct elf_symbol *)(ret->data);
520 uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
521 if (sym_size) *sym_size = sym->size;
522 free(item.key);
523 return rslt;
524 }
526 quit:
527 free(item.key);
528 return (uintptr_t) NULL;
529 }
531 const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
532 uintptr_t* poffset) {
533 int n = 0;
534 if (!symtab) return NULL;
535 for (; n < symtab->num_symbols; n++) {
536 struct elf_symbol* sym = &(symtab->symbols[n]);
537 if (sym->name != NULL &&
538 offset >= sym->offset && offset < sym->offset + sym->size) {
539 if (poffset) *poffset = (offset - sym->offset);
540 return sym->name;
541 }
542 }
543 return NULL;
544 }