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