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