comparison agent/src/os/linux/symtab.c @ 1294:7de45b5044c3

6932270: Allow Java's ELF symtab reader to use separate debuginfo files Reviewed-by: never Contributed-by: Andrew Haley <aph@redhat.com>
author never
date Tue, 09 Mar 2010 11:02:39 -0800
parents a61af66fc99e
children c18cbe5936b8
comparison
equal deleted inserted replaced
1293:51db1e4b379d 1294:7de45b5044c3
51 size_t num_symbols; 51 size_t num_symbols;
52 struct elf_symbol *symbols; 52 struct elf_symbol *symbols;
53 struct hsearch_data *hash_table; 53 struct hsearch_data *hash_table;
54 } symtab_t; 54 } symtab_t;
55 55
56 // read symbol table from given fd. 56
57 struct symtab* build_symtab(int fd) { 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 unsigned 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) {
58 ELF_EHDR ehdr; 324 ELF_EHDR ehdr;
59 char *names = NULL; 325 char *names = NULL;
60 struct symtab* symtab = NULL; 326 struct symtab* symtab = NULL;
61 327
62 // Reading of elf header 328 // Reading of elf header
64 int cnt = 0; 330 int cnt = 0;
65 ELF_SHDR* shbuf = NULL; 331 ELF_SHDR* shbuf = NULL;
66 ELF_SHDR* cursct = NULL; 332 ELF_SHDR* cursct = NULL;
67 ELF_PHDR* phbuf = NULL; 333 ELF_PHDR* phbuf = NULL;
68 ELF_PHDR* phdr = NULL; 334 ELF_PHDR* phdr = NULL;
335 int sym_section = SHT_DYNSYM;
69 336
70 uintptr_t baseaddr = (uintptr_t)-1; 337 uintptr_t baseaddr = (uintptr_t)-1;
71 338
72 lseek(fd, (off_t)0L, SEEK_SET); 339 lseek(fd, (off_t)0L, SEEK_SET);
73 if (! read_elf_header(fd, &ehdr)) { 340 if (! read_elf_header(fd, &ehdr)) {
88 goto quit; 355 goto quit;
89 } 356 }
90 357
91 for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { 358 for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
92 scn_cache[cnt].c_shdr = cursct; 359 scn_cache[cnt].c_shdr = cursct;
93 if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB) { 360 if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB
361 || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) {
94 if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { 362 if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
95 goto quit; 363 goto quit;
96 } 364 }
97 } 365 }
366 if (cursct->sh_type == SHT_SYMTAB) {
367 // Full symbol table available so use that
368 sym_section = cursct->sh_type;
369 }
98 cursct++; 370 cursct++;
99 } 371 }
100 372
101 for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { 373 for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
102 ELF_SHDR *shdr = scn_cache[cnt].c_shdr; 374 ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
103 375
104 if (shdr->sh_type == SHT_SYMTAB) { 376 if (shdr->sh_type == sym_section) {
105 ELF_SYM *syms; 377 ELF_SYM *syms;
106 int j, n, rslt; 378 int j, n, rslt;
107 size_t size; 379 size_t size;
108 380
109 // FIXME: there could be multiple data buffers associated with the 381 // FIXME: there could be multiple data buffers associated with the
158 item.key = sym_name; 430 item.key = sym_name;
159 item.data = (void *)&(symtab->symbols[j]); 431 item.data = (void *)&(symtab->symbols[j]);
160 432
161 hsearch_r(item, ENTER, &ret, symtab->hash_table); 433 hsearch_r(item, ENTER, &ret, symtab->hash_table);
162 } 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;
163 } 474 }
164 } 475 }
165 476
166 quit: 477 quit:
167 if (shbuf) free(shbuf); 478 if (shbuf) free(shbuf);
174 } 485 }
175 free(scn_cache); 486 free(scn_cache);
176 } 487 }
177 return symtab; 488 return symtab;
178 } 489 }
490
491 struct symtab* build_symtab(int fd, const char *filename) {
492 return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
493 }
494
179 495
180 void destroy_symtab(struct symtab* symtab) { 496 void destroy_symtab(struct symtab* symtab) {
181 if (!symtab) return; 497 if (!symtab) return;
182 if (symtab->strs) free(symtab->strs); 498 if (symtab->strs) free(symtab->strs);
183 if (symtab->symbols) free(symtab->symbols); 499 if (symtab->symbols) free(symtab->symbols);