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