blob: fb40bdf575127208a9cd89a54cf461cbb15ff2f4 [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,
sewardj08a50f62002-06-17 02:21:20 +0000251 Int entry /* only needed for debug printing */
252 )
sewardjb51f2e62002-06-01 23:11:19 +0000253{
254 RiLoc loc;
255 Int size = next - this;
256
257 /* Ignore zero-sized locs */
258 if (this == next) return;
259
260 /* Maximum sanity checking. Some versions of GNU as do a shabby
261 * job with stabs entries; if anything looks suspicious, revert to
262 * a size of 1. This should catch the instruction of interest
263 * (since if using asm-level debug info, one instruction will
264 * correspond to one line, unlike with C-level debug info where
265 * multiple instructions can map to the one line), but avoid
266 * catching any other instructions bogusly. */
267 if (this > next) {
268 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000269 "warning: line info addresses out of order "
sewardjb51f2e62002-06-01 23:11:19 +0000270 "at entry %d: 0x%x 0x%x", entry, this, next);
271 size = 1;
272 }
273
274 if (size > MAX_LOC_SIZE) {
275 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000276 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000277 "at entry %d: %d", entry, size);
278 size = 1;
279 }
280
sewardje509f4f2002-06-04 17:11:03 +0000281
sewardj08a50f62002-06-17 02:21:20 +0000282#if 0
283 if (this >= 0 && this < 1000) {
284 this += si->start;
285 next += si->start;
286 }
287#endif
288
289 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000290 if (this >= si->start + si->size || next-1 < si->start) {
sewardj08a50f62002-06-17 02:21:20 +0000291 VG_(message)(Vg_DebugMsg,
292 "warning: ignoring line info entry falling "
293 "outside current SegInfo: %p %p %p %p",
294 si->start, si->start + si->size,
295 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000296 return;
297 }
298
299 vg_assert(lineno >= 0);
300 if (lineno > MAX_LINENO) {
301 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000302 "warning: ignoring line info entry with "
303 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000304 VG_(message)(Vg_UserMsg,
305 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000306 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000307 return;
308 }
sewardjb51f2e62002-06-01 23:11:19 +0000309
310 loc.addr = this;
311 loc.size = (UShort)size;
312 loc.lineno = lineno;
313 loc.fnmoff = fnmoff;
314 addLoc ( si, &loc );
315}
316
sewardjde4a1d02002-03-22 01:27:54 +0000317
318/*------------------------------------------------------------*/
319/*--- Helpers ---*/
320/*------------------------------------------------------------*/
321
322/* Non-fatal -- use vg_panic if terminal. */
323static
324void vg_symerr ( Char* msg )
325{
326 if (VG_(clo_verbosity) > 1)
327 VG_(message)(Vg_UserMsg,"%s", msg );
328}
329
330
331/* Print a symbol. */
332static
333void printSym ( SegInfo* si, Int i )
334{
335 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
336 i,
337 si->symtab[i].addr,
338 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
339 &si->strtab[si->symtab[i].nmoff] );
340}
341
342
343#if 0
344/* Print the entire sym tab. */
345static __attribute__ ((unused))
346void printSymtab ( void )
347{
348 Int i;
349 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
350 for (i = 0; i < vg_symtab_used; i++)
351 printSym(i);
352 VG_(printf)("------ BEGIN vg_symtab ------\n");
353}
354#endif
355
356#if 0
357/* Paranoid strcat. */
358static
359void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
360{
361 UInt i = 0, j = 0;
362 while (True) {
363 if (i >= maxlen) return;
364 if (dst[i] == 0) break;
365 i++;
366 }
367 while (True) {
368 if (i >= maxlen) return;
369 dst[i] = src[j];
370 if (src[j] == 0) return;
371 i++; j++;
372 }
373}
374#endif
375
sewardjb51f2e62002-06-01 23:11:19 +0000376
sewardjde4a1d02002-03-22 01:27:54 +0000377/*------------------------------------------------------------*/
378/*--- Canonicalisers ---*/
379/*------------------------------------------------------------*/
380
381/* Sort the symtab by starting address, and emit warnings if any
382 symbols have overlapping address ranges. We use that old chestnut,
383 shellsort. Mash the table around so as to establish the property
384 that addresses are in order and the ranges to not overlap. This
385 facilitates using binary search to map addresses to symbols when we
386 come to query the table.
387*/
388static
389void canonicaliseSymtab ( SegInfo* si )
390{
391 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
392 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
393 4592, 13776, 33936, 86961, 198768,
394 463792, 1391376 };
395 Int lo = 0;
396 Int hi = si->symtab_used-1;
397 Int i, j, h, bigN, hp, n_merged, n_truncated;
398 RiSym v;
399 Addr s1, s2, e1, e2;
400
401# define SWAP(ty,aa,bb) \
402 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
403
404 bigN = hi - lo + 1; if (bigN < 2) return;
405 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
406 vg_assert(0 <= hp && hp < 16);
407
408 for (; hp >= 0; hp--) {
409 h = incs[hp];
410 i = lo + h;
411 while (1) {
412 if (i > hi) break;
413 v = si->symtab[i];
414 j = i;
415 while (si->symtab[j-h].addr > v.addr) {
416 si->symtab[j] = si->symtab[j-h];
417 j = j - h;
418 if (j <= (lo + h - 1)) break;
419 }
420 si->symtab[j] = v;
421 i++;
422 }
423 }
424
425 cleanup_more:
426
427 /* If two symbols have identical address ranges, favour the
428 one with the longer name.
429 */
430 do {
431 n_merged = 0;
432 j = si->symtab_used;
433 si->symtab_used = 0;
434 for (i = 0; i < j; i++) {
435 if (i < j-1
436 && si->symtab[i].addr == si->symtab[i+1].addr
437 && si->symtab[i].size == si->symtab[i+1].size) {
438 n_merged++;
439 /* merge the two into one */
440 if (VG_(strlen)(&si->strtab[si->symtab[i].nmoff])
441 > VG_(strlen)(&si->strtab[si->symtab[i+1].nmoff])) {
442 si->symtab[si->symtab_used++] = si->symtab[i];
443 } else {
444 si->symtab[si->symtab_used++] = si->symtab[i+1];
445 }
446 i++;
447 } else {
448 si->symtab[si->symtab_used++] = si->symtab[i];
449 }
450 }
451 if (VG_(clo_trace_symtab))
452 VG_(printf)( "%d merged\n", n_merged);
453 }
454 while (n_merged > 0);
455
456 /* Detect and "fix" overlapping address ranges. */
457 n_truncated = 0;
458
459 for (i = 0; i < si->symtab_used-1; i++) {
460
461 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
462
463 /* Check for common (no overlap) case. */
464 if (si->symtab[i].addr + si->symtab[i].size
465 <= si->symtab[i+1].addr)
466 continue;
467
468 /* There's an overlap. Truncate one or the other. */
469 if (VG_(clo_trace_symtab)) {
470 VG_(printf)("overlapping address ranges in symbol table\n\t");
471 printSym(si,i);
472 VG_(printf)("\t");
473 printSym(si,i+1);
474 VG_(printf)("\n");
475 }
476
477 /* Truncate one or the other. */
478 s1 = si->symtab[i].addr;
479 s2 = si->symtab[i+1].addr;
480 e1 = s1 + si->symtab[i].size - 1;
481 e2 = s2 + si->symtab[i+1].size - 1;
482 if (s1 < s2) {
483 e1 = s2-1;
484 } else {
485 vg_assert(s1 == s2);
486 if (e1 > e2) {
487 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
488 } else
489 if (e1 < e2) {
490 s2 = e1+1;
491 } else {
492 /* e1 == e2. Identical addr ranges. We'll eventually wind
493 up back at cleanup_more, which will take care of it. */
494 }
495 }
496 si->symtab[i].addr = s1;
497 si->symtab[i+1].addr = s2;
498 si->symtab[i].size = e1 - s1 + 1;
499 si->symtab[i+1].size = e2 - s2 + 1;
500 vg_assert(s1 <= s2);
501 vg_assert(si->symtab[i].size > 0);
502 vg_assert(si->symtab[i+1].size > 0);
503 /* It may be that the i+1 entry now needs to be moved further
504 along to maintain the address order requirement. */
505 j = i+1;
506 while (j < si->symtab_used-1
507 && si->symtab[j].addr > si->symtab[j+1].addr) {
508 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
509 j++;
510 }
511 n_truncated++;
512 }
513
514 if (n_truncated > 0) goto cleanup_more;
515
516 /* Ensure relevant postconditions hold. */
517 for (i = 0; i < si->symtab_used-1; i++) {
518 /* No zero-sized symbols. */
519 vg_assert(si->symtab[i].size > 0);
520 /* In order. */
521 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
522 /* No overlaps. */
523 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
524 < si->symtab[i+1].addr);
525 }
526# undef SWAP
527}
528
529
530
531/* Sort the location table by starting address. Mash the table around
532 so as to establish the property that addresses are in order and the
533 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000534 addresses to locations when we come to query the table.
535*/
sewardjde4a1d02002-03-22 01:27:54 +0000536static
537void canonicaliseLoctab ( SegInfo* si )
538{
539 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
540 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
541 4592, 13776, 33936, 86961, 198768,
542 463792, 1391376 };
543 Int lo = 0;
544 Int hi = si->loctab_used-1;
545 Int i, j, h, bigN, hp;
546 RiLoc v;
547
548# define SWAP(ty,aa,bb) \
549 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
550
551 /* Sort by start address. */
552
553 bigN = hi - lo + 1; if (bigN < 2) return;
554 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
555 vg_assert(0 <= hp && hp < 16);
556
557 for (; hp >= 0; hp--) {
558 h = incs[hp];
559 i = lo + h;
560 while (1) {
561 if (i > hi) break;
562 v = si->loctab[i];
563 j = i;
564 while (si->loctab[j-h].addr > v.addr) {
565 si->loctab[j] = si->loctab[j-h];
566 j = j - h;
567 if (j <= (lo + h - 1)) break;
568 }
569 si->loctab[j] = v;
570 i++;
571 }
572 }
573
574 /* If two adjacent entries overlap, truncate the first. */
575 for (i = 0; i < si->loctab_used-1; i++) {
576 vg_assert(si->loctab[i].size < 10000);
577 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
578 /* Do this in signed int32 because the actual .size fields
579 are unsigned 16s. */
580 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
581 if (new_size < 0) {
582 si->loctab[i].size = 0;
583 } else
584 if (new_size >= 65536) {
585 si->loctab[i].size = 65535;
586 } else {
587 si->loctab[i].size = (UShort)new_size;
588 }
589 }
590 }
591
592 /* Zap any zero-sized entries resulting from the truncation
593 process. */
594 j = 0;
595 for (i = 0; i < si->loctab_used; i++) {
596 if (si->loctab[i].size > 0) {
597 si->loctab[j] = si->loctab[i];
598 j++;
599 }
600 }
601 si->loctab_used = j;
602
603 /* Ensure relevant postconditions hold. */
604 for (i = 0; i < si->loctab_used-1; i++) {
605 /*
606 VG_(printf)("%d (%d) %d 0x%x\n",
607 i, si->loctab[i+1].confident,
608 si->loctab[i+1].size, si->loctab[i+1].addr );
609 */
610 /* No zero-sized symbols. */
611 vg_assert(si->loctab[i].size > 0);
612 /* In order. */
613 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
614 /* No overlaps. */
615 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
616 < si->loctab[i+1].addr);
617 }
618# undef SWAP
619}
620
621
622/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000623/*--- Read STABS format debug info. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000624/*------------------------------------------------------------*/
625
sewardjb51f2e62002-06-01 23:11:19 +0000626/* Stabs entry types, from:
627 * The "stabs" debug format
628 * Menapace, Kingdon and MacKenzie
629 * Cygnus Support
630 */
631typedef enum { N_GSYM = 32, /* Global symbol */
632 N_FUN = 36, /* Function start or end */
633 N_STSYM = 38, /* Data segment file-scope variable */
634 N_LCSYM = 40, /* BSS segment file-scope variable */
635 N_RSYM = 64, /* Register variable */
636 N_SLINE = 68, /* Source line number */
637 N_SO = 100, /* Source file path and name */
638 N_LSYM = 128, /* Stack variable or type */
639 N_SOL = 132, /* Include file name */
640 N_LBRAC = 192, /* Start of lexical block */
641 N_RBRAC = 224 /* End of lexical block */
642 } stab_types;
643
644
645/* Read stabs-format debug info. This is all rather horrible because
646 stabs is a underspecified, kludgy hack.
647*/
648static
649void read_debuginfo_stabs ( SegInfo* si,
650 UChar* stabC, Int stab_sz,
651 UChar* stabstr, Int stabstr_sz )
sewardjde4a1d02002-03-22 01:27:54 +0000652{
sewardjb51f2e62002-06-01 23:11:19 +0000653 Int i;
654 Int curr_filenmoff;
njnb79ad342002-06-05 15:30:30 +0000655 Addr curr_fn_stabs_addr = (Addr)NULL;
656 Addr curr_fnbaseaddr = (Addr)NULL;
sewardjb51f2e62002-06-01 23:11:19 +0000657 Char *curr_file_name, *curr_fn_name;
658 Int n_stab_entries;
njnb79ad342002-06-05 15:30:30 +0000659 Int prev_lineno = 0, lineno = 0;
660 Int lineno_overflows = 0;
661 Bool same_file = True;
sewardjb51f2e62002-06-01 23:11:19 +0000662 struct nlist* stab = (struct nlist*)stabC;
njnb79ad342002-06-05 15:30:30 +0000663
sewardjb51f2e62002-06-01 23:11:19 +0000664 /* Ok. It all looks plausible. Go on and read debug data.
665 stab kinds: 100 N_SO a source file name
666 68 N_SLINE a source line number
667 36 N_FUN start of a function
njn4f9c9342002-04-29 16:03:24 +0000668
sewardjb51f2e62002-06-01 23:11:19 +0000669 In this loop, we maintain a current file name, updated as
670 N_SO/N_SOLs appear, and a current function base address,
671 updated as N_FUNs appear. Based on that, address ranges for
672 N_SLINEs are calculated, and stuffed into the line info table.
sewardjde4a1d02002-03-22 01:27:54 +0000673
sewardjb51f2e62002-06-01 23:11:19 +0000674 Finding the instruction address range covered by an N_SLINE is
675 complicated; see the N_SLINE case below.
676 */
njnb79ad342002-06-05 15:30:30 +0000677 curr_filenmoff = addStr(si,"???");
678 curr_file_name = curr_fn_name = (Char*)NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000679
sewardjb51f2e62002-06-01 23:11:19 +0000680 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
njne0ee0712002-05-03 16:41:05 +0000681
sewardjb51f2e62002-06-01 23:11:19 +0000682 for (i = 0; i < n_stab_entries; i++) {
683# if 0
684 VG_(printf) ( " %2d ", i );
685 VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s",
686 stab[i].n_type, stab[i].n_other, stab[i].n_desc,
687 (int)stab[i].n_value,
688 (int)stab[i].n_un.n_strx,
689 stabstr + stab[i].n_un.n_strx );
690 VG_(printf)("\n");
691# endif
njne0ee0712002-05-03 16:41:05 +0000692
sewardjb51f2e62002-06-01 23:11:19 +0000693 Char *no_fn_name = "???";
694
695 switch (stab[i].n_type) {
696 UInt next_addr;
697
698 /* Two complicated things here:
699 *
700 * 1. the n_desc field in 'struct n_list' in a.out.h is only
701 * 16-bits, which gives a maximum of 65535 lines. We handle
702 * files bigger than this by detecting heuristically
703 * overflows -- if the line count goes from 65000-odd to
704 * 0-odd within the same file, we assume it's an overflow.
705 * Once we switch files, we zero the overflow count.
706 *
707 * 2. To compute the instr address range covered by a single
708 * line, find the address of the next thing and compute the
709 * difference. The approach used depends on what kind of
710 * entry/entries follow...
711 */
712 case N_SLINE: {
713 Int this_addr = (UInt)stab[i].n_value;
714
715 /* Although stored as a short, neg values really are >
716 * 32768, hence the UShort cast. Then we use an Int to
717 * handle overflows. */
718 prev_lineno = lineno;
719 lineno = (Int)((UShort)stab[i].n_desc);
720
721 if (prev_lineno > lineno + OVERFLOW_DIFFERENCE && same_file) {
722 VG_(message)(Vg_DebugMsg,
723 "Line number overflow detected (%d --> %d) in %s",
724 prev_lineno, lineno, curr_file_name);
725 lineno_overflows++;
726 }
727 same_file = True;
728
729 LOOP:
730 if (i+1 >= n_stab_entries) {
731 /* If it's the last entry, just guess the range is
732 * four; can't do any better */
733 next_addr = this_addr + 4;
734 } else {
735 switch (stab[i+1].n_type) {
736 /* Easy, common case: use address of next entry */
737 case N_SLINE: case N_SO:
738 next_addr = (UInt)stab[i+1].n_value;
739 break;
740
741 /* Boring one: skip, look for something more
742 useful. */
743 case N_RSYM: case N_LSYM: case N_LBRAC: case N_RBRAC:
744 case N_STSYM: case N_LCSYM: case N_GSYM:
745 i++;
746 goto LOOP;
747
njnb79ad342002-06-05 15:30:30 +0000748 /* If end-of-this-fun entry, use its address.
749 * If start-of-next-fun entry, find difference between start
750 * of current function and start of next function to work
751 * it out.
752 */
sewardjb51f2e62002-06-01 23:11:19 +0000753 case N_FUN:
754 if ('\0' == * (stabstr + stab[i+1].n_un.n_strx) ) {
755 next_addr = (UInt)stab[i+1].n_value;
756 } else {
njnb79ad342002-06-05 15:30:30 +0000757 next_addr =
758 (UInt)stab[i+1].n_value - curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000759 }
760 break;
761
762 /* N_SOL should be followed by an N_SLINE which can
763 be used */
764 case N_SOL:
765 if (i+2 < n_stab_entries && N_SLINE == stab[i+2].n_type) {
766 next_addr = (UInt)stab[i+2].n_value;
767 break;
768 } else {
769 VG_(printf)("unhandled N_SOL stabs case: %d %d %d",
770 stab[i+1].n_type, i, n_stab_entries);
771 VG_(panic)("unhandled N_SOL stabs case");
772 }
773
774 default:
775 VG_(printf)("unhandled (other) stabs case: %d %d",
776 stab[i+1].n_type,i);
777 /* VG_(panic)("unhandled (other) stabs case"); */
778 next_addr = this_addr + 4;
779 break;
780 }
781 }
782
783 addLineInfo ( si, curr_filenmoff, curr_fnbaseaddr + this_addr,
784 curr_fnbaseaddr + next_addr,
785 lineno + lineno_overflows * LINENO_OVERFLOW, i);
786 break;
787 }
788
789 case N_FUN: {
790 if ('\0' != (stabstr + stab[i].n_un.n_strx)[0] ) {
791 /* N_FUN with a name -- indicates the start of a fn. */
njnb79ad342002-06-05 15:30:30 +0000792 curr_fn_stabs_addr = (Addr)stab[i].n_value;
793 curr_fnbaseaddr = si->offset + curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000794 curr_fn_name = stabstr + stab[i].n_un.n_strx;
795 } else {
796 curr_fn_name = no_fn_name;
797 }
798 break;
799 }
800
801 case N_SOL:
802 if (lineno_overflows != 0) {
803 VG_(message)(Vg_UserMsg,
804 "Warning: file %s is very big (> 65535 lines) "
805 "Line numbers and annotation for this file might "
806 "be wrong. Sorry",
807 curr_file_name);
808 }
809 /* fall through! */
810 case N_SO:
811 lineno_overflows = 0;
812
813 /* seems to give lots of locations in header files */
814 /* case 130: */ /* BINCL */
815 {
816 UChar* nm = stabstr + stab[i].n_un.n_strx;
817 UInt len = VG_(strlen)(nm);
818
819 if (len > 0 && nm[len-1] != '/') {
820 curr_filenmoff = addStr ( si, nm );
821 curr_file_name = stabstr + stab[i].n_un.n_strx;
822 }
823 else
824 if (len == 0)
825 curr_filenmoff = addStr ( si, "?1\0" );
826
827 break;
828 }
829
830# if 0
831 case 162: /* EINCL */
832 curr_filenmoff = addStr ( si, "?2\0" );
833 break;
834# endif
835
836 default:
837 break;
838 }
839 } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000840}
841
842
sewardjb51f2e62002-06-01 23:11:19 +0000843/*------------------------------------------------------------*/
844/*--- Read DWARF2 format debug info. ---*/
845/*------------------------------------------------------------*/
sewardjc134dd92002-06-01 14:21:36 +0000846
847/* Structure found in the .debug_line section. */
848typedef struct
849{
850 UChar li_length [4];
851 UChar li_version [2];
852 UChar li_prologue_length [4];
853 UChar li_min_insn_length [1];
854 UChar li_default_is_stmt [1];
855 UChar li_line_base [1];
856 UChar li_line_range [1];
857 UChar li_opcode_base [1];
858}
859DWARF2_External_LineInfo;
860typedef struct
861{
sewardj08a50f62002-06-17 02:21:20 +0000862 UInt li_length;
sewardjc134dd92002-06-01 14:21:36 +0000863 UShort li_version;
864 UInt li_prologue_length;
865 UChar li_min_insn_length;
866 UChar li_default_is_stmt;
sewardj08a50f62002-06-17 02:21:20 +0000867 Int li_line_base;
sewardjc134dd92002-06-01 14:21:36 +0000868 UChar li_line_range;
869 UChar li_opcode_base;
870}
871DWARF2_Internal_LineInfo;
872/* Line number opcodes. */
873enum dwarf_line_number_ops
874 {
875 DW_LNS_extended_op = 0,
876 DW_LNS_copy = 1,
877 DW_LNS_advance_pc = 2,
878 DW_LNS_advance_line = 3,
879 DW_LNS_set_file = 4,
880 DW_LNS_set_column = 5,
881 DW_LNS_negate_stmt = 6,
882 DW_LNS_set_basic_block = 7,
883 DW_LNS_const_add_pc = 8,
884 DW_LNS_fixed_advance_pc = 9,
885 /* DWARF 3. */
886 DW_LNS_set_prologue_end = 10,
887 DW_LNS_set_epilogue_begin = 11,
888 DW_LNS_set_isa = 12
889 };
890
891/* Line number extended opcodes. */
892enum dwarf_line_number_x_ops
893 {
894 DW_LNE_end_sequence = 1,
895 DW_LNE_set_address = 2,
896 DW_LNE_define_file = 3
897 };
898
899typedef struct State_Machine_Registers
900{
sewardj08a50f62002-06-17 02:21:20 +0000901 Addr address;
sewardjc134dd92002-06-01 14:21:36 +0000902 UInt file;
903 UInt line;
904 UInt column;
905 Int is_stmt;
906 Int basic_block;
sewardj08a50f62002-06-17 02:21:20 +0000907 Int end_sequence;
908 /* This variable hold the number of the last entry seen
909 in the File Table. */
sewardjc134dd92002-06-01 14:21:36 +0000910 UInt last_file_entry;
911} SMR;
912
sewardjb51f2e62002-06-01 23:11:19 +0000913
914static
915UInt read_leb128 ( UChar* data, Int* length_return, Int sign )
916{
sewardj08a50f62002-06-17 02:21:20 +0000917 UInt result = 0;
918 UInt num_read = 0;
919 Int shift = 0;
920 UChar byte;
sewardjb51f2e62002-06-01 23:11:19 +0000921
922 do
923 {
924 byte = * data ++;
925 num_read ++;
926
927 result |= (byte & 0x7f) << shift;
928
929 shift += 7;
930
931 }
932 while (byte & 0x80);
933
934 if (length_return != NULL)
935 * length_return = num_read;
936
937 if (sign && (shift < 32) && (byte & 0x40))
938 result |= -1 << shift;
939
940 return result;
941}
942
943
sewardjc134dd92002-06-01 14:21:36 +0000944static SMR state_machine_regs;
945
sewardj08a50f62002-06-17 02:21:20 +0000946static
947void reset_state_machine ( Int is_stmt )
sewardjc134dd92002-06-01 14:21:36 +0000948{
sewardj08a50f62002-06-17 02:21:20 +0000949 if (0) VG_(printf)("smr.a := %p (reset)\n", 0 );
sewardjc134dd92002-06-01 14:21:36 +0000950 state_machine_regs.address = 0;
951 state_machine_regs.file = 1;
952 state_machine_regs.line = 1;
953 state_machine_regs.column = 0;
954 state_machine_regs.is_stmt = is_stmt;
955 state_machine_regs.basic_block = 0;
956 state_machine_regs.end_sequence = 0;
957 state_machine_regs.last_file_entry = 0;
958}
959
960/* Handled an extend line op. Returns true if this is the end
961 of sequence. */
sewardj08a50f62002-06-17 02:21:20 +0000962static
963int process_extended_line_op( SegInfo *si, UInt** fnames,
964 UChar* data, Int is_stmt, Int pointer_size)
sewardjc134dd92002-06-01 14:21:36 +0000965{
966 UChar op_code;
sewardj08a50f62002-06-17 02:21:20 +0000967 Int bytes_read;
sewardjc134dd92002-06-01 14:21:36 +0000968 UInt len;
969 UChar * name;
sewardj08a50f62002-06-17 02:21:20 +0000970 Addr adr;
sewardjc134dd92002-06-01 14:21:36 +0000971
972 len = read_leb128 (data, & bytes_read, 0);
973 data += bytes_read;
974
975 if (len == 0)
976 {
sewardj08a50f62002-06-17 02:21:20 +0000977 VG_(message)(Vg_UserMsg,
978 "badly formed extended line op encountered!\n");
sewardjc134dd92002-06-01 14:21:36 +0000979 return bytes_read;
980 }
981
982 len += bytes_read;
983 op_code = * data ++;
984
985
986 switch (op_code)
987 {
988 case DW_LNE_end_sequence:
sewardj08a50f62002-06-17 02:21:20 +0000989 if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",
990 si->offset, state_machine_regs.address );
991 addLineInfo (si, (*fnames)[state_machine_regs.file],
992 si->offset + (state_machine_regs.address - 1),
993 si->offset + (state_machine_regs.address),
994 0, 0);
sewardjc134dd92002-06-01 14:21:36 +0000995 reset_state_machine (is_stmt);
996 break;
997
998 case DW_LNE_set_address:
999 /* XXX: Pointer size could be 8 */
sewardj08a50f62002-06-17 02:21:20 +00001000 vg_assert(pointer_size == 4);
sewardjc134dd92002-06-01 14:21:36 +00001001 adr = *((Addr *)data);
sewardj08a50f62002-06-17 02:21:20 +00001002 if (0) VG_(printf)("smr.a := %p\n", adr );
sewardjc134dd92002-06-01 14:21:36 +00001003 state_machine_regs.address = adr;
1004 break;
1005
1006 case DW_LNE_define_file:
sewardjc134dd92002-06-01 14:21:36 +00001007 ++ state_machine_regs.last_file_entry;
1008 name = data;
1009 if (*fnames == NULL)
1010 *fnames = VG_(malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
1011 else
sewardj08a50f62002-06-17 02:21:20 +00001012 *fnames = VG_(realloc)(
1013 VG_AR_SYMTAB, *fnames,
1014 sizeof(UInt)
1015 * (state_machine_regs.last_file_entry + 1));
sewardjc134dd92002-06-01 14:21:36 +00001016 (*fnames)[state_machine_regs.last_file_entry] = addStr (si,name);
1017 data += VG_(strlen) ((char *) data) + 1;
1018 read_leb128 (data, & bytes_read, 0);
1019 data += bytes_read;
1020 read_leb128 (data, & bytes_read, 0);
1021 data += bytes_read;
sewardj08a50f62002-06-17 02:21:20 +00001022 read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001023 break;
1024
1025 default:
1026 break;
1027 }
1028
1029 return len;
1030}
1031
1032
sewardjb51f2e62002-06-01 23:11:19 +00001033static
1034void read_debuginfo_dwarf2 ( SegInfo* si, UChar* dwarf2, Int dwarf2_sz )
sewardjc134dd92002-06-01 14:21:36 +00001035{
1036 DWARF2_External_LineInfo * external;
1037 DWARF2_Internal_LineInfo info;
1038 UChar * standard_opcodes;
sewardjb51f2e62002-06-01 23:11:19 +00001039 UChar * data = dwarf2;
1040 UChar * end = dwarf2 + dwarf2_sz;
sewardjc134dd92002-06-01 14:21:36 +00001041 UChar * end_of_sequence;
sewardj08a50f62002-06-17 02:21:20 +00001042 UInt * fnames = NULL;
sewardjc134dd92002-06-01 14:21:36 +00001043
1044
1045 while (data < end)
1046 {
1047 external = (DWARF2_External_LineInfo *) data;
1048
1049 /* Check the length of the block. */
sewardj08a50f62002-06-17 02:21:20 +00001050 info.li_length = * ((UInt *)(external->li_length));
sewardjc134dd92002-06-01 14:21:36 +00001051
1052 if (info.li_length == 0xffffffff)
1053 {
sewardjb51f2e62002-06-01 23:11:19 +00001054 vg_symerr("64-bit DWARF line info is not supported yet.");
sewardjc134dd92002-06-01 14:21:36 +00001055 break;
1056 }
1057
sewardjb51f2e62002-06-01 23:11:19 +00001058 if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
sewardjc134dd92002-06-01 14:21:36 +00001059 {
sewardj08a50f62002-06-17 02:21:20 +00001060 vg_symerr("DWARF line info appears to be corrupt "
1061 "- the section is too small");
sewardjb51f2e62002-06-01 23:11:19 +00001062 return;
sewardjc134dd92002-06-01 14:21:36 +00001063 }
1064
1065 /* Check its version number. */
sewardj08a50f62002-06-17 02:21:20 +00001066 info.li_version = * ((UShort *) (external->li_version));
sewardjc134dd92002-06-01 14:21:36 +00001067 if (info.li_version != 2)
1068 {
sewardj08a50f62002-06-17 02:21:20 +00001069 vg_symerr("Only DWARF version 2 line info "
1070 "is currently supported.");
sewardjb51f2e62002-06-01 23:11:19 +00001071 return;
sewardjc134dd92002-06-01 14:21:36 +00001072 }
1073
1074 info.li_prologue_length = *((UInt *)(external->li_prologue_length));
1075 info.li_min_insn_length = *((UChar *) (external->li_min_insn_length));
1076 info.li_default_is_stmt = *((UChar *) (external->li_default_is_stmt));
1077 info.li_line_base = *((Int *) (external->li_line_base));
1078 info.li_line_range = *((UChar *) (external->li_line_range));
1079 info.li_opcode_base = *((UChar *) (external->li_opcode_base));
1080
1081 /* Sign extend the line base field. */
1082 info.li_line_base <<= 24;
1083 info.li_line_base >>= 24;
1084
sewardj08a50f62002-06-17 02:21:20 +00001085 end_of_sequence = data + info.li_length
1086 + sizeof (external->li_length);
sewardjc134dd92002-06-01 14:21:36 +00001087
1088 reset_state_machine (info.li_default_is_stmt);
1089
1090 /* Read the contents of the Opcodes table. */
1091 standard_opcodes = data + sizeof (* external);
1092
sewardjc134dd92002-06-01 14:21:36 +00001093 /* Read the contents of the Directory table. */
1094 data = standard_opcodes + info.li_opcode_base - 1;
1095
sewardj08a50f62002-06-17 02:21:20 +00001096 if (* data == 0)
1097 {
1098 }
sewardjc134dd92002-06-01 14:21:36 +00001099 else
1100 {
sewardj08a50f62002-06-17 02:21:20 +00001101 /* We ignore the directory table, since gcc gives the entire
1102 path as part of the filename */
sewardjc134dd92002-06-01 14:21:36 +00001103 while (* data != 0)
1104 {
1105 data += VG_(strlen) ((char *) data) + 1;
1106 }
1107 }
1108
1109 /* Skip the NUL at the end of the table. */
1110 data ++;
1111
1112 /* Read the contents of the File Name table. */
sewardj08a50f62002-06-17 02:21:20 +00001113 if (* data == 0)
1114 {
1115 }
sewardjc134dd92002-06-01 14:21:36 +00001116 else
1117 {
sewardjc134dd92002-06-01 14:21:36 +00001118 while (* data != 0)
1119 {
1120 UChar * name;
1121 Int bytes_read;
1122
sewardj08a50f62002-06-17 02:21:20 +00001123 ++ state_machine_regs.last_file_entry;
sewardjc134dd92002-06-01 14:21:36 +00001124 name = data;
sewardj08a50f62002-06-17 02:21:20 +00001125 /* Since we don't have realloc (0, ....) == malloc (...)
1126 semantics, we need to malloc the first time. */
sewardjc134dd92002-06-01 14:21:36 +00001127
1128 if (fnames == NULL)
1129 fnames = VG_(malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
1130 else
sewardj08a50f62002-06-17 02:21:20 +00001131 fnames = VG_(realloc)(VG_AR_SYMTAB, fnames,
1132 sizeof(UInt)
1133 * (state_machine_regs.last_file_entry + 1));
1134 data += VG_(strlen) ((Char *) data) + 1;
sewardjc134dd92002-06-01 14:21:36 +00001135 fnames[state_machine_regs.last_file_entry] = addStr (si,name);
1136
1137 read_leb128 (data, & bytes_read, 0);
1138 data += bytes_read;
1139 read_leb128 (data, & bytes_read, 0);
1140 data += bytes_read;
1141 read_leb128 (data, & bytes_read, 0);
1142 data += bytes_read;
1143 }
1144 }
1145
1146 /* Skip the NUL at the end of the table. */
1147 data ++;
1148
1149 /* Now display the statements. */
1150
1151 while (data < end_of_sequence)
1152 {
1153 UChar op_code;
1154 Int adv;
1155 Int bytes_read;
1156
1157 op_code = * data ++;
1158
1159 if (op_code >= info.li_opcode_base)
1160 {
1161 Int advAddr;
1162 op_code -= info.li_opcode_base;
sewardj08a50f62002-06-17 02:21:20 +00001163 adv = (op_code / info.li_line_range)
1164 * info.li_min_insn_length;
sewardjc134dd92002-06-01 14:21:36 +00001165 advAddr = adv;
1166 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001167 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001168 adv = (op_code % info.li_line_range) + info.li_line_base;
sewardj08a50f62002-06-17 02:21:20 +00001169 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1170 si->offset, state_machine_regs.address );
1171 addLineInfo (si, fnames[state_machine_regs.file],
1172 si->offset + (state_machine_regs.address
1173 - advAddr),
1174 si->offset + (state_machine_regs.address),
1175 state_machine_regs.line, 0);
sewardjc134dd92002-06-01 14:21:36 +00001176 state_machine_regs.line += adv;
1177 }
1178 else switch (op_code)
1179 {
1180 case DW_LNS_extended_op:
sewardj08a50f62002-06-17 02:21:20 +00001181 data += process_extended_line_op (
1182 si, &fnames, data,
1183 info.li_default_is_stmt, sizeof (Addr));
sewardjc134dd92002-06-01 14:21:36 +00001184 break;
1185
1186 case DW_LNS_copy:
sewardj08a50f62002-06-17 02:21:20 +00001187 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1188 si->offset, state_machine_regs.address );
1189 addLineInfo (si, fnames[state_machine_regs.file],
1190 si->offset + state_machine_regs.address,
1191 si->offset + (state_machine_regs.address + 1),
1192 state_machine_regs.line , 0);
sewardjc134dd92002-06-01 14:21:36 +00001193 break;
1194
1195 case DW_LNS_advance_pc:
sewardj08a50f62002-06-17 02:21:20 +00001196 adv = info.li_min_insn_length
1197 * read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001198 data += bytes_read;
1199 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001200 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001201 break;
1202
1203 case DW_LNS_advance_line:
1204 adv = read_leb128 (data, & bytes_read, 1);
1205 data += bytes_read;
1206 state_machine_regs.line += adv;
1207 break;
1208
1209 case DW_LNS_set_file:
1210 adv = read_leb128 (data, & bytes_read, 0);
1211 data += bytes_read;
1212 state_machine_regs.file = adv;
1213 break;
1214
1215 case DW_LNS_set_column:
1216 adv = read_leb128 (data, & bytes_read, 0);
1217 data += bytes_read;
1218 state_machine_regs.column = adv;
1219 break;
1220
1221 case DW_LNS_negate_stmt:
1222 adv = state_machine_regs.is_stmt;
1223 adv = ! adv;
1224 state_machine_regs.is_stmt = adv;
1225 break;
1226
1227 case DW_LNS_set_basic_block:
1228 state_machine_regs.basic_block = 1;
1229 break;
1230
1231 case DW_LNS_const_add_pc:
1232 adv = (((255 - info.li_opcode_base) / info.li_line_range)
1233 * info.li_min_insn_length);
1234 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001235 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001236 break;
1237
1238 case DW_LNS_fixed_advance_pc:
1239 /* XXX: Need something to get 2 bytes */
1240 adv = *((UShort *)data);
1241 data += 2;
1242 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001243 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001244 break;
1245
1246 case DW_LNS_set_prologue_end:
1247 break;
1248
1249 case DW_LNS_set_epilogue_begin:
1250 break;
1251
1252 case DW_LNS_set_isa:
1253 adv = read_leb128 (data, & bytes_read, 0);
1254 data += bytes_read;
1255 break;
1256
1257 default:
1258 {
1259 int j;
1260 for (j = standard_opcodes[op_code - 1]; j > 0 ; --j)
1261 {
1262 read_leb128 (data, &bytes_read, 0);
1263 data += bytes_read;
1264 }
1265 }
1266 break;
1267 }
1268 }
1269 VG_(free)(VG_AR_SYMTAB, fnames);
1270 fnames = NULL;
1271 }
sewardjc134dd92002-06-01 14:21:36 +00001272}
1273
sewardjb51f2e62002-06-01 23:11:19 +00001274
1275/*------------------------------------------------------------*/
1276/*--- Read info from a .so/exe file. ---*/
1277/*------------------------------------------------------------*/
1278
sewardjde4a1d02002-03-22 01:27:54 +00001279/* Read the symbols from the object/exe specified by the SegInfo into
1280 the tables within the supplied SegInfo. */
1281static
1282void vg_read_lib_symbols ( SegInfo* si )
1283{
1284 Elf32_Ehdr* ehdr; /* The ELF header */
1285 Elf32_Shdr* shdr; /* The section table */
1286 UChar* sh_strtab; /* The section table's string table */
sewardjb51f2e62002-06-01 23:11:19 +00001287 UChar* stab; /* The .stab table */
sewardjde4a1d02002-03-22 01:27:54 +00001288 UChar* stabstr; /* The .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001289 UChar* dwarf2; /* The DWARF2 location info table */
sewardjde4a1d02002-03-22 01:27:54 +00001290 Int stab_sz; /* Size in bytes of the .stab table */
1291 Int stabstr_sz; /* Size in bytes of the .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001292 Int dwarf2_sz; /* Size in bytes of the DWARF2 srcloc table*/
sewardjde4a1d02002-03-22 01:27:54 +00001293 Int fd;
1294 Int i;
1295 Bool ok;
1296 Addr oimage;
1297 Int n_oimage;
sewardjb3586202002-05-09 17:38:13 +00001298 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001299
sewardjde4a1d02002-03-22 01:27:54 +00001300 oimage = (Addr)NULL;
1301 if (VG_(clo_verbosity) > 1)
njne0ee0712002-05-03 16:41:05 +00001302 VG_(message)(Vg_UserMsg, "Reading syms from %s", si->filename );
sewardjde4a1d02002-03-22 01:27:54 +00001303
1304 /* mmap the object image aboard, so that we can read symbols and
1305 line number info out of it. It will be munmapped immediately
1306 thereafter; it is only aboard transiently. */
1307
sewardjb3586202002-05-09 17:38:13 +00001308 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001309 if (i != 0) {
1310 vg_symerr("Can't stat .so/.exe (to determine its size)?!");
1311 return;
1312 }
1313 n_oimage = stat_buf.st_size;
1314
1315 fd = VG_(open_read)(si->filename);
1316 if (fd == -1) {
1317 vg_symerr("Can't open .so/.exe to read symbols?!");
1318 return;
1319 }
1320
sewardjb3586202002-05-09 17:38:13 +00001321 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
1322 VKI_PROT_READ, VKI_MAP_PRIVATE, fd, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001323 if (oimage == ((Addr)(-1))) {
1324 VG_(message)(Vg_UserMsg,
1325 "mmap failed on %s", si->filename );
1326 VG_(close)(fd);
1327 return;
1328 }
1329
1330 VG_(close)(fd);
1331
1332 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1333 Now verify that it is a valid ELF .so or executable image.
1334 */
1335 ok = (n_oimage >= sizeof(Elf32_Ehdr));
1336 ehdr = (Elf32_Ehdr*)oimage;
1337
1338 if (ok) {
1339 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
1340 && ehdr->e_ident[EI_MAG1] == 'E'
1341 && ehdr->e_ident[EI_MAG2] == 'L'
1342 && ehdr->e_ident[EI_MAG3] == 'F');
1343 ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
1344 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1345 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
1346 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
1347 ok &= (ehdr->e_machine == EM_386);
1348 ok &= (ehdr->e_version == EV_CURRENT);
1349 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
1350 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
1351 }
1352
1353 if (!ok) {
1354 vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
1355 VG_(munmap) ( (void*)oimage, n_oimage );
1356 return;
1357 }
1358
1359 if (VG_(clo_trace_symtab))
1360 VG_(printf)(
1361 "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
1362 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
1363
1364 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
1365 vg_symerr("ELF section header is beyond image end?!");
1366 VG_(munmap) ( (void*)oimage, n_oimage );
1367 return;
1368 }
1369
1370 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
1371 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1372
1373 /* try and read the object's symbol table */
1374 {
1375 UChar* o_strtab = NULL;
1376 Elf32_Sym* o_symtab = NULL;
1377 UInt o_strtab_sz = 0;
1378 UInt o_symtab_sz = 0;
1379
1380 UChar* o_got = NULL;
1381 UChar* o_plt = NULL;
1382 UInt o_got_sz = 0;
1383 UInt o_plt_sz = 0;
1384
1385 Bool snaffle_it;
1386 Addr sym_addr;
1387
1388 /* find the .stabstr and .stab sections */
1389 for (i = 0; i < ehdr->e_shnum; i++) {
1390 if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
1391 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1392 o_symtab_sz = shdr[i].sh_size;
1393 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1394 /* check image overrun here */
1395 }
1396 if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
1397 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1398 o_strtab_sz = shdr[i].sh_size;
1399 /* check image overrun here */
1400 }
1401
1402 /* find out where the .got and .plt sections will be in the
1403 executable image, not in the object image transiently loaded.
1404 */
1405 if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
1406 o_got = (UChar*)(si->offset
1407 + shdr[i].sh_offset);
1408 o_got_sz = shdr[i].sh_size;
1409 /* check image overrun here */
1410 }
1411 if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
1412 o_plt = (UChar*)(si->offset
1413 + shdr[i].sh_offset);
1414 o_plt_sz = shdr[i].sh_size;
1415 /* check image overrun here */
1416 }
1417
1418 }
1419
1420 if (VG_(clo_trace_symtab)) {
1421 if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
1422 o_plt, o_plt + o_plt_sz - 1 );
1423 if (o_got) VG_(printf)( "GOT: %p .. %p\n",
1424 o_got, o_got + o_got_sz - 1 );
1425 }
1426
1427 if (o_strtab == NULL || o_symtab == NULL) {
1428 vg_symerr(" object doesn't have a symbol table");
1429 } else {
1430 /* Perhaps should start at i = 1; ELF docs suggest that entry
1431 0 always denotes `unknown symbol'. */
1432 for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
1433# if 0
1434 VG_(printf)("raw symbol: ");
1435 switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
1436 case STB_LOCAL: VG_(printf)("LOC "); break;
1437 case STB_GLOBAL: VG_(printf)("GLO "); break;
1438 case STB_WEAK: VG_(printf)("WEA "); break;
1439 case STB_LOPROC: VG_(printf)("lop "); break;
1440 case STB_HIPROC: VG_(printf)("hip "); break;
1441 default: VG_(printf)("??? "); break;
1442 }
1443 switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
1444 case STT_NOTYPE: VG_(printf)("NOT "); break;
1445 case STT_OBJECT: VG_(printf)("OBJ "); break;
1446 case STT_FUNC: VG_(printf)("FUN "); break;
1447 case STT_SECTION: VG_(printf)("SEC "); break;
1448 case STT_FILE: VG_(printf)("FIL "); break;
1449 case STT_LOPROC: VG_(printf)("lop "); break;
1450 case STT_HIPROC: VG_(printf)("hip "); break;
1451 default: VG_(printf)("??? "); break;
1452 }
1453 VG_(printf)(
1454 ": value %p, size %d, name %s\n",
1455 si->offset+(UChar*)o_symtab[i].st_value,
1456 o_symtab[i].st_size,
1457 o_symtab[i].st_name
1458 ? ((Char*)o_strtab+o_symtab[i].st_name)
1459 : (Char*)"NONAME");
1460# endif
1461
1462 /* Figure out if we're interested in the symbol.
1463 Firstly, is it of the right flavour?
1464 */
1465 snaffle_it
1466 = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
1467 ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
1468 ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
1469 &&
1470 (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*||
1471 ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/)
1472 );
1473
1474 /* Secondly, if it's apparently in a GOT or PLT, it's really
1475 a reference to a symbol defined elsewhere, so ignore it.
1476 */
1477 sym_addr = si->offset
1478 + (UInt)o_symtab[i].st_value;
1479 if (o_got != NULL
1480 && sym_addr >= (Addr)o_got
1481 && sym_addr < (Addr)(o_got+o_got_sz)) {
1482 snaffle_it = False;
1483 if (VG_(clo_trace_symtab)) {
1484 VG_(printf)( "in GOT: %s\n",
1485 o_strtab+o_symtab[i].st_name);
1486 }
1487 }
1488 if (o_plt != NULL
1489 && sym_addr >= (Addr)o_plt
1490 && sym_addr < (Addr)(o_plt+o_plt_sz)) {
1491 snaffle_it = False;
1492 if (VG_(clo_trace_symtab)) {
1493 VG_(printf)( "in PLT: %s\n",
1494 o_strtab+o_symtab[i].st_name);
1495 }
1496 }
1497
1498 /* Don't bother if nameless, or zero-sized. */
1499 if (snaffle_it
1500 && (o_symtab[i].st_name == (Elf32_Word)NULL
1501 || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
1502 /* equivalent but cheaper ... */
1503 * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
1504 || o_symtab[i].st_size == 0)) {
1505 snaffle_it = False;
1506 if (VG_(clo_trace_symtab)) {
1507 VG_(printf)( "size=0: %s\n",
1508 o_strtab+o_symtab[i].st_name);
1509 }
1510 }
1511
1512# if 0
1513 /* Avoid _dl_ junk. (Why?) */
1514 /* 01-02-24: disabled until I find out if it really helps. */
1515 if (snaffle_it
1516 && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
1517 || VG_(strncmp)("_r_debug",
1518 o_strtab+o_symtab[i].st_name, 8) == 0)) {
1519 snaffle_it = False;
1520 if (VG_(clo_trace_symtab)) {
1521 VG_(printf)( "_dl_ junk: %s\n",
1522 o_strtab+o_symtab[i].st_name);
1523 }
1524 }
1525# endif
1526
1527 /* This seems to significantly reduce the number of junk
1528 symbols, and particularly reduces the number of
1529 overlapping address ranges. Don't ask me why ... */
1530 if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
1531 snaffle_it = False;
1532 if (VG_(clo_trace_symtab)) {
1533 VG_(printf)( "valu=0: %s\n",
1534 o_strtab+o_symtab[i].st_name);
1535 }
1536 }
1537
1538 /* If no part of the symbol falls within the mapped range,
1539 ignore it. */
1540 if (sym_addr+o_symtab[i].st_size <= si->start
1541 || sym_addr >= si->start+si->size) {
1542 snaffle_it = False;
1543 }
1544
1545 if (snaffle_it) {
1546 /* it's an interesting symbol; record ("snaffle") it. */
1547 RiSym sym;
1548 Char* t0 = o_symtab[i].st_name
1549 ? (Char*)(o_strtab+o_symtab[i].st_name)
1550 : (Char*)"NONAME";
1551 Int nmoff = addStr ( si, t0 );
1552 vg_assert(nmoff >= 0
1553 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
1554 vg_assert( (Int)o_symtab[i].st_value >= 0);
1555 /* VG_(printf)("%p + %d: %s\n", si->addr,
1556 (Int)o_symtab[i].st_value, t0 ); */
1557 sym.addr = sym_addr;
1558 sym.size = o_symtab[i].st_size;
1559 sym.nmoff = nmoff;
1560 addSym ( si, &sym );
1561 }
1562 }
1563 }
1564 }
1565
sewardjb51f2e62002-06-01 23:11:19 +00001566 /* Reading of the stabs and/or dwarf2 debug format information, if
1567 any. */
sewardjde4a1d02002-03-22 01:27:54 +00001568 stabstr = NULL;
1569 stab = NULL;
sewardjb51f2e62002-06-01 23:11:19 +00001570 dwarf2 = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001571 stabstr_sz = 0;
1572 stab_sz = 0;
sewardjb51f2e62002-06-01 23:11:19 +00001573 dwarf2_sz = 0;
1574
1575 /* find the .stabstr / .stab / .debug_line sections */
sewardjde4a1d02002-03-22 01:27:54 +00001576 for (i = 0; i < ehdr->e_shnum; i++) {
1577 if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001578 stab = (UChar*)(oimage + shdr[i].sh_offset);
sewardjde4a1d02002-03-22 01:27:54 +00001579 stab_sz = shdr[i].sh_size;
1580 }
1581 if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
1582 stabstr = (UChar*)(oimage + shdr[i].sh_offset);
1583 stabstr_sz = shdr[i].sh_size;
1584 }
sewardjc134dd92002-06-01 14:21:36 +00001585 if (0 == VG_(strcmp)(".debug_line",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001586 dwarf2 = (UChar *)(oimage + shdr[i].sh_offset);
1587 dwarf2_sz = shdr[i].sh_size;
sewardjc134dd92002-06-01 14:21:36 +00001588 }
sewardjde4a1d02002-03-22 01:27:54 +00001589 }
1590
sewardjb51f2e62002-06-01 23:11:19 +00001591 if ((stab == NULL || stabstr == NULL) && dwarf2 == NULL) {
sewardjde4a1d02002-03-22 01:27:54 +00001592 vg_symerr(" object doesn't have any debug info");
1593 VG_(munmap) ( (void*)oimage, n_oimage );
1594 return;
1595 }
1596
1597 if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
1598 || stabstr_sz + (UChar*)stabstr
1599 > n_oimage + (UChar*)oimage ) {
sewardjb51f2e62002-06-01 23:11:19 +00001600 vg_symerr(" ELF (stabs) debug data is beyond image end?!");
sewardjde4a1d02002-03-22 01:27:54 +00001601 VG_(munmap) ( (void*)oimage, n_oimage );
1602 return;
1603 }
1604
sewardjb51f2e62002-06-01 23:11:19 +00001605 if ( dwarf2_sz + (UChar*)dwarf2 > n_oimage + (UChar*)oimage ) {
1606 vg_symerr(" ELF (dwarf2) debug data is beyond image end?!");
1607 VG_(munmap) ( (void*)oimage, n_oimage );
1608 return;
1609 }
sewardjde4a1d02002-03-22 01:27:54 +00001610
sewardjb51f2e62002-06-01 23:11:19 +00001611 /* Looks plausible. Go on and read debug data. */
1612 if (stab != NULL && stabstr != NULL) {
1613 read_debuginfo_stabs ( si, stab, stab_sz, stabstr, stabstr_sz );
1614 }
sewardjde4a1d02002-03-22 01:27:54 +00001615
sewardjb51f2e62002-06-01 23:11:19 +00001616 if (dwarf2 != NULL) {
1617 read_debuginfo_dwarf2 ( si, dwarf2, dwarf2_sz );
1618 }
sewardjde4a1d02002-03-22 01:27:54 +00001619
1620 /* Last, but not least, heave the oimage back overboard. */
1621 VG_(munmap) ( (void*)oimage, n_oimage );
1622}
1623
1624
1625/*------------------------------------------------------------*/
1626/*--- Main entry point for symbols table reading. ---*/
1627/*------------------------------------------------------------*/
1628
1629/* The root structure for the entire symbol table system. It is a
1630 linked list of SegInfos. Note that this entire mechanism assumes
1631 that what we read from /proc/self/maps doesn't contain overlapping
1632 address ranges, and as a result the SegInfos in this list describe
1633 disjoint address ranges.
1634*/
1635static SegInfo* segInfo = NULL;
1636
1637
1638static
1639void read_symtab_callback (
1640 Addr start, UInt size,
1641 Char rr, Char ww, Char xx,
1642 UInt foffset, UChar* filename )
1643{
1644 SegInfo* si;
1645
1646 /* Stay sane ... */
1647 if (size == 0)
1648 return;
1649
1650 /* We're only interested in collecting symbols in executable
1651 segments which are associated with a real file. Hence: */
1652 if (filename == NULL || xx != 'x')
1653 return;
1654 if (0 == VG_(strcmp)(filename, "/dev/zero"))
1655 return;
1656
1657 /* Perhaps we already have this one? If so, skip. */
1658 for (si = segInfo; si != NULL; si = si->next) {
1659 /*
1660 if (0==VG_(strcmp)(si->filename, filename))
1661 VG_(printf)("same fnames: %c%c%c (%p, %d) (%p, %d) %s\n",
1662 rr,ww,xx,si->start,si->size,start,size,filename);
1663 */
1664 /* For some reason the observed size of a mapping can change, so
1665 we don't use that to determine uniqueness. */
1666 if (si->start == start
1667 /* && si->size == size */
1668 && 0==VG_(strcmp)(si->filename, filename)) {
1669 return;
1670 }
1671 }
1672
1673 /* Get the record initialised right. */
1674 si = VG_(malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
1675 si->next = segInfo;
1676 segInfo = si;
1677
1678 si->start = start;
1679 si->size = size;
1680 si->foffset = foffset;
1681 si->filename = VG_(malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(filename));
1682 VG_(strcpy)(si->filename, filename);
1683
1684 si->symtab = NULL;
1685 si->symtab_size = si->symtab_used = 0;
1686 si->loctab = NULL;
1687 si->loctab_size = si->loctab_used = 0;
1688 si->strtab = NULL;
1689 si->strtab_size = si->strtab_used = 0;
1690
1691 /* Kludge ... */
1692 si->offset
1693 = si->start==VG_ASSUMED_EXE_BASE ? 0 : si->start;
1694
1695 /* And actually fill it up. */
sewardj18d75132002-05-16 11:06:21 +00001696 if (VG_(clo_instrument) || VG_(clo_cachesim)) {
1697 vg_read_lib_symbols ( si );
1698 canonicaliseSymtab ( si );
1699 canonicaliseLoctab ( si );
1700 }
sewardjde4a1d02002-03-22 01:27:54 +00001701}
1702
1703
1704/* This one really is the Head Honcho. Update the symbol tables to
1705 reflect the current state of /proc/self/maps. Rather than re-read
1706 everything, just read the entries which are not already in segInfo.
1707 So we can call here repeatedly, after every mmap of a non-anonymous
1708 segment with execute permissions, for example, to pick up new
1709 libraries as they are dlopen'd. Conversely, when the client does
1710 munmap(), vg_symtab_notify_munmap() throws away any symbol tables
1711 which happen to correspond to the munmap()d area. */
1712void VG_(read_symbols) ( void )
1713{
sewardjde4a1d02002-03-22 01:27:54 +00001714 VG_(read_procselfmaps) ( read_symtab_callback );
1715
1716 /* Do a sanity check on the symbol tables: ensure that the address
1717 space pieces they cover do not overlap (otherwise we are severely
1718 hosed). This is a quadratic algorithm, but there shouldn't be
1719 many of them.
1720 */
1721 { SegInfo *si, *si2;
1722 for (si = segInfo; si != NULL; si = si->next) {
1723 /* Check no overlap between *si and those in the rest of the
1724 list. */
1725 for (si2 = si->next; si2 != NULL; si2 = si2->next) {
1726 Addr lo = si->start;
1727 Addr hi = si->start + si->size - 1;
1728 Addr lo2 = si2->start;
1729 Addr hi2 = si2->start + si2->size - 1;
1730 Bool overlap;
1731 vg_assert(lo < hi);
1732 vg_assert(lo2 < hi2);
1733 /* the main assertion */
1734 overlap = (lo <= lo2 && lo2 <= hi)
1735 || (lo <= hi2 && hi2 <= hi);
sewardjde4a1d02002-03-22 01:27:54 +00001736 if (overlap) {
1737 VG_(printf)("\n\nOVERLAPPING SEGMENTS\n" );
1738 ppSegInfo ( si );
1739 ppSegInfo ( si2 );
1740 VG_(printf)("\n\n");
1741 vg_assert(! overlap);
1742 }
1743 }
1744 }
1745 }
1746}
1747
1748
1749/* When an munmap() call happens, check to see whether it corresponds
1750 to a segment for a .so, and if so discard the relevant SegInfo.
1751 This might not be a very clever idea from the point of view of
1752 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001753 maintain the no-overlapping invariant.
1754
1755 16 May 02: Returns a Bool indicating whether or not the discarded
1756 range falls inside a known executable segment. See comment at top
1757 of file for why.
sewardjde4a1d02002-03-22 01:27:54 +00001758*/
sewardj18d75132002-05-16 11:06:21 +00001759Bool VG_(symtab_notify_munmap) ( Addr start, UInt length )
sewardjde4a1d02002-03-22 01:27:54 +00001760{
1761 SegInfo *prev, *curr;
1762
sewardjde4a1d02002-03-22 01:27:54 +00001763 prev = NULL;
1764 curr = segInfo;
1765 while (True) {
1766 if (curr == NULL) break;
1767 if (start == curr->start) break;
1768 prev = curr;
1769 curr = curr->next;
1770 }
sewardj18d75132002-05-16 11:06:21 +00001771 if (curr == NULL)
1772 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001773
1774 VG_(message)(Vg_UserMsg,
1775 "discard syms in %s due to munmap()",
1776 curr->filename ? curr->filename : (UChar*)"???");
1777
1778 vg_assert(prev == NULL || prev->next == curr);
1779
1780 if (prev == NULL) {
1781 segInfo = curr->next;
1782 } else {
1783 prev->next = curr->next;
1784 }
1785
1786 freeSegInfo(curr);
sewardj18d75132002-05-16 11:06:21 +00001787 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001788}
1789
1790
1791/*------------------------------------------------------------*/
1792/*--- Use of symbol table & location info to create ---*/
1793/*--- plausible-looking stack dumps. ---*/
1794/*------------------------------------------------------------*/
1795
1796/* Find a symbol-table index containing the specified pointer, or -1
1797 if not found. Binary search. */
1798
1799static Int search_one_symtab ( SegInfo* si, Addr ptr )
1800{
1801 Addr a_mid_lo, a_mid_hi;
1802 Int mid,
1803 lo = 0,
1804 hi = si->symtab_used-1;
1805 while (True) {
1806 /* current unsearched space is from lo to hi, inclusive. */
1807 if (lo > hi) return -1; /* not found */
1808 mid = (lo + hi) / 2;
1809 a_mid_lo = si->symtab[mid].addr;
1810 a_mid_hi = ((Addr)si->symtab[mid].addr) + si->symtab[mid].size - 1;
1811
1812 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1813 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1814 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1815 return mid;
1816 }
1817}
1818
1819
1820/* Search all symtabs that we know about to locate ptr. If found, set
1821 *psi to the relevant SegInfo, and *symno to the symtab entry number
1822 within that. If not found, *psi is set to NULL. */
1823
1824static void search_all_symtabs ( Addr ptr, SegInfo** psi, Int* symno )
1825{
1826 Int sno;
1827 SegInfo* si;
1828 for (si = segInfo; si != NULL; si = si->next) {
1829 if (si->start <= ptr && ptr < si->start+si->size) {
1830 sno = search_one_symtab ( si, ptr );
1831 if (sno == -1) goto not_found;
1832 *symno = sno;
1833 *psi = si;
1834 return;
1835 }
1836 }
1837 not_found:
1838 *psi = NULL;
1839}
1840
1841
1842/* Find a location-table index containing the specified pointer, or -1
1843 if not found. Binary search. */
1844
1845static Int search_one_loctab ( SegInfo* si, Addr ptr )
1846{
1847 Addr a_mid_lo, a_mid_hi;
1848 Int mid,
1849 lo = 0,
1850 hi = si->loctab_used-1;
1851 while (True) {
1852 /* current unsearched space is from lo to hi, inclusive. */
1853 if (lo > hi) return -1; /* not found */
1854 mid = (lo + hi) / 2;
1855 a_mid_lo = si->loctab[mid].addr;
1856 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1857
1858 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1859 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1860 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1861 return mid;
1862 }
1863}
1864
1865
1866/* Search all loctabs that we know about to locate ptr. If found, set
1867 *psi to the relevant SegInfo, and *locno to the loctab entry number
1868 within that. If not found, *psi is set to NULL.
1869*/
1870static void search_all_loctabs ( Addr ptr, SegInfo** psi, Int* locno )
1871{
1872 Int lno;
1873 SegInfo* si;
1874 for (si = segInfo; si != NULL; si = si->next) {
1875 if (si->start <= ptr && ptr < si->start+si->size) {
1876 lno = search_one_loctab ( si, ptr );
1877 if (lno == -1) goto not_found;
1878 *locno = lno;
1879 *psi = si;
1880 return;
1881 }
1882 }
1883 not_found:
1884 *psi = NULL;
1885}
1886
1887
1888/* The whole point of this whole big deal: map a code address to a
1889 plausible symbol name. Returns False if no idea; otherwise True.
1890 Caller supplies buf and nbuf. If no_demangle is True, don't do
1891 demangling, regardless of vg_clo_demangle -- probably because the
1892 call has come from vg_what_fn_or_object_is_this. */
njn4f9c9342002-04-29 16:03:24 +00001893Bool VG_(what_fn_is_this) ( Bool no_demangle, Addr a,
1894 Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001895{
1896 SegInfo* si;
1897 Int sno;
1898 search_all_symtabs ( a, &si, &sno );
1899 if (si == NULL)
1900 return False;
1901 if (no_demangle) {
1902 VG_(strncpy_safely)
1903 ( buf, & si->strtab[si->symtab[sno].nmoff], nbuf );
1904 } else {
1905 VG_(demangle) ( & si->strtab[si->symtab[sno].nmoff], buf, nbuf );
1906 }
1907 return True;
1908}
1909
1910
1911/* Map a code address to the name of a shared object file. Returns
1912 False if no idea; otherwise False. Caller supplies buf and
1913 nbuf. */
1914static
1915Bool vg_what_object_is_this ( Addr a, Char* buf, Int nbuf )
1916{
1917 SegInfo* si;
1918 for (si = segInfo; si != NULL; si = si->next) {
1919 if (si->start <= a && a < si->start+si->size) {
1920 VG_(strncpy_safely)(buf, si->filename, nbuf);
1921 return True;
1922 }
1923 }
1924 return False;
1925}
1926
1927/* Return the name of an erring fn in a way which is useful
1928 for comparing against the contents of a suppressions file.
1929 Always writes something to buf. Also, doesn't demangle the
1930 name, because we want to refer to mangled names in the
1931 suppressions file.
1932*/
1933void VG_(what_obj_and_fun_is_this) ( Addr a,
1934 Char* obj_buf, Int n_obj_buf,
1935 Char* fun_buf, Int n_fun_buf )
1936{
1937 (void)vg_what_object_is_this ( a, obj_buf, n_obj_buf );
njn4f9c9342002-04-29 16:03:24 +00001938 (void)VG_(what_fn_is_this) ( True, a, fun_buf, n_fun_buf );
sewardjde4a1d02002-03-22 01:27:54 +00001939}
1940
1941
1942/* Map a code address to a (filename, line number) pair.
1943 Returns True if successful.
1944*/
njn4f9c9342002-04-29 16:03:24 +00001945Bool VG_(what_line_is_this)( Addr a,
1946 UChar* filename, Int n_filename,
1947 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001948{
1949 SegInfo* si;
1950 Int locno;
1951 search_all_loctabs ( a, &si, &locno );
1952 if (si == NULL)
1953 return False;
1954 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
1955 n_filename);
1956 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00001957
sewardjde4a1d02002-03-22 01:27:54 +00001958 return True;
1959}
1960
1961
1962/* Print a mini stack dump, showing the current location. */
1963void VG_(mini_stack_dump) ( ExeContext* ec )
1964{
1965
1966#define APPEND(str) \
1967 { UChar* sss; \
1968 for (sss = str; n < M_VG_ERRTXT-1 && *sss != 0; n++,sss++) \
1969 buf[n] = *sss; \
1970 buf[n] = 0; \
1971 }
1972
1973 Bool know_fnname;
1974 Bool know_objname;
1975 Bool know_srcloc;
1976 UInt lineno;
1977 UChar ibuf[20];
sewardj04b91062002-06-05 21:22:04 +00001978 UInt i, n;
sewardjde4a1d02002-03-22 01:27:54 +00001979
1980 UChar buf[M_VG_ERRTXT];
1981 UChar buf_fn[M_VG_ERRTXT];
1982 UChar buf_obj[M_VG_ERRTXT];
1983 UChar buf_srcloc[M_VG_ERRTXT];
1984
1985 Int stop_at = VG_(clo_backtrace_size);
1986
1987 n = 0;
1988
njn4f9c9342002-04-29 16:03:24 +00001989 know_fnname = VG_(what_fn_is_this)(False,ec->eips[0], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00001990 know_objname = vg_what_object_is_this(ec->eips[0], buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00001991 know_srcloc = VG_(what_line_is_this)(ec->eips[0],
1992 buf_srcloc, M_VG_ERRTXT,
1993 &lineno);
sewardjde4a1d02002-03-22 01:27:54 +00001994
1995 APPEND(" at ");
1996 VG_(sprintf)(ibuf,"0x%x: ", ec->eips[0]);
1997 APPEND(ibuf);
1998 if (know_fnname) {
1999 APPEND(buf_fn);
2000 if (!know_srcloc && know_objname) {
2001 APPEND(" (in ");
2002 APPEND(buf_obj);
2003 APPEND(")");
2004 }
2005 } else if (know_objname && !know_srcloc) {
2006 APPEND("(within ");
2007 APPEND(buf_obj);
2008 APPEND(")");
2009 } else {
2010 APPEND("???");
2011 }
2012 if (know_srcloc) {
2013 APPEND(" (");
2014 APPEND(buf_srcloc);
2015 APPEND(":");
2016 VG_(sprintf)(ibuf,"%d",lineno);
2017 APPEND(ibuf);
2018 APPEND(")");
2019 }
2020 VG_(message)(Vg_UserMsg, "%s", buf);
2021
sewardj04b91062002-06-05 21:22:04 +00002022 for (i = 1; i < stop_at && ec->eips[i] != 0; i++) {
njn4f9c9342002-04-29 16:03:24 +00002023 know_fnname = VG_(what_fn_is_this)(False,ec->eips[i], buf_fn, M_VG_ERRTXT);
sewardjde4a1d02002-03-22 01:27:54 +00002024 know_objname = vg_what_object_is_this(ec->eips[i],buf_obj, M_VG_ERRTXT);
njn4f9c9342002-04-29 16:03:24 +00002025 know_srcloc = VG_(what_line_is_this)(ec->eips[i],
sewardjde4a1d02002-03-22 01:27:54 +00002026 buf_srcloc, M_VG_ERRTXT,
2027 &lineno);
2028 n = 0;
2029 APPEND(" by ");
sewardj04b91062002-06-05 21:22:04 +00002030 VG_(sprintf)(ibuf,"0x%x: ",ec->eips[i]);
2031 APPEND(ibuf);
sewardjde4a1d02002-03-22 01:27:54 +00002032 if (know_fnname) {
2033 APPEND(buf_fn)
2034 if (!know_srcloc && know_objname) {
2035 APPEND(" (in ");
2036 APPEND(buf_obj);
2037 APPEND(")");
2038 }
2039 } else {
2040 if (know_objname && !know_srcloc) {
2041 APPEND("(within ");
2042 APPEND(buf_obj);
2043 APPEND(")");
2044 } else {
2045 APPEND("???");
2046 }
sewardjde4a1d02002-03-22 01:27:54 +00002047 };
2048 if (know_srcloc) {
2049 APPEND(" (");
2050 APPEND(buf_srcloc);
2051 APPEND(":");
2052 VG_(sprintf)(ibuf,"%d",lineno);
2053 APPEND(ibuf);
2054 APPEND(")");
2055 }
2056 VG_(message)(Vg_UserMsg, "%s", buf);
2057 }
2058}
2059
2060#undef APPEND
2061
2062/*--------------------------------------------------------------------*/
2063/*--- end vg_symtab2.c ---*/
2064/*--------------------------------------------------------------------*/