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