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