blob: 25d0ce64ed901ca37bded8555f9640ab8e181f41 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001/*--------------------------------------------------------------------*/
2/*--- Management of symbols and debugging information. ---*/
3/*--- vg_symtab2.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, an x86 protected-mode emulator
8 designed for debugging and profiling binaries on x86-Unixes.
9
10 Copyright (C) 2000-2002 Julian Seward
11 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file LICENSE.
29*/
30
31#include "vg_include.h"
32#include "vg_unsafe.h"
33
34#include <elf.h> /* ELF defns */
35#include <a.out.h> /* stabs defns */
36
njn9aae6742002-04-30 13:44:01 +000037
sewardjde4a1d02002-03-22 01:27:54 +000038/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
39 dlopen()ed libraries, which is something that KDE3 does a lot.
40 Still kludgey, though less than before:
41
42 * we don't check whether we should throw away some symbol tables
43 when munmap() happens
44
45 * symbol table reading code for ELF binaries is a shambles.
46 Use GHC's fptools/ghc/rts/Linker.c as the basis for something better.
47*/
48
49/*------------------------------------------------------------*/
50/*--- Structs n stuff ---*/
51/*------------------------------------------------------------*/
52
njn4f9c9342002-04-29 16:03:24 +000053/* Stabs entry types, from:
54 * The "stabs" debug format
55 * Menapace, Kingdon and MacKenzie
56 * Cygnus Support
57 */
njn9885df02002-05-01 08:25:03 +000058typedef enum { N_GSYM = 32, /* Global symbol */
59 N_FUN = 36, /* Function start or end */
njn4f9c9342002-04-29 16:03:24 +000060 N_STSYM = 38, /* Data segment file-scope variable */
61 N_LCSYM = 40, /* BSS segment file-scope variable */
62 N_RSYM = 64, /* Register variable */
63 N_SLINE = 68, /* Source line number */
64 N_SO = 100, /* Source file path and name */
65 N_LSYM = 128, /* Stack variable or type */
66 N_SOL = 132, /* Include file name */
67 N_LBRAC = 192, /* Start of lexical block */
68 N_RBRAC = 224 /* End of lexical block */
69 } stab_types;
70
sewardjde4a1d02002-03-22 01:27:54 +000071/* A structure to hold an ELF symbol (very crudely). */
72typedef
73 struct {
74 Addr addr; /* lowest address of entity */
75 UInt size; /* size in bytes */
76 Int nmoff; /* offset of name in this SegInfo's str tab */
77 }
78 RiSym;
79
80
81/* A structure to hold addr-to-source info for a single line. */
82typedef
83 struct {
84 Addr addr; /* lowest address for this line */
85 Int fnmoff; /* source filename; offset in this SegInfo's str tab */
86 UShort lineno; /* source line number, or zero */
87 UShort size; /* size in bytes; we go to a bit of trouble to
88 catch overflows of this */
89 }
90 RiLoc;
91
92
93/* A structure which contains information pertaining to one mapped
94 text segment. */
95typedef
96 struct _SegInfo {
97 struct _SegInfo* next;
98 /* Description of the mapped segment. */
99 Addr start;
100 UInt size;
101 UChar* filename; /* in mallocville */
102 UInt foffset;
103 /* An expandable array of symbols. */
104 RiSym* symtab;
105 UInt symtab_used;
106 UInt symtab_size;
107 /* An expandable array of locations. */
108 RiLoc* loctab;
109 UInt loctab_used;
110 UInt loctab_size;
111 /* An expandable array of characters -- the string table. */
112 Char* strtab;
113 UInt strtab_used;
114 UInt strtab_size;
115 /* offset is what we need to add to symbol table entries
116 to get the real location of that symbol in memory.
117 For executables, offset is zero.
118 For .so's, offset == base_addr.
119 This seems like a giant kludge to me.
120 */
121 UInt offset;
122 }
123 SegInfo;
124
125
126/* -- debug helper -- */
127static void ppSegInfo ( SegInfo* si )
128{
129 VG_(printf)("name: %s\n"
130 "start %p, size %d, foffset %d\n",
131 si->filename?si->filename : (UChar*)"NULL",
132 si->start, si->size, si->foffset );
133}
134
135static void freeSegInfo ( SegInfo* si )
136{
137 vg_assert(si != NULL);
138 if (si->filename) VG_(free)(VG_AR_SYMTAB, si->filename);
139 if (si->symtab) VG_(free)(VG_AR_SYMTAB, si->symtab);
140 if (si->loctab) VG_(free)(VG_AR_SYMTAB, si->loctab);
141 if (si->strtab) VG_(free)(VG_AR_SYMTAB, si->strtab);
142 VG_(free)(VG_AR_SYMTAB, si);
143}
144
145
146/*------------------------------------------------------------*/
147/*--- Adding stuff ---*/
148/*------------------------------------------------------------*/
149
150/* Add a str to the string table, including terminating zero, and
151 return offset of the string in vg_strtab. */
152
153static __inline__
154Int addStr ( SegInfo* si, Char* str )
155{
156 Char* new_tab;
157 Int new_sz, i, space_needed;
158
159 space_needed = 1 + VG_(strlen)(str);
160 if (si->strtab_used + space_needed > si->strtab_size) {
161 new_sz = 2 * si->strtab_size;
162 if (new_sz == 0) new_sz = 5000;
163 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz);
164 if (si->strtab != NULL) {
165 for (i = 0; i < si->strtab_used; i++)
166 new_tab[i] = si->strtab[i];
167 VG_(free)(VG_AR_SYMTAB, si->strtab);
168 }
169 si->strtab = new_tab;
170 si->strtab_size = new_sz;
171 }
172
173 for (i = 0; i < space_needed; i++)
174 si->strtab[si->strtab_used+i] = str[i];
175
176 si->strtab_used += space_needed;
177 vg_assert(si->strtab_used <= si->strtab_size);
178 return si->strtab_used - space_needed;
179}
180
181/* Add a symbol to the symbol table. */
182
183static __inline__
184void addSym ( SegInfo* si, RiSym* sym )
185{
186 Int new_sz, i;
187 RiSym* new_tab;
188
189 /* Ignore zero-sized syms. */
190 if (sym->size == 0) return;
191
192 if (si->symtab_used == si->symtab_size) {
193 new_sz = 2 * si->symtab_size;
194 if (new_sz == 0) new_sz = 500;
195 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
196 if (si->symtab != NULL) {
197 for (i = 0; i < si->symtab_used; i++)
198 new_tab[i] = si->symtab[i];
199 VG_(free)(VG_AR_SYMTAB, si->symtab);
200 }
201 si->symtab = new_tab;
202 si->symtab_size = new_sz;
203 }
204
205 si->symtab[si->symtab_used] = *sym;
206 si->symtab_used++;
207 vg_assert(si->symtab_used <= si->symtab_size);
208}
209
210/* Add a location to the location table. */
211
212static __inline__
213void addLoc ( SegInfo* si, RiLoc* loc )
214{
215 Int new_sz, i;
216 RiLoc* new_tab;
217
218 /* Ignore zero-sized locs. */
219 if (loc->size == 0) return;
220
221 if (si->loctab_used == si->loctab_size) {
222 new_sz = 2 * si->loctab_size;
223 if (new_sz == 0) new_sz = 500;
224 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
225 if (si->loctab != NULL) {
226 for (i = 0; i < si->loctab_used; i++)
227 new_tab[i] = si->loctab[i];
228 VG_(free)(VG_AR_SYMTAB, si->loctab);
229 }
230 si->loctab = new_tab;
231 si->loctab_size = new_sz;
232 }
233
234 si->loctab[si->loctab_used] = *loc;
235 si->loctab_used++;
236 vg_assert(si->loctab_used <= si->loctab_size);
237}
238
239
240
241/*------------------------------------------------------------*/
242/*--- Helpers ---*/
243/*------------------------------------------------------------*/
244
245/* Non-fatal -- use vg_panic if terminal. */
246static
247void vg_symerr ( Char* msg )
248{
249 if (VG_(clo_verbosity) > 1)
250 VG_(message)(Vg_UserMsg,"%s", msg );
251}
252
253
254/* Print a symbol. */
255static
256void printSym ( SegInfo* si, Int i )
257{
258 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
259 i,
260 si->symtab[i].addr,
261 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
262 &si->strtab[si->symtab[i].nmoff] );
263}
264
265
266#if 0
267/* Print the entire sym tab. */
268static __attribute__ ((unused))
269void printSymtab ( void )
270{
271 Int i;
272 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
273 for (i = 0; i < vg_symtab_used; i++)
274 printSym(i);
275 VG_(printf)("------ BEGIN vg_symtab ------\n");
276}
277#endif
278
279#if 0
280/* Paranoid strcat. */
281static
282void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
283{
284 UInt i = 0, j = 0;
285 while (True) {
286 if (i >= maxlen) return;
287 if (dst[i] == 0) break;
288 i++;
289 }
290 while (True) {
291 if (i >= maxlen) return;
292 dst[i] = src[j];
293 if (src[j] == 0) return;
294 i++; j++;
295 }
296}
297#endif
298
299/*------------------------------------------------------------*/
300/*--- Canonicalisers ---*/
301/*------------------------------------------------------------*/
302
303/* Sort the symtab by starting address, and emit warnings if any
304 symbols have overlapping address ranges. We use that old chestnut,
305 shellsort. Mash the table around so as to establish the property
306 that addresses are in order and the ranges to not overlap. This
307 facilitates using binary search to map addresses to symbols when we
308 come to query the table.
309*/
310static
311void canonicaliseSymtab ( SegInfo* si )
312{
313 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
314 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
315 4592, 13776, 33936, 86961, 198768,
316 463792, 1391376 };
317 Int lo = 0;
318 Int hi = si->symtab_used-1;
319 Int i, j, h, bigN, hp, n_merged, n_truncated;
320 RiSym v;
321 Addr s1, s2, e1, e2;
322
323# define SWAP(ty,aa,bb) \
324 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
325
326 bigN = hi - lo + 1; if (bigN < 2) return;
327 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
328 vg_assert(0 <= hp && hp < 16);
329
330 for (; hp >= 0; hp--) {
331 h = incs[hp];
332 i = lo + h;
333 while (1) {
334 if (i > hi) break;
335 v = si->symtab[i];
336 j = i;
337 while (si->symtab[j-h].addr > v.addr) {
338 si->symtab[j] = si->symtab[j-h];
339 j = j - h;
340 if (j <= (lo + h - 1)) break;
341 }
342 si->symtab[j] = v;
343 i++;
344 }
345 }
346
347 cleanup_more:
348
349 /* If two symbols have identical address ranges, favour the
350 one with the longer name.
351 */
352 do {
353 n_merged = 0;
354 j = si->symtab_used;
355 si->symtab_used = 0;
356 for (i = 0; i < j; i++) {
357 if (i < j-1
358 && si->symtab[i].addr == si->symtab[i+1].addr
359 && si->symtab[i].size == si->symtab[i+1].size) {
360 n_merged++;
361 /* merge the two into one */
362 if (VG_(strlen)(&si->strtab[si->symtab[i].nmoff])
363 > VG_(strlen)(&si->strtab[si->symtab[i+1].nmoff])) {
364 si->symtab[si->symtab_used++] = si->symtab[i];
365 } else {
366 si->symtab[si->symtab_used++] = si->symtab[i+1];
367 }
368 i++;
369 } else {
370 si->symtab[si->symtab_used++] = si->symtab[i];
371 }
372 }
373 if (VG_(clo_trace_symtab))
374 VG_(printf)( "%d merged\n", n_merged);
375 }
376 while (n_merged > 0);
377
378 /* Detect and "fix" overlapping address ranges. */
379 n_truncated = 0;
380
381 for (i = 0; i < si->symtab_used-1; i++) {
382
383 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
384
385 /* Check for common (no overlap) case. */
386 if (si->symtab[i].addr + si->symtab[i].size
387 <= si->symtab[i+1].addr)
388 continue;
389
390 /* There's an overlap. Truncate one or the other. */
391 if (VG_(clo_trace_symtab)) {
392 VG_(printf)("overlapping address ranges in symbol table\n\t");
393 printSym(si,i);
394 VG_(printf)("\t");
395 printSym(si,i+1);
396 VG_(printf)("\n");
397 }
398
399 /* Truncate one or the other. */
400 s1 = si->symtab[i].addr;
401 s2 = si->symtab[i+1].addr;
402 e1 = s1 + si->symtab[i].size - 1;
403 e2 = s2 + si->symtab[i+1].size - 1;
404 if (s1 < s2) {
405 e1 = s2-1;
406 } else {
407 vg_assert(s1 == s2);
408 if (e1 > e2) {
409 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
410 } else
411 if (e1 < e2) {
412 s2 = e1+1;
413 } else {
414 /* e1 == e2. Identical addr ranges. We'll eventually wind
415 up back at cleanup_more, which will take care of it. */
416 }
417 }
418 si->symtab[i].addr = s1;
419 si->symtab[i+1].addr = s2;
420 si->symtab[i].size = e1 - s1 + 1;
421 si->symtab[i+1].size = e2 - s2 + 1;
422 vg_assert(s1 <= s2);
423 vg_assert(si->symtab[i].size > 0);
424 vg_assert(si->symtab[i+1].size > 0);
425 /* It may be that the i+1 entry now needs to be moved further
426 along to maintain the address order requirement. */
427 j = i+1;
428 while (j < si->symtab_used-1
429 && si->symtab[j].addr > si->symtab[j+1].addr) {
430 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
431 j++;
432 }
433 n_truncated++;
434 }
435
436 if (n_truncated > 0) goto cleanup_more;
437
438 /* Ensure relevant postconditions hold. */
439 for (i = 0; i < si->symtab_used-1; i++) {
440 /* No zero-sized symbols. */
441 vg_assert(si->symtab[i].size > 0);
442 /* In order. */
443 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
444 /* No overlaps. */
445 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
446 < si->symtab[i+1].addr);
447 }
448# undef SWAP
449}
450
451
452
453/* Sort the location table by starting address. Mash the table around
454 so as to establish the property that addresses are in order and the
455 ranges do not overlap. This facilitates using binary search to map
456 addresses to locations when we come to query the table. */
457static
458void canonicaliseLoctab ( SegInfo* si )
459{
460 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
461 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
462 4592, 13776, 33936, 86961, 198768,
463 463792, 1391376 };
464 Int lo = 0;
465 Int hi = si->loctab_used-1;
466 Int i, j, h, bigN, hp;
467 RiLoc v;
468
469# define SWAP(ty,aa,bb) \
470 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
471
472 /* Sort by start address. */
473
474 bigN = hi - lo + 1; if (bigN < 2) return;
475 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
476 vg_assert(0 <= hp && hp < 16);
477
478 for (; hp >= 0; hp--) {
479 h = incs[hp];
480 i = lo + h;
481 while (1) {
482 if (i > hi) break;
483 v = si->loctab[i];
484 j = i;
485 while (si->loctab[j-h].addr > v.addr) {
486 si->loctab[j] = si->loctab[j-h];
487 j = j - h;
488 if (j <= (lo + h - 1)) break;
489 }
490 si->loctab[j] = v;
491 i++;
492 }
493 }
494
495 /* If two adjacent entries overlap, truncate the first. */
496 for (i = 0; i < si->loctab_used-1; i++) {
497 vg_assert(si->loctab[i].size < 10000);
498 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
499 /* Do this in signed int32 because the actual .size fields
500 are unsigned 16s. */
501 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
502 if (new_size < 0) {
503 si->loctab[i].size = 0;
504 } else
505 if (new_size >= 65536) {
506 si->loctab[i].size = 65535;
507 } else {
508 si->loctab[i].size = (UShort)new_size;
509 }
510 }
511 }
512
513 /* Zap any zero-sized entries resulting from the truncation
514 process. */
515 j = 0;
516 for (i = 0; i < si->loctab_used; i++) {
517 if (si->loctab[i].size > 0) {
518 si->loctab[j] = si->loctab[i];
519 j++;
520 }
521 }
522 si->loctab_used = j;
523
524 /* Ensure relevant postconditions hold. */
525 for (i = 0; i < si->loctab_used-1; i++) {
526 /*
527 VG_(printf)("%d (%d) %d 0x%x\n",
528 i, si->loctab[i+1].confident,
529 si->loctab[i+1].size, si->loctab[i+1].addr );
530 */
531 /* No zero-sized symbols. */
532 vg_assert(si->loctab[i].size > 0);
533 /* In order. */
534 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
535 /* No overlaps. */
536 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
537 < si->loctab[i+1].addr);
538 }
539# undef SWAP
540}
541
542
543/*------------------------------------------------------------*/
544/*--- Read info from a .so/exe file. ---*/
545/*------------------------------------------------------------*/
546
547static __inline__
548void addLineInfo ( SegInfo* si,
549 Int fnmoff,
550 Addr start,
551 Addr end,
552 UInt lineno )
553{
554 RiLoc loc;
555 UInt size = end - start + 1;
njn4f9c9342002-04-29 16:03:24 +0000556
sewardjde4a1d02002-03-22 01:27:54 +0000557 /* Sanity ... */
558 if (size > 10000) return;
559
560 if (start >= si->start+si->size
561 || end < si->start) return;
562
563 loc.addr = start;
564 loc.size = (UShort)size;
565 loc.lineno = lineno;
566 loc.fnmoff = fnmoff;
567 addLoc ( si, &loc );
568}
569
570
571/* Read the symbols from the object/exe specified by the SegInfo into
572 the tables within the supplied SegInfo. */
573static
574void vg_read_lib_symbols ( SegInfo* si )
575{
576 Elf32_Ehdr* ehdr; /* The ELF header */
577 Elf32_Shdr* shdr; /* The section table */
578 UChar* sh_strtab; /* The section table's string table */
579 struct nlist* stab; /* The .stab table */
580 UChar* stabstr; /* The .stab string table */
581 Int stab_sz; /* Size in bytes of the .stab table */
582 Int stabstr_sz; /* Size in bytes of the .stab string table */
583 Int fd;
584 Int i;
585 Bool ok;
586 Addr oimage;
587 Int n_oimage;
588 struct stat stat_buf;
589
590 /* for the .stabs reader */
591 Int curr_filenmoff;
592 Addr curr_fnbaseaddr;
njn4f9c9342002-04-29 16:03:24 +0000593 Char* curr_file_name;
594 Int n_stab_entries;
sewardjde4a1d02002-03-22 01:27:54 +0000595
596 oimage = (Addr)NULL;
597 if (VG_(clo_verbosity) > 1)
598 VG_(message)(Vg_UserMsg, "Reading syms from %s",
599 si->filename );
600
601 /* mmap the object image aboard, so that we can read symbols and
602 line number info out of it. It will be munmapped immediately
603 thereafter; it is only aboard transiently. */
604
605 i = stat(si->filename, &stat_buf);
606 if (i != 0) {
607 vg_symerr("Can't stat .so/.exe (to determine its size)?!");
608 return;
609 }
610 n_oimage = stat_buf.st_size;
611
612 fd = VG_(open_read)(si->filename);
613 if (fd == -1) {
614 vg_symerr("Can't open .so/.exe to read symbols?!");
615 return;
616 }
617
618 oimage = (Addr)VG_(mmap)( NULL, n_oimage, PROT_READ, MAP_PRIVATE, fd, 0 );
619 if (oimage == ((Addr)(-1))) {
620 VG_(message)(Vg_UserMsg,
621 "mmap failed on %s", si->filename );
622 VG_(close)(fd);
623 return;
624 }
625
626 VG_(close)(fd);
627
628 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
629 Now verify that it is a valid ELF .so or executable image.
630 */
631 ok = (n_oimage >= sizeof(Elf32_Ehdr));
632 ehdr = (Elf32_Ehdr*)oimage;
633
634 if (ok) {
635 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
636 && ehdr->e_ident[EI_MAG1] == 'E'
637 && ehdr->e_ident[EI_MAG2] == 'L'
638 && ehdr->e_ident[EI_MAG3] == 'F');
639 ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
640 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
641 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
642 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
643 ok &= (ehdr->e_machine == EM_386);
644 ok &= (ehdr->e_version == EV_CURRENT);
645 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
646 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
647 }
648
649 if (!ok) {
650 vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
651 VG_(munmap) ( (void*)oimage, n_oimage );
652 return;
653 }
654
655 if (VG_(clo_trace_symtab))
656 VG_(printf)(
657 "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
658 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
659
660 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
661 vg_symerr("ELF section header is beyond image end?!");
662 VG_(munmap) ( (void*)oimage, n_oimage );
663 return;
664 }
665
666 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
667 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
668
669 /* try and read the object's symbol table */
670 {
671 UChar* o_strtab = NULL;
672 Elf32_Sym* o_symtab = NULL;
673 UInt o_strtab_sz = 0;
674 UInt o_symtab_sz = 0;
675
676 UChar* o_got = NULL;
677 UChar* o_plt = NULL;
678 UInt o_got_sz = 0;
679 UInt o_plt_sz = 0;
680
681 Bool snaffle_it;
682 Addr sym_addr;
683
684 /* find the .stabstr and .stab sections */
685 for (i = 0; i < ehdr->e_shnum; i++) {
686 if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
687 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
688 o_symtab_sz = shdr[i].sh_size;
689 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
690 /* check image overrun here */
691 }
692 if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
693 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
694 o_strtab_sz = shdr[i].sh_size;
695 /* check image overrun here */
696 }
697
698 /* find out where the .got and .plt sections will be in the
699 executable image, not in the object image transiently loaded.
700 */
701 if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
702 o_got = (UChar*)(si->offset
703 + shdr[i].sh_offset);
704 o_got_sz = shdr[i].sh_size;
705 /* check image overrun here */
706 }
707 if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
708 o_plt = (UChar*)(si->offset
709 + shdr[i].sh_offset);
710 o_plt_sz = shdr[i].sh_size;
711 /* check image overrun here */
712 }
713
714 }
715
716 if (VG_(clo_trace_symtab)) {
717 if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
718 o_plt, o_plt + o_plt_sz - 1 );
719 if (o_got) VG_(printf)( "GOT: %p .. %p\n",
720 o_got, o_got + o_got_sz - 1 );
721 }
722
723 if (o_strtab == NULL || o_symtab == NULL) {
724 vg_symerr(" object doesn't have a symbol table");
725 } else {
726 /* Perhaps should start at i = 1; ELF docs suggest that entry
727 0 always denotes `unknown symbol'. */
728 for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
729# if 0
730 VG_(printf)("raw symbol: ");
731 switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
732 case STB_LOCAL: VG_(printf)("LOC "); break;
733 case STB_GLOBAL: VG_(printf)("GLO "); break;
734 case STB_WEAK: VG_(printf)("WEA "); break;
735 case STB_LOPROC: VG_(printf)("lop "); break;
736 case STB_HIPROC: VG_(printf)("hip "); break;
737 default: VG_(printf)("??? "); break;
738 }
739 switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
740 case STT_NOTYPE: VG_(printf)("NOT "); break;
741 case STT_OBJECT: VG_(printf)("OBJ "); break;
742 case STT_FUNC: VG_(printf)("FUN "); break;
743 case STT_SECTION: VG_(printf)("SEC "); break;
744 case STT_FILE: VG_(printf)("FIL "); break;
745 case STT_LOPROC: VG_(printf)("lop "); break;
746 case STT_HIPROC: VG_(printf)("hip "); break;
747 default: VG_(printf)("??? "); break;
748 }
749 VG_(printf)(
750 ": value %p, size %d, name %s\n",
751 si->offset+(UChar*)o_symtab[i].st_value,
752 o_symtab[i].st_size,
753 o_symtab[i].st_name
754 ? ((Char*)o_strtab+o_symtab[i].st_name)
755 : (Char*)"NONAME");
756# endif
757
758 /* Figure out if we're interested in the symbol.
759 Firstly, is it of the right flavour?
760 */
761 snaffle_it
762 = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
763 ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
764 ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
765 &&
766 (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*||
767 ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/)
768 );
769
770 /* Secondly, if it's apparently in a GOT or PLT, it's really
771 a reference to a symbol defined elsewhere, so ignore it.
772 */
773 sym_addr = si->offset
774 + (UInt)o_symtab[i].st_value;
775 if (o_got != NULL
776 && sym_addr >= (Addr)o_got
777 && sym_addr < (Addr)(o_got+o_got_sz)) {
778 snaffle_it = False;
779 if (VG_(clo_trace_symtab)) {
780 VG_(printf)( "in GOT: %s\n",
781 o_strtab+o_symtab[i].st_name);
782 }
783 }
784 if (o_plt != NULL
785 && sym_addr >= (Addr)o_plt
786 && sym_addr < (Addr)(o_plt+o_plt_sz)) {
787 snaffle_it = False;
788 if (VG_(clo_trace_symtab)) {
789 VG_(printf)( "in PLT: %s\n",
790 o_strtab+o_symtab[i].st_name);
791 }
792 }
793
794 /* Don't bother if nameless, or zero-sized. */
795 if (snaffle_it
796 && (o_symtab[i].st_name == (Elf32_Word)NULL
797 || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
798 /* equivalent but cheaper ... */
799 * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
800 || o_symtab[i].st_size == 0)) {
801 snaffle_it = False;
802 if (VG_(clo_trace_symtab)) {
803 VG_(printf)( "size=0: %s\n",
804 o_strtab+o_symtab[i].st_name);
805 }
806 }
807
808# if 0
809 /* Avoid _dl_ junk. (Why?) */
810 /* 01-02-24: disabled until I find out if it really helps. */
811 if (snaffle_it
812 && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
813 || VG_(strncmp)("_r_debug",
814 o_strtab+o_symtab[i].st_name, 8) == 0)) {
815 snaffle_it = False;
816 if (VG_(clo_trace_symtab)) {
817 VG_(printf)( "_dl_ junk: %s\n",
818 o_strtab+o_symtab[i].st_name);
819 }
820 }
821# endif
822
823 /* This seems to significantly reduce the number of junk
824 symbols, and particularly reduces the number of
825 overlapping address ranges. Don't ask me why ... */
826 if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
827 snaffle_it = False;
828 if (VG_(clo_trace_symtab)) {
829 VG_(printf)( "valu=0: %s\n",
830 o_strtab+o_symtab[i].st_name);
831 }
832 }
833
834 /* If no part of the symbol falls within the mapped range,
835 ignore it. */
836 if (sym_addr+o_symtab[i].st_size <= si->start
837 || sym_addr >= si->start+si->size) {
838 snaffle_it = False;
839 }
840
841 if (snaffle_it) {
842 /* it's an interesting symbol; record ("snaffle") it. */
843 RiSym sym;
844 Char* t0 = o_symtab[i].st_name
845 ? (Char*)(o_strtab+o_symtab[i].st_name)
846 : (Char*)"NONAME";
847 Int nmoff = addStr ( si, t0 );
848 vg_assert(nmoff >= 0
849 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
850 vg_assert( (Int)o_symtab[i].st_value >= 0);
851 /* VG_(printf)("%p + %d: %s\n", si->addr,
852 (Int)o_symtab[i].st_value, t0 ); */
853 sym.addr = sym_addr;
854 sym.size = o_symtab[i].st_size;
855 sym.nmoff = nmoff;
856 addSym ( si, &sym );
857 }
858 }
859 }
860 }
861
862 /* Reading of the "stabs" debug format information, if any. */
863 stabstr = NULL;
864 stab = NULL;
865 stabstr_sz = 0;
866 stab_sz = 0;
867 /* find the .stabstr and .stab sections */
868 for (i = 0; i < ehdr->e_shnum; i++) {
869 if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
870 stab = (struct nlist *)(oimage + shdr[i].sh_offset);
871 stab_sz = shdr[i].sh_size;
872 }
873 if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
874 stabstr = (UChar*)(oimage + shdr[i].sh_offset);
875 stabstr_sz = shdr[i].sh_size;
876 }
877 }
878
879 if (stab == NULL || stabstr == NULL) {
880 vg_symerr(" object doesn't have any debug info");
881 VG_(munmap) ( (void*)oimage, n_oimage );
882 return;
883 }
884
885 if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
886 || stabstr_sz + (UChar*)stabstr
887 > n_oimage + (UChar*)oimage ) {
888 vg_symerr(" ELF debug data is beyond image end?!");
889 VG_(munmap) ( (void*)oimage, n_oimage );
890 return;
891 }
892
893 /* Ok. It all looks plausible. Go on and read debug data.
894 stab kinds: 100 N_SO a source file name
895 68 N_SLINE a source line number
njn4f9c9342002-04-29 16:03:24 +0000896 36 N_FUN start of a function
sewardjde4a1d02002-03-22 01:27:54 +0000897
njn4f9c9342002-04-29 16:03:24 +0000898 In this loop, we maintain a current file name, updated as
899 N_SO/N_SOLs appear, and a current function base address,
900 updated as N_FUNs appear. Based on that, address ranges for
901 N_SLINEs are calculated, and stuffed into the line info table.
sewardjde4a1d02002-03-22 01:27:54 +0000902
njn4f9c9342002-04-29 16:03:24 +0000903 Finding the instruction address range covered by an N_SLINE is
904 complicated; see the N_SLINE case below.
sewardjde4a1d02002-03-22 01:27:54 +0000905 */
906 curr_filenmoff = addStr(si,"???");
907 curr_fnbaseaddr = (Addr)NULL;
njn4f9c9342002-04-29 16:03:24 +0000908 curr_file_name = (Char*)NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000909
njn4f9c9342002-04-29 16:03:24 +0000910 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
911
912 for (i = 0; i < n_stab_entries; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000913# if 0
914 VG_(printf) ( " %2d ", i );
915 VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s",
916 stab[i].n_type, stab[i].n_other, stab[i].n_desc,
917 (int)stab[i].n_value,
918 (int)stab[i].n_un.n_strx,
919 stabstr + stab[i].n_un.n_strx );
920 VG_(printf)("\n");
921# endif
922
923 switch (stab[i].n_type) {
njn4f9c9342002-04-29 16:03:24 +0000924 UInt next_addr;
sewardjde4a1d02002-03-22 01:27:54 +0000925
njn4f9c9342002-04-29 16:03:24 +0000926 /* To compute the instr address range covered by a single line, find
927 * the address of the next thing and compute the difference. The
928 * approach used depends on what kind of entry/entries follow... */
929 case N_SLINE: {
930 Int lineno = stab[i].n_desc;
931 Int this_addr = (UInt)stab[i].n_value;
932
933 LOOP:
njn9aae6742002-04-30 13:44:01 +0000934 if (i+1 >= n_stab_entries) {
935 /* If it's the last entry, just guess the range is four; can't
936 * do any better */
937 next_addr = 4;
938 } else {
939 switch (stab[i+1].n_type) {
940 /* Easy, common case: use address of next entry */
941 case N_SLINE: case N_SO:
njn4f9c9342002-04-29 16:03:24 +0000942 next_addr = (UInt)stab[i+1].n_value;
njn4f9c9342002-04-29 16:03:24 +0000943 break;
njn4f9c9342002-04-29 16:03:24 +0000944
njn9aae6742002-04-30 13:44:01 +0000945 /* Boring one: skip, look for something more useful. */
946 case N_RSYM: case N_LSYM: case N_LBRAC: case N_RBRAC:
njn9885df02002-05-01 08:25:03 +0000947 case N_STSYM: case N_LCSYM: case N_GSYM:
njn9aae6742002-04-30 13:44:01 +0000948 i++;
949 goto LOOP;
950
951 /* Should be an end of fun entry, use its address */
952 case N_FUN:
953 if ('\0' == * (stabstr + stab[i+1].n_un.n_strx) ) {
954 next_addr = (UInt)stab[i+1].n_value;
955 } else {
956 VG_(printf)("unhandled stabs case: N_FUN start %d %s\n",
957 i, (stabstr + stab[i+1].n_un.n_strx) );
sewardj177d3232002-05-01 09:25:56 +0000958 VG_(panic)("unhandled N_FUN stabs case");
njn9aae6742002-04-30 13:44:01 +0000959 }
960 break;
961
962 /* N_SOL should be followed by an N_SLINE which can be used */
963 case N_SOL:
964 if (i+2 < n_stab_entries && N_SLINE == stab[i+2].n_type) {
965 next_addr = (UInt)stab[i+2].n_value;
966 break;
967 } else {
968 VG_(printf)("unhandled N_SOL stabs case: %d %d %d",
969 stab[i+1].n_type, i, n_stab_entries);
sewardj177d3232002-05-01 09:25:56 +0000970 VG_(panic)("unhandled N_SOL stabs case");
njn9aae6742002-04-30 13:44:01 +0000971 }
972
973 default:
974 VG_(printf)("unhandled stabs case: %d %d",
975 stab[i+1].n_type,i);
sewardj177d3232002-05-01 09:25:56 +0000976 VG_(panic)("unhandled (other) stabs case");
njn9aae6742002-04-30 13:44:01 +0000977 }
sewardjde4a1d02002-03-22 01:27:54 +0000978 }
njn4f9c9342002-04-29 16:03:24 +0000979
980 //Int offset2 = (i+1 < n_stab_entries && 68 == stab[i+1].n_type
981 // ? (UInt)stab[i+1].n_value - 1
982 // : offset + 1);
983 //if (i+1 < n_stab_entries) {
984 // int x;
985 // if (68 != (x = stab[i+1].n_type)) {
986 // VG_(printf)("%d ", x);
987 // }
988 //}
989
990 addLineInfo ( si, curr_filenmoff, curr_fnbaseaddr + this_addr,
991 curr_fnbaseaddr + next_addr - 1, lineno );
sewardjde4a1d02002-03-22 01:27:54 +0000992 break;
993 }
994
njn4f9c9342002-04-29 16:03:24 +0000995 case N_FUN: {
996 if ('\0' != (stabstr + stab[i].n_un.n_strx)[0] ) {
sewardjde4a1d02002-03-22 01:27:54 +0000997 /* N_FUN with a name -- indicates the start of a fn. */
njn4f9c9342002-04-29 16:03:24 +0000998 curr_fnbaseaddr = si->offset + (Addr)stab[i].n_value;
sewardjde4a1d02002-03-22 01:27:54 +0000999 }
1000 break;
1001 }
1002
njn4f9c9342002-04-29 16:03:24 +00001003 case N_SO: case N_SOL:
sewardjde4a1d02002-03-22 01:27:54 +00001004 /* seems to give lots of locations in header files */
1005 /* case 130: */ /* BINCL */
1006 {
1007 UChar* nm = stabstr + stab[i].n_un.n_strx;
1008 UInt len = VG_(strlen)(nm);
njn4f9c9342002-04-29 16:03:24 +00001009
1010 if (len > 0 && nm[len-1] != '/') {
sewardjde4a1d02002-03-22 01:27:54 +00001011 curr_filenmoff = addStr ( si, nm );
njn4f9c9342002-04-29 16:03:24 +00001012 curr_file_name = stabstr + stab[i].n_un.n_strx;
1013 }
sewardjde4a1d02002-03-22 01:27:54 +00001014 else
1015 if (len == 0)
1016 curr_filenmoff = addStr ( si, "?1\0" );
njn4f9c9342002-04-29 16:03:24 +00001017
sewardjde4a1d02002-03-22 01:27:54 +00001018 break;
1019 }
1020
1021# if 0
1022 case 162: /* EINCL */
1023 curr_filenmoff = addStr ( si, "?2\0" );
1024 break;
1025# endif
1026
1027 default:
1028 break;
1029 }
1030 } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */
1031
1032 /* Last, but not least, heave the oimage back overboard. */
1033 VG_(munmap) ( (void*)oimage, n_oimage );
1034}
1035
1036
1037/*------------------------------------------------------------*/
1038/*--- Main entry point for symbols table reading. ---*/
1039/*------------------------------------------------------------*/
1040
1041/* The root structure for the entire symbol table system. It is a
1042 linked list of SegInfos. Note that this entire mechanism assumes
1043 that what we read from /proc/self/maps doesn't contain overlapping
1044 address ranges, and as a result the SegInfos in this list describe
1045 disjoint address ranges.
1046*/
1047static SegInfo* segInfo = NULL;
1048
1049
1050static
1051void read_symtab_callback (
1052 Addr start, UInt size,
1053 Char rr, Char ww, Char xx,
1054 UInt foffset, UChar* filename )
1055{
1056 SegInfo* si;
1057
1058 /* Stay sane ... */
1059 if (size == 0)
1060 return;
1061
1062 /* We're only interested in collecting symbols in executable
1063 segments which are associated with a real file. Hence: */
1064 if (filename == NULL || xx != 'x')
1065 return;
1066 if (0 == VG_(strcmp)(filename, "/dev/zero"))
1067 return;
1068
1069 /* Perhaps we already have this one? If so, skip. */
1070 for (si = segInfo; si != NULL; si = si->next) {
1071 /*
1072 if (0==VG_(strcmp)(si->filename, filename))
1073 VG_(printf)("same fnames: %c%c%c (%p, %d) (%p, %d) %s\n",
1074 rr,ww,xx,si->start,si->size,start,size,filename);
1075 */
1076 /* For some reason the observed size of a mapping can change, so
1077 we don't use that to determine uniqueness. */
1078 if (si->start == start
1079 /* && si->size == size */
1080 && 0==VG_(strcmp)(si->filename, filename)) {
1081 return;
1082 }
1083 }
1084
1085 /* Get the record initialised right. */
1086 si = VG_(malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
1087 si->next = segInfo;
1088 segInfo = si;
1089
1090 si->start = start;
1091 si->size = size;
1092 si->foffset = foffset;
1093 si->filename = VG_(malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(filename));
1094 VG_(strcpy)(si->filename, filename);
1095
1096 si->symtab = NULL;
1097 si->symtab_size = si->symtab_used = 0;
1098 si->loctab = NULL;
1099 si->loctab_size = si->loctab_used = 0;
1100 si->strtab = NULL;
1101 si->strtab_size = si->strtab_used = 0;
1102
1103 /* Kludge ... */
1104 si->offset
1105 = si->start==VG_ASSUMED_EXE_BASE ? 0 : si->start;
1106
1107 /* And actually fill it up. */
1108 vg_read_lib_symbols ( si );
1109 canonicaliseSymtab ( si );
1110 canonicaliseLoctab ( si );
1111}
1112
1113
1114/* This one really is the Head Honcho. Update the symbol tables to
1115 reflect the current state of /proc/self/maps. Rather than re-read
1116 everything, just read the entries which are not already in segInfo.
1117 So we can call here repeatedly, after every mmap of a non-anonymous
1118 segment with execute permissions, for example, to pick up new
1119 libraries as they are dlopen'd. Conversely, when the client does
1120 munmap(), vg_symtab_notify_munmap() throws away any symbol tables
1121 which happen to correspond to the munmap()d area. */
1122void VG_(read_symbols) ( void )
1123{
njn4f9c9342002-04-29 16:03:24 +00001124 if (! VG_(clo_instrument) && ! VG_(clo_cachesim))
1125 return;
sewardjde4a1d02002-03-22 01:27:54 +00001126
1127 VG_(read_procselfmaps) ( read_symtab_callback );
1128
1129 /* Do a sanity check on the symbol tables: ensure that the address
1130 space pieces they cover do not overlap (otherwise we are severely
1131 hosed). This is a quadratic algorithm, but there shouldn't be
1132 many of them.
1133 */
1134 { SegInfo *si, *si2;
1135 for (si = segInfo; si != NULL; si = si->next) {
1136 /* Check no overlap between *si and those in the rest of the
1137 list. */
1138 for (si2 = si->next; si2 != NULL; si2 = si2->next) {
1139 Addr lo = si->start;
1140 Addr hi = si->start + si->size - 1;
1141 Addr lo2 = si2->start;
1142 Addr hi2 = si2->start + si2->size - 1;
1143 Bool overlap;
1144 vg_assert(lo < hi);
1145 vg_assert(lo2 < hi2);
1146 /* the main assertion */
1147 overlap = (lo <= lo2 && lo2 <= hi)
1148 || (lo <= hi2 && hi2 <= hi);
1149 //vg_assert(!overlap);
1150 if (overlap) {
1151 VG_(printf)("\n\nOVERLAPPING SEGMENTS\n" );
1152 ppSegInfo ( si );
1153 ppSegInfo ( si2 );
1154 VG_(printf)("\n\n");
1155 vg_assert(! overlap);
1156 }
1157 }
1158 }
1159 }
1160}
1161
1162
1163/* When an munmap() call happens, check to see whether it corresponds
1164 to a segment for a .so, and if so discard the relevant SegInfo.
1165 This might not be a very clever idea from the point of view of
1166 accuracy of error messages, but we need to do it in order to
1167 maintain the no-overlapping invariant.
1168*/
1169void VG_(symtab_notify_munmap) ( Addr start, UInt length )
1170{
1171 SegInfo *prev, *curr;
1172
1173 if (! VG_(clo_instrument))
1174 return;
1175
1176 prev = NULL;
1177 curr = segInfo;
1178 while (True) {
1179 if (curr == NULL) break;
1180 if (start == curr->start) break;
1181 prev = curr;
1182 curr = curr->next;
1183 }
1184 if (curr == NULL) return;
1185
1186 VG_(message)(Vg_UserMsg,
1187 "discard syms in %s due to munmap()",
1188 curr->filename ? curr->filename : (UChar*)"???");
1189
1190 vg_assert(prev == NULL || prev->next == curr);
1191
1192 if (prev == NULL) {
1193 segInfo = curr->next;
1194 } else {
1195 prev->next = curr->next;
1196 }
1197
1198 freeSegInfo(curr);
1199}
1200
1201
1202/*------------------------------------------------------------*/
1203/*--- Use of symbol table & location info to create ---*/
1204/*--- plausible-looking stack dumps. ---*/
1205/*------------------------------------------------------------*/
1206
1207/* Find a symbol-table index containing the specified pointer, or -1
1208 if not found. Binary search. */
1209
1210static Int search_one_symtab ( SegInfo* si, Addr ptr )
1211{
1212 Addr a_mid_lo, a_mid_hi;
1213 Int mid,
1214 lo = 0,
1215 hi = si->symtab_used-1;
1216 while (True) {
1217 /* current unsearched space is from lo to hi, inclusive. */
1218 if (lo > hi) return -1; /* not found */
1219 mid = (lo + hi) / 2;
1220 a_mid_lo = si->symtab[mid].addr;
1221 a_mid_hi = ((Addr)si->symtab[mid].addr) + si->symtab[mid].size - 1;
1222
1223 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1224 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1225 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1226 return mid;
1227 }
1228}
1229
1230
1231/* Search all symtabs that we know about to locate ptr. If found, set
1232 *psi to the relevant SegInfo, and *symno to the symtab entry number
1233 within that. If not found, *psi is set to NULL. */
1234
1235static void search_all_symtabs ( Addr ptr, SegInfo** psi, Int* symno )
1236{
1237 Int sno;
1238 SegInfo* si;
1239 for (si = segInfo; si != NULL; si = si->next) {
1240 if (si->start <= ptr && ptr < si->start+si->size) {
1241 sno = search_one_symtab ( si, ptr );
1242 if (sno == -1) goto not_found;
1243 *symno = sno;
1244 *psi = si;
1245 return;
1246 }
1247 }
1248 not_found:
1249 *psi = NULL;
1250}
1251
1252
1253/* Find a location-table index containing the specified pointer, or -1
1254 if not found. Binary search. */
1255
1256static Int search_one_loctab ( SegInfo* si, Addr ptr )
1257{
1258 Addr a_mid_lo, a_mid_hi;
1259 Int mid,
1260 lo = 0,
1261 hi = si->loctab_used-1;
1262 while (True) {
1263 /* current unsearched space is from lo to hi, inclusive. */
1264 if (lo > hi) return -1; /* not found */
1265 mid = (lo + hi) / 2;
1266 a_mid_lo = si->loctab[mid].addr;
1267 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1268
1269 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1270 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1271 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1272 return mid;
1273 }
1274}
1275
1276
1277/* Search all loctabs that we know about to locate ptr. If found, set
1278 *psi to the relevant SegInfo, and *locno to the loctab entry number
1279 within that. If not found, *psi is set to NULL.
1280*/
1281static void search_all_loctabs ( Addr ptr, SegInfo** psi, Int* locno )
1282{
1283 Int lno;
1284 SegInfo* si;
1285 for (si = segInfo; si != NULL; si = si->next) {
1286 if (si->start <= ptr && ptr < si->start+si->size) {
1287 lno = search_one_loctab ( si, ptr );
1288 if (lno == -1) goto not_found;
1289 *locno = lno;
1290 *psi = si;
1291 return;
1292 }
1293 }
1294 not_found:
1295 *psi = NULL;
1296}
1297
1298
1299/* The whole point of this whole big deal: map a code address to a
1300 plausible symbol name. Returns False if no idea; otherwise True.
1301 Caller supplies buf and nbuf. If no_demangle is True, don't do
1302 demangling, regardless of vg_clo_demangle -- probably because the
1303 call has come from vg_what_fn_or_object_is_this. */
njn4f9c9342002-04-29 16:03:24 +00001304Bool VG_(what_fn_is_this) ( Bool no_demangle, Addr a,
1305 Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001306{
1307 SegInfo* si;
1308 Int sno;
1309 search_all_symtabs ( a, &si, &sno );
1310 if (si == NULL)
1311 return False;
1312 if (no_demangle) {
1313 VG_(strncpy_safely)
1314 ( buf, & si->strtab[si->symtab[sno].nmoff], nbuf );
1315 } else {
1316 VG_(demangle) ( & si->strtab[si->symtab[sno].nmoff], buf, nbuf );
1317 }
1318 return True;
1319}
1320
1321
1322/* Map a code address to the name of a shared object file. Returns
1323 False if no idea; otherwise False. Caller supplies buf and
1324 nbuf. */
1325static
1326Bool vg_what_object_is_this ( Addr a, Char* buf, Int nbuf )
1327{
1328 SegInfo* si;
1329 for (si = segInfo; si != NULL; si = si->next) {
1330 if (si->start <= a && a < si->start+si->size) {
1331 VG_(strncpy_safely)(buf, si->filename, nbuf);
1332 return True;
1333 }
1334 }
1335 return False;
1336}
1337
1338/* Return the name of an erring fn in a way which is useful
1339 for comparing against the contents of a suppressions file.
1340 Always writes something to buf. Also, doesn't demangle the
1341 name, because we want to refer to mangled names in the
1342 suppressions file.
1343*/
1344void VG_(what_obj_and_fun_is_this) ( Addr a,
1345 Char* obj_buf, Int n_obj_buf,
1346 Char* fun_buf, Int n_fun_buf )
1347{
1348 (void)vg_what_object_is_this ( a, obj_buf, n_obj_buf );
njn4f9c9342002-04-29 16:03:24 +00001349 (void)VG_(what_fn_is_this) ( True, a, fun_buf, n_fun_buf );
sewardjde4a1d02002-03-22 01:27:54 +00001350}
1351
1352
1353/* Map a code address to a (filename, line number) pair.
1354 Returns True if successful.
1355*/
njn4f9c9342002-04-29 16:03:24 +00001356Bool VG_(what_line_is_this)( Addr a,
1357 UChar* filename, Int n_filename,
1358 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001359{
1360 SegInfo* si;
1361 Int locno;
1362 search_all_loctabs ( a, &si, &locno );
1363 if (si == NULL)
1364 return False;
1365 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
1366 n_filename);
1367 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00001368
sewardjde4a1d02002-03-22 01:27:54 +00001369 return True;
1370}
1371
1372
1373/* Print a mini stack dump, showing the current location. */
1374void VG_(mini_stack_dump) ( ExeContext* ec )
1375{
1376
1377#define APPEND(str) \
1378 { UChar* sss; \
1379 for (sss = str; n < M_VG_ERRTXT-1 && *sss != 0; n++,sss++) \
1380 buf[n] = *sss; \
1381 buf[n] = 0; \
1382 }
1383
1384 Bool know_fnname;
1385 Bool know_objname;
1386 Bool know_srcloc;
1387 UInt lineno;
1388 UChar ibuf[20];
1389 UInt i, n, clueless;
1390
1391 UChar buf[M_VG_ERRTXT];
1392 UChar buf_fn[M_VG_ERRTXT];
1393 UChar buf_obj[M_VG_ERRTXT];
1394 UChar buf_srcloc[M_VG_ERRTXT];
1395
1396 Int stop_at = VG_(clo_backtrace_size);
1397
1398 n = 0;
1399
njn4f9c9342002-04-29 16:03:24 +00001400 know_fnname = VG_(what_fn_is_this)(False,ec->eips[0], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00001401 know_objname = vg_what_object_is_this(ec->eips[0], buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00001402 know_srcloc = VG_(what_line_is_this)(ec->eips[0],
1403 buf_srcloc, M_VG_ERRTXT,
1404 &lineno);
sewardjde4a1d02002-03-22 01:27:54 +00001405
1406 APPEND(" at ");
1407 VG_(sprintf)(ibuf,"0x%x: ", ec->eips[0]);
1408 APPEND(ibuf);
1409 if (know_fnname) {
1410 APPEND(buf_fn);
1411 if (!know_srcloc && know_objname) {
1412 APPEND(" (in ");
1413 APPEND(buf_obj);
1414 APPEND(")");
1415 }
1416 } else if (know_objname && !know_srcloc) {
1417 APPEND("(within ");
1418 APPEND(buf_obj);
1419 APPEND(")");
1420 } else {
1421 APPEND("???");
1422 }
1423 if (know_srcloc) {
1424 APPEND(" (");
1425 APPEND(buf_srcloc);
1426 APPEND(":");
1427 VG_(sprintf)(ibuf,"%d",lineno);
1428 APPEND(ibuf);
1429 APPEND(")");
1430 }
1431 VG_(message)(Vg_UserMsg, "%s", buf);
1432
1433 clueless = 0;
1434 for (i = 1; i < stop_at; i++) {
njn4f9c9342002-04-29 16:03:24 +00001435 know_fnname = VG_(what_fn_is_this)(False,ec->eips[i], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00001436 know_objname = vg_what_object_is_this(ec->eips[i],buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00001437 know_srcloc = VG_(what_line_is_this)(ec->eips[i],
sewardjde4a1d02002-03-22 01:27:54 +00001438 buf_srcloc, M_VG_ERRTXT,
1439 &lineno);
1440 n = 0;
1441 APPEND(" by ");
1442 if (ec->eips[i] == 0) {
1443 APPEND("<bogus frame pointer> ");
1444 } else {
1445 VG_(sprintf)(ibuf,"0x%x: ",ec->eips[i]);
1446 APPEND(ibuf);
1447 }
1448 if (know_fnname) {
1449 APPEND(buf_fn)
1450 if (!know_srcloc && know_objname) {
1451 APPEND(" (in ");
1452 APPEND(buf_obj);
1453 APPEND(")");
1454 }
1455 } else {
1456 if (know_objname && !know_srcloc) {
1457 APPEND("(within ");
1458 APPEND(buf_obj);
1459 APPEND(")");
1460 } else {
1461 APPEND("???");
1462 }
1463 if (!know_srcloc) clueless++;
1464 if (clueless == 2)
1465 i = stop_at; /* force exit after this iteration */
1466 };
1467 if (know_srcloc) {
1468 APPEND(" (");
1469 APPEND(buf_srcloc);
1470 APPEND(":");
1471 VG_(sprintf)(ibuf,"%d",lineno);
1472 APPEND(ibuf);
1473 APPEND(")");
1474 }
1475 VG_(message)(Vg_UserMsg, "%s", buf);
1476 }
1477}
1478
1479#undef APPEND
1480
1481/*--------------------------------------------------------------------*/
1482/*--- end vg_symtab2.c ---*/
1483/*--------------------------------------------------------------------*/