blob: 1c0d41a9af8666664965208a1cb64a48f836d334 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001/*--------------------------------------------------------------------*/
2/*--- Management of symbols and debugging information. ---*/
3/*--- vg_symtab2.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
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
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
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
njn25e49d8e72002-09-23 09:36:25 +000040 Stabs reader greatly improved by Nick Nethercote, Apr 02.
sewardjde4a1d02002-03-22 01:27:54 +000041*/
42
njn25e49d8e72002-09-23 09:36:25 +000043/* Set to True when first debug info search is performed */
44Bool VG_(using_debug_info) = False;
45
sewardjde4a1d02002-03-22 01:27:54 +000046/*------------------------------------------------------------*/
47/*--- Structs n stuff ---*/
48/*------------------------------------------------------------*/
49
50/* A structure to hold an ELF symbol (very crudely). */
51typedef
52 struct {
53 Addr addr; /* lowest address of entity */
54 UInt size; /* size in bytes */
55 Int nmoff; /* offset of name in this SegInfo's str tab */
56 }
57 RiSym;
58
njne0ee0712002-05-03 16:41:05 +000059/* Line count at which overflow happens, due to line numbers being stored as
60 * shorts in `struct nlist' in a.out.h. */
61#define LINENO_OVERFLOW (1 << (sizeof(short) * 8))
sewardjde4a1d02002-03-22 01:27:54 +000062
njne0ee0712002-05-03 16:41:05 +000063#define LINENO_BITS 20
64#define LOC_SIZE_BITS (32 - LINENO_BITS)
sewardj97ff05f2002-05-09 01:32:57 +000065#define MAX_LINENO ((1 << LINENO_BITS) - 1)
njne0ee0712002-05-03 16:41:05 +000066
67/* Unlikely to have any lines with instruction ranges > 4096 bytes */
sewardj97ff05f2002-05-09 01:32:57 +000068#define MAX_LOC_SIZE ((1 << LOC_SIZE_BITS) - 1)
njne0ee0712002-05-03 16:41:05 +000069
70/* Number used to detect line number overflows; if one line is 60000-odd
71 * smaller than the previous, is was probably an overflow.
72 */
73#define OVERFLOW_DIFFERENCE (LINENO_OVERFLOW - 5000)
74
75/* A structure to hold addr-to-source info for a single line. There can be a
76 * lot of these, hence the dense packing. */
sewardjde4a1d02002-03-22 01:27:54 +000077typedef
78 struct {
njne0ee0712002-05-03 16:41:05 +000079 /* Word 1 */
80 Addr addr; /* lowest address for this line */
81 /* Word 2 */
82 UShort size:LOC_SIZE_BITS; /* byte size; we catch overflows of this */
83 UInt lineno:LINENO_BITS; /* source line number, or zero */
84 /* Word 3 */
85 UInt fnmoff; /* source filename; offset in this
86 SegInfo's str tab */
sewardjde4a1d02002-03-22 01:27:54 +000087 }
88 RiLoc;
89
90
91/* A structure which contains information pertaining to one mapped
92 text segment. */
93typedef
94 struct _SegInfo {
95 struct _SegInfo* next;
96 /* Description of the mapped segment. */
97 Addr start;
98 UInt size;
99 UChar* filename; /* in mallocville */
100 UInt foffset;
101 /* An expandable array of symbols. */
102 RiSym* symtab;
103 UInt symtab_used;
104 UInt symtab_size;
105 /* An expandable array of locations. */
106 RiLoc* loctab;
107 UInt loctab_used;
108 UInt loctab_size;
109 /* An expandable array of characters -- the string table. */
110 Char* strtab;
111 UInt strtab_used;
112 UInt strtab_size;
113 /* offset is what we need to add to symbol table entries
114 to get the real location of that symbol in memory.
115 For executables, offset is zero.
116 For .so's, offset == base_addr.
117 This seems like a giant kludge to me.
118 */
119 UInt offset;
120 }
121 SegInfo;
122
123
sewardjde4a1d02002-03-22 01:27:54 +0000124static void freeSegInfo ( SegInfo* si )
125{
126 vg_assert(si != NULL);
njn25e49d8e72002-09-23 09:36:25 +0000127 if (si->filename) VG_(arena_free)(VG_AR_SYMTAB, si->filename);
128 if (si->symtab) VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
129 if (si->loctab) VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
130 if (si->strtab) VG_(arena_free)(VG_AR_SYMTAB, si->strtab);
131 VG_(arena_free)(VG_AR_SYMTAB, si);
sewardjde4a1d02002-03-22 01:27:54 +0000132}
133
134
135/*------------------------------------------------------------*/
136/*--- Adding stuff ---*/
137/*------------------------------------------------------------*/
138
139/* Add a str to the string table, including terminating zero, and
njn25e49d8e72002-09-23 09:36:25 +0000140 return offset of the string in vg_strtab. Unless it's been seen
141 recently, in which case we find the old index and return that.
142 This avoids the most egregious duplications. */
sewardjde4a1d02002-03-22 01:27:54 +0000143
144static __inline__
145Int addStr ( SegInfo* si, Char* str )
146{
njn25e49d8e72002-09-23 09:36:25 +0000147# define EMPTY 0xffffffff
148# define NN 5
149
150 /* prevN[0] has the most recent, prevN[NN-1] the least recent */
151 static UInt prevN[] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
152 static SegInfo* curr_si = NULL;
153
sewardjde4a1d02002-03-22 01:27:54 +0000154 Char* new_tab;
155 Int new_sz, i, space_needed;
njn25e49d8e72002-09-23 09:36:25 +0000156
157 /* Avoid gratuitous duplication: if we saw `str' within the last NN,
158 * within this segment, return that index. Saves about 200KB in glibc,
159 * extra time taken is too small to measure. --NJN 2002-Aug-30 */
160 if (curr_si == si) {
161 for (i = NN-1; i >= 0; i--) {
sewardjcda419b2002-10-01 08:59:36 +0000162 if (EMPTY != prevN[i]
163 && NULL != si->strtab
164 && 0 == VG_(strcmp)(str, &si->strtab[prevN[i]])) {
njn25e49d8e72002-09-23 09:36:25 +0000165 return prevN[i];
166 }
167 }
168 } else {
169 /* New segment */
170 curr_si = si;
sewardjcda419b2002-10-01 08:59:36 +0000171 for (i = 0; i < NN; i++) prevN[i] = EMPTY;
njn25e49d8e72002-09-23 09:36:25 +0000172 }
173 /* Shuffle prevous ones along, put new one in. */
174 for (i = NN-1; i > 0; i--) prevN[i] = prevN[i-1];
175 prevN[0] = si->strtab_used;
176
177# undef EMPTY
178
sewardjde4a1d02002-03-22 01:27:54 +0000179 space_needed = 1 + VG_(strlen)(str);
njn25e49d8e72002-09-23 09:36:25 +0000180
sewardjde4a1d02002-03-22 01:27:54 +0000181 if (si->strtab_used + space_needed > si->strtab_size) {
182 new_sz = 2 * si->strtab_size;
183 if (new_sz == 0) new_sz = 5000;
njn25e49d8e72002-09-23 09:36:25 +0000184 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz);
sewardjde4a1d02002-03-22 01:27:54 +0000185 if (si->strtab != NULL) {
186 for (i = 0; i < si->strtab_used; i++)
187 new_tab[i] = si->strtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000188 VG_(arena_free)(VG_AR_SYMTAB, si->strtab);
sewardjde4a1d02002-03-22 01:27:54 +0000189 }
190 si->strtab = new_tab;
191 si->strtab_size = new_sz;
192 }
193
194 for (i = 0; i < space_needed; i++)
195 si->strtab[si->strtab_used+i] = str[i];
196
197 si->strtab_used += space_needed;
198 vg_assert(si->strtab_used <= si->strtab_size);
njn25e49d8e72002-09-23 09:36:25 +0000199
sewardjde4a1d02002-03-22 01:27:54 +0000200 return si->strtab_used - space_needed;
201}
202
203/* Add a symbol to the symbol table. */
204
205static __inline__
206void addSym ( SegInfo* si, RiSym* sym )
207{
208 Int new_sz, i;
209 RiSym* new_tab;
210
211 /* Ignore zero-sized syms. */
212 if (sym->size == 0) return;
213
214 if (si->symtab_used == si->symtab_size) {
215 new_sz = 2 * si->symtab_size;
216 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000217 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
sewardjde4a1d02002-03-22 01:27:54 +0000218 if (si->symtab != NULL) {
219 for (i = 0; i < si->symtab_used; i++)
220 new_tab[i] = si->symtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000221 VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
sewardjde4a1d02002-03-22 01:27:54 +0000222 }
223 si->symtab = new_tab;
224 si->symtab_size = new_sz;
225 }
226
227 si->symtab[si->symtab_used] = *sym;
228 si->symtab_used++;
229 vg_assert(si->symtab_used <= si->symtab_size);
230}
231
232/* Add a location to the location table. */
233
234static __inline__
235void addLoc ( SegInfo* si, RiLoc* loc )
236{
237 Int new_sz, i;
238 RiLoc* new_tab;
239
njne0ee0712002-05-03 16:41:05 +0000240 /* Zero-sized locs should have been ignored earlier */
241 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000242
243 if (si->loctab_used == si->loctab_size) {
244 new_sz = 2 * si->loctab_size;
245 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000246 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
sewardjde4a1d02002-03-22 01:27:54 +0000247 if (si->loctab != NULL) {
248 for (i = 0; i < si->loctab_used; i++)
249 new_tab[i] = si->loctab[i];
njn25e49d8e72002-09-23 09:36:25 +0000250 VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
sewardjde4a1d02002-03-22 01:27:54 +0000251 }
252 si->loctab = new_tab;
253 si->loctab_size = new_sz;
254 }
255
256 si->loctab[si->loctab_used] = *loc;
257 si->loctab_used++;
258 vg_assert(si->loctab_used <= si->loctab_size);
259}
260
261
sewardjb51f2e62002-06-01 23:11:19 +0000262/* Top-level place to call to add a source-location mapping entry. */
263
264static __inline__
265void addLineInfo ( SegInfo* si,
266 Int fnmoff,
267 Addr this,
268 Addr next,
269 Int lineno,
sewardj08a50f62002-06-17 02:21:20 +0000270 Int entry /* only needed for debug printing */
271 )
sewardjb51f2e62002-06-01 23:11:19 +0000272{
273 RiLoc loc;
274 Int size = next - this;
275
276 /* Ignore zero-sized locs */
277 if (this == next) return;
278
279 /* Maximum sanity checking. Some versions of GNU as do a shabby
280 * job with stabs entries; if anything looks suspicious, revert to
281 * a size of 1. This should catch the instruction of interest
282 * (since if using asm-level debug info, one instruction will
283 * correspond to one line, unlike with C-level debug info where
284 * multiple instructions can map to the one line), but avoid
285 * catching any other instructions bogusly. */
286 if (this > next) {
287 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000288 "warning: line info addresses out of order "
sewardjb51f2e62002-06-01 23:11:19 +0000289 "at entry %d: 0x%x 0x%x", entry, this, next);
290 size = 1;
291 }
292
293 if (size > MAX_LOC_SIZE) {
sewardjd84606d2002-06-18 01:04:57 +0000294 if (0)
sewardjb51f2e62002-06-01 23:11:19 +0000295 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000296 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000297 "at entry %d: %d", entry, size);
298 size = 1;
299 }
300
sewardj08a50f62002-06-17 02:21:20 +0000301 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000302 if (this >= si->start + si->size || next-1 < si->start) {
sewardjd84606d2002-06-18 01:04:57 +0000303 if (0)
sewardj08a50f62002-06-17 02:21:20 +0000304 VG_(message)(Vg_DebugMsg,
305 "warning: ignoring line info entry falling "
306 "outside current SegInfo: %p %p %p %p",
307 si->start, si->start + si->size,
308 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000309 return;
310 }
311
312 vg_assert(lineno >= 0);
313 if (lineno > MAX_LINENO) {
314 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000315 "warning: ignoring line info entry with "
316 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000317 VG_(message)(Vg_UserMsg,
318 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000319 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000320 return;
321 }
sewardjb51f2e62002-06-01 23:11:19 +0000322
323 loc.addr = this;
324 loc.size = (UShort)size;
325 loc.lineno = lineno;
326 loc.fnmoff = fnmoff;
sewardjb642dc22002-10-12 17:27:16 +0000327
328 if (0) VG_(message)(Vg_DebugMsg,
329 "addLoc: addr %p, size %d, line %d, file %s",
330 this,size,lineno,&si->strtab[fnmoff]);
331
sewardjb51f2e62002-06-01 23:11:19 +0000332 addLoc ( si, &loc );
333}
334
sewardjde4a1d02002-03-22 01:27:54 +0000335
336/*------------------------------------------------------------*/
337/*--- Helpers ---*/
338/*------------------------------------------------------------*/
339
340/* Non-fatal -- use vg_panic if terminal. */
341static
342void vg_symerr ( Char* msg )
343{
344 if (VG_(clo_verbosity) > 1)
345 VG_(message)(Vg_UserMsg,"%s", msg );
346}
347
348
349/* Print a symbol. */
350static
351void printSym ( SegInfo* si, Int i )
352{
353 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
354 i,
355 si->symtab[i].addr,
356 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
357 &si->strtab[si->symtab[i].nmoff] );
358}
359
360
361#if 0
362/* Print the entire sym tab. */
363static __attribute__ ((unused))
364void printSymtab ( void )
365{
366 Int i;
367 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
368 for (i = 0; i < vg_symtab_used; i++)
369 printSym(i);
370 VG_(printf)("------ BEGIN vg_symtab ------\n");
371}
372#endif
373
374#if 0
375/* Paranoid strcat. */
376static
377void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
378{
379 UInt i = 0, j = 0;
380 while (True) {
381 if (i >= maxlen) return;
382 if (dst[i] == 0) break;
383 i++;
384 }
385 while (True) {
386 if (i >= maxlen) return;
387 dst[i] = src[j];
388 if (src[j] == 0) return;
389 i++; j++;
390 }
391}
392#endif
393
sewardjb51f2e62002-06-01 23:11:19 +0000394
sewardjde4a1d02002-03-22 01:27:54 +0000395/*------------------------------------------------------------*/
396/*--- Canonicalisers ---*/
397/*------------------------------------------------------------*/
398
399/* Sort the symtab by starting address, and emit warnings if any
400 symbols have overlapping address ranges. We use that old chestnut,
401 shellsort. Mash the table around so as to establish the property
402 that addresses are in order and the ranges to not overlap. This
403 facilitates using binary search to map addresses to symbols when we
404 come to query the table.
405*/
406static
407void canonicaliseSymtab ( SegInfo* si )
408{
409 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
410 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
411 4592, 13776, 33936, 86961, 198768,
412 463792, 1391376 };
413 Int lo = 0;
414 Int hi = si->symtab_used-1;
415 Int i, j, h, bigN, hp, n_merged, n_truncated;
416 RiSym v;
417 Addr s1, s2, e1, e2;
418
419# define SWAP(ty,aa,bb) \
420 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
421
422 bigN = hi - lo + 1; if (bigN < 2) return;
423 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
424 vg_assert(0 <= hp && hp < 16);
425
426 for (; hp >= 0; hp--) {
427 h = incs[hp];
428 i = lo + h;
429 while (1) {
430 if (i > hi) break;
431 v = si->symtab[i];
432 j = i;
433 while (si->symtab[j-h].addr > v.addr) {
434 si->symtab[j] = si->symtab[j-h];
435 j = j - h;
436 if (j <= (lo + h - 1)) break;
437 }
438 si->symtab[j] = v;
439 i++;
440 }
441 }
442
443 cleanup_more:
444
445 /* If two symbols have identical address ranges, favour the
446 one with the longer name.
447 */
448 do {
449 n_merged = 0;
450 j = si->symtab_used;
451 si->symtab_used = 0;
452 for (i = 0; i < j; i++) {
453 if (i < j-1
454 && si->symtab[i].addr == si->symtab[i+1].addr
455 && si->symtab[i].size == si->symtab[i+1].size) {
456 n_merged++;
457 /* merge the two into one */
458 if (VG_(strlen)(&si->strtab[si->symtab[i].nmoff])
459 > VG_(strlen)(&si->strtab[si->symtab[i+1].nmoff])) {
460 si->symtab[si->symtab_used++] = si->symtab[i];
461 } else {
462 si->symtab[si->symtab_used++] = si->symtab[i+1];
463 }
464 i++;
465 } else {
466 si->symtab[si->symtab_used++] = si->symtab[i];
467 }
468 }
469 if (VG_(clo_trace_symtab))
470 VG_(printf)( "%d merged\n", n_merged);
471 }
472 while (n_merged > 0);
473
474 /* Detect and "fix" overlapping address ranges. */
475 n_truncated = 0;
476
477 for (i = 0; i < si->symtab_used-1; i++) {
478
479 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
480
481 /* Check for common (no overlap) case. */
482 if (si->symtab[i].addr + si->symtab[i].size
483 <= si->symtab[i+1].addr)
484 continue;
485
486 /* There's an overlap. Truncate one or the other. */
487 if (VG_(clo_trace_symtab)) {
488 VG_(printf)("overlapping address ranges in symbol table\n\t");
489 printSym(si,i);
490 VG_(printf)("\t");
491 printSym(si,i+1);
492 VG_(printf)("\n");
493 }
494
495 /* Truncate one or the other. */
496 s1 = si->symtab[i].addr;
497 s2 = si->symtab[i+1].addr;
498 e1 = s1 + si->symtab[i].size - 1;
499 e2 = s2 + si->symtab[i+1].size - 1;
500 if (s1 < s2) {
501 e1 = s2-1;
502 } else {
503 vg_assert(s1 == s2);
504 if (e1 > e2) {
505 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
506 } else
507 if (e1 < e2) {
508 s2 = e1+1;
509 } else {
510 /* e1 == e2. Identical addr ranges. We'll eventually wind
511 up back at cleanup_more, which will take care of it. */
512 }
513 }
514 si->symtab[i].addr = s1;
515 si->symtab[i+1].addr = s2;
516 si->symtab[i].size = e1 - s1 + 1;
517 si->symtab[i+1].size = e2 - s2 + 1;
518 vg_assert(s1 <= s2);
519 vg_assert(si->symtab[i].size > 0);
520 vg_assert(si->symtab[i+1].size > 0);
521 /* It may be that the i+1 entry now needs to be moved further
522 along to maintain the address order requirement. */
523 j = i+1;
524 while (j < si->symtab_used-1
525 && si->symtab[j].addr > si->symtab[j+1].addr) {
526 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
527 j++;
528 }
529 n_truncated++;
530 }
531
532 if (n_truncated > 0) goto cleanup_more;
533
534 /* Ensure relevant postconditions hold. */
535 for (i = 0; i < si->symtab_used-1; i++) {
536 /* No zero-sized symbols. */
537 vg_assert(si->symtab[i].size > 0);
538 /* In order. */
539 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
540 /* No overlaps. */
541 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
542 < si->symtab[i+1].addr);
543 }
544# undef SWAP
545}
546
547
548
549/* Sort the location table by starting address. Mash the table around
550 so as to establish the property that addresses are in order and the
551 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000552 addresses to locations when we come to query the table.
553*/
sewardjde4a1d02002-03-22 01:27:54 +0000554static
555void canonicaliseLoctab ( SegInfo* si )
556{
557 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
558 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
559 4592, 13776, 33936, 86961, 198768,
560 463792, 1391376 };
561 Int lo = 0;
562 Int hi = si->loctab_used-1;
563 Int i, j, h, bigN, hp;
564 RiLoc v;
565
566# define SWAP(ty,aa,bb) \
567 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
568
569 /* Sort by start address. */
570
571 bigN = hi - lo + 1; if (bigN < 2) return;
572 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
573 vg_assert(0 <= hp && hp < 16);
574
575 for (; hp >= 0; hp--) {
576 h = incs[hp];
577 i = lo + h;
578 while (1) {
579 if (i > hi) break;
580 v = si->loctab[i];
581 j = i;
582 while (si->loctab[j-h].addr > v.addr) {
583 si->loctab[j] = si->loctab[j-h];
584 j = j - h;
585 if (j <= (lo + h - 1)) break;
586 }
587 si->loctab[j] = v;
588 i++;
589 }
590 }
591
592 /* If two adjacent entries overlap, truncate the first. */
593 for (i = 0; i < si->loctab_used-1; i++) {
594 vg_assert(si->loctab[i].size < 10000);
595 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
596 /* Do this in signed int32 because the actual .size fields
597 are unsigned 16s. */
598 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
599 if (new_size < 0) {
600 si->loctab[i].size = 0;
601 } else
602 if (new_size >= 65536) {
603 si->loctab[i].size = 65535;
604 } else {
605 si->loctab[i].size = (UShort)new_size;
606 }
607 }
608 }
609
610 /* Zap any zero-sized entries resulting from the truncation
611 process. */
612 j = 0;
613 for (i = 0; i < si->loctab_used; i++) {
614 if (si->loctab[i].size > 0) {
615 si->loctab[j] = si->loctab[i];
616 j++;
617 }
618 }
619 si->loctab_used = j;
620
621 /* Ensure relevant postconditions hold. */
622 for (i = 0; i < si->loctab_used-1; i++) {
623 /*
624 VG_(printf)("%d (%d) %d 0x%x\n",
625 i, si->loctab[i+1].confident,
626 si->loctab[i+1].size, si->loctab[i+1].addr );
627 */
628 /* No zero-sized symbols. */
629 vg_assert(si->loctab[i].size > 0);
630 /* In order. */
631 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
632 /* No overlaps. */
633 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
634 < si->loctab[i+1].addr);
635 }
636# undef SWAP
637}
638
639
640/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000641/*--- Read STABS format debug info. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000642/*------------------------------------------------------------*/
643
sewardjb51f2e62002-06-01 23:11:19 +0000644/* Stabs entry types, from:
645 * The "stabs" debug format
646 * Menapace, Kingdon and MacKenzie
647 * Cygnus Support
648 */
649typedef enum { N_GSYM = 32, /* Global symbol */
650 N_FUN = 36, /* Function start or end */
651 N_STSYM = 38, /* Data segment file-scope variable */
652 N_LCSYM = 40, /* BSS segment file-scope variable */
653 N_RSYM = 64, /* Register variable */
654 N_SLINE = 68, /* Source line number */
655 N_SO = 100, /* Source file path and name */
656 N_LSYM = 128, /* Stack variable or type */
657 N_SOL = 132, /* Include file name */
658 N_LBRAC = 192, /* Start of lexical block */
659 N_RBRAC = 224 /* End of lexical block */
660 } stab_types;
661
662
663/* Read stabs-format debug info. This is all rather horrible because
664 stabs is a underspecified, kludgy hack.
665*/
666static
667void read_debuginfo_stabs ( SegInfo* si,
668 UChar* stabC, Int stab_sz,
669 UChar* stabstr, Int stabstr_sz )
sewardjde4a1d02002-03-22 01:27:54 +0000670{
sewardjb51f2e62002-06-01 23:11:19 +0000671 Int i;
672 Int curr_filenmoff;
njnb79ad342002-06-05 15:30:30 +0000673 Addr curr_fn_stabs_addr = (Addr)NULL;
674 Addr curr_fnbaseaddr = (Addr)NULL;
sewardjb51f2e62002-06-01 23:11:19 +0000675 Char *curr_file_name, *curr_fn_name;
676 Int n_stab_entries;
njnb79ad342002-06-05 15:30:30 +0000677 Int prev_lineno = 0, lineno = 0;
678 Int lineno_overflows = 0;
679 Bool same_file = True;
sewardjb51f2e62002-06-01 23:11:19 +0000680 struct nlist* stab = (struct nlist*)stabC;
njnb79ad342002-06-05 15:30:30 +0000681
sewardjb51f2e62002-06-01 23:11:19 +0000682 /* Ok. It all looks plausible. Go on and read debug data.
683 stab kinds: 100 N_SO a source file name
684 68 N_SLINE a source line number
685 36 N_FUN start of a function
njn4f9c9342002-04-29 16:03:24 +0000686
sewardjb51f2e62002-06-01 23:11:19 +0000687 In this loop, we maintain a current file name, updated as
688 N_SO/N_SOLs appear, and a current function base address,
689 updated as N_FUNs appear. Based on that, address ranges for
690 N_SLINEs are calculated, and stuffed into the line info table.
sewardjde4a1d02002-03-22 01:27:54 +0000691
sewardjb51f2e62002-06-01 23:11:19 +0000692 Finding the instruction address range covered by an N_SLINE is
693 complicated; see the N_SLINE case below.
694 */
njnb79ad342002-06-05 15:30:30 +0000695 curr_filenmoff = addStr(si,"???");
696 curr_file_name = curr_fn_name = (Char*)NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000697
sewardjb51f2e62002-06-01 23:11:19 +0000698 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
njne0ee0712002-05-03 16:41:05 +0000699
sewardjb51f2e62002-06-01 23:11:19 +0000700 for (i = 0; i < n_stab_entries; i++) {
701# if 0
702 VG_(printf) ( " %2d ", i );
703 VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s",
704 stab[i].n_type, stab[i].n_other, stab[i].n_desc,
705 (int)stab[i].n_value,
706 (int)stab[i].n_un.n_strx,
707 stabstr + stab[i].n_un.n_strx );
708 VG_(printf)("\n");
709# endif
njne0ee0712002-05-03 16:41:05 +0000710
sewardjb51f2e62002-06-01 23:11:19 +0000711 Char *no_fn_name = "???";
712
713 switch (stab[i].n_type) {
714 UInt next_addr;
715
716 /* Two complicated things here:
717 *
718 * 1. the n_desc field in 'struct n_list' in a.out.h is only
719 * 16-bits, which gives a maximum of 65535 lines. We handle
720 * files bigger than this by detecting heuristically
721 * overflows -- if the line count goes from 65000-odd to
722 * 0-odd within the same file, we assume it's an overflow.
723 * Once we switch files, we zero the overflow count.
724 *
725 * 2. To compute the instr address range covered by a single
726 * line, find the address of the next thing and compute the
727 * difference. The approach used depends on what kind of
728 * entry/entries follow...
729 */
730 case N_SLINE: {
731 Int this_addr = (UInt)stab[i].n_value;
732
733 /* Although stored as a short, neg values really are >
734 * 32768, hence the UShort cast. Then we use an Int to
735 * handle overflows. */
736 prev_lineno = lineno;
737 lineno = (Int)((UShort)stab[i].n_desc);
738
739 if (prev_lineno > lineno + OVERFLOW_DIFFERENCE && same_file) {
740 VG_(message)(Vg_DebugMsg,
741 "Line number overflow detected (%d --> %d) in %s",
742 prev_lineno, lineno, curr_file_name);
743 lineno_overflows++;
744 }
745 same_file = True;
746
747 LOOP:
748 if (i+1 >= n_stab_entries) {
749 /* If it's the last entry, just guess the range is
750 * four; can't do any better */
751 next_addr = this_addr + 4;
752 } else {
753 switch (stab[i+1].n_type) {
754 /* Easy, common case: use address of next entry */
755 case N_SLINE: case N_SO:
756 next_addr = (UInt)stab[i+1].n_value;
757 break;
758
njn25e49d8e72002-09-23 09:36:25 +0000759 /* Boring one: skip, look for something more useful. */
sewardjb51f2e62002-06-01 23:11:19 +0000760 case N_RSYM: case N_LSYM: case N_LBRAC: case N_RBRAC:
761 case N_STSYM: case N_LCSYM: case N_GSYM:
762 i++;
763 goto LOOP;
764
njnb79ad342002-06-05 15:30:30 +0000765 /* If end-of-this-fun entry, use its address.
766 * If start-of-next-fun entry, find difference between start
767 * of current function and start of next function to work
768 * it out.
769 */
sewardjb51f2e62002-06-01 23:11:19 +0000770 case N_FUN:
771 if ('\0' == * (stabstr + stab[i+1].n_un.n_strx) ) {
772 next_addr = (UInt)stab[i+1].n_value;
773 } else {
njnb79ad342002-06-05 15:30:30 +0000774 next_addr =
775 (UInt)stab[i+1].n_value - curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000776 }
777 break;
778
779 /* N_SOL should be followed by an N_SLINE which can
780 be used */
781 case N_SOL:
782 if (i+2 < n_stab_entries && N_SLINE == stab[i+2].n_type) {
783 next_addr = (UInt)stab[i+2].n_value;
784 break;
785 } else {
786 VG_(printf)("unhandled N_SOL stabs case: %d %d %d",
787 stab[i+1].n_type, i, n_stab_entries);
njne427a662002-10-02 11:08:25 +0000788 VG_(core_panic)("unhandled N_SOL stabs case");
sewardjb51f2e62002-06-01 23:11:19 +0000789 }
790
791 default:
792 VG_(printf)("unhandled (other) stabs case: %d %d",
793 stab[i+1].n_type,i);
njne427a662002-10-02 11:08:25 +0000794 /* VG_(core_panic)("unhandled (other) stabs case"); */
sewardjb51f2e62002-06-01 23:11:19 +0000795 next_addr = this_addr + 4;
796 break;
797 }
798 }
799
800 addLineInfo ( si, curr_filenmoff, curr_fnbaseaddr + this_addr,
801 curr_fnbaseaddr + next_addr,
802 lineno + lineno_overflows * LINENO_OVERFLOW, i);
803 break;
804 }
805
806 case N_FUN: {
807 if ('\0' != (stabstr + stab[i].n_un.n_strx)[0] ) {
808 /* N_FUN with a name -- indicates the start of a fn. */
njnb79ad342002-06-05 15:30:30 +0000809 curr_fn_stabs_addr = (Addr)stab[i].n_value;
810 curr_fnbaseaddr = si->offset + curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000811 curr_fn_name = stabstr + stab[i].n_un.n_strx;
812 } else {
813 curr_fn_name = no_fn_name;
814 }
815 break;
816 }
817
818 case N_SOL:
819 if (lineno_overflows != 0) {
820 VG_(message)(Vg_UserMsg,
821 "Warning: file %s is very big (> 65535 lines) "
822 "Line numbers and annotation for this file might "
823 "be wrong. Sorry",
824 curr_file_name);
825 }
826 /* fall through! */
827 case N_SO:
828 lineno_overflows = 0;
829
830 /* seems to give lots of locations in header files */
831 /* case 130: */ /* BINCL */
832 {
833 UChar* nm = stabstr + stab[i].n_un.n_strx;
834 UInt len = VG_(strlen)(nm);
835
836 if (len > 0 && nm[len-1] != '/') {
837 curr_filenmoff = addStr ( si, nm );
838 curr_file_name = stabstr + stab[i].n_un.n_strx;
839 }
840 else
841 if (len == 0)
842 curr_filenmoff = addStr ( si, "?1\0" );
843
844 break;
845 }
846
847# if 0
848 case 162: /* EINCL */
849 curr_filenmoff = addStr ( si, "?2\0" );
850 break;
851# endif
852
853 default:
854 break;
855 }
856 } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000857}
858
859
sewardjb51f2e62002-06-01 23:11:19 +0000860/*------------------------------------------------------------*/
861/*--- Read DWARF2 format debug info. ---*/
862/*------------------------------------------------------------*/
sewardjc134dd92002-06-01 14:21:36 +0000863
864/* Structure found in the .debug_line section. */
865typedef struct
866{
867 UChar li_length [4];
868 UChar li_version [2];
869 UChar li_prologue_length [4];
870 UChar li_min_insn_length [1];
871 UChar li_default_is_stmt [1];
872 UChar li_line_base [1];
873 UChar li_line_range [1];
874 UChar li_opcode_base [1];
875}
876DWARF2_External_LineInfo;
sewardjd84606d2002-06-18 01:04:57 +0000877
sewardjc134dd92002-06-01 14:21:36 +0000878typedef struct
879{
sewardj08a50f62002-06-17 02:21:20 +0000880 UInt li_length;
sewardjc134dd92002-06-01 14:21:36 +0000881 UShort li_version;
882 UInt li_prologue_length;
883 UChar li_min_insn_length;
884 UChar li_default_is_stmt;
sewardj08a50f62002-06-17 02:21:20 +0000885 Int li_line_base;
sewardjc134dd92002-06-01 14:21:36 +0000886 UChar li_line_range;
887 UChar li_opcode_base;
888}
889DWARF2_Internal_LineInfo;
sewardjd84606d2002-06-18 01:04:57 +0000890
sewardjc134dd92002-06-01 14:21:36 +0000891/* Line number opcodes. */
892enum dwarf_line_number_ops
893 {
894 DW_LNS_extended_op = 0,
895 DW_LNS_copy = 1,
896 DW_LNS_advance_pc = 2,
897 DW_LNS_advance_line = 3,
898 DW_LNS_set_file = 4,
899 DW_LNS_set_column = 5,
900 DW_LNS_negate_stmt = 6,
901 DW_LNS_set_basic_block = 7,
902 DW_LNS_const_add_pc = 8,
903 DW_LNS_fixed_advance_pc = 9,
904 /* DWARF 3. */
905 DW_LNS_set_prologue_end = 10,
906 DW_LNS_set_epilogue_begin = 11,
907 DW_LNS_set_isa = 12
908 };
909
910/* Line number extended opcodes. */
911enum dwarf_line_number_x_ops
912 {
913 DW_LNE_end_sequence = 1,
914 DW_LNE_set_address = 2,
915 DW_LNE_define_file = 3
916 };
917
918typedef struct State_Machine_Registers
919{
sewardj08a50f62002-06-17 02:21:20 +0000920 Addr address;
sewardjb642dc22002-10-12 17:27:16 +0000921 /* Holds the address of the last statement boundary.
922 * We use it to calculate statement lengths. Without it,
923 * we would need to search backwards for last statement begin
924 * each time we are emitting a statement with addLineInfo */
925 Addr last_address;
sewardjc134dd92002-06-01 14:21:36 +0000926 UInt file;
927 UInt line;
928 UInt column;
929 Int is_stmt;
930 Int basic_block;
sewardj08a50f62002-06-17 02:21:20 +0000931 Int end_sequence;
932 /* This variable hold the number of the last entry seen
933 in the File Table. */
sewardjc134dd92002-06-01 14:21:36 +0000934 UInt last_file_entry;
935} SMR;
936
sewardjb51f2e62002-06-01 23:11:19 +0000937
938static
939UInt read_leb128 ( UChar* data, Int* length_return, Int sign )
940{
sewardj08a50f62002-06-17 02:21:20 +0000941 UInt result = 0;
942 UInt num_read = 0;
943 Int shift = 0;
944 UChar byte;
sewardjb51f2e62002-06-01 23:11:19 +0000945
946 do
947 {
948 byte = * data ++;
949 num_read ++;
950
951 result |= (byte & 0x7f) << shift;
952
953 shift += 7;
954
955 }
956 while (byte & 0x80);
957
958 if (length_return != NULL)
959 * length_return = num_read;
960
961 if (sign && (shift < 32) && (byte & 0x40))
962 result |= -1 << shift;
963
964 return result;
965}
966
967
sewardjc134dd92002-06-01 14:21:36 +0000968static SMR state_machine_regs;
969
sewardj08a50f62002-06-17 02:21:20 +0000970static
971void reset_state_machine ( Int is_stmt )
sewardjc134dd92002-06-01 14:21:36 +0000972{
sewardj08a50f62002-06-17 02:21:20 +0000973 if (0) VG_(printf)("smr.a := %p (reset)\n", 0 );
sewardjc134dd92002-06-01 14:21:36 +0000974 state_machine_regs.address = 0;
sewardjb642dc22002-10-12 17:27:16 +0000975 state_machine_regs.last_address = 0;
sewardjc134dd92002-06-01 14:21:36 +0000976 state_machine_regs.file = 1;
977 state_machine_regs.line = 1;
978 state_machine_regs.column = 0;
979 state_machine_regs.is_stmt = is_stmt;
980 state_machine_regs.basic_block = 0;
981 state_machine_regs.end_sequence = 0;
982 state_machine_regs.last_file_entry = 0;
983}
984
985/* Handled an extend line op. Returns true if this is the end
986 of sequence. */
sewardj08a50f62002-06-17 02:21:20 +0000987static
988int process_extended_line_op( SegInfo *si, UInt** fnames,
989 UChar* data, Int is_stmt, Int pointer_size)
sewardjc134dd92002-06-01 14:21:36 +0000990{
991 UChar op_code;
sewardj08a50f62002-06-17 02:21:20 +0000992 Int bytes_read;
sewardjc134dd92002-06-01 14:21:36 +0000993 UInt len;
994 UChar * name;
sewardj08a50f62002-06-17 02:21:20 +0000995 Addr adr;
sewardjc134dd92002-06-01 14:21:36 +0000996
997 len = read_leb128 (data, & bytes_read, 0);
998 data += bytes_read;
999
1000 if (len == 0)
1001 {
sewardj08a50f62002-06-17 02:21:20 +00001002 VG_(message)(Vg_UserMsg,
1003 "badly formed extended line op encountered!\n");
sewardjc134dd92002-06-01 14:21:36 +00001004 return bytes_read;
1005 }
1006
1007 len += bytes_read;
1008 op_code = * data ++;
1009
sewardjb642dc22002-10-12 17:27:16 +00001010 if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
sewardjc134dd92002-06-01 14:21:36 +00001011
1012 switch (op_code)
1013 {
1014 case DW_LNE_end_sequence:
sewardj08a50f62002-06-17 02:21:20 +00001015 if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",
1016 si->offset, state_machine_regs.address );
sewardjd84606d2002-06-18 01:04:57 +00001017 state_machine_regs.end_sequence = 1; /* JRS: added for compliance
1018 with spec; is pointless due to reset_state_machine below
1019 */
sewardjb642dc22002-10-12 17:27:16 +00001020 if (state_machine_regs.is_stmt) {
1021 if (state_machine_regs.last_address)
1022 addLineInfo (si, (*fnames)[state_machine_regs.file],
1023 si->offset + state_machine_regs.last_address,
1024 si->offset + state_machine_regs.address,
1025 state_machine_regs.line, 0);
1026 }
sewardjc134dd92002-06-01 14:21:36 +00001027 reset_state_machine (is_stmt);
1028 break;
1029
1030 case DW_LNE_set_address:
1031 /* XXX: Pointer size could be 8 */
sewardj08a50f62002-06-17 02:21:20 +00001032 vg_assert(pointer_size == 4);
sewardjc134dd92002-06-01 14:21:36 +00001033 adr = *((Addr *)data);
sewardj08a50f62002-06-17 02:21:20 +00001034 if (0) VG_(printf)("smr.a := %p\n", adr );
sewardjc134dd92002-06-01 14:21:36 +00001035 state_machine_regs.address = adr;
1036 break;
1037
1038 case DW_LNE_define_file:
sewardjc134dd92002-06-01 14:21:36 +00001039 ++ state_machine_regs.last_file_entry;
1040 name = data;
1041 if (*fnames == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001042 *fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
sewardjc134dd92002-06-01 14:21:36 +00001043 else
njn25e49d8e72002-09-23 09:36:25 +00001044 *fnames = VG_(arena_realloc)(
1045 VG_AR_SYMTAB, *fnames, /*alignment*/4,
sewardj08a50f62002-06-17 02:21:20 +00001046 sizeof(UInt)
1047 * (state_machine_regs.last_file_entry + 1));
sewardjc134dd92002-06-01 14:21:36 +00001048 (*fnames)[state_machine_regs.last_file_entry] = addStr (si,name);
1049 data += VG_(strlen) ((char *) data) + 1;
1050 read_leb128 (data, & bytes_read, 0);
1051 data += bytes_read;
1052 read_leb128 (data, & bytes_read, 0);
1053 data += bytes_read;
sewardj08a50f62002-06-17 02:21:20 +00001054 read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001055 break;
1056
1057 default:
1058 break;
1059 }
1060
1061 return len;
1062}
1063
1064
sewardjb51f2e62002-06-01 23:11:19 +00001065static
1066void read_debuginfo_dwarf2 ( SegInfo* si, UChar* dwarf2, Int dwarf2_sz )
sewardjc134dd92002-06-01 14:21:36 +00001067{
1068 DWARF2_External_LineInfo * external;
1069 DWARF2_Internal_LineInfo info;
1070 UChar * standard_opcodes;
sewardjb51f2e62002-06-01 23:11:19 +00001071 UChar * data = dwarf2;
1072 UChar * end = dwarf2 + dwarf2_sz;
sewardjc134dd92002-06-01 14:21:36 +00001073 UChar * end_of_sequence;
sewardj08a50f62002-06-17 02:21:20 +00001074 UInt * fnames = NULL;
sewardjc134dd92002-06-01 14:21:36 +00001075
sewardjd84606d2002-06-18 01:04:57 +00001076 /* Fails due to gcc padding ...
1077 vg_assert(sizeof(DWARF2_External_LineInfo)
1078 == sizeof(DWARF2_Internal_LineInfo));
1079 */
sewardjc134dd92002-06-01 14:21:36 +00001080
1081 while (data < end)
1082 {
1083 external = (DWARF2_External_LineInfo *) data;
1084
1085 /* Check the length of the block. */
sewardj08a50f62002-06-17 02:21:20 +00001086 info.li_length = * ((UInt *)(external->li_length));
sewardjc134dd92002-06-01 14:21:36 +00001087
1088 if (info.li_length == 0xffffffff)
1089 {
sewardjb51f2e62002-06-01 23:11:19 +00001090 vg_symerr("64-bit DWARF line info is not supported yet.");
sewardjc134dd92002-06-01 14:21:36 +00001091 break;
1092 }
1093
sewardjb51f2e62002-06-01 23:11:19 +00001094 if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
sewardjc134dd92002-06-01 14:21:36 +00001095 {
sewardj08a50f62002-06-17 02:21:20 +00001096 vg_symerr("DWARF line info appears to be corrupt "
1097 "- the section is too small");
sewardjb51f2e62002-06-01 23:11:19 +00001098 return;
sewardjc134dd92002-06-01 14:21:36 +00001099 }
1100
1101 /* Check its version number. */
sewardj08a50f62002-06-17 02:21:20 +00001102 info.li_version = * ((UShort *) (external->li_version));
sewardjc134dd92002-06-01 14:21:36 +00001103 if (info.li_version != 2)
1104 {
sewardj08a50f62002-06-17 02:21:20 +00001105 vg_symerr("Only DWARF version 2 line info "
1106 "is currently supported.");
sewardjb51f2e62002-06-01 23:11:19 +00001107 return;
sewardjc134dd92002-06-01 14:21:36 +00001108 }
1109
sewardjd84606d2002-06-18 01:04:57 +00001110 info.li_prologue_length = * ((UInt *) (external->li_prologue_length));
1111 info.li_min_insn_length = * ((UChar *)(external->li_min_insn_length));
1112 info.li_default_is_stmt = * ((UChar *)(external->li_default_is_stmt));
1113
1114 /* JRS: changed (UInt*) to (UChar*) */
1115 info.li_line_base = * ((UChar *)(external->li_line_base));
1116
1117 info.li_line_range = * ((UChar *)(external->li_line_range));
1118 info.li_opcode_base = * ((UChar *)(external->li_opcode_base));
sewardjc134dd92002-06-01 14:21:36 +00001119
sewardjb642dc22002-10-12 17:27:16 +00001120 if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
1121 info.li_line_base, info.li_line_range, info.li_opcode_base);
1122
sewardjc134dd92002-06-01 14:21:36 +00001123 /* Sign extend the line base field. */
1124 info.li_line_base <<= 24;
1125 info.li_line_base >>= 24;
1126
sewardj08a50f62002-06-17 02:21:20 +00001127 end_of_sequence = data + info.li_length
1128 + sizeof (external->li_length);
sewardjc134dd92002-06-01 14:21:36 +00001129
1130 reset_state_machine (info.li_default_is_stmt);
1131
1132 /* Read the contents of the Opcodes table. */
1133 standard_opcodes = data + sizeof (* external);
1134
sewardjc134dd92002-06-01 14:21:36 +00001135 /* Read the contents of the Directory table. */
1136 data = standard_opcodes + info.li_opcode_base - 1;
1137
sewardj08a50f62002-06-17 02:21:20 +00001138 if (* data == 0)
1139 {
1140 }
sewardjc134dd92002-06-01 14:21:36 +00001141 else
1142 {
sewardj08a50f62002-06-17 02:21:20 +00001143 /* We ignore the directory table, since gcc gives the entire
1144 path as part of the filename */
sewardjc134dd92002-06-01 14:21:36 +00001145 while (* data != 0)
1146 {
1147 data += VG_(strlen) ((char *) data) + 1;
1148 }
1149 }
1150
1151 /* Skip the NUL at the end of the table. */
sewardjd84606d2002-06-18 01:04:57 +00001152 if (*data != 0) {
1153 vg_symerr("can't find NUL at end of DWARF2 directory table");
1154 return;
1155 }
sewardjc134dd92002-06-01 14:21:36 +00001156 data ++;
1157
1158 /* Read the contents of the File Name table. */
sewardj08a50f62002-06-17 02:21:20 +00001159 if (* data == 0)
1160 {
1161 }
sewardjc134dd92002-06-01 14:21:36 +00001162 else
1163 {
sewardjc134dd92002-06-01 14:21:36 +00001164 while (* data != 0)
1165 {
1166 UChar * name;
1167 Int bytes_read;
1168
sewardj08a50f62002-06-17 02:21:20 +00001169 ++ state_machine_regs.last_file_entry;
sewardjc134dd92002-06-01 14:21:36 +00001170 name = data;
sewardj08a50f62002-06-17 02:21:20 +00001171 /* Since we don't have realloc (0, ....) == malloc (...)
1172 semantics, we need to malloc the first time. */
sewardjc134dd92002-06-01 14:21:36 +00001173
1174 if (fnames == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001175 fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
sewardjc134dd92002-06-01 14:21:36 +00001176 else
njn25e49d8e72002-09-23 09:36:25 +00001177 fnames = VG_(arena_realloc)(VG_AR_SYMTAB, fnames, /*alignment*/4,
sewardj08a50f62002-06-17 02:21:20 +00001178 sizeof(UInt)
1179 * (state_machine_regs.last_file_entry + 1));
1180 data += VG_(strlen) ((Char *) data) + 1;
sewardjc134dd92002-06-01 14:21:36 +00001181 fnames[state_machine_regs.last_file_entry] = addStr (si,name);
1182
1183 read_leb128 (data, & bytes_read, 0);
1184 data += bytes_read;
1185 read_leb128 (data, & bytes_read, 0);
1186 data += bytes_read;
1187 read_leb128 (data, & bytes_read, 0);
1188 data += bytes_read;
1189 }
1190 }
1191
1192 /* Skip the NUL at the end of the table. */
sewardjd84606d2002-06-18 01:04:57 +00001193 if (*data != 0) {
1194 vg_symerr("can't find NUL at end of DWARF2 file name table");
1195 return;
1196 }
sewardjc134dd92002-06-01 14:21:36 +00001197 data ++;
1198
1199 /* Now display the statements. */
1200
1201 while (data < end_of_sequence)
1202 {
1203 UChar op_code;
1204 Int adv;
1205 Int bytes_read;
1206
1207 op_code = * data ++;
1208
sewardjb642dc22002-10-12 17:27:16 +00001209 if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
1210
sewardjc134dd92002-06-01 14:21:36 +00001211 if (op_code >= info.li_opcode_base)
1212 {
1213 Int advAddr;
1214 op_code -= info.li_opcode_base;
sewardj08a50f62002-06-17 02:21:20 +00001215 adv = (op_code / info.li_line_range)
1216 * info.li_min_insn_length;
sewardjc134dd92002-06-01 14:21:36 +00001217 advAddr = adv;
1218 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001219 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001220 adv = (op_code % info.li_line_range) + info.li_line_base;
sewardj08a50f62002-06-17 02:21:20 +00001221 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1222 si->offset, state_machine_regs.address );
sewardjb642dc22002-10-12 17:27:16 +00001223 if (state_machine_regs.is_stmt) {
1224 /* only add a statement if there was a previous boundary */
1225 if (state_machine_regs.last_address)
1226 addLineInfo (si, fnames[state_machine_regs.file],
1227 si->offset + state_machine_regs.last_address,
1228 si->offset + state_machine_regs.address,
sewardj08a50f62002-06-17 02:21:20 +00001229 state_machine_regs.line, 0);
sewardjb642dc22002-10-12 17:27:16 +00001230 state_machine_regs.last_address = state_machine_regs.address;
1231 }
sewardjc134dd92002-06-01 14:21:36 +00001232 state_machine_regs.line += adv;
1233 }
1234 else switch (op_code)
1235 {
1236 case DW_LNS_extended_op:
sewardj08a50f62002-06-17 02:21:20 +00001237 data += process_extended_line_op (
1238 si, &fnames, data,
1239 info.li_default_is_stmt, sizeof (Addr));
sewardjc134dd92002-06-01 14:21:36 +00001240 break;
1241
1242 case DW_LNS_copy:
sewardj08a50f62002-06-17 02:21:20 +00001243 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1244 si->offset, state_machine_regs.address );
sewardjb642dc22002-10-12 17:27:16 +00001245 if (state_machine_regs.is_stmt) {
1246 /* only add a statement if there was a previous boundary */
1247 if (state_machine_regs.last_address)
1248 addLineInfo (si, fnames[state_machine_regs.file],
1249 si->offset + state_machine_regs.last_address,
1250 si->offset + state_machine_regs.address,
sewardj08a50f62002-06-17 02:21:20 +00001251 state_machine_regs.line , 0);
sewardjb642dc22002-10-12 17:27:16 +00001252 state_machine_regs.last_address = state_machine_regs.address;
1253 }
sewardjd84606d2002-06-18 01:04:57 +00001254 state_machine_regs.basic_block = 0; /* JRS added */
sewardjc134dd92002-06-01 14:21:36 +00001255 break;
1256
1257 case DW_LNS_advance_pc:
sewardj08a50f62002-06-17 02:21:20 +00001258 adv = info.li_min_insn_length
1259 * read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001260 data += bytes_read;
1261 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001262 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001263 break;
1264
1265 case DW_LNS_advance_line:
1266 adv = read_leb128 (data, & bytes_read, 1);
1267 data += bytes_read;
1268 state_machine_regs.line += adv;
1269 break;
1270
1271 case DW_LNS_set_file:
1272 adv = read_leb128 (data, & bytes_read, 0);
1273 data += bytes_read;
1274 state_machine_regs.file = adv;
1275 break;
1276
1277 case DW_LNS_set_column:
1278 adv = read_leb128 (data, & bytes_read, 0);
1279 data += bytes_read;
1280 state_machine_regs.column = adv;
1281 break;
1282
1283 case DW_LNS_negate_stmt:
1284 adv = state_machine_regs.is_stmt;
1285 adv = ! adv;
1286 state_machine_regs.is_stmt = adv;
1287 break;
1288
1289 case DW_LNS_set_basic_block:
1290 state_machine_regs.basic_block = 1;
1291 break;
1292
1293 case DW_LNS_const_add_pc:
1294 adv = (((255 - info.li_opcode_base) / info.li_line_range)
1295 * info.li_min_insn_length);
1296 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001297 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001298 break;
1299
1300 case DW_LNS_fixed_advance_pc:
1301 /* XXX: Need something to get 2 bytes */
1302 adv = *((UShort *)data);
1303 data += 2;
1304 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001305 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001306 break;
1307
1308 case DW_LNS_set_prologue_end:
1309 break;
1310
1311 case DW_LNS_set_epilogue_begin:
1312 break;
1313
1314 case DW_LNS_set_isa:
1315 adv = read_leb128 (data, & bytes_read, 0);
1316 data += bytes_read;
1317 break;
1318
1319 default:
1320 {
1321 int j;
1322 for (j = standard_opcodes[op_code - 1]; j > 0 ; --j)
1323 {
1324 read_leb128 (data, &bytes_read, 0);
1325 data += bytes_read;
1326 }
1327 }
1328 break;
1329 }
1330 }
njn25e49d8e72002-09-23 09:36:25 +00001331 VG_(arena_free)(VG_AR_SYMTAB, fnames);
sewardjc134dd92002-06-01 14:21:36 +00001332 fnames = NULL;
1333 }
sewardjc134dd92002-06-01 14:21:36 +00001334}
1335
sewardjb51f2e62002-06-01 23:11:19 +00001336
1337/*------------------------------------------------------------*/
1338/*--- Read info from a .so/exe file. ---*/
1339/*------------------------------------------------------------*/
1340
sewardjde4a1d02002-03-22 01:27:54 +00001341/* Read the symbols from the object/exe specified by the SegInfo into
1342 the tables within the supplied SegInfo. */
1343static
1344void vg_read_lib_symbols ( SegInfo* si )
1345{
1346 Elf32_Ehdr* ehdr; /* The ELF header */
1347 Elf32_Shdr* shdr; /* The section table */
1348 UChar* sh_strtab; /* The section table's string table */
sewardjb51f2e62002-06-01 23:11:19 +00001349 UChar* stab; /* The .stab table */
sewardjde4a1d02002-03-22 01:27:54 +00001350 UChar* stabstr; /* The .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001351 UChar* dwarf2; /* The DWARF2 location info table */
sewardjde4a1d02002-03-22 01:27:54 +00001352 Int stab_sz; /* Size in bytes of the .stab table */
1353 Int stabstr_sz; /* Size in bytes of the .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001354 Int dwarf2_sz; /* Size in bytes of the DWARF2 srcloc table*/
sewardjde4a1d02002-03-22 01:27:54 +00001355 Int fd;
1356 Int i;
1357 Bool ok;
1358 Addr oimage;
1359 Int n_oimage;
sewardjb3586202002-05-09 17:38:13 +00001360 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001361
sewardjde4a1d02002-03-22 01:27:54 +00001362 oimage = (Addr)NULL;
1363 if (VG_(clo_verbosity) > 1)
njne0ee0712002-05-03 16:41:05 +00001364 VG_(message)(Vg_UserMsg, "Reading syms from %s", si->filename );
sewardjde4a1d02002-03-22 01:27:54 +00001365
1366 /* mmap the object image aboard, so that we can read symbols and
1367 line number info out of it. It will be munmapped immediately
1368 thereafter; it is only aboard transiently. */
1369
sewardjb3586202002-05-09 17:38:13 +00001370 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001371 if (i != 0) {
1372 vg_symerr("Can't stat .so/.exe (to determine its size)?!");
1373 return;
1374 }
1375 n_oimage = stat_buf.st_size;
1376
njn25e49d8e72002-09-23 09:36:25 +00001377 fd = VG_(open)(si->filename, VKI_O_RDONLY, 0);
sewardjde4a1d02002-03-22 01:27:54 +00001378 if (fd == -1) {
1379 vg_symerr("Can't open .so/.exe to read symbols?!");
1380 return;
1381 }
1382
sewardjb3586202002-05-09 17:38:13 +00001383 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
1384 VKI_PROT_READ, VKI_MAP_PRIVATE, fd, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001385 if (oimage == ((Addr)(-1))) {
1386 VG_(message)(Vg_UserMsg,
1387 "mmap failed on %s", si->filename );
1388 VG_(close)(fd);
1389 return;
1390 }
1391
1392 VG_(close)(fd);
1393
1394 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1395 Now verify that it is a valid ELF .so or executable image.
1396 */
1397 ok = (n_oimage >= sizeof(Elf32_Ehdr));
1398 ehdr = (Elf32_Ehdr*)oimage;
1399
1400 if (ok) {
1401 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
1402 && ehdr->e_ident[EI_MAG1] == 'E'
1403 && ehdr->e_ident[EI_MAG2] == 'L'
1404 && ehdr->e_ident[EI_MAG3] == 'F');
1405 ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
1406 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1407 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
1408 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
1409 ok &= (ehdr->e_machine == EM_386);
1410 ok &= (ehdr->e_version == EV_CURRENT);
1411 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
1412 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
1413 }
1414
1415 if (!ok) {
1416 vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
1417 VG_(munmap) ( (void*)oimage, n_oimage );
1418 return;
1419 }
1420
1421 if (VG_(clo_trace_symtab))
1422 VG_(printf)(
1423 "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
1424 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
1425
1426 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
1427 vg_symerr("ELF section header is beyond image end?!");
1428 VG_(munmap) ( (void*)oimage, n_oimage );
1429 return;
1430 }
1431
1432 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
1433 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1434
1435 /* try and read the object's symbol table */
1436 {
1437 UChar* o_strtab = NULL;
1438 Elf32_Sym* o_symtab = NULL;
1439 UInt o_strtab_sz = 0;
1440 UInt o_symtab_sz = 0;
1441
1442 UChar* o_got = NULL;
1443 UChar* o_plt = NULL;
1444 UInt o_got_sz = 0;
1445 UInt o_plt_sz = 0;
1446
1447 Bool snaffle_it;
1448 Addr sym_addr;
1449
1450 /* find the .stabstr and .stab sections */
1451 for (i = 0; i < ehdr->e_shnum; i++) {
sewardj48115152002-10-02 10:20:30 +00001452
1453 /* As a fallback position, we look first for the dynamic
1454 symbols of a library to increase the chances that we can
1455 say something helpful even if the standard and debug
1456 symbols are missing. */
1457
1458 if (0 == VG_(strcmp)(".dynsym",sh_strtab + shdr[i].sh_name)) {
1459 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1460 o_symtab_sz = shdr[i].sh_size;
1461 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1462 /* check image overrun here */
1463 }
1464 if (0 == VG_(strcmp)(".dynstr",sh_strtab + shdr[i].sh_name)) {
1465 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1466 o_strtab_sz = shdr[i].sh_size;
1467 /* check image overrun here */
1468 }
1469
1470 /* now look for the main symbol and string tables. */
sewardjde4a1d02002-03-22 01:27:54 +00001471 if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
1472 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1473 o_symtab_sz = shdr[i].sh_size;
1474 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1475 /* check image overrun here */
1476 }
1477 if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
1478 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1479 o_strtab_sz = shdr[i].sh_size;
1480 /* check image overrun here */
1481 }
1482
1483 /* find out where the .got and .plt sections will be in the
1484 executable image, not in the object image transiently loaded.
1485 */
1486 if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
1487 o_got = (UChar*)(si->offset
1488 + shdr[i].sh_offset);
1489 o_got_sz = shdr[i].sh_size;
1490 /* check image overrun here */
1491 }
1492 if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
1493 o_plt = (UChar*)(si->offset
1494 + shdr[i].sh_offset);
1495 o_plt_sz = shdr[i].sh_size;
1496 /* check image overrun here */
1497 }
1498
1499 }
1500
1501 if (VG_(clo_trace_symtab)) {
1502 if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
1503 o_plt, o_plt + o_plt_sz - 1 );
1504 if (o_got) VG_(printf)( "GOT: %p .. %p\n",
1505 o_got, o_got + o_got_sz - 1 );
1506 }
1507
1508 if (o_strtab == NULL || o_symtab == NULL) {
1509 vg_symerr(" object doesn't have a symbol table");
1510 } else {
1511 /* Perhaps should start at i = 1; ELF docs suggest that entry
1512 0 always denotes `unknown symbol'. */
1513 for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
1514# if 0
1515 VG_(printf)("raw symbol: ");
1516 switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
1517 case STB_LOCAL: VG_(printf)("LOC "); break;
1518 case STB_GLOBAL: VG_(printf)("GLO "); break;
1519 case STB_WEAK: VG_(printf)("WEA "); break;
1520 case STB_LOPROC: VG_(printf)("lop "); break;
1521 case STB_HIPROC: VG_(printf)("hip "); break;
1522 default: VG_(printf)("??? "); break;
1523 }
1524 switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
1525 case STT_NOTYPE: VG_(printf)("NOT "); break;
1526 case STT_OBJECT: VG_(printf)("OBJ "); break;
1527 case STT_FUNC: VG_(printf)("FUN "); break;
1528 case STT_SECTION: VG_(printf)("SEC "); break;
1529 case STT_FILE: VG_(printf)("FIL "); break;
1530 case STT_LOPROC: VG_(printf)("lop "); break;
1531 case STT_HIPROC: VG_(printf)("hip "); break;
1532 default: VG_(printf)("??? "); break;
1533 }
1534 VG_(printf)(
1535 ": value %p, size %d, name %s\n",
1536 si->offset+(UChar*)o_symtab[i].st_value,
1537 o_symtab[i].st_size,
1538 o_symtab[i].st_name
1539 ? ((Char*)o_strtab+o_symtab[i].st_name)
1540 : (Char*)"NONAME");
1541# endif
1542
1543 /* Figure out if we're interested in the symbol.
1544 Firstly, is it of the right flavour?
1545 */
1546 snaffle_it
1547 = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
1548 ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
1549 ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
1550 &&
1551 (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*||
1552 ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/)
1553 );
1554
1555 /* Secondly, if it's apparently in a GOT or PLT, it's really
1556 a reference to a symbol defined elsewhere, so ignore it.
1557 */
1558 sym_addr = si->offset
1559 + (UInt)o_symtab[i].st_value;
1560 if (o_got != NULL
1561 && sym_addr >= (Addr)o_got
1562 && sym_addr < (Addr)(o_got+o_got_sz)) {
1563 snaffle_it = False;
1564 if (VG_(clo_trace_symtab)) {
1565 VG_(printf)( "in GOT: %s\n",
1566 o_strtab+o_symtab[i].st_name);
1567 }
1568 }
1569 if (o_plt != NULL
1570 && sym_addr >= (Addr)o_plt
1571 && sym_addr < (Addr)(o_plt+o_plt_sz)) {
1572 snaffle_it = False;
1573 if (VG_(clo_trace_symtab)) {
1574 VG_(printf)( "in PLT: %s\n",
1575 o_strtab+o_symtab[i].st_name);
1576 }
1577 }
1578
1579 /* Don't bother if nameless, or zero-sized. */
1580 if (snaffle_it
1581 && (o_symtab[i].st_name == (Elf32_Word)NULL
1582 || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
1583 /* equivalent but cheaper ... */
1584 * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
1585 || o_symtab[i].st_size == 0)) {
1586 snaffle_it = False;
1587 if (VG_(clo_trace_symtab)) {
1588 VG_(printf)( "size=0: %s\n",
1589 o_strtab+o_symtab[i].st_name);
1590 }
1591 }
1592
1593# if 0
1594 /* Avoid _dl_ junk. (Why?) */
1595 /* 01-02-24: disabled until I find out if it really helps. */
1596 if (snaffle_it
1597 && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
1598 || VG_(strncmp)("_r_debug",
1599 o_strtab+o_symtab[i].st_name, 8) == 0)) {
1600 snaffle_it = False;
1601 if (VG_(clo_trace_symtab)) {
1602 VG_(printf)( "_dl_ junk: %s\n",
1603 o_strtab+o_symtab[i].st_name);
1604 }
1605 }
1606# endif
1607
1608 /* This seems to significantly reduce the number of junk
1609 symbols, and particularly reduces the number of
1610 overlapping address ranges. Don't ask me why ... */
1611 if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
1612 snaffle_it = False;
1613 if (VG_(clo_trace_symtab)) {
1614 VG_(printf)( "valu=0: %s\n",
1615 o_strtab+o_symtab[i].st_name);
1616 }
1617 }
1618
1619 /* If no part of the symbol falls within the mapped range,
1620 ignore it. */
1621 if (sym_addr+o_symtab[i].st_size <= si->start
1622 || sym_addr >= si->start+si->size) {
1623 snaffle_it = False;
1624 }
1625
1626 if (snaffle_it) {
1627 /* it's an interesting symbol; record ("snaffle") it. */
1628 RiSym sym;
1629 Char* t0 = o_symtab[i].st_name
1630 ? (Char*)(o_strtab+o_symtab[i].st_name)
1631 : (Char*)"NONAME";
1632 Int nmoff = addStr ( si, t0 );
1633 vg_assert(nmoff >= 0
1634 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
1635 vg_assert( (Int)o_symtab[i].st_value >= 0);
1636 /* VG_(printf)("%p + %d: %s\n", si->addr,
1637 (Int)o_symtab[i].st_value, t0 ); */
1638 sym.addr = sym_addr;
1639 sym.size = o_symtab[i].st_size;
1640 sym.nmoff = nmoff;
1641 addSym ( si, &sym );
1642 }
1643 }
1644 }
1645 }
1646
sewardjb51f2e62002-06-01 23:11:19 +00001647 /* Reading of the stabs and/or dwarf2 debug format information, if
1648 any. */
sewardjde4a1d02002-03-22 01:27:54 +00001649 stabstr = NULL;
1650 stab = NULL;
sewardjb51f2e62002-06-01 23:11:19 +00001651 dwarf2 = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001652 stabstr_sz = 0;
1653 stab_sz = 0;
sewardjb51f2e62002-06-01 23:11:19 +00001654 dwarf2_sz = 0;
1655
1656 /* find the .stabstr / .stab / .debug_line sections */
sewardjde4a1d02002-03-22 01:27:54 +00001657 for (i = 0; i < ehdr->e_shnum; i++) {
1658 if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001659 stab = (UChar*)(oimage + shdr[i].sh_offset);
sewardjde4a1d02002-03-22 01:27:54 +00001660 stab_sz = shdr[i].sh_size;
1661 }
1662 if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
1663 stabstr = (UChar*)(oimage + shdr[i].sh_offset);
1664 stabstr_sz = shdr[i].sh_size;
1665 }
sewardjc134dd92002-06-01 14:21:36 +00001666 if (0 == VG_(strcmp)(".debug_line",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001667 dwarf2 = (UChar *)(oimage + shdr[i].sh_offset);
1668 dwarf2_sz = shdr[i].sh_size;
sewardjc134dd92002-06-01 14:21:36 +00001669 }
sewardjde4a1d02002-03-22 01:27:54 +00001670 }
1671
sewardjb51f2e62002-06-01 23:11:19 +00001672 if ((stab == NULL || stabstr == NULL) && dwarf2 == NULL) {
sewardjde4a1d02002-03-22 01:27:54 +00001673 vg_symerr(" object doesn't have any debug info");
1674 VG_(munmap) ( (void*)oimage, n_oimage );
1675 return;
1676 }
1677
1678 if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
1679 || stabstr_sz + (UChar*)stabstr
1680 > n_oimage + (UChar*)oimage ) {
sewardjb51f2e62002-06-01 23:11:19 +00001681 vg_symerr(" ELF (stabs) debug data is beyond image end?!");
sewardjde4a1d02002-03-22 01:27:54 +00001682 VG_(munmap) ( (void*)oimage, n_oimage );
1683 return;
1684 }
1685
sewardjb51f2e62002-06-01 23:11:19 +00001686 if ( dwarf2_sz + (UChar*)dwarf2 > n_oimage + (UChar*)oimage ) {
1687 vg_symerr(" ELF (dwarf2) debug data is beyond image end?!");
1688 VG_(munmap) ( (void*)oimage, n_oimage );
1689 return;
1690 }
sewardjde4a1d02002-03-22 01:27:54 +00001691
sewardjb51f2e62002-06-01 23:11:19 +00001692 /* Looks plausible. Go on and read debug data. */
1693 if (stab != NULL && stabstr != NULL) {
1694 read_debuginfo_stabs ( si, stab, stab_sz, stabstr, stabstr_sz );
1695 }
sewardjde4a1d02002-03-22 01:27:54 +00001696
sewardjb51f2e62002-06-01 23:11:19 +00001697 if (dwarf2 != NULL) {
1698 read_debuginfo_dwarf2 ( si, dwarf2, dwarf2_sz );
1699 }
sewardjde4a1d02002-03-22 01:27:54 +00001700
1701 /* Last, but not least, heave the oimage back overboard. */
1702 VG_(munmap) ( (void*)oimage, n_oimage );
1703}
1704
1705
1706/*------------------------------------------------------------*/
1707/*--- Main entry point for symbols table reading. ---*/
1708/*------------------------------------------------------------*/
1709
1710/* The root structure for the entire symbol table system. It is a
1711 linked list of SegInfos. Note that this entire mechanism assumes
1712 that what we read from /proc/self/maps doesn't contain overlapping
1713 address ranges, and as a result the SegInfos in this list describe
1714 disjoint address ranges.
1715*/
1716static SegInfo* segInfo = NULL;
1717
1718
njn25e49d8e72002-09-23 09:36:25 +00001719void VG_(read_symtab_callback) (
sewardjde4a1d02002-03-22 01:27:54 +00001720 Addr start, UInt size,
1721 Char rr, Char ww, Char xx,
1722 UInt foffset, UChar* filename )
1723{
1724 SegInfo* si;
1725
1726 /* Stay sane ... */
1727 if (size == 0)
1728 return;
1729
1730 /* We're only interested in collecting symbols in executable
1731 segments which are associated with a real file. Hence: */
1732 if (filename == NULL || xx != 'x')
1733 return;
1734 if (0 == VG_(strcmp)(filename, "/dev/zero"))
1735 return;
1736
1737 /* Perhaps we already have this one? If so, skip. */
1738 for (si = segInfo; si != NULL; si = si->next) {
1739 /*
1740 if (0==VG_(strcmp)(si->filename, filename))
1741 VG_(printf)("same fnames: %c%c%c (%p, %d) (%p, %d) %s\n",
1742 rr,ww,xx,si->start,si->size,start,size,filename);
1743 */
1744 /* For some reason the observed size of a mapping can change, so
1745 we don't use that to determine uniqueness. */
1746 if (si->start == start
1747 /* && si->size == size */
1748 && 0==VG_(strcmp)(si->filename, filename)) {
1749 return;
1750 }
1751 }
1752
1753 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001754 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001755 si->next = segInfo;
1756 segInfo = si;
1757
1758 si->start = start;
1759 si->size = size;
1760 si->foffset = foffset;
njn25e49d8e72002-09-23 09:36:25 +00001761 si->filename = VG_(arena_malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(filename));
sewardjde4a1d02002-03-22 01:27:54 +00001762 VG_(strcpy)(si->filename, filename);
1763
1764 si->symtab = NULL;
1765 si->symtab_size = si->symtab_used = 0;
1766 si->loctab = NULL;
1767 si->loctab_size = si->loctab_used = 0;
1768 si->strtab = NULL;
1769 si->strtab_size = si->strtab_used = 0;
1770
1771 /* Kludge ... */
njn25e49d8e72002-09-23 09:36:25 +00001772 si->offset = si->start==VG_ASSUMED_EXE_BASE ? 0 : si->start;
sewardjde4a1d02002-03-22 01:27:54 +00001773
1774 /* And actually fill it up. */
njn25e49d8e72002-09-23 09:36:25 +00001775 vg_read_lib_symbols ( si );
1776 canonicaliseSymtab ( si );
1777 canonicaliseLoctab ( si );
sewardjde4a1d02002-03-22 01:27:54 +00001778}
1779
1780
1781/* This one really is the Head Honcho. Update the symbol tables to
1782 reflect the current state of /proc/self/maps. Rather than re-read
1783 everything, just read the entries which are not already in segInfo.
1784 So we can call here repeatedly, after every mmap of a non-anonymous
1785 segment with execute permissions, for example, to pick up new
1786 libraries as they are dlopen'd. Conversely, when the client does
1787 munmap(), vg_symtab_notify_munmap() throws away any symbol tables
1788 which happen to correspond to the munmap()d area. */
njn25e49d8e72002-09-23 09:36:25 +00001789void VG_(maybe_read_symbols) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001790{
njn25e49d8e72002-09-23 09:36:25 +00001791 if (!VG_(using_debug_info))
1792 return;
sewardjde4a1d02002-03-22 01:27:54 +00001793
njn25e49d8e72002-09-23 09:36:25 +00001794 VGP_PUSHCC(VgpReadSyms);
1795 VG_(read_procselfmaps) ( VG_(read_symtab_callback) );
1796 VGP_POPCC(VgpReadSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001797}
1798
sewardjde4a1d02002-03-22 01:27:54 +00001799/* When an munmap() call happens, check to see whether it corresponds
1800 to a segment for a .so, and if so discard the relevant SegInfo.
1801 This might not be a very clever idea from the point of view of
1802 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001803 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001804*/
njn25e49d8e72002-09-23 09:36:25 +00001805void VG_(maybe_unload_symbols) ( Addr start, UInt length )
sewardjde4a1d02002-03-22 01:27:54 +00001806{
1807 SegInfo *prev, *curr;
1808
njn25e49d8e72002-09-23 09:36:25 +00001809 if (!VG_(using_debug_info))
1810 return;
1811
sewardjde4a1d02002-03-22 01:27:54 +00001812 prev = NULL;
1813 curr = segInfo;
1814 while (True) {
1815 if (curr == NULL) break;
1816 if (start == curr->start) break;
1817 prev = curr;
1818 curr = curr->next;
1819 }
sewardj18d75132002-05-16 11:06:21 +00001820 if (curr == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001821 return;
sewardjde4a1d02002-03-22 01:27:54 +00001822
1823 VG_(message)(Vg_UserMsg,
1824 "discard syms in %s due to munmap()",
1825 curr->filename ? curr->filename : (UChar*)"???");
1826
1827 vg_assert(prev == NULL || prev->next == curr);
1828
1829 if (prev == NULL) {
1830 segInfo = curr->next;
1831 } else {
1832 prev->next = curr->next;
1833 }
1834
1835 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001836 return;
sewardjde4a1d02002-03-22 01:27:54 +00001837}
1838
1839
1840/*------------------------------------------------------------*/
1841/*--- Use of symbol table & location info to create ---*/
1842/*--- plausible-looking stack dumps. ---*/
1843/*------------------------------------------------------------*/
1844
njn25e49d8e72002-09-23 09:36:25 +00001845static __inline__ void ensure_debug_info_inited ( void )
1846{
1847 if (!VG_(using_debug_info)) {
1848 VG_(using_debug_info) = True;
1849 VG_(maybe_read_symbols)();
1850 }
1851}
1852
sewardjde4a1d02002-03-22 01:27:54 +00001853/* Find a symbol-table index containing the specified pointer, or -1
1854 if not found. Binary search. */
1855
njn25e49d8e72002-09-23 09:36:25 +00001856static Int search_one_symtab ( SegInfo* si, Addr ptr,
1857 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001858{
1859 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001860 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001861 lo = 0,
1862 hi = si->symtab_used-1;
1863 while (True) {
1864 /* current unsearched space is from lo to hi, inclusive. */
1865 if (lo > hi) return -1; /* not found */
1866 mid = (lo + hi) / 2;
1867 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001868 size = ( match_anywhere_in_fun
1869 ? si->symtab[mid].size
1870 : 1);
1871 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001872
1873 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1874 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1875 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1876 return mid;
1877 }
1878}
1879
1880
1881/* Search all symtabs that we know about to locate ptr. If found, set
1882 *psi to the relevant SegInfo, and *symno to the symtab entry number
1883 within that. If not found, *psi is set to NULL. */
1884
njn25e49d8e72002-09-23 09:36:25 +00001885static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1886 /*OUT*/Int* symno,
1887 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001888{
1889 Int sno;
1890 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001891
1892 ensure_debug_info_inited();
1893 VGP_PUSHCC(VgpSearchSyms);
1894
sewardjde4a1d02002-03-22 01:27:54 +00001895 for (si = segInfo; si != NULL; si = si->next) {
1896 if (si->start <= ptr && ptr < si->start+si->size) {
njn25e49d8e72002-09-23 09:36:25 +00001897 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001898 if (sno == -1) goto not_found;
1899 *symno = sno;
1900 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001901 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001902 return;
1903 }
1904 }
1905 not_found:
1906 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001907 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001908}
1909
1910
1911/* Find a location-table index containing the specified pointer, or -1
1912 if not found. Binary search. */
1913
1914static Int search_one_loctab ( SegInfo* si, Addr ptr )
1915{
1916 Addr a_mid_lo, a_mid_hi;
1917 Int mid,
1918 lo = 0,
1919 hi = si->loctab_used-1;
1920 while (True) {
1921 /* current unsearched space is from lo to hi, inclusive. */
1922 if (lo > hi) return -1; /* not found */
1923 mid = (lo + hi) / 2;
1924 a_mid_lo = si->loctab[mid].addr;
1925 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1926
1927 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1928 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1929 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1930 return mid;
1931 }
1932}
1933
1934
1935/* Search all loctabs that we know about to locate ptr. If found, set
1936 *psi to the relevant SegInfo, and *locno to the loctab entry number
1937 within that. If not found, *psi is set to NULL.
1938*/
njn25e49d8e72002-09-23 09:36:25 +00001939static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
1940 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00001941{
1942 Int lno;
1943 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001944
1945 VGP_PUSHCC(VgpSearchSyms);
1946
1947 ensure_debug_info_inited();
sewardjde4a1d02002-03-22 01:27:54 +00001948 for (si = segInfo; si != NULL; si = si->next) {
1949 if (si->start <= ptr && ptr < si->start+si->size) {
1950 lno = search_one_loctab ( si, ptr );
1951 if (lno == -1) goto not_found;
1952 *locno = lno;
1953 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001954 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001955 return;
1956 }
1957 }
1958 not_found:
1959 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001960 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001961}
1962
1963
1964/* The whole point of this whole big deal: map a code address to a
1965 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00001966 Caller supplies buf and nbuf. If demangle is False, don't do
sewardjde4a1d02002-03-22 01:27:54 +00001967 demangling, regardless of vg_clo_demangle -- probably because the
1968 call has come from vg_what_fn_or_object_is_this. */
njn25e49d8e72002-09-23 09:36:25 +00001969static
1970Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
1971 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001972{
1973 SegInfo* si;
1974 Int sno;
njn25e49d8e72002-09-23 09:36:25 +00001975 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001976 if (si == NULL)
1977 return False;
njn25e49d8e72002-09-23 09:36:25 +00001978 if (demangle) {
1979 VG_(demangle) ( & si->strtab[si->symtab[sno].nmoff], buf, nbuf );
1980 } else {
sewardjde4a1d02002-03-22 01:27:54 +00001981 VG_(strncpy_safely)
1982 ( buf, & si->strtab[si->symtab[sno].nmoff], nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00001983 }
1984 return True;
1985}
1986
njn25e49d8e72002-09-23 09:36:25 +00001987/* This is available to skins... always demangle C++ names */
1988Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1989{
1990 return get_fnname ( /*demangle*/True, a, buf, nbuf,
1991 /*match_anywhere_in_fun*/True );
1992}
sewardjde4a1d02002-03-22 01:27:54 +00001993
njn25e49d8e72002-09-23 09:36:25 +00001994/* This is available to skins... always demangle C++ names,
1995 only succeed if 'a' matches first instruction of function. */
1996Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1997{
1998 return get_fnname ( /*demangle*/True, a, buf, nbuf,
1999 /*match_anywhere_in_fun*/False );
2000}
2001
2002/* This is only available to core... don't demangle C++ names */
2003Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
2004{
2005 return get_fnname ( /*demangle*/False, a, buf, nbuf,
2006 /*match_anywhere_in_fun*/True );
2007}
2008
2009/* Map a code address to the name of a shared object file or the executable.
2010 Returns False if no idea; otherwise True. Doesn't require debug info.
2011 Caller supplies buf and nbuf. */
2012Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00002013{
2014 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00002015
2016 ensure_debug_info_inited();
sewardjde4a1d02002-03-22 01:27:54 +00002017 for (si = segInfo; si != NULL; si = si->next) {
2018 if (si->start <= a && a < si->start+si->size) {
2019 VG_(strncpy_safely)(buf, si->filename, nbuf);
2020 return True;
2021 }
2022 }
2023 return False;
2024}
2025
njn25e49d8e72002-09-23 09:36:25 +00002026
2027/* Map a code address to a filename. Returns True if successful. */
2028Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00002029{
njn25e49d8e72002-09-23 09:36:25 +00002030 SegInfo* si;
2031 Int locno;
2032 search_all_loctabs ( a, &si, &locno );
2033 if (si == NULL)
2034 return False;
2035 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
2036 n_filename);
2037 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002038}
2039
njn25e49d8e72002-09-23 09:36:25 +00002040/* Map a code address to a line number. Returns True if successful. */
2041Bool VG_(get_linenum)( Addr a, UInt* lineno )
2042{
2043 SegInfo* si;
2044 Int locno;
2045 search_all_loctabs ( a, &si, &locno );
2046 if (si == NULL)
2047 return False;
2048 *lineno = si->loctab[locno].lineno;
2049
2050 return True;
2051}
sewardjde4a1d02002-03-22 01:27:54 +00002052
2053/* Map a code address to a (filename, line number) pair.
2054 Returns True if successful.
2055*/
njn25e49d8e72002-09-23 09:36:25 +00002056Bool VG_(get_filename_linenum)( Addr a,
2057 Char* filename, Int n_filename,
2058 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00002059{
2060 SegInfo* si;
2061 Int locno;
2062 search_all_loctabs ( a, &si, &locno );
2063 if (si == NULL)
2064 return False;
2065 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
2066 n_filename);
2067 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00002068
sewardjde4a1d02002-03-22 01:27:54 +00002069 return True;
2070}
2071
2072
2073/* Print a mini stack dump, showing the current location. */
2074void VG_(mini_stack_dump) ( ExeContext* ec )
2075{
2076
2077#define APPEND(str) \
2078 { UChar* sss; \
2079 for (sss = str; n < M_VG_ERRTXT-1 && *sss != 0; n++,sss++) \
2080 buf[n] = *sss; \
2081 buf[n] = 0; \
2082 }
2083
2084 Bool know_fnname;
2085 Bool know_objname;
2086 Bool know_srcloc;
2087 UInt lineno;
2088 UChar ibuf[20];
sewardj04b91062002-06-05 21:22:04 +00002089 UInt i, n;
sewardjde4a1d02002-03-22 01:27:54 +00002090
2091 UChar buf[M_VG_ERRTXT];
2092 UChar buf_fn[M_VG_ERRTXT];
2093 UChar buf_obj[M_VG_ERRTXT];
2094 UChar buf_srcloc[M_VG_ERRTXT];
2095
2096 Int stop_at = VG_(clo_backtrace_size);
2097
njn49ef4622002-10-04 15:15:08 +00002098 vg_assert(stop_at > 0);
sewardjde4a1d02002-03-22 01:27:54 +00002099
njn49ef4622002-10-04 15:15:08 +00002100 i = 0;
2101 do {
2102 n = 0;
njn25e49d8e72002-09-23 09:36:25 +00002103 know_fnname = VG_(get_fnname) (ec->eips[i], buf_fn, M_VG_ERRTXT);
2104 know_objname = VG_(get_objname)(ec->eips[i], buf_obj, M_VG_ERRTXT);
2105 know_srcloc = VG_(get_filename_linenum)(ec->eips[i],
2106 buf_srcloc, M_VG_ERRTXT,
2107 &lineno);
njn49ef4622002-10-04 15:15:08 +00002108 if (i == 0) APPEND(" at ") else APPEND(" by ");
2109
2110 VG_(sprintf)(ibuf,"0x%x: ", ec->eips[i]);
sewardj04b91062002-06-05 21:22:04 +00002111 APPEND(ibuf);
sewardjde4a1d02002-03-22 01:27:54 +00002112 if (know_fnname) {
njn49ef4622002-10-04 15:15:08 +00002113 APPEND(buf_fn);
sewardjde4a1d02002-03-22 01:27:54 +00002114 if (!know_srcloc && know_objname) {
2115 APPEND(" (in ");
2116 APPEND(buf_obj);
2117 APPEND(")");
2118 }
njn49ef4622002-10-04 15:15:08 +00002119 } else if (know_objname && !know_srcloc) {
2120 APPEND("(within ");
2121 APPEND(buf_obj);
2122 APPEND(")");
sewardjde4a1d02002-03-22 01:27:54 +00002123 } else {
njn49ef4622002-10-04 15:15:08 +00002124 APPEND("???");
2125 }
sewardjde4a1d02002-03-22 01:27:54 +00002126 if (know_srcloc) {
2127 APPEND(" (");
2128 APPEND(buf_srcloc);
2129 APPEND(":");
2130 VG_(sprintf)(ibuf,"%d",lineno);
2131 APPEND(ibuf);
2132 APPEND(")");
2133 }
2134 VG_(message)(Vg_UserMsg, "%s", buf);
njn49ef4622002-10-04 15:15:08 +00002135 i++;
2136
2137 } while (i < stop_at && ec->eips[i] != 0);
sewardjde4a1d02002-03-22 01:27:54 +00002138}
2139
2140#undef APPEND
2141
2142/*--------------------------------------------------------------------*/
2143/*--- end vg_symtab2.c ---*/
2144/*--------------------------------------------------------------------*/