blob: 5e3b8384cd4dd3fed8cf1108420294036a1f54f1 [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"
sewardjde4a1d02002-03-22 01:27:54 +000032
33#include <elf.h> /* ELF defns */
34#include <a.out.h> /* stabs defns */
35
njn9aae6742002-04-30 13:44:01 +000036
sewardjde4a1d02002-03-22 01:27:54 +000037/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
38 dlopen()ed libraries, which is something that KDE3 does a lot.
sewardjde4a1d02002-03-22 01:27:54 +000039
sewardj18d75132002-05-16 11:06:21 +000040 Stabs reader greatly improved by Nick Nethercode, Apr 02.
sewardjde4a1d02002-03-22 01:27:54 +000041
sewardj18d75132002-05-16 11:06:21 +000042 16 May 02: when notified about munmap, return a Bool indicating
43 whether or not the area being munmapped had executable permissions.
44 This is then used to determine whether or not
45 VG_(invalid_translations) should be called for that area. In order
46 that this work even if --instrument=no, in this case we still keep
47 track of the mapped executable segments, but do not load any debug
48 info or symbols.
sewardjde4a1d02002-03-22 01:27:54 +000049*/
50
51/*------------------------------------------------------------*/
52/*--- Structs n stuff ---*/
53/*------------------------------------------------------------*/
54
55/* A structure to hold an ELF symbol (very crudely). */
56typedef
57 struct {
58 Addr addr; /* lowest address of entity */
59 UInt size; /* size in bytes */
60 Int nmoff; /* offset of name in this SegInfo's str tab */
61 }
62 RiSym;
63
njne0ee0712002-05-03 16:41:05 +000064/* Line count at which overflow happens, due to line numbers being stored as
65 * shorts in `struct nlist' in a.out.h. */
66#define LINENO_OVERFLOW (1 << (sizeof(short) * 8))
sewardjde4a1d02002-03-22 01:27:54 +000067
njne0ee0712002-05-03 16:41:05 +000068#define LINENO_BITS 20
69#define LOC_SIZE_BITS (32 - LINENO_BITS)
sewardj97ff05f2002-05-09 01:32:57 +000070#define MAX_LINENO ((1 << LINENO_BITS) - 1)
njne0ee0712002-05-03 16:41:05 +000071
72/* Unlikely to have any lines with instruction ranges > 4096 bytes */
sewardj97ff05f2002-05-09 01:32:57 +000073#define MAX_LOC_SIZE ((1 << LOC_SIZE_BITS) - 1)
njne0ee0712002-05-03 16:41:05 +000074
75/* Number used to detect line number overflows; if one line is 60000-odd
76 * smaller than the previous, is was probably an overflow.
77 */
78#define OVERFLOW_DIFFERENCE (LINENO_OVERFLOW - 5000)
79
80/* A structure to hold addr-to-source info for a single line. There can be a
81 * lot of these, hence the dense packing. */
sewardjde4a1d02002-03-22 01:27:54 +000082typedef
83 struct {
njne0ee0712002-05-03 16:41:05 +000084 /* Word 1 */
85 Addr addr; /* lowest address for this line */
86 /* Word 2 */
87 UShort size:LOC_SIZE_BITS; /* byte size; we catch overflows of this */
88 UInt lineno:LINENO_BITS; /* source line number, or zero */
89 /* Word 3 */
90 UInt fnmoff; /* source filename; offset in this
91 SegInfo's str tab */
sewardjde4a1d02002-03-22 01:27:54 +000092 }
93 RiLoc;
94
95
96/* A structure which contains information pertaining to one mapped
97 text segment. */
98typedef
99 struct _SegInfo {
100 struct _SegInfo* next;
101 /* Description of the mapped segment. */
102 Addr start;
103 UInt size;
104 UChar* filename; /* in mallocville */
105 UInt foffset;
106 /* An expandable array of symbols. */
107 RiSym* symtab;
108 UInt symtab_used;
109 UInt symtab_size;
110 /* An expandable array of locations. */
111 RiLoc* loctab;
112 UInt loctab_used;
113 UInt loctab_size;
114 /* An expandable array of characters -- the string table. */
115 Char* strtab;
116 UInt strtab_used;
117 UInt strtab_size;
118 /* offset is what we need to add to symbol table entries
119 to get the real location of that symbol in memory.
120 For executables, offset is zero.
121 For .so's, offset == base_addr.
122 This seems like a giant kludge to me.
123 */
124 UInt offset;
125 }
126 SegInfo;
127
128
129/* -- debug helper -- */
130static void ppSegInfo ( SegInfo* si )
131{
132 VG_(printf)("name: %s\n"
133 "start %p, size %d, foffset %d\n",
134 si->filename?si->filename : (UChar*)"NULL",
135 si->start, si->size, si->foffset );
136}
137
138static void freeSegInfo ( SegInfo* si )
139{
140 vg_assert(si != NULL);
141 if (si->filename) VG_(free)(VG_AR_SYMTAB, si->filename);
142 if (si->symtab) VG_(free)(VG_AR_SYMTAB, si->symtab);
143 if (si->loctab) VG_(free)(VG_AR_SYMTAB, si->loctab);
144 if (si->strtab) VG_(free)(VG_AR_SYMTAB, si->strtab);
145 VG_(free)(VG_AR_SYMTAB, si);
146}
147
148
149/*------------------------------------------------------------*/
150/*--- Adding stuff ---*/
151/*------------------------------------------------------------*/
152
153/* Add a str to the string table, including terminating zero, and
154 return offset of the string in vg_strtab. */
155
156static __inline__
157Int addStr ( SegInfo* si, Char* str )
158{
159 Char* new_tab;
160 Int new_sz, i, space_needed;
161
162 space_needed = 1 + VG_(strlen)(str);
163 if (si->strtab_used + space_needed > si->strtab_size) {
164 new_sz = 2 * si->strtab_size;
165 if (new_sz == 0) new_sz = 5000;
166 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz);
167 if (si->strtab != NULL) {
168 for (i = 0; i < si->strtab_used; i++)
169 new_tab[i] = si->strtab[i];
170 VG_(free)(VG_AR_SYMTAB, si->strtab);
171 }
172 si->strtab = new_tab;
173 si->strtab_size = new_sz;
174 }
175
176 for (i = 0; i < space_needed; i++)
177 si->strtab[si->strtab_used+i] = str[i];
178
179 si->strtab_used += space_needed;
180 vg_assert(si->strtab_used <= si->strtab_size);
181 return si->strtab_used - space_needed;
182}
183
184/* Add a symbol to the symbol table. */
185
186static __inline__
187void addSym ( SegInfo* si, RiSym* sym )
188{
189 Int new_sz, i;
190 RiSym* new_tab;
191
192 /* Ignore zero-sized syms. */
193 if (sym->size == 0) return;
194
195 if (si->symtab_used == si->symtab_size) {
196 new_sz = 2 * si->symtab_size;
197 if (new_sz == 0) new_sz = 500;
198 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
199 if (si->symtab != NULL) {
200 for (i = 0; i < si->symtab_used; i++)
201 new_tab[i] = si->symtab[i];
202 VG_(free)(VG_AR_SYMTAB, si->symtab);
203 }
204 si->symtab = new_tab;
205 si->symtab_size = new_sz;
206 }
207
208 si->symtab[si->symtab_used] = *sym;
209 si->symtab_used++;
210 vg_assert(si->symtab_used <= si->symtab_size);
211}
212
213/* Add a location to the location table. */
214
215static __inline__
216void addLoc ( SegInfo* si, RiLoc* loc )
217{
218 Int new_sz, i;
219 RiLoc* new_tab;
220
njne0ee0712002-05-03 16:41:05 +0000221 /* Zero-sized locs should have been ignored earlier */
222 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000223
224 if (si->loctab_used == si->loctab_size) {
225 new_sz = 2 * si->loctab_size;
226 if (new_sz == 0) new_sz = 500;
227 new_tab = VG_(malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
228 if (si->loctab != NULL) {
229 for (i = 0; i < si->loctab_used; i++)
230 new_tab[i] = si->loctab[i];
231 VG_(free)(VG_AR_SYMTAB, si->loctab);
232 }
233 si->loctab = new_tab;
234 si->loctab_size = new_sz;
235 }
236
237 si->loctab[si->loctab_used] = *loc;
238 si->loctab_used++;
239 vg_assert(si->loctab_used <= si->loctab_size);
240}
241
242
sewardjb51f2e62002-06-01 23:11:19 +0000243/* Top-level place to call to add a source-location mapping entry. */
244
245static __inline__
246void addLineInfo ( SegInfo* si,
247 Int fnmoff,
248 Addr this,
249 Addr next,
250 Int lineno,
251 Int entry )
252{
253 RiLoc loc;
254 Int size = next - this;
255
256 /* Ignore zero-sized locs */
257 if (this == next) return;
258
259 /* Maximum sanity checking. Some versions of GNU as do a shabby
260 * job with stabs entries; if anything looks suspicious, revert to
261 * a size of 1. This should catch the instruction of interest
262 * (since if using asm-level debug info, one instruction will
263 * correspond to one line, unlike with C-level debug info where
264 * multiple instructions can map to the one line), but avoid
265 * catching any other instructions bogusly. */
266 if (this > next) {
267 VG_(message)(Vg_DebugMsg,
268 "warning: stabs addresses out of order "
269 "at entry %d: 0x%x 0x%x", entry, this, next);
270 size = 1;
271 }
272
273 if (size > MAX_LOC_SIZE) {
274 VG_(message)(Vg_DebugMsg,
275 "warning: stabs line address range too large "
276 "at entry %d: %d", entry, size);
277 size = 1;
278 }
279
280 vg_assert(this < si->start + si->size && next-1 >= si->start);
281 vg_assert(lineno >= 0 && lineno <= MAX_LINENO);
282
283 loc.addr = this;
284 loc.size = (UShort)size;
285 loc.lineno = lineno;
286 loc.fnmoff = fnmoff;
287 addLoc ( si, &loc );
288}
289
sewardjde4a1d02002-03-22 01:27:54 +0000290
291/*------------------------------------------------------------*/
292/*--- Helpers ---*/
293/*------------------------------------------------------------*/
294
295/* Non-fatal -- use vg_panic if terminal. */
296static
297void vg_symerr ( Char* msg )
298{
299 if (VG_(clo_verbosity) > 1)
300 VG_(message)(Vg_UserMsg,"%s", msg );
301}
302
303
304/* Print a symbol. */
305static
306void printSym ( SegInfo* si, Int i )
307{
308 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
309 i,
310 si->symtab[i].addr,
311 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
312 &si->strtab[si->symtab[i].nmoff] );
313}
314
315
316#if 0
317/* Print the entire sym tab. */
318static __attribute__ ((unused))
319void printSymtab ( void )
320{
321 Int i;
322 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
323 for (i = 0; i < vg_symtab_used; i++)
324 printSym(i);
325 VG_(printf)("------ BEGIN vg_symtab ------\n");
326}
327#endif
328
329#if 0
330/* Paranoid strcat. */
331static
332void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
333{
334 UInt i = 0, j = 0;
335 while (True) {
336 if (i >= maxlen) return;
337 if (dst[i] == 0) break;
338 i++;
339 }
340 while (True) {
341 if (i >= maxlen) return;
342 dst[i] = src[j];
343 if (src[j] == 0) return;
344 i++; j++;
345 }
346}
347#endif
348
sewardjb51f2e62002-06-01 23:11:19 +0000349
sewardjde4a1d02002-03-22 01:27:54 +0000350/*------------------------------------------------------------*/
351/*--- Canonicalisers ---*/
352/*------------------------------------------------------------*/
353
354/* Sort the symtab by starting address, and emit warnings if any
355 symbols have overlapping address ranges. We use that old chestnut,
356 shellsort. Mash the table around so as to establish the property
357 that addresses are in order and the ranges to not overlap. This
358 facilitates using binary search to map addresses to symbols when we
359 come to query the table.
360*/
361static
362void canonicaliseSymtab ( SegInfo* si )
363{
364 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
365 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
366 4592, 13776, 33936, 86961, 198768,
367 463792, 1391376 };
368 Int lo = 0;
369 Int hi = si->symtab_used-1;
370 Int i, j, h, bigN, hp, n_merged, n_truncated;
371 RiSym v;
372 Addr s1, s2, e1, e2;
373
374# define SWAP(ty,aa,bb) \
375 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
376
377 bigN = hi - lo + 1; if (bigN < 2) return;
378 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
379 vg_assert(0 <= hp && hp < 16);
380
381 for (; hp >= 0; hp--) {
382 h = incs[hp];
383 i = lo + h;
384 while (1) {
385 if (i > hi) break;
386 v = si->symtab[i];
387 j = i;
388 while (si->symtab[j-h].addr > v.addr) {
389 si->symtab[j] = si->symtab[j-h];
390 j = j - h;
391 if (j <= (lo + h - 1)) break;
392 }
393 si->symtab[j] = v;
394 i++;
395 }
396 }
397
398 cleanup_more:
399
400 /* If two symbols have identical address ranges, favour the
401 one with the longer name.
402 */
403 do {
404 n_merged = 0;
405 j = si->symtab_used;
406 si->symtab_used = 0;
407 for (i = 0; i < j; i++) {
408 if (i < j-1
409 && si->symtab[i].addr == si->symtab[i+1].addr
410 && si->symtab[i].size == si->symtab[i+1].size) {
411 n_merged++;
412 /* merge the two into one */
413 if (VG_(strlen)(&si->strtab[si->symtab[i].nmoff])
414 > VG_(strlen)(&si->strtab[si->symtab[i+1].nmoff])) {
415 si->symtab[si->symtab_used++] = si->symtab[i];
416 } else {
417 si->symtab[si->symtab_used++] = si->symtab[i+1];
418 }
419 i++;
420 } else {
421 si->symtab[si->symtab_used++] = si->symtab[i];
422 }
423 }
424 if (VG_(clo_trace_symtab))
425 VG_(printf)( "%d merged\n", n_merged);
426 }
427 while (n_merged > 0);
428
429 /* Detect and "fix" overlapping address ranges. */
430 n_truncated = 0;
431
432 for (i = 0; i < si->symtab_used-1; i++) {
433
434 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
435
436 /* Check for common (no overlap) case. */
437 if (si->symtab[i].addr + si->symtab[i].size
438 <= si->symtab[i+1].addr)
439 continue;
440
441 /* There's an overlap. Truncate one or the other. */
442 if (VG_(clo_trace_symtab)) {
443 VG_(printf)("overlapping address ranges in symbol table\n\t");
444 printSym(si,i);
445 VG_(printf)("\t");
446 printSym(si,i+1);
447 VG_(printf)("\n");
448 }
449
450 /* Truncate one or the other. */
451 s1 = si->symtab[i].addr;
452 s2 = si->symtab[i+1].addr;
453 e1 = s1 + si->symtab[i].size - 1;
454 e2 = s2 + si->symtab[i+1].size - 1;
455 if (s1 < s2) {
456 e1 = s2-1;
457 } else {
458 vg_assert(s1 == s2);
459 if (e1 > e2) {
460 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
461 } else
462 if (e1 < e2) {
463 s2 = e1+1;
464 } else {
465 /* e1 == e2. Identical addr ranges. We'll eventually wind
466 up back at cleanup_more, which will take care of it. */
467 }
468 }
469 si->symtab[i].addr = s1;
470 si->symtab[i+1].addr = s2;
471 si->symtab[i].size = e1 - s1 + 1;
472 si->symtab[i+1].size = e2 - s2 + 1;
473 vg_assert(s1 <= s2);
474 vg_assert(si->symtab[i].size > 0);
475 vg_assert(si->symtab[i+1].size > 0);
476 /* It may be that the i+1 entry now needs to be moved further
477 along to maintain the address order requirement. */
478 j = i+1;
479 while (j < si->symtab_used-1
480 && si->symtab[j].addr > si->symtab[j+1].addr) {
481 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
482 j++;
483 }
484 n_truncated++;
485 }
486
487 if (n_truncated > 0) goto cleanup_more;
488
489 /* Ensure relevant postconditions hold. */
490 for (i = 0; i < si->symtab_used-1; i++) {
491 /* No zero-sized symbols. */
492 vg_assert(si->symtab[i].size > 0);
493 /* In order. */
494 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
495 /* No overlaps. */
496 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
497 < si->symtab[i+1].addr);
498 }
499# undef SWAP
500}
501
502
503
504/* Sort the location table by starting address. Mash the table around
505 so as to establish the property that addresses are in order and the
506 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000507 addresses to locations when we come to query the table.
508*/
sewardjde4a1d02002-03-22 01:27:54 +0000509static
510void canonicaliseLoctab ( SegInfo* si )
511{
512 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
513 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
514 4592, 13776, 33936, 86961, 198768,
515 463792, 1391376 };
516 Int lo = 0;
517 Int hi = si->loctab_used-1;
518 Int i, j, h, bigN, hp;
519 RiLoc v;
520
521# define SWAP(ty,aa,bb) \
522 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
523
524 /* Sort by start address. */
525
526 bigN = hi - lo + 1; if (bigN < 2) return;
527 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
528 vg_assert(0 <= hp && hp < 16);
529
530 for (; hp >= 0; hp--) {
531 h = incs[hp];
532 i = lo + h;
533 while (1) {
534 if (i > hi) break;
535 v = si->loctab[i];
536 j = i;
537 while (si->loctab[j-h].addr > v.addr) {
538 si->loctab[j] = si->loctab[j-h];
539 j = j - h;
540 if (j <= (lo + h - 1)) break;
541 }
542 si->loctab[j] = v;
543 i++;
544 }
545 }
546
547 /* If two adjacent entries overlap, truncate the first. */
548 for (i = 0; i < si->loctab_used-1; i++) {
549 vg_assert(si->loctab[i].size < 10000);
550 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
551 /* Do this in signed int32 because the actual .size fields
552 are unsigned 16s. */
553 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
554 if (new_size < 0) {
555 si->loctab[i].size = 0;
556 } else
557 if (new_size >= 65536) {
558 si->loctab[i].size = 65535;
559 } else {
560 si->loctab[i].size = (UShort)new_size;
561 }
562 }
563 }
564
565 /* Zap any zero-sized entries resulting from the truncation
566 process. */
567 j = 0;
568 for (i = 0; i < si->loctab_used; i++) {
569 if (si->loctab[i].size > 0) {
570 si->loctab[j] = si->loctab[i];
571 j++;
572 }
573 }
574 si->loctab_used = j;
575
576 /* Ensure relevant postconditions hold. */
577 for (i = 0; i < si->loctab_used-1; i++) {
578 /*
579 VG_(printf)("%d (%d) %d 0x%x\n",
580 i, si->loctab[i+1].confident,
581 si->loctab[i+1].size, si->loctab[i+1].addr );
582 */
583 /* No zero-sized symbols. */
584 vg_assert(si->loctab[i].size > 0);
585 /* In order. */
586 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
587 /* No overlaps. */
588 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
589 < si->loctab[i+1].addr);
590 }
591# undef SWAP
592}
593
594
595/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000596/*--- Read STABS format debug info. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000597/*------------------------------------------------------------*/
598
sewardjb51f2e62002-06-01 23:11:19 +0000599/* Stabs entry types, from:
600 * The "stabs" debug format
601 * Menapace, Kingdon and MacKenzie
602 * Cygnus Support
603 */
604typedef enum { N_GSYM = 32, /* Global symbol */
605 N_FUN = 36, /* Function start or end */
606 N_STSYM = 38, /* Data segment file-scope variable */
607 N_LCSYM = 40, /* BSS segment file-scope variable */
608 N_RSYM = 64, /* Register variable */
609 N_SLINE = 68, /* Source line number */
610 N_SO = 100, /* Source file path and name */
611 N_LSYM = 128, /* Stack variable or type */
612 N_SOL = 132, /* Include file name */
613 N_LBRAC = 192, /* Start of lexical block */
614 N_RBRAC = 224 /* End of lexical block */
615 } stab_types;
616
617
618/* Read stabs-format debug info. This is all rather horrible because
619 stabs is a underspecified, kludgy hack.
620*/
621static
622void read_debuginfo_stabs ( SegInfo* si,
623 UChar* stabC, Int stab_sz,
624 UChar* stabstr, Int stabstr_sz )
sewardjde4a1d02002-03-22 01:27:54 +0000625{
sewardjb51f2e62002-06-01 23:11:19 +0000626 Int i;
627 Int curr_filenmoff;
628 Addr curr_fnbaseaddr;
629 Char *curr_file_name, *curr_fn_name;
630 Int n_stab_entries;
631 Int prev_lineno, lineno;
632 Int lineno_overflows;
633 Bool same_file;
634 struct nlist* stab = (struct nlist*)stabC;
635 /* Ok. It all looks plausible. Go on and read debug data.
636 stab kinds: 100 N_SO a source file name
637 68 N_SLINE a source line number
638 36 N_FUN start of a function
njn4f9c9342002-04-29 16:03:24 +0000639
sewardjb51f2e62002-06-01 23:11:19 +0000640 In this loop, we maintain a current file name, updated as
641 N_SO/N_SOLs appear, and a current function base address,
642 updated as N_FUNs appear. Based on that, address ranges for
643 N_SLINEs are calculated, and stuffed into the line info table.
sewardjde4a1d02002-03-22 01:27:54 +0000644
sewardjb51f2e62002-06-01 23:11:19 +0000645 Finding the instruction address range covered by an N_SLINE is
646 complicated; see the N_SLINE case below.
647 */
648 curr_filenmoff = addStr(si,"???");
649 curr_fnbaseaddr = (Addr)NULL;
650 curr_file_name = curr_fn_name = (Char*)NULL;
651 lineno = prev_lineno = 0;
652 lineno_overflows = 0;
653 same_file = True;
sewardjde4a1d02002-03-22 01:27:54 +0000654
sewardjb51f2e62002-06-01 23:11:19 +0000655 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
njne0ee0712002-05-03 16:41:05 +0000656
sewardjb51f2e62002-06-01 23:11:19 +0000657 for (i = 0; i < n_stab_entries; i++) {
658# if 0
659 VG_(printf) ( " %2d ", i );
660 VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s",
661 stab[i].n_type, stab[i].n_other, stab[i].n_desc,
662 (int)stab[i].n_value,
663 (int)stab[i].n_un.n_strx,
664 stabstr + stab[i].n_un.n_strx );
665 VG_(printf)("\n");
666# endif
njne0ee0712002-05-03 16:41:05 +0000667
sewardjb51f2e62002-06-01 23:11:19 +0000668 Char *no_fn_name = "???";
669
670 switch (stab[i].n_type) {
671 UInt next_addr;
672
673 /* Two complicated things here:
674 *
675 * 1. the n_desc field in 'struct n_list' in a.out.h is only
676 * 16-bits, which gives a maximum of 65535 lines. We handle
677 * files bigger than this by detecting heuristically
678 * overflows -- if the line count goes from 65000-odd to
679 * 0-odd within the same file, we assume it's an overflow.
680 * Once we switch files, we zero the overflow count.
681 *
682 * 2. To compute the instr address range covered by a single
683 * line, find the address of the next thing and compute the
684 * difference. The approach used depends on what kind of
685 * entry/entries follow...
686 */
687 case N_SLINE: {
688 Int this_addr = (UInt)stab[i].n_value;
689
690 /* Although stored as a short, neg values really are >
691 * 32768, hence the UShort cast. Then we use an Int to
692 * handle overflows. */
693 prev_lineno = lineno;
694 lineno = (Int)((UShort)stab[i].n_desc);
695
696 if (prev_lineno > lineno + OVERFLOW_DIFFERENCE && same_file) {
697 VG_(message)(Vg_DebugMsg,
698 "Line number overflow detected (%d --> %d) in %s",
699 prev_lineno, lineno, curr_file_name);
700 lineno_overflows++;
701 }
702 same_file = True;
703
704 LOOP:
705 if (i+1 >= n_stab_entries) {
706 /* If it's the last entry, just guess the range is
707 * four; can't do any better */
708 next_addr = this_addr + 4;
709 } else {
710 switch (stab[i+1].n_type) {
711 /* Easy, common case: use address of next entry */
712 case N_SLINE: case N_SO:
713 next_addr = (UInt)stab[i+1].n_value;
714 break;
715
716 /* Boring one: skip, look for something more
717 useful. */
718 case N_RSYM: case N_LSYM: case N_LBRAC: case N_RBRAC:
719 case N_STSYM: case N_LCSYM: case N_GSYM:
720 i++;
721 goto LOOP;
722
723 /* Should be an end of fun entry, use its address */
724 case N_FUN:
725 if ('\0' == * (stabstr + stab[i+1].n_un.n_strx) ) {
726 next_addr = (UInt)stab[i+1].n_value;
727 } else {
728 VG_(message)(Vg_DebugMsg,
729 "warning: function %s missing closing "
730 "N_FUN stab at entry %d",
731 curr_fn_name, i );
732 next_addr = this_addr; /* assume zero-size loc */
733 }
734 break;
735
736 /* N_SOL should be followed by an N_SLINE which can
737 be used */
738 case N_SOL:
739 if (i+2 < n_stab_entries && N_SLINE == stab[i+2].n_type) {
740 next_addr = (UInt)stab[i+2].n_value;
741 break;
742 } else {
743 VG_(printf)("unhandled N_SOL stabs case: %d %d %d",
744 stab[i+1].n_type, i, n_stab_entries);
745 VG_(panic)("unhandled N_SOL stabs case");
746 }
747
748 default:
749 VG_(printf)("unhandled (other) stabs case: %d %d",
750 stab[i+1].n_type,i);
751 /* VG_(panic)("unhandled (other) stabs case"); */
752 next_addr = this_addr + 4;
753 break;
754 }
755 }
756
757 addLineInfo ( si, curr_filenmoff, curr_fnbaseaddr + this_addr,
758 curr_fnbaseaddr + next_addr,
759 lineno + lineno_overflows * LINENO_OVERFLOW, i);
760 break;
761 }
762
763 case N_FUN: {
764 if ('\0' != (stabstr + stab[i].n_un.n_strx)[0] ) {
765 /* N_FUN with a name -- indicates the start of a fn. */
766 curr_fnbaseaddr = si->offset + (Addr)stab[i].n_value;
767 curr_fn_name = stabstr + stab[i].n_un.n_strx;
768 } else {
769 curr_fn_name = no_fn_name;
770 }
771 break;
772 }
773
774 case N_SOL:
775 if (lineno_overflows != 0) {
776 VG_(message)(Vg_UserMsg,
777 "Warning: file %s is very big (> 65535 lines) "
778 "Line numbers and annotation for this file might "
779 "be wrong. Sorry",
780 curr_file_name);
781 }
782 /* fall through! */
783 case N_SO:
784 lineno_overflows = 0;
785
786 /* seems to give lots of locations in header files */
787 /* case 130: */ /* BINCL */
788 {
789 UChar* nm = stabstr + stab[i].n_un.n_strx;
790 UInt len = VG_(strlen)(nm);
791
792 if (len > 0 && nm[len-1] != '/') {
793 curr_filenmoff = addStr ( si, nm );
794 curr_file_name = stabstr + stab[i].n_un.n_strx;
795 }
796 else
797 if (len == 0)
798 curr_filenmoff = addStr ( si, "?1\0" );
799
800 break;
801 }
802
803# if 0
804 case 162: /* EINCL */
805 curr_filenmoff = addStr ( si, "?2\0" );
806 break;
807# endif
808
809 default:
810 break;
811 }
812 } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000813}
814
815
sewardjb51f2e62002-06-01 23:11:19 +0000816/*------------------------------------------------------------*/
817/*--- Read DWARF2 format debug info. ---*/
818/*------------------------------------------------------------*/
sewardjc134dd92002-06-01 14:21:36 +0000819
820/* Structure found in the .debug_line section. */
821typedef struct
822{
823 UChar li_length [4];
824 UChar li_version [2];
825 UChar li_prologue_length [4];
826 UChar li_min_insn_length [1];
827 UChar li_default_is_stmt [1];
828 UChar li_line_base [1];
829 UChar li_line_range [1];
830 UChar li_opcode_base [1];
831}
832DWARF2_External_LineInfo;
833typedef struct
834{
835 UInt li_length;
836 UShort li_version;
837 UInt li_prologue_length;
838 UChar li_min_insn_length;
839 UChar li_default_is_stmt;
840 Int li_line_base;
841 UChar li_line_range;
842 UChar li_opcode_base;
843}
844DWARF2_Internal_LineInfo;
845/* Line number opcodes. */
846enum dwarf_line_number_ops
847 {
848 DW_LNS_extended_op = 0,
849 DW_LNS_copy = 1,
850 DW_LNS_advance_pc = 2,
851 DW_LNS_advance_line = 3,
852 DW_LNS_set_file = 4,
853 DW_LNS_set_column = 5,
854 DW_LNS_negate_stmt = 6,
855 DW_LNS_set_basic_block = 7,
856 DW_LNS_const_add_pc = 8,
857 DW_LNS_fixed_advance_pc = 9,
858 /* DWARF 3. */
859 DW_LNS_set_prologue_end = 10,
860 DW_LNS_set_epilogue_begin = 11,
861 DW_LNS_set_isa = 12
862 };
863
864/* Line number extended opcodes. */
865enum dwarf_line_number_x_ops
866 {
867 DW_LNE_end_sequence = 1,
868 DW_LNE_set_address = 2,
869 DW_LNE_define_file = 3
870 };
871
872typedef struct State_Machine_Registers
873{
874 Addr address;
875 UInt file;
876 UInt line;
877 UInt column;
878 Int is_stmt;
879 Int basic_block;
880 Int end_sequence;
881/* This variable hold the number of the last entry seen
882 in the File Table. */
883 UInt last_file_entry;
884} SMR;
885
sewardjb51f2e62002-06-01 23:11:19 +0000886
887static
888UInt read_leb128 ( UChar* data, Int* length_return, Int sign )
889{
890 UInt result = 0;
891 UInt num_read = 0;
892 Int shift = 0;
893 UChar byte;
894
895 do
896 {
897 byte = * data ++;
898 num_read ++;
899
900 result |= (byte & 0x7f) << shift;
901
902 shift += 7;
903
904 }
905 while (byte & 0x80);
906
907 if (length_return != NULL)
908 * length_return = num_read;
909
910 if (sign && (shift < 32) && (byte & 0x40))
911 result |= -1 << shift;
912
913 return result;
914}
915
916
sewardjc134dd92002-06-01 14:21:36 +0000917static SMR state_machine_regs;
918
919static void
920reset_state_machine (is_stmt)
921 Int is_stmt;
922{
923 state_machine_regs.address = 0;
924 state_machine_regs.file = 1;
925 state_machine_regs.line = 1;
926 state_machine_regs.column = 0;
927 state_machine_regs.is_stmt = is_stmt;
928 state_machine_regs.basic_block = 0;
929 state_machine_regs.end_sequence = 0;
930 state_machine_regs.last_file_entry = 0;
931}
932
933/* Handled an extend line op. Returns true if this is the end
934 of sequence. */
935static int
936process_extended_line_op (si, fnames, data, is_stmt, pointer_size)
937 SegInfo *si;
938 UInt **fnames;
939 UChar * data;
940 Int is_stmt;
941 Int pointer_size;
942{
943 UChar op_code;
944 Int bytes_read;
945 UInt len;
946 UChar * name;
947 Addr adr;
948
949 len = read_leb128 (data, & bytes_read, 0);
950 data += bytes_read;
951
952 if (len == 0)
953 {
954 VG_(message) (Vg_UserMsg,"badly formed extended line op encountered!\n");
955 return bytes_read;
956 }
957
958 len += bytes_read;
959 op_code = * data ++;
960
961
962 switch (op_code)
963 {
964 case DW_LNE_end_sequence:
965 addLineInfo (si, (*fnames)[state_machine_regs.file], si->offset + (state_machine_regs.address - 1), si->offset + (state_machine_regs.address), 0, 0);
966 reset_state_machine (is_stmt);
967 break;
968
969 case DW_LNE_set_address:
970 /* XXX: Pointer size could be 8 */
971 adr = *((Addr *)data);
972 state_machine_regs.address = adr;
973 break;
974
975 case DW_LNE_define_file:
976
977 ++ state_machine_regs.last_file_entry;
978 name = data;
979 if (*fnames == NULL)
980 *fnames = VG_(malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
981 else
982 *fnames = VG_(realloc)(VG_AR_SYMTAB, *fnames, sizeof (UInt) * (state_machine_regs.last_file_entry + 1));
983 (*fnames)[state_machine_regs.last_file_entry] = addStr (si,name);
984 data += VG_(strlen) ((char *) data) + 1;
985 read_leb128 (data, & bytes_read, 0);
986 data += bytes_read;
987 read_leb128 (data, & bytes_read, 0);
988 data += bytes_read;
989 read_leb128 (data, & bytes_read, 0);
990 break;
991
992 default:
993 break;
994 }
995
996 return len;
997}
998
999
sewardjb51f2e62002-06-01 23:11:19 +00001000static
1001void read_debuginfo_dwarf2 ( SegInfo* si, UChar* dwarf2, Int dwarf2_sz )
sewardjc134dd92002-06-01 14:21:36 +00001002{
1003 DWARF2_External_LineInfo * external;
1004 DWARF2_Internal_LineInfo info;
1005 UChar * standard_opcodes;
sewardjb51f2e62002-06-01 23:11:19 +00001006 UChar * data = dwarf2;
1007 UChar * end = dwarf2 + dwarf2_sz;
sewardjc134dd92002-06-01 14:21:36 +00001008 UChar * end_of_sequence;
1009 UInt *fnames = NULL;
1010
1011
1012 while (data < end)
1013 {
1014 external = (DWARF2_External_LineInfo *) data;
1015
1016 /* Check the length of the block. */
1017 info.li_length =*((UInt *)(external->li_length));
1018
1019 if (info.li_length == 0xffffffff)
1020 {
sewardjb51f2e62002-06-01 23:11:19 +00001021 vg_symerr("64-bit DWARF line info is not supported yet.");
sewardjc134dd92002-06-01 14:21:36 +00001022 break;
1023 }
1024
sewardjb51f2e62002-06-01 23:11:19 +00001025 if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
sewardjc134dd92002-06-01 14:21:36 +00001026 {
sewardjb51f2e62002-06-01 23:11:19 +00001027 vg_symerr("DWARF line info appears to be corrupt - the section is too small");
1028 return;
sewardjc134dd92002-06-01 14:21:36 +00001029 }
1030
1031 /* Check its version number. */
1032 info.li_version =*((UShort *) (external->li_version));
1033 if (info.li_version != 2)
1034 {
sewardjb51f2e62002-06-01 23:11:19 +00001035 vg_symerr("Only DWARF version 2 line info is currently supported.");
1036 return;
sewardjc134dd92002-06-01 14:21:36 +00001037 }
1038
1039 info.li_prologue_length = *((UInt *)(external->li_prologue_length));
1040 info.li_min_insn_length = *((UChar *) (external->li_min_insn_length));
1041 info.li_default_is_stmt = *((UChar *) (external->li_default_is_stmt));
1042 info.li_line_base = *((Int *) (external->li_line_base));
1043 info.li_line_range = *((UChar *) (external->li_line_range));
1044 info.li_opcode_base = *((UChar *) (external->li_opcode_base));
1045
1046 /* Sign extend the line base field. */
1047 info.li_line_base <<= 24;
1048 info.li_line_base >>= 24;
1049
1050 end_of_sequence = data + info.li_length + sizeof (external->li_length);
1051
1052 reset_state_machine (info.li_default_is_stmt);
1053
1054 /* Read the contents of the Opcodes table. */
1055 standard_opcodes = data + sizeof (* external);
1056
1057
1058
1059 /* Read the contents of the Directory table. */
1060 data = standard_opcodes + info.li_opcode_base - 1;
1061
1062 if (* data == 0);
1063 else
1064 {
1065 /* We ignore the directory table, since gcc gives the entire path as part of the filename */
1066 while (* data != 0)
1067 {
1068 data += VG_(strlen) ((char *) data) + 1;
1069 }
1070 }
1071
1072 /* Skip the NUL at the end of the table. */
1073 data ++;
1074
1075 /* Read the contents of the File Name table. */
1076 if (* data == 0);
1077 else
1078 {
1079
1080 while (* data != 0)
1081 {
1082 UChar * name;
1083 Int bytes_read;
1084
1085 ++ state_machine_regs.last_file_entry;
1086 name = data;
1087 /* Since we don't have realloc (0, ....) == malloc (...) semantics, we need to malloc the first time. */
1088
1089 if (fnames == NULL)
1090 fnames = VG_(malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
1091 else
1092 fnames = VG_(realloc)(VG_AR_SYMTAB, fnames, sizeof (UInt) * (state_machine_regs.last_file_entry + 1));
1093 data += VG_(strlen) ((char *) data) + 1;
1094 fnames[state_machine_regs.last_file_entry] = addStr (si,name);
1095
1096 read_leb128 (data, & bytes_read, 0);
1097 data += bytes_read;
1098 read_leb128 (data, & bytes_read, 0);
1099 data += bytes_read;
1100 read_leb128 (data, & bytes_read, 0);
1101 data += bytes_read;
1102 }
1103 }
1104
1105 /* Skip the NUL at the end of the table. */
1106 data ++;
1107
1108 /* Now display the statements. */
1109
1110 while (data < end_of_sequence)
1111 {
1112 UChar op_code;
1113 Int adv;
1114 Int bytes_read;
1115
1116 op_code = * data ++;
1117
1118 if (op_code >= info.li_opcode_base)
1119 {
1120 Int advAddr;
1121 op_code -= info.li_opcode_base;
1122 adv = (op_code / info.li_line_range) * info.li_min_insn_length;
1123 advAddr = adv;
1124 state_machine_regs.address += adv;
1125 adv = (op_code % info.li_line_range) + info.li_line_base;
1126 addLineInfo (si, fnames[state_machine_regs.file], si->offset + (state_machine_regs.address - advAddr), si->offset + (state_machine_regs.address), state_machine_regs.line, 0);
1127 state_machine_regs.line += adv;
1128 }
1129 else switch (op_code)
1130 {
1131 case DW_LNS_extended_op:
1132 data += process_extended_line_op (si, &fnames, data, info.li_default_is_stmt,
1133 sizeof (Addr));
1134 break;
1135
1136 case DW_LNS_copy:
1137 addLineInfo (si, fnames[state_machine_regs.file], si->offset + state_machine_regs.address, si->offset + (state_machine_regs.address + 1), state_machine_regs.line , 0);
1138 break;
1139
1140 case DW_LNS_advance_pc:
1141 adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
1142 data += bytes_read;
1143 state_machine_regs.address += adv;
1144 break;
1145
1146 case DW_LNS_advance_line:
1147 adv = read_leb128 (data, & bytes_read, 1);
1148 data += bytes_read;
1149 state_machine_regs.line += adv;
1150 break;
1151
1152 case DW_LNS_set_file:
1153 adv = read_leb128 (data, & bytes_read, 0);
1154 data += bytes_read;
1155 state_machine_regs.file = adv;
1156 break;
1157
1158 case DW_LNS_set_column:
1159 adv = read_leb128 (data, & bytes_read, 0);
1160 data += bytes_read;
1161 state_machine_regs.column = adv;
1162 break;
1163
1164 case DW_LNS_negate_stmt:
1165 adv = state_machine_regs.is_stmt;
1166 adv = ! adv;
1167 state_machine_regs.is_stmt = adv;
1168 break;
1169
1170 case DW_LNS_set_basic_block:
1171 state_machine_regs.basic_block = 1;
1172 break;
1173
1174 case DW_LNS_const_add_pc:
1175 adv = (((255 - info.li_opcode_base) / info.li_line_range)
1176 * info.li_min_insn_length);
1177 state_machine_regs.address += adv;
1178 break;
1179
1180 case DW_LNS_fixed_advance_pc:
1181 /* XXX: Need something to get 2 bytes */
1182 adv = *((UShort *)data);
1183 data += 2;
1184 state_machine_regs.address += adv;
1185 break;
1186
1187 case DW_LNS_set_prologue_end:
1188 break;
1189
1190 case DW_LNS_set_epilogue_begin:
1191 break;
1192
1193 case DW_LNS_set_isa:
1194 adv = read_leb128 (data, & bytes_read, 0);
1195 data += bytes_read;
1196 break;
1197
1198 default:
1199 {
1200 int j;
1201 for (j = standard_opcodes[op_code - 1]; j > 0 ; --j)
1202 {
1203 read_leb128 (data, &bytes_read, 0);
1204 data += bytes_read;
1205 }
1206 }
1207 break;
1208 }
1209 }
1210 VG_(free)(VG_AR_SYMTAB, fnames);
1211 fnames = NULL;
1212 }
sewardjc134dd92002-06-01 14:21:36 +00001213}
1214
sewardjb51f2e62002-06-01 23:11:19 +00001215
1216/*------------------------------------------------------------*/
1217/*--- Read info from a .so/exe file. ---*/
1218/*------------------------------------------------------------*/
1219
sewardjde4a1d02002-03-22 01:27:54 +00001220/* Read the symbols from the object/exe specified by the SegInfo into
1221 the tables within the supplied SegInfo. */
1222static
1223void vg_read_lib_symbols ( SegInfo* si )
1224{
1225 Elf32_Ehdr* ehdr; /* The ELF header */
1226 Elf32_Shdr* shdr; /* The section table */
1227 UChar* sh_strtab; /* The section table's string table */
sewardjb51f2e62002-06-01 23:11:19 +00001228 UChar* stab; /* The .stab table */
sewardjde4a1d02002-03-22 01:27:54 +00001229 UChar* stabstr; /* The .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001230 UChar* dwarf2; /* The DWARF2 location info table */
sewardjde4a1d02002-03-22 01:27:54 +00001231 Int stab_sz; /* Size in bytes of the .stab table */
1232 Int stabstr_sz; /* Size in bytes of the .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001233 Int dwarf2_sz; /* Size in bytes of the DWARF2 srcloc table*/
sewardjde4a1d02002-03-22 01:27:54 +00001234 Int fd;
1235 Int i;
1236 Bool ok;
1237 Addr oimage;
1238 Int n_oimage;
sewardjb3586202002-05-09 17:38:13 +00001239 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001240
sewardjde4a1d02002-03-22 01:27:54 +00001241 oimage = (Addr)NULL;
1242 if (VG_(clo_verbosity) > 1)
njne0ee0712002-05-03 16:41:05 +00001243 VG_(message)(Vg_UserMsg, "Reading syms from %s", si->filename );
sewardjde4a1d02002-03-22 01:27:54 +00001244
1245 /* mmap the object image aboard, so that we can read symbols and
1246 line number info out of it. It will be munmapped immediately
1247 thereafter; it is only aboard transiently. */
1248
sewardjb3586202002-05-09 17:38:13 +00001249 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001250 if (i != 0) {
1251 vg_symerr("Can't stat .so/.exe (to determine its size)?!");
1252 return;
1253 }
1254 n_oimage = stat_buf.st_size;
1255
1256 fd = VG_(open_read)(si->filename);
1257 if (fd == -1) {
1258 vg_symerr("Can't open .so/.exe to read symbols?!");
1259 return;
1260 }
1261
sewardjb3586202002-05-09 17:38:13 +00001262 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
1263 VKI_PROT_READ, VKI_MAP_PRIVATE, fd, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001264 if (oimage == ((Addr)(-1))) {
1265 VG_(message)(Vg_UserMsg,
1266 "mmap failed on %s", si->filename );
1267 VG_(close)(fd);
1268 return;
1269 }
1270
1271 VG_(close)(fd);
1272
1273 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1274 Now verify that it is a valid ELF .so or executable image.
1275 */
1276 ok = (n_oimage >= sizeof(Elf32_Ehdr));
1277 ehdr = (Elf32_Ehdr*)oimage;
1278
1279 if (ok) {
1280 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
1281 && ehdr->e_ident[EI_MAG1] == 'E'
1282 && ehdr->e_ident[EI_MAG2] == 'L'
1283 && ehdr->e_ident[EI_MAG3] == 'F');
1284 ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
1285 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1286 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
1287 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
1288 ok &= (ehdr->e_machine == EM_386);
1289 ok &= (ehdr->e_version == EV_CURRENT);
1290 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
1291 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
1292 }
1293
1294 if (!ok) {
1295 vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
1296 VG_(munmap) ( (void*)oimage, n_oimage );
1297 return;
1298 }
1299
1300 if (VG_(clo_trace_symtab))
1301 VG_(printf)(
1302 "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
1303 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
1304
1305 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
1306 vg_symerr("ELF section header is beyond image end?!");
1307 VG_(munmap) ( (void*)oimage, n_oimage );
1308 return;
1309 }
1310
1311 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
1312 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1313
1314 /* try and read the object's symbol table */
1315 {
1316 UChar* o_strtab = NULL;
1317 Elf32_Sym* o_symtab = NULL;
1318 UInt o_strtab_sz = 0;
1319 UInt o_symtab_sz = 0;
1320
1321 UChar* o_got = NULL;
1322 UChar* o_plt = NULL;
1323 UInt o_got_sz = 0;
1324 UInt o_plt_sz = 0;
1325
1326 Bool snaffle_it;
1327 Addr sym_addr;
1328
1329 /* find the .stabstr and .stab sections */
1330 for (i = 0; i < ehdr->e_shnum; i++) {
1331 if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
1332 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1333 o_symtab_sz = shdr[i].sh_size;
1334 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1335 /* check image overrun here */
1336 }
1337 if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
1338 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1339 o_strtab_sz = shdr[i].sh_size;
1340 /* check image overrun here */
1341 }
1342
1343 /* find out where the .got and .plt sections will be in the
1344 executable image, not in the object image transiently loaded.
1345 */
1346 if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
1347 o_got = (UChar*)(si->offset
1348 + shdr[i].sh_offset);
1349 o_got_sz = shdr[i].sh_size;
1350 /* check image overrun here */
1351 }
1352 if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
1353 o_plt = (UChar*)(si->offset
1354 + shdr[i].sh_offset);
1355 o_plt_sz = shdr[i].sh_size;
1356 /* check image overrun here */
1357 }
1358
1359 }
1360
1361 if (VG_(clo_trace_symtab)) {
1362 if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
1363 o_plt, o_plt + o_plt_sz - 1 );
1364 if (o_got) VG_(printf)( "GOT: %p .. %p\n",
1365 o_got, o_got + o_got_sz - 1 );
1366 }
1367
1368 if (o_strtab == NULL || o_symtab == NULL) {
1369 vg_symerr(" object doesn't have a symbol table");
1370 } else {
1371 /* Perhaps should start at i = 1; ELF docs suggest that entry
1372 0 always denotes `unknown symbol'. */
1373 for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
1374# if 0
1375 VG_(printf)("raw symbol: ");
1376 switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
1377 case STB_LOCAL: VG_(printf)("LOC "); break;
1378 case STB_GLOBAL: VG_(printf)("GLO "); break;
1379 case STB_WEAK: VG_(printf)("WEA "); break;
1380 case STB_LOPROC: VG_(printf)("lop "); break;
1381 case STB_HIPROC: VG_(printf)("hip "); break;
1382 default: VG_(printf)("??? "); break;
1383 }
1384 switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
1385 case STT_NOTYPE: VG_(printf)("NOT "); break;
1386 case STT_OBJECT: VG_(printf)("OBJ "); break;
1387 case STT_FUNC: VG_(printf)("FUN "); break;
1388 case STT_SECTION: VG_(printf)("SEC "); break;
1389 case STT_FILE: VG_(printf)("FIL "); break;
1390 case STT_LOPROC: VG_(printf)("lop "); break;
1391 case STT_HIPROC: VG_(printf)("hip "); break;
1392 default: VG_(printf)("??? "); break;
1393 }
1394 VG_(printf)(
1395 ": value %p, size %d, name %s\n",
1396 si->offset+(UChar*)o_symtab[i].st_value,
1397 o_symtab[i].st_size,
1398 o_symtab[i].st_name
1399 ? ((Char*)o_strtab+o_symtab[i].st_name)
1400 : (Char*)"NONAME");
1401# endif
1402
1403 /* Figure out if we're interested in the symbol.
1404 Firstly, is it of the right flavour?
1405 */
1406 snaffle_it
1407 = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
1408 ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
1409 ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
1410 &&
1411 (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*||
1412 ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/)
1413 );
1414
1415 /* Secondly, if it's apparently in a GOT or PLT, it's really
1416 a reference to a symbol defined elsewhere, so ignore it.
1417 */
1418 sym_addr = si->offset
1419 + (UInt)o_symtab[i].st_value;
1420 if (o_got != NULL
1421 && sym_addr >= (Addr)o_got
1422 && sym_addr < (Addr)(o_got+o_got_sz)) {
1423 snaffle_it = False;
1424 if (VG_(clo_trace_symtab)) {
1425 VG_(printf)( "in GOT: %s\n",
1426 o_strtab+o_symtab[i].st_name);
1427 }
1428 }
1429 if (o_plt != NULL
1430 && sym_addr >= (Addr)o_plt
1431 && sym_addr < (Addr)(o_plt+o_plt_sz)) {
1432 snaffle_it = False;
1433 if (VG_(clo_trace_symtab)) {
1434 VG_(printf)( "in PLT: %s\n",
1435 o_strtab+o_symtab[i].st_name);
1436 }
1437 }
1438
1439 /* Don't bother if nameless, or zero-sized. */
1440 if (snaffle_it
1441 && (o_symtab[i].st_name == (Elf32_Word)NULL
1442 || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
1443 /* equivalent but cheaper ... */
1444 * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
1445 || o_symtab[i].st_size == 0)) {
1446 snaffle_it = False;
1447 if (VG_(clo_trace_symtab)) {
1448 VG_(printf)( "size=0: %s\n",
1449 o_strtab+o_symtab[i].st_name);
1450 }
1451 }
1452
1453# if 0
1454 /* Avoid _dl_ junk. (Why?) */
1455 /* 01-02-24: disabled until I find out if it really helps. */
1456 if (snaffle_it
1457 && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
1458 || VG_(strncmp)("_r_debug",
1459 o_strtab+o_symtab[i].st_name, 8) == 0)) {
1460 snaffle_it = False;
1461 if (VG_(clo_trace_symtab)) {
1462 VG_(printf)( "_dl_ junk: %s\n",
1463 o_strtab+o_symtab[i].st_name);
1464 }
1465 }
1466# endif
1467
1468 /* This seems to significantly reduce the number of junk
1469 symbols, and particularly reduces the number of
1470 overlapping address ranges. Don't ask me why ... */
1471 if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
1472 snaffle_it = False;
1473 if (VG_(clo_trace_symtab)) {
1474 VG_(printf)( "valu=0: %s\n",
1475 o_strtab+o_symtab[i].st_name);
1476 }
1477 }
1478
1479 /* If no part of the symbol falls within the mapped range,
1480 ignore it. */
1481 if (sym_addr+o_symtab[i].st_size <= si->start
1482 || sym_addr >= si->start+si->size) {
1483 snaffle_it = False;
1484 }
1485
1486 if (snaffle_it) {
1487 /* it's an interesting symbol; record ("snaffle") it. */
1488 RiSym sym;
1489 Char* t0 = o_symtab[i].st_name
1490 ? (Char*)(o_strtab+o_symtab[i].st_name)
1491 : (Char*)"NONAME";
1492 Int nmoff = addStr ( si, t0 );
1493 vg_assert(nmoff >= 0
1494 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
1495 vg_assert( (Int)o_symtab[i].st_value >= 0);
1496 /* VG_(printf)("%p + %d: %s\n", si->addr,
1497 (Int)o_symtab[i].st_value, t0 ); */
1498 sym.addr = sym_addr;
1499 sym.size = o_symtab[i].st_size;
1500 sym.nmoff = nmoff;
1501 addSym ( si, &sym );
1502 }
1503 }
1504 }
1505 }
1506
sewardjb51f2e62002-06-01 23:11:19 +00001507 /* Reading of the stabs and/or dwarf2 debug format information, if
1508 any. */
sewardjde4a1d02002-03-22 01:27:54 +00001509 stabstr = NULL;
1510 stab = NULL;
sewardjb51f2e62002-06-01 23:11:19 +00001511 dwarf2 = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001512 stabstr_sz = 0;
1513 stab_sz = 0;
sewardjb51f2e62002-06-01 23:11:19 +00001514 dwarf2_sz = 0;
1515
1516 /* find the .stabstr / .stab / .debug_line sections */
sewardjde4a1d02002-03-22 01:27:54 +00001517 for (i = 0; i < ehdr->e_shnum; i++) {
1518 if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001519 stab = (UChar*)(oimage + shdr[i].sh_offset);
sewardjde4a1d02002-03-22 01:27:54 +00001520 stab_sz = shdr[i].sh_size;
1521 }
1522 if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
1523 stabstr = (UChar*)(oimage + shdr[i].sh_offset);
1524 stabstr_sz = shdr[i].sh_size;
1525 }
sewardjc134dd92002-06-01 14:21:36 +00001526 if (0 == VG_(strcmp)(".debug_line",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001527 dwarf2 = (UChar *)(oimage + shdr[i].sh_offset);
1528 dwarf2_sz = shdr[i].sh_size;
sewardjc134dd92002-06-01 14:21:36 +00001529 }
sewardjde4a1d02002-03-22 01:27:54 +00001530 }
1531
sewardjb51f2e62002-06-01 23:11:19 +00001532 if ((stab == NULL || stabstr == NULL) && dwarf2 == NULL) {
sewardjde4a1d02002-03-22 01:27:54 +00001533 vg_symerr(" object doesn't have any debug info");
1534 VG_(munmap) ( (void*)oimage, n_oimage );
1535 return;
1536 }
1537
1538 if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
1539 || stabstr_sz + (UChar*)stabstr
1540 > n_oimage + (UChar*)oimage ) {
sewardjb51f2e62002-06-01 23:11:19 +00001541 vg_symerr(" ELF (stabs) debug data is beyond image end?!");
sewardjde4a1d02002-03-22 01:27:54 +00001542 VG_(munmap) ( (void*)oimage, n_oimage );
1543 return;
1544 }
1545
sewardjb51f2e62002-06-01 23:11:19 +00001546 if ( dwarf2_sz + (UChar*)dwarf2 > n_oimage + (UChar*)oimage ) {
1547 vg_symerr(" ELF (dwarf2) debug data is beyond image end?!");
1548 VG_(munmap) ( (void*)oimage, n_oimage );
1549 return;
1550 }
sewardjde4a1d02002-03-22 01:27:54 +00001551
sewardjb51f2e62002-06-01 23:11:19 +00001552 /* Looks plausible. Go on and read debug data. */
1553 if (stab != NULL && stabstr != NULL) {
1554 read_debuginfo_stabs ( si, stab, stab_sz, stabstr, stabstr_sz );
1555 }
sewardjde4a1d02002-03-22 01:27:54 +00001556
sewardjb51f2e62002-06-01 23:11:19 +00001557 if (dwarf2 != NULL) {
1558 read_debuginfo_dwarf2 ( si, dwarf2, dwarf2_sz );
1559 }
sewardjde4a1d02002-03-22 01:27:54 +00001560
1561 /* Last, but not least, heave the oimage back overboard. */
1562 VG_(munmap) ( (void*)oimage, n_oimage );
1563}
1564
1565
1566/*------------------------------------------------------------*/
1567/*--- Main entry point for symbols table reading. ---*/
1568/*------------------------------------------------------------*/
1569
1570/* The root structure for the entire symbol table system. It is a
1571 linked list of SegInfos. Note that this entire mechanism assumes
1572 that what we read from /proc/self/maps doesn't contain overlapping
1573 address ranges, and as a result the SegInfos in this list describe
1574 disjoint address ranges.
1575*/
1576static SegInfo* segInfo = NULL;
1577
1578
1579static
1580void read_symtab_callback (
1581 Addr start, UInt size,
1582 Char rr, Char ww, Char xx,
1583 UInt foffset, UChar* filename )
1584{
1585 SegInfo* si;
1586
1587 /* Stay sane ... */
1588 if (size == 0)
1589 return;
1590
1591 /* We're only interested in collecting symbols in executable
1592 segments which are associated with a real file. Hence: */
1593 if (filename == NULL || xx != 'x')
1594 return;
1595 if (0 == VG_(strcmp)(filename, "/dev/zero"))
1596 return;
1597
1598 /* Perhaps we already have this one? If so, skip. */
1599 for (si = segInfo; si != NULL; si = si->next) {
1600 /*
1601 if (0==VG_(strcmp)(si->filename, filename))
1602 VG_(printf)("same fnames: %c%c%c (%p, %d) (%p, %d) %s\n",
1603 rr,ww,xx,si->start,si->size,start,size,filename);
1604 */
1605 /* For some reason the observed size of a mapping can change, so
1606 we don't use that to determine uniqueness. */
1607 if (si->start == start
1608 /* && si->size == size */
1609 && 0==VG_(strcmp)(si->filename, filename)) {
1610 return;
1611 }
1612 }
1613
1614 /* Get the record initialised right. */
1615 si = VG_(malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
1616 si->next = segInfo;
1617 segInfo = si;
1618
1619 si->start = start;
1620 si->size = size;
1621 si->foffset = foffset;
1622 si->filename = VG_(malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(filename));
1623 VG_(strcpy)(si->filename, filename);
1624
1625 si->symtab = NULL;
1626 si->symtab_size = si->symtab_used = 0;
1627 si->loctab = NULL;
1628 si->loctab_size = si->loctab_used = 0;
1629 si->strtab = NULL;
1630 si->strtab_size = si->strtab_used = 0;
1631
1632 /* Kludge ... */
1633 si->offset
1634 = si->start==VG_ASSUMED_EXE_BASE ? 0 : si->start;
1635
1636 /* And actually fill it up. */
sewardj18d75132002-05-16 11:06:21 +00001637 if (VG_(clo_instrument) || VG_(clo_cachesim)) {
1638 vg_read_lib_symbols ( si );
1639 canonicaliseSymtab ( si );
1640 canonicaliseLoctab ( si );
1641 }
sewardjde4a1d02002-03-22 01:27:54 +00001642}
1643
1644
1645/* This one really is the Head Honcho. Update the symbol tables to
1646 reflect the current state of /proc/self/maps. Rather than re-read
1647 everything, just read the entries which are not already in segInfo.
1648 So we can call here repeatedly, after every mmap of a non-anonymous
1649 segment with execute permissions, for example, to pick up new
1650 libraries as they are dlopen'd. Conversely, when the client does
1651 munmap(), vg_symtab_notify_munmap() throws away any symbol tables
1652 which happen to correspond to the munmap()d area. */
1653void VG_(read_symbols) ( void )
1654{
sewardjde4a1d02002-03-22 01:27:54 +00001655 VG_(read_procselfmaps) ( read_symtab_callback );
1656
1657 /* Do a sanity check on the symbol tables: ensure that the address
1658 space pieces they cover do not overlap (otherwise we are severely
1659 hosed). This is a quadratic algorithm, but there shouldn't be
1660 many of them.
1661 */
1662 { SegInfo *si, *si2;
1663 for (si = segInfo; si != NULL; si = si->next) {
1664 /* Check no overlap between *si and those in the rest of the
1665 list. */
1666 for (si2 = si->next; si2 != NULL; si2 = si2->next) {
1667 Addr lo = si->start;
1668 Addr hi = si->start + si->size - 1;
1669 Addr lo2 = si2->start;
1670 Addr hi2 = si2->start + si2->size - 1;
1671 Bool overlap;
1672 vg_assert(lo < hi);
1673 vg_assert(lo2 < hi2);
1674 /* the main assertion */
1675 overlap = (lo <= lo2 && lo2 <= hi)
1676 || (lo <= hi2 && hi2 <= hi);
sewardjde4a1d02002-03-22 01:27:54 +00001677 if (overlap) {
1678 VG_(printf)("\n\nOVERLAPPING SEGMENTS\n" );
1679 ppSegInfo ( si );
1680 ppSegInfo ( si2 );
1681 VG_(printf)("\n\n");
1682 vg_assert(! overlap);
1683 }
1684 }
1685 }
1686 }
1687}
1688
1689
1690/* When an munmap() call happens, check to see whether it corresponds
1691 to a segment for a .so, and if so discard the relevant SegInfo.
1692 This might not be a very clever idea from the point of view of
1693 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001694 maintain the no-overlapping invariant.
1695
1696 16 May 02: Returns a Bool indicating whether or not the discarded
1697 range falls inside a known executable segment. See comment at top
1698 of file for why.
sewardjde4a1d02002-03-22 01:27:54 +00001699*/
sewardj18d75132002-05-16 11:06:21 +00001700Bool VG_(symtab_notify_munmap) ( Addr start, UInt length )
sewardjde4a1d02002-03-22 01:27:54 +00001701{
1702 SegInfo *prev, *curr;
1703
sewardjde4a1d02002-03-22 01:27:54 +00001704 prev = NULL;
1705 curr = segInfo;
1706 while (True) {
1707 if (curr == NULL) break;
1708 if (start == curr->start) break;
1709 prev = curr;
1710 curr = curr->next;
1711 }
sewardj18d75132002-05-16 11:06:21 +00001712 if (curr == NULL)
1713 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001714
1715 VG_(message)(Vg_UserMsg,
1716 "discard syms in %s due to munmap()",
1717 curr->filename ? curr->filename : (UChar*)"???");
1718
1719 vg_assert(prev == NULL || prev->next == curr);
1720
1721 if (prev == NULL) {
1722 segInfo = curr->next;
1723 } else {
1724 prev->next = curr->next;
1725 }
1726
1727 freeSegInfo(curr);
sewardj18d75132002-05-16 11:06:21 +00001728 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001729}
1730
1731
1732/*------------------------------------------------------------*/
1733/*--- Use of symbol table & location info to create ---*/
1734/*--- plausible-looking stack dumps. ---*/
1735/*------------------------------------------------------------*/
1736
1737/* Find a symbol-table index containing the specified pointer, or -1
1738 if not found. Binary search. */
1739
1740static Int search_one_symtab ( SegInfo* si, Addr ptr )
1741{
1742 Addr a_mid_lo, a_mid_hi;
1743 Int mid,
1744 lo = 0,
1745 hi = si->symtab_used-1;
1746 while (True) {
1747 /* current unsearched space is from lo to hi, inclusive. */
1748 if (lo > hi) return -1; /* not found */
1749 mid = (lo + hi) / 2;
1750 a_mid_lo = si->symtab[mid].addr;
1751 a_mid_hi = ((Addr)si->symtab[mid].addr) + si->symtab[mid].size - 1;
1752
1753 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1754 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1755 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1756 return mid;
1757 }
1758}
1759
1760
1761/* Search all symtabs that we know about to locate ptr. If found, set
1762 *psi to the relevant SegInfo, and *symno to the symtab entry number
1763 within that. If not found, *psi is set to NULL. */
1764
1765static void search_all_symtabs ( Addr ptr, SegInfo** psi, Int* symno )
1766{
1767 Int sno;
1768 SegInfo* si;
1769 for (si = segInfo; si != NULL; si = si->next) {
1770 if (si->start <= ptr && ptr < si->start+si->size) {
1771 sno = search_one_symtab ( si, ptr );
1772 if (sno == -1) goto not_found;
1773 *symno = sno;
1774 *psi = si;
1775 return;
1776 }
1777 }
1778 not_found:
1779 *psi = NULL;
1780}
1781
1782
1783/* Find a location-table index containing the specified pointer, or -1
1784 if not found. Binary search. */
1785
1786static Int search_one_loctab ( SegInfo* si, Addr ptr )
1787{
1788 Addr a_mid_lo, a_mid_hi;
1789 Int mid,
1790 lo = 0,
1791 hi = si->loctab_used-1;
1792 while (True) {
1793 /* current unsearched space is from lo to hi, inclusive. */
1794 if (lo > hi) return -1; /* not found */
1795 mid = (lo + hi) / 2;
1796 a_mid_lo = si->loctab[mid].addr;
1797 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1798
1799 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1800 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1801 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1802 return mid;
1803 }
1804}
1805
1806
1807/* Search all loctabs that we know about to locate ptr. If found, set
1808 *psi to the relevant SegInfo, and *locno to the loctab entry number
1809 within that. If not found, *psi is set to NULL.
1810*/
1811static void search_all_loctabs ( Addr ptr, SegInfo** psi, Int* locno )
1812{
1813 Int lno;
1814 SegInfo* si;
1815 for (si = segInfo; si != NULL; si = si->next) {
1816 if (si->start <= ptr && ptr < si->start+si->size) {
1817 lno = search_one_loctab ( si, ptr );
1818 if (lno == -1) goto not_found;
1819 *locno = lno;
1820 *psi = si;
1821 return;
1822 }
1823 }
1824 not_found:
1825 *psi = NULL;
1826}
1827
1828
1829/* The whole point of this whole big deal: map a code address to a
1830 plausible symbol name. Returns False if no idea; otherwise True.
1831 Caller supplies buf and nbuf. If no_demangle is True, don't do
1832 demangling, regardless of vg_clo_demangle -- probably because the
1833 call has come from vg_what_fn_or_object_is_this. */
njn4f9c9342002-04-29 16:03:24 +00001834Bool VG_(what_fn_is_this) ( Bool no_demangle, Addr a,
1835 Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001836{
1837 SegInfo* si;
1838 Int sno;
1839 search_all_symtabs ( a, &si, &sno );
1840 if (si == NULL)
1841 return False;
1842 if (no_demangle) {
1843 VG_(strncpy_safely)
1844 ( buf, & si->strtab[si->symtab[sno].nmoff], nbuf );
1845 } else {
1846 VG_(demangle) ( & si->strtab[si->symtab[sno].nmoff], buf, nbuf );
1847 }
1848 return True;
1849}
1850
1851
1852/* Map a code address to the name of a shared object file. Returns
1853 False if no idea; otherwise False. Caller supplies buf and
1854 nbuf. */
1855static
1856Bool vg_what_object_is_this ( Addr a, Char* buf, Int nbuf )
1857{
1858 SegInfo* si;
1859 for (si = segInfo; si != NULL; si = si->next) {
1860 if (si->start <= a && a < si->start+si->size) {
1861 VG_(strncpy_safely)(buf, si->filename, nbuf);
1862 return True;
1863 }
1864 }
1865 return False;
1866}
1867
1868/* Return the name of an erring fn in a way which is useful
1869 for comparing against the contents of a suppressions file.
1870 Always writes something to buf. Also, doesn't demangle the
1871 name, because we want to refer to mangled names in the
1872 suppressions file.
1873*/
1874void VG_(what_obj_and_fun_is_this) ( Addr a,
1875 Char* obj_buf, Int n_obj_buf,
1876 Char* fun_buf, Int n_fun_buf )
1877{
1878 (void)vg_what_object_is_this ( a, obj_buf, n_obj_buf );
njn4f9c9342002-04-29 16:03:24 +00001879 (void)VG_(what_fn_is_this) ( True, a, fun_buf, n_fun_buf );
sewardjde4a1d02002-03-22 01:27:54 +00001880}
1881
1882
1883/* Map a code address to a (filename, line number) pair.
1884 Returns True if successful.
1885*/
njn4f9c9342002-04-29 16:03:24 +00001886Bool VG_(what_line_is_this)( Addr a,
1887 UChar* filename, Int n_filename,
1888 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001889{
1890 SegInfo* si;
1891 Int locno;
1892 search_all_loctabs ( a, &si, &locno );
1893 if (si == NULL)
1894 return False;
1895 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
1896 n_filename);
1897 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00001898
sewardjde4a1d02002-03-22 01:27:54 +00001899 return True;
1900}
1901
1902
1903/* Print a mini stack dump, showing the current location. */
1904void VG_(mini_stack_dump) ( ExeContext* ec )
1905{
1906
1907#define APPEND(str) \
1908 { UChar* sss; \
1909 for (sss = str; n < M_VG_ERRTXT-1 && *sss != 0; n++,sss++) \
1910 buf[n] = *sss; \
1911 buf[n] = 0; \
1912 }
1913
1914 Bool know_fnname;
1915 Bool know_objname;
1916 Bool know_srcloc;
1917 UInt lineno;
1918 UChar ibuf[20];
1919 UInt i, n, clueless;
1920
1921 UChar buf[M_VG_ERRTXT];
1922 UChar buf_fn[M_VG_ERRTXT];
1923 UChar buf_obj[M_VG_ERRTXT];
1924 UChar buf_srcloc[M_VG_ERRTXT];
1925
1926 Int stop_at = VG_(clo_backtrace_size);
1927
1928 n = 0;
1929
njn4f9c9342002-04-29 16:03:24 +00001930 know_fnname = VG_(what_fn_is_this)(False,ec->eips[0], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00001931 know_objname = vg_what_object_is_this(ec->eips[0], buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00001932 know_srcloc = VG_(what_line_is_this)(ec->eips[0],
1933 buf_srcloc, M_VG_ERRTXT,
1934 &lineno);
sewardjde4a1d02002-03-22 01:27:54 +00001935
1936 APPEND(" at ");
1937 VG_(sprintf)(ibuf,"0x%x: ", ec->eips[0]);
1938 APPEND(ibuf);
1939 if (know_fnname) {
1940 APPEND(buf_fn);
1941 if (!know_srcloc && know_objname) {
1942 APPEND(" (in ");
1943 APPEND(buf_obj);
1944 APPEND(")");
1945 }
1946 } else if (know_objname && !know_srcloc) {
1947 APPEND("(within ");
1948 APPEND(buf_obj);
1949 APPEND(")");
1950 } else {
1951 APPEND("???");
1952 }
1953 if (know_srcloc) {
1954 APPEND(" (");
1955 APPEND(buf_srcloc);
1956 APPEND(":");
1957 VG_(sprintf)(ibuf,"%d",lineno);
1958 APPEND(ibuf);
1959 APPEND(")");
1960 }
1961 VG_(message)(Vg_UserMsg, "%s", buf);
1962
1963 clueless = 0;
1964 for (i = 1; i < stop_at; i++) {
njn4f9c9342002-04-29 16:03:24 +00001965 know_fnname = VG_(what_fn_is_this)(False,ec->eips[i], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00001966 know_objname = vg_what_object_is_this(ec->eips[i],buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00001967 know_srcloc = VG_(what_line_is_this)(ec->eips[i],
sewardjde4a1d02002-03-22 01:27:54 +00001968 buf_srcloc, M_VG_ERRTXT,
1969 &lineno);
1970 n = 0;
1971 APPEND(" by ");
1972 if (ec->eips[i] == 0) {
1973 APPEND("<bogus frame pointer> ");
1974 } else {
1975 VG_(sprintf)(ibuf,"0x%x: ",ec->eips[i]);
1976 APPEND(ibuf);
1977 }
1978 if (know_fnname) {
1979 APPEND(buf_fn)
1980 if (!know_srcloc && know_objname) {
1981 APPEND(" (in ");
1982 APPEND(buf_obj);
1983 APPEND(")");
1984 }
1985 } else {
1986 if (know_objname && !know_srcloc) {
1987 APPEND("(within ");
1988 APPEND(buf_obj);
1989 APPEND(")");
1990 } else {
1991 APPEND("???");
1992 }
1993 if (!know_srcloc) clueless++;
1994 if (clueless == 2)
1995 i = stop_at; /* force exit after this iteration */
1996 };
1997 if (know_srcloc) {
1998 APPEND(" (");
1999 APPEND(buf_srcloc);
2000 APPEND(":");
2001 VG_(sprintf)(ibuf,"%d",lineno);
2002 APPEND(ibuf);
2003 APPEND(")");
2004 }
2005 VG_(message)(Vg_UserMsg, "%s", buf);
2006 }
2007}
2008
2009#undef APPEND
2010
2011/*--------------------------------------------------------------------*/
2012/*--- end vg_symtab2.c ---*/
2013/*--------------------------------------------------------------------*/