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