blob: c536fa3ec69e1e563823427e5b9119c3329a1803 [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
sewardj47104382002-10-20 18:35:48 +000092 text segment. (typedef in vg_skin.h) */
93struct _SegInfo {
94 struct _SegInfo* next;
95 /* Description of the mapped segment. */
96 Addr start;
97 UInt size;
98 UChar* filename; /* in mallocville */
99 UInt foffset;
100 /* An expandable array of symbols. */
101 RiSym* symtab;
102 UInt symtab_used;
103 UInt symtab_size;
104 /* An expandable array of locations. */
105 RiLoc* loctab;
106 UInt loctab_used;
107 UInt loctab_size;
108 /* An expandable array of characters -- the string table. */
109 Char* strtab;
110 UInt strtab_used;
111 UInt strtab_size;
112 /* offset is what we need to add to symbol table entries
113 to get the real location of that symbol in memory.
114 For executables, offset is zero.
115 For .so's, offset == base_addr.
116 This seems like a giant kludge to me.
117 */
118 UInt offset;
119
sewardj8fe15a32002-10-20 19:29:21 +0000120 /* Bounds of data, BSS, PLT and GOT, so that skins can see what
121 section an address is in */
sewardj47104382002-10-20 18:35:48 +0000122 Addr plt_start;
123 UInt plt_size;
124 Addr got_start;
125 UInt got_size;
sewardj8fe15a32002-10-20 19:29:21 +0000126 Addr data_start;
127 UInt data_size;
128 Addr bss_start;
129 UInt bss_size;
sewardj47104382002-10-20 18:35:48 +0000130};
sewardjde4a1d02002-03-22 01:27:54 +0000131
132
sewardjde4a1d02002-03-22 01:27:54 +0000133static void freeSegInfo ( SegInfo* si )
134{
135 vg_assert(si != NULL);
njn25e49d8e72002-09-23 09:36:25 +0000136 if (si->filename) VG_(arena_free)(VG_AR_SYMTAB, si->filename);
137 if (si->symtab) VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
138 if (si->loctab) VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
139 if (si->strtab) VG_(arena_free)(VG_AR_SYMTAB, si->strtab);
140 VG_(arena_free)(VG_AR_SYMTAB, si);
sewardjde4a1d02002-03-22 01:27:54 +0000141}
142
143
144/*------------------------------------------------------------*/
145/*--- Adding stuff ---*/
146/*------------------------------------------------------------*/
147
148/* Add a str to the string table, including terminating zero, and
njn25e49d8e72002-09-23 09:36:25 +0000149 return offset of the string in vg_strtab. Unless it's been seen
150 recently, in which case we find the old index and return that.
151 This avoids the most egregious duplications. */
sewardjde4a1d02002-03-22 01:27:54 +0000152
153static __inline__
154Int addStr ( SegInfo* si, Char* str )
155{
njn25e49d8e72002-09-23 09:36:25 +0000156# define EMPTY 0xffffffff
157# define NN 5
158
159 /* prevN[0] has the most recent, prevN[NN-1] the least recent */
sewardj8fe15a32002-10-20 19:29:21 +0000160 static UInt prevN[NN] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
njn25e49d8e72002-09-23 09:36:25 +0000161 static SegInfo* curr_si = NULL;
162
sewardjde4a1d02002-03-22 01:27:54 +0000163 Char* new_tab;
164 Int new_sz, i, space_needed;
njn25e49d8e72002-09-23 09:36:25 +0000165
166 /* Avoid gratuitous duplication: if we saw `str' within the last NN,
167 * within this segment, return that index. Saves about 200KB in glibc,
168 * extra time taken is too small to measure. --NJN 2002-Aug-30 */
169 if (curr_si == si) {
170 for (i = NN-1; i >= 0; i--) {
sewardjcda419b2002-10-01 08:59:36 +0000171 if (EMPTY != prevN[i]
172 && NULL != si->strtab
173 && 0 == VG_(strcmp)(str, &si->strtab[prevN[i]])) {
njn25e49d8e72002-09-23 09:36:25 +0000174 return prevN[i];
175 }
176 }
177 } else {
178 /* New segment */
179 curr_si = si;
sewardjcda419b2002-10-01 08:59:36 +0000180 for (i = 0; i < NN; i++) prevN[i] = EMPTY;
njn25e49d8e72002-09-23 09:36:25 +0000181 }
182 /* Shuffle prevous ones along, put new one in. */
183 for (i = NN-1; i > 0; i--) prevN[i] = prevN[i-1];
184 prevN[0] = si->strtab_used;
185
186# undef EMPTY
187
sewardjde4a1d02002-03-22 01:27:54 +0000188 space_needed = 1 + VG_(strlen)(str);
njn25e49d8e72002-09-23 09:36:25 +0000189
sewardjde4a1d02002-03-22 01:27:54 +0000190 if (si->strtab_used + space_needed > si->strtab_size) {
191 new_sz = 2 * si->strtab_size;
192 if (new_sz == 0) new_sz = 5000;
njn25e49d8e72002-09-23 09:36:25 +0000193 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz);
sewardjde4a1d02002-03-22 01:27:54 +0000194 if (si->strtab != NULL) {
195 for (i = 0; i < si->strtab_used; i++)
196 new_tab[i] = si->strtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000197 VG_(arena_free)(VG_AR_SYMTAB, si->strtab);
sewardjde4a1d02002-03-22 01:27:54 +0000198 }
199 si->strtab = new_tab;
200 si->strtab_size = new_sz;
201 }
202
203 for (i = 0; i < space_needed; i++)
204 si->strtab[si->strtab_used+i] = str[i];
205
206 si->strtab_used += space_needed;
207 vg_assert(si->strtab_used <= si->strtab_size);
njn25e49d8e72002-09-23 09:36:25 +0000208
sewardjde4a1d02002-03-22 01:27:54 +0000209 return si->strtab_used - space_needed;
210}
211
212/* Add a symbol to the symbol table. */
213
214static __inline__
215void addSym ( SegInfo* si, RiSym* sym )
216{
217 Int new_sz, i;
218 RiSym* new_tab;
219
220 /* Ignore zero-sized syms. */
221 if (sym->size == 0) return;
222
223 if (si->symtab_used == si->symtab_size) {
224 new_sz = 2 * si->symtab_size;
225 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000226 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
sewardjde4a1d02002-03-22 01:27:54 +0000227 if (si->symtab != NULL) {
228 for (i = 0; i < si->symtab_used; i++)
229 new_tab[i] = si->symtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000230 VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
sewardjde4a1d02002-03-22 01:27:54 +0000231 }
232 si->symtab = new_tab;
233 si->symtab_size = new_sz;
234 }
235
236 si->symtab[si->symtab_used] = *sym;
237 si->symtab_used++;
238 vg_assert(si->symtab_used <= si->symtab_size);
239}
240
241/* Add a location to the location table. */
242
243static __inline__
244void addLoc ( SegInfo* si, RiLoc* loc )
245{
246 Int new_sz, i;
247 RiLoc* new_tab;
248
njne0ee0712002-05-03 16:41:05 +0000249 /* Zero-sized locs should have been ignored earlier */
250 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000251
252 if (si->loctab_used == si->loctab_size) {
253 new_sz = 2 * si->loctab_size;
254 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000255 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
sewardjde4a1d02002-03-22 01:27:54 +0000256 if (si->loctab != NULL) {
257 for (i = 0; i < si->loctab_used; i++)
258 new_tab[i] = si->loctab[i];
njn25e49d8e72002-09-23 09:36:25 +0000259 VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
sewardjde4a1d02002-03-22 01:27:54 +0000260 }
261 si->loctab = new_tab;
262 si->loctab_size = new_sz;
263 }
264
265 si->loctab[si->loctab_used] = *loc;
266 si->loctab_used++;
267 vg_assert(si->loctab_used <= si->loctab_size);
268}
269
270
sewardjb51f2e62002-06-01 23:11:19 +0000271/* Top-level place to call to add a source-location mapping entry. */
272
273static __inline__
274void addLineInfo ( SegInfo* si,
275 Int fnmoff,
276 Addr this,
277 Addr next,
278 Int lineno,
sewardj08a50f62002-06-17 02:21:20 +0000279 Int entry /* only needed for debug printing */
280 )
sewardjb51f2e62002-06-01 23:11:19 +0000281{
282 RiLoc loc;
283 Int size = next - this;
284
285 /* Ignore zero-sized locs */
286 if (this == next) return;
287
288 /* Maximum sanity checking. Some versions of GNU as do a shabby
289 * job with stabs entries; if anything looks suspicious, revert to
290 * a size of 1. This should catch the instruction of interest
291 * (since if using asm-level debug info, one instruction will
292 * correspond to one line, unlike with C-level debug info where
293 * multiple instructions can map to the one line), but avoid
294 * catching any other instructions bogusly. */
295 if (this > next) {
296 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000297 "warning: line info addresses out of order "
sewardjb51f2e62002-06-01 23:11:19 +0000298 "at entry %d: 0x%x 0x%x", entry, this, next);
299 size = 1;
300 }
301
302 if (size > MAX_LOC_SIZE) {
sewardjd84606d2002-06-18 01:04:57 +0000303 if (0)
sewardjb51f2e62002-06-01 23:11:19 +0000304 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000305 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000306 "at entry %d: %d", entry, size);
307 size = 1;
308 }
309
sewardj08a50f62002-06-17 02:21:20 +0000310 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000311 if (this >= si->start + si->size || next-1 < si->start) {
sewardjd84606d2002-06-18 01:04:57 +0000312 if (0)
sewardj08a50f62002-06-17 02:21:20 +0000313 VG_(message)(Vg_DebugMsg,
314 "warning: ignoring line info entry falling "
315 "outside current SegInfo: %p %p %p %p",
316 si->start, si->start + si->size,
317 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000318 return;
319 }
320
321 vg_assert(lineno >= 0);
322 if (lineno > MAX_LINENO) {
323 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000324 "warning: ignoring line info entry with "
325 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000326 VG_(message)(Vg_UserMsg,
327 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000328 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000329 return;
330 }
sewardjb51f2e62002-06-01 23:11:19 +0000331
332 loc.addr = this;
333 loc.size = (UShort)size;
334 loc.lineno = lineno;
335 loc.fnmoff = fnmoff;
sewardjb642dc22002-10-12 17:27:16 +0000336
337 if (0) VG_(message)(Vg_DebugMsg,
338 "addLoc: addr %p, size %d, line %d, file %s",
339 this,size,lineno,&si->strtab[fnmoff]);
340
sewardjb51f2e62002-06-01 23:11:19 +0000341 addLoc ( si, &loc );
342}
343
sewardjde4a1d02002-03-22 01:27:54 +0000344/*------------------------------------------------------------*/
345/*--- Helpers ---*/
346/*------------------------------------------------------------*/
347
348/* Non-fatal -- use vg_panic if terminal. */
349static
350void vg_symerr ( Char* msg )
351{
352 if (VG_(clo_verbosity) > 1)
353 VG_(message)(Vg_UserMsg,"%s", msg );
354}
355
356
357/* Print a symbol. */
358static
359void printSym ( SegInfo* si, Int i )
360{
361 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
362 i,
363 si->symtab[i].addr,
364 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
365 &si->strtab[si->symtab[i].nmoff] );
366}
367
368
369#if 0
370/* Print the entire sym tab. */
371static __attribute__ ((unused))
372void printSymtab ( void )
373{
374 Int i;
375 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
376 for (i = 0; i < vg_symtab_used; i++)
377 printSym(i);
378 VG_(printf)("------ BEGIN vg_symtab ------\n");
379}
380#endif
381
382#if 0
383/* Paranoid strcat. */
384static
385void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
386{
387 UInt i = 0, j = 0;
388 while (True) {
389 if (i >= maxlen) return;
390 if (dst[i] == 0) break;
391 i++;
392 }
393 while (True) {
394 if (i >= maxlen) return;
395 dst[i] = src[j];
396 if (src[j] == 0) return;
397 i++; j++;
398 }
399}
400#endif
401
sewardjb51f2e62002-06-01 23:11:19 +0000402
sewardjde4a1d02002-03-22 01:27:54 +0000403/*------------------------------------------------------------*/
404/*--- Canonicalisers ---*/
405/*------------------------------------------------------------*/
406
407/* Sort the symtab by starting address, and emit warnings if any
408 symbols have overlapping address ranges. We use that old chestnut,
409 shellsort. Mash the table around so as to establish the property
410 that addresses are in order and the ranges to not overlap. This
411 facilitates using binary search to map addresses to symbols when we
412 come to query the table.
413*/
414static
415void canonicaliseSymtab ( SegInfo* si )
416{
417 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
418 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
419 4592, 13776, 33936, 86961, 198768,
420 463792, 1391376 };
421 Int lo = 0;
422 Int hi = si->symtab_used-1;
423 Int i, j, h, bigN, hp, n_merged, n_truncated;
424 RiSym v;
425 Addr s1, s2, e1, e2;
426
427# define SWAP(ty,aa,bb) \
428 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
429
430 bigN = hi - lo + 1; if (bigN < 2) return;
431 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
432 vg_assert(0 <= hp && hp < 16);
433
434 for (; hp >= 0; hp--) {
435 h = incs[hp];
436 i = lo + h;
437 while (1) {
438 if (i > hi) break;
439 v = si->symtab[i];
440 j = i;
441 while (si->symtab[j-h].addr > v.addr) {
442 si->symtab[j] = si->symtab[j-h];
443 j = j - h;
444 if (j <= (lo + h - 1)) break;
445 }
446 si->symtab[j] = v;
447 i++;
448 }
449 }
450
451 cleanup_more:
452
453 /* If two symbols have identical address ranges, favour the
454 one with the longer name.
455 */
456 do {
457 n_merged = 0;
458 j = si->symtab_used;
459 si->symtab_used = 0;
460 for (i = 0; i < j; i++) {
461 if (i < j-1
462 && si->symtab[i].addr == si->symtab[i+1].addr
463 && si->symtab[i].size == si->symtab[i+1].size) {
464 n_merged++;
465 /* merge the two into one */
466 if (VG_(strlen)(&si->strtab[si->symtab[i].nmoff])
467 > VG_(strlen)(&si->strtab[si->symtab[i+1].nmoff])) {
468 si->symtab[si->symtab_used++] = si->symtab[i];
469 } else {
470 si->symtab[si->symtab_used++] = si->symtab[i+1];
471 }
472 i++;
473 } else {
474 si->symtab[si->symtab_used++] = si->symtab[i];
475 }
476 }
477 if (VG_(clo_trace_symtab))
478 VG_(printf)( "%d merged\n", n_merged);
479 }
480 while (n_merged > 0);
481
482 /* Detect and "fix" overlapping address ranges. */
483 n_truncated = 0;
484
485 for (i = 0; i < si->symtab_used-1; i++) {
486
487 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
488
489 /* Check for common (no overlap) case. */
490 if (si->symtab[i].addr + si->symtab[i].size
491 <= si->symtab[i+1].addr)
492 continue;
493
494 /* There's an overlap. Truncate one or the other. */
495 if (VG_(clo_trace_symtab)) {
496 VG_(printf)("overlapping address ranges in symbol table\n\t");
497 printSym(si,i);
498 VG_(printf)("\t");
499 printSym(si,i+1);
500 VG_(printf)("\n");
501 }
502
503 /* Truncate one or the other. */
504 s1 = si->symtab[i].addr;
505 s2 = si->symtab[i+1].addr;
506 e1 = s1 + si->symtab[i].size - 1;
507 e2 = s2 + si->symtab[i+1].size - 1;
508 if (s1 < s2) {
509 e1 = s2-1;
510 } else {
511 vg_assert(s1 == s2);
512 if (e1 > e2) {
513 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
514 } else
515 if (e1 < e2) {
516 s2 = e1+1;
517 } else {
518 /* e1 == e2. Identical addr ranges. We'll eventually wind
519 up back at cleanup_more, which will take care of it. */
520 }
521 }
522 si->symtab[i].addr = s1;
523 si->symtab[i+1].addr = s2;
524 si->symtab[i].size = e1 - s1 + 1;
525 si->symtab[i+1].size = e2 - s2 + 1;
526 vg_assert(s1 <= s2);
527 vg_assert(si->symtab[i].size > 0);
528 vg_assert(si->symtab[i+1].size > 0);
529 /* It may be that the i+1 entry now needs to be moved further
530 along to maintain the address order requirement. */
531 j = i+1;
532 while (j < si->symtab_used-1
533 && si->symtab[j].addr > si->symtab[j+1].addr) {
534 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
535 j++;
536 }
537 n_truncated++;
538 }
539
540 if (n_truncated > 0) goto cleanup_more;
541
542 /* Ensure relevant postconditions hold. */
543 for (i = 0; i < si->symtab_used-1; i++) {
544 /* No zero-sized symbols. */
545 vg_assert(si->symtab[i].size > 0);
546 /* In order. */
547 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
548 /* No overlaps. */
549 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
550 < si->symtab[i+1].addr);
551 }
552# undef SWAP
553}
554
555
556
557/* Sort the location table by starting address. Mash the table around
558 so as to establish the property that addresses are in order and the
559 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000560 addresses to locations when we come to query the table.
561*/
sewardjde4a1d02002-03-22 01:27:54 +0000562static
563void canonicaliseLoctab ( SegInfo* si )
564{
565 /* Magic numbers due to Janet Incerpi and Robert Sedgewick. */
566 Int incs[16] = { 1, 3, 7, 21, 48, 112, 336, 861, 1968,
567 4592, 13776, 33936, 86961, 198768,
568 463792, 1391376 };
569 Int lo = 0;
570 Int hi = si->loctab_used-1;
571 Int i, j, h, bigN, hp;
572 RiLoc v;
573
574# define SWAP(ty,aa,bb) \
575 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
576
577 /* Sort by start address. */
578
579 bigN = hi - lo + 1; if (bigN < 2) return;
580 hp = 0; while (hp < 16 && incs[hp] < bigN) hp++; hp--;
581 vg_assert(0 <= hp && hp < 16);
582
583 for (; hp >= 0; hp--) {
584 h = incs[hp];
585 i = lo + h;
586 while (1) {
587 if (i > hi) break;
588 v = si->loctab[i];
589 j = i;
590 while (si->loctab[j-h].addr > v.addr) {
591 si->loctab[j] = si->loctab[j-h];
592 j = j - h;
593 if (j <= (lo + h - 1)) break;
594 }
595 si->loctab[j] = v;
596 i++;
597 }
598 }
599
600 /* If two adjacent entries overlap, truncate the first. */
601 for (i = 0; i < si->loctab_used-1; i++) {
602 vg_assert(si->loctab[i].size < 10000);
603 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
604 /* Do this in signed int32 because the actual .size fields
605 are unsigned 16s. */
606 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
607 if (new_size < 0) {
608 si->loctab[i].size = 0;
609 } else
610 if (new_size >= 65536) {
611 si->loctab[i].size = 65535;
612 } else {
613 si->loctab[i].size = (UShort)new_size;
614 }
615 }
616 }
617
618 /* Zap any zero-sized entries resulting from the truncation
619 process. */
620 j = 0;
621 for (i = 0; i < si->loctab_used; i++) {
622 if (si->loctab[i].size > 0) {
623 si->loctab[j] = si->loctab[i];
624 j++;
625 }
626 }
627 si->loctab_used = j;
628
629 /* Ensure relevant postconditions hold. */
630 for (i = 0; i < si->loctab_used-1; i++) {
631 /*
632 VG_(printf)("%d (%d) %d 0x%x\n",
633 i, si->loctab[i+1].confident,
634 si->loctab[i+1].size, si->loctab[i+1].addr );
635 */
636 /* No zero-sized symbols. */
637 vg_assert(si->loctab[i].size > 0);
638 /* In order. */
639 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
640 /* No overlaps. */
641 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
642 < si->loctab[i+1].addr);
643 }
644# undef SWAP
645}
646
647
648/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000649/*--- Read STABS format debug info. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000650/*------------------------------------------------------------*/
651
sewardjb51f2e62002-06-01 23:11:19 +0000652/* Stabs entry types, from:
653 * The "stabs" debug format
654 * Menapace, Kingdon and MacKenzie
655 * Cygnus Support
656 */
657typedef enum { N_GSYM = 32, /* Global symbol */
658 N_FUN = 36, /* Function start or end */
659 N_STSYM = 38, /* Data segment file-scope variable */
660 N_LCSYM = 40, /* BSS segment file-scope variable */
661 N_RSYM = 64, /* Register variable */
662 N_SLINE = 68, /* Source line number */
663 N_SO = 100, /* Source file path and name */
664 N_LSYM = 128, /* Stack variable or type */
665 N_SOL = 132, /* Include file name */
666 N_LBRAC = 192, /* Start of lexical block */
667 N_RBRAC = 224 /* End of lexical block */
668 } stab_types;
669
670
671/* Read stabs-format debug info. This is all rather horrible because
672 stabs is a underspecified, kludgy hack.
673*/
674static
675void read_debuginfo_stabs ( SegInfo* si,
676 UChar* stabC, Int stab_sz,
677 UChar* stabstr, Int stabstr_sz )
sewardjde4a1d02002-03-22 01:27:54 +0000678{
sewardjb51f2e62002-06-01 23:11:19 +0000679 Int i;
680 Int curr_filenmoff;
njnb79ad342002-06-05 15:30:30 +0000681 Addr curr_fn_stabs_addr = (Addr)NULL;
682 Addr curr_fnbaseaddr = (Addr)NULL;
sewardjb51f2e62002-06-01 23:11:19 +0000683 Char *curr_file_name, *curr_fn_name;
684 Int n_stab_entries;
njnb79ad342002-06-05 15:30:30 +0000685 Int prev_lineno = 0, lineno = 0;
686 Int lineno_overflows = 0;
687 Bool same_file = True;
sewardjb51f2e62002-06-01 23:11:19 +0000688 struct nlist* stab = (struct nlist*)stabC;
njnb79ad342002-06-05 15:30:30 +0000689
sewardjb51f2e62002-06-01 23:11:19 +0000690 /* Ok. It all looks plausible. Go on and read debug data.
691 stab kinds: 100 N_SO a source file name
692 68 N_SLINE a source line number
693 36 N_FUN start of a function
njn4f9c9342002-04-29 16:03:24 +0000694
sewardjb51f2e62002-06-01 23:11:19 +0000695 In this loop, we maintain a current file name, updated as
696 N_SO/N_SOLs appear, and a current function base address,
697 updated as N_FUNs appear. Based on that, address ranges for
698 N_SLINEs are calculated, and stuffed into the line info table.
sewardjde4a1d02002-03-22 01:27:54 +0000699
sewardjb51f2e62002-06-01 23:11:19 +0000700 Finding the instruction address range covered by an N_SLINE is
701 complicated; see the N_SLINE case below.
702 */
njnb79ad342002-06-05 15:30:30 +0000703 curr_filenmoff = addStr(si,"???");
704 curr_file_name = curr_fn_name = (Char*)NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000705
sewardjb51f2e62002-06-01 23:11:19 +0000706 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
njne0ee0712002-05-03 16:41:05 +0000707
sewardjb51f2e62002-06-01 23:11:19 +0000708 for (i = 0; i < n_stab_entries; i++) {
709# if 0
710 VG_(printf) ( " %2d ", i );
711 VG_(printf) ( "type=0x%x othr=%d desc=%d value=0x%x strx=%d %s",
712 stab[i].n_type, stab[i].n_other, stab[i].n_desc,
713 (int)stab[i].n_value,
714 (int)stab[i].n_un.n_strx,
715 stabstr + stab[i].n_un.n_strx );
716 VG_(printf)("\n");
717# endif
njne0ee0712002-05-03 16:41:05 +0000718
sewardjb51f2e62002-06-01 23:11:19 +0000719 Char *no_fn_name = "???";
720
721 switch (stab[i].n_type) {
722 UInt next_addr;
723
724 /* Two complicated things here:
725 *
726 * 1. the n_desc field in 'struct n_list' in a.out.h is only
727 * 16-bits, which gives a maximum of 65535 lines. We handle
728 * files bigger than this by detecting heuristically
729 * overflows -- if the line count goes from 65000-odd to
730 * 0-odd within the same file, we assume it's an overflow.
731 * Once we switch files, we zero the overflow count.
732 *
733 * 2. To compute the instr address range covered by a single
734 * line, find the address of the next thing and compute the
735 * difference. The approach used depends on what kind of
736 * entry/entries follow...
737 */
738 case N_SLINE: {
739 Int this_addr = (UInt)stab[i].n_value;
740
741 /* Although stored as a short, neg values really are >
742 * 32768, hence the UShort cast. Then we use an Int to
743 * handle overflows. */
744 prev_lineno = lineno;
745 lineno = (Int)((UShort)stab[i].n_desc);
746
747 if (prev_lineno > lineno + OVERFLOW_DIFFERENCE && same_file) {
748 VG_(message)(Vg_DebugMsg,
749 "Line number overflow detected (%d --> %d) in %s",
750 prev_lineno, lineno, curr_file_name);
751 lineno_overflows++;
752 }
753 same_file = True;
754
755 LOOP:
756 if (i+1 >= n_stab_entries) {
757 /* If it's the last entry, just guess the range is
758 * four; can't do any better */
759 next_addr = this_addr + 4;
760 } else {
761 switch (stab[i+1].n_type) {
762 /* Easy, common case: use address of next entry */
763 case N_SLINE: case N_SO:
764 next_addr = (UInt)stab[i+1].n_value;
765 break;
766
njn25e49d8e72002-09-23 09:36:25 +0000767 /* Boring one: skip, look for something more useful. */
sewardjb51f2e62002-06-01 23:11:19 +0000768 case N_RSYM: case N_LSYM: case N_LBRAC: case N_RBRAC:
769 case N_STSYM: case N_LCSYM: case N_GSYM:
770 i++;
771 goto LOOP;
772
njnb79ad342002-06-05 15:30:30 +0000773 /* If end-of-this-fun entry, use its address.
774 * If start-of-next-fun entry, find difference between start
775 * of current function and start of next function to work
776 * it out.
777 */
sewardjb51f2e62002-06-01 23:11:19 +0000778 case N_FUN:
779 if ('\0' == * (stabstr + stab[i+1].n_un.n_strx) ) {
780 next_addr = (UInt)stab[i+1].n_value;
781 } else {
njnb79ad342002-06-05 15:30:30 +0000782 next_addr =
783 (UInt)stab[i+1].n_value - curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000784 }
785 break;
786
787 /* N_SOL should be followed by an N_SLINE which can
788 be used */
789 case N_SOL:
790 if (i+2 < n_stab_entries && N_SLINE == stab[i+2].n_type) {
791 next_addr = (UInt)stab[i+2].n_value;
792 break;
793 } else {
794 VG_(printf)("unhandled N_SOL stabs case: %d %d %d",
795 stab[i+1].n_type, i, n_stab_entries);
njne427a662002-10-02 11:08:25 +0000796 VG_(core_panic)("unhandled N_SOL stabs case");
sewardjb51f2e62002-06-01 23:11:19 +0000797 }
798
799 default:
800 VG_(printf)("unhandled (other) stabs case: %d %d",
801 stab[i+1].n_type,i);
njne427a662002-10-02 11:08:25 +0000802 /* VG_(core_panic)("unhandled (other) stabs case"); */
sewardjb51f2e62002-06-01 23:11:19 +0000803 next_addr = this_addr + 4;
804 break;
805 }
806 }
807
808 addLineInfo ( si, curr_filenmoff, curr_fnbaseaddr + this_addr,
809 curr_fnbaseaddr + next_addr,
810 lineno + lineno_overflows * LINENO_OVERFLOW, i);
811 break;
812 }
813
814 case N_FUN: {
815 if ('\0' != (stabstr + stab[i].n_un.n_strx)[0] ) {
816 /* N_FUN with a name -- indicates the start of a fn. */
njnb79ad342002-06-05 15:30:30 +0000817 curr_fn_stabs_addr = (Addr)stab[i].n_value;
818 curr_fnbaseaddr = si->offset + curr_fn_stabs_addr;
sewardjb51f2e62002-06-01 23:11:19 +0000819 curr_fn_name = stabstr + stab[i].n_un.n_strx;
820 } else {
821 curr_fn_name = no_fn_name;
822 }
823 break;
824 }
825
826 case N_SOL:
827 if (lineno_overflows != 0) {
828 VG_(message)(Vg_UserMsg,
829 "Warning: file %s is very big (> 65535 lines) "
830 "Line numbers and annotation for this file might "
831 "be wrong. Sorry",
832 curr_file_name);
833 }
834 /* fall through! */
835 case N_SO:
836 lineno_overflows = 0;
837
838 /* seems to give lots of locations in header files */
839 /* case 130: */ /* BINCL */
840 {
841 UChar* nm = stabstr + stab[i].n_un.n_strx;
842 UInt len = VG_(strlen)(nm);
843
844 if (len > 0 && nm[len-1] != '/') {
845 curr_filenmoff = addStr ( si, nm );
846 curr_file_name = stabstr + stab[i].n_un.n_strx;
847 }
848 else
849 if (len == 0)
850 curr_filenmoff = addStr ( si, "?1\0" );
851
852 break;
853 }
854
855# if 0
856 case 162: /* EINCL */
857 curr_filenmoff = addStr ( si, "?2\0" );
858 break;
859# endif
860
861 default:
862 break;
863 }
864 } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */
sewardjde4a1d02002-03-22 01:27:54 +0000865}
866
867
sewardjb51f2e62002-06-01 23:11:19 +0000868/*------------------------------------------------------------*/
869/*--- Read DWARF2 format debug info. ---*/
870/*------------------------------------------------------------*/
sewardjc134dd92002-06-01 14:21:36 +0000871
872/* Structure found in the .debug_line section. */
873typedef struct
874{
875 UChar li_length [4];
876 UChar li_version [2];
877 UChar li_prologue_length [4];
878 UChar li_min_insn_length [1];
879 UChar li_default_is_stmt [1];
880 UChar li_line_base [1];
881 UChar li_line_range [1];
882 UChar li_opcode_base [1];
883}
884DWARF2_External_LineInfo;
sewardjd84606d2002-06-18 01:04:57 +0000885
sewardjc134dd92002-06-01 14:21:36 +0000886typedef struct
887{
sewardj08a50f62002-06-17 02:21:20 +0000888 UInt li_length;
sewardjc134dd92002-06-01 14:21:36 +0000889 UShort li_version;
890 UInt li_prologue_length;
891 UChar li_min_insn_length;
892 UChar li_default_is_stmt;
sewardj08a50f62002-06-17 02:21:20 +0000893 Int li_line_base;
sewardjc134dd92002-06-01 14:21:36 +0000894 UChar li_line_range;
895 UChar li_opcode_base;
896}
897DWARF2_Internal_LineInfo;
sewardjd84606d2002-06-18 01:04:57 +0000898
sewardjc134dd92002-06-01 14:21:36 +0000899/* Line number opcodes. */
900enum dwarf_line_number_ops
901 {
902 DW_LNS_extended_op = 0,
903 DW_LNS_copy = 1,
904 DW_LNS_advance_pc = 2,
905 DW_LNS_advance_line = 3,
906 DW_LNS_set_file = 4,
907 DW_LNS_set_column = 5,
908 DW_LNS_negate_stmt = 6,
909 DW_LNS_set_basic_block = 7,
910 DW_LNS_const_add_pc = 8,
911 DW_LNS_fixed_advance_pc = 9,
912 /* DWARF 3. */
913 DW_LNS_set_prologue_end = 10,
914 DW_LNS_set_epilogue_begin = 11,
915 DW_LNS_set_isa = 12
916 };
917
918/* Line number extended opcodes. */
919enum dwarf_line_number_x_ops
920 {
921 DW_LNE_end_sequence = 1,
922 DW_LNE_set_address = 2,
923 DW_LNE_define_file = 3
924 };
925
926typedef struct State_Machine_Registers
927{
sewardj08a50f62002-06-17 02:21:20 +0000928 Addr address;
sewardjb642dc22002-10-12 17:27:16 +0000929 /* Holds the address of the last statement boundary.
930 * We use it to calculate statement lengths. Without it,
931 * we would need to search backwards for last statement begin
932 * each time we are emitting a statement with addLineInfo */
933 Addr last_address;
sewardjc134dd92002-06-01 14:21:36 +0000934 UInt file;
935 UInt line;
936 UInt column;
937 Int is_stmt;
938 Int basic_block;
sewardj08a50f62002-06-17 02:21:20 +0000939 Int end_sequence;
940 /* This variable hold the number of the last entry seen
941 in the File Table. */
sewardjc134dd92002-06-01 14:21:36 +0000942 UInt last_file_entry;
943} SMR;
944
sewardjb51f2e62002-06-01 23:11:19 +0000945
946static
947UInt read_leb128 ( UChar* data, Int* length_return, Int sign )
948{
sewardj08a50f62002-06-17 02:21:20 +0000949 UInt result = 0;
950 UInt num_read = 0;
951 Int shift = 0;
952 UChar byte;
sewardjb51f2e62002-06-01 23:11:19 +0000953
954 do
955 {
956 byte = * data ++;
957 num_read ++;
958
959 result |= (byte & 0x7f) << shift;
960
961 shift += 7;
962
963 }
964 while (byte & 0x80);
965
966 if (length_return != NULL)
967 * length_return = num_read;
968
969 if (sign && (shift < 32) && (byte & 0x40))
970 result |= -1 << shift;
971
972 return result;
973}
974
975
sewardjc134dd92002-06-01 14:21:36 +0000976static SMR state_machine_regs;
977
sewardj08a50f62002-06-17 02:21:20 +0000978static
979void reset_state_machine ( Int is_stmt )
sewardjc134dd92002-06-01 14:21:36 +0000980{
sewardj08a50f62002-06-17 02:21:20 +0000981 if (0) VG_(printf)("smr.a := %p (reset)\n", 0 );
sewardjc134dd92002-06-01 14:21:36 +0000982 state_machine_regs.address = 0;
sewardjb642dc22002-10-12 17:27:16 +0000983 state_machine_regs.last_address = 0;
sewardjc134dd92002-06-01 14:21:36 +0000984 state_machine_regs.file = 1;
985 state_machine_regs.line = 1;
986 state_machine_regs.column = 0;
987 state_machine_regs.is_stmt = is_stmt;
988 state_machine_regs.basic_block = 0;
989 state_machine_regs.end_sequence = 0;
990 state_machine_regs.last_file_entry = 0;
991}
992
993/* Handled an extend line op. Returns true if this is the end
994 of sequence. */
sewardj08a50f62002-06-17 02:21:20 +0000995static
996int process_extended_line_op( SegInfo *si, UInt** fnames,
997 UChar* data, Int is_stmt, Int pointer_size)
sewardjc134dd92002-06-01 14:21:36 +0000998{
999 UChar op_code;
sewardj08a50f62002-06-17 02:21:20 +00001000 Int bytes_read;
sewardjc134dd92002-06-01 14:21:36 +00001001 UInt len;
1002 UChar * name;
sewardj08a50f62002-06-17 02:21:20 +00001003 Addr adr;
sewardjc134dd92002-06-01 14:21:36 +00001004
1005 len = read_leb128 (data, & bytes_read, 0);
1006 data += bytes_read;
1007
1008 if (len == 0)
1009 {
sewardj08a50f62002-06-17 02:21:20 +00001010 VG_(message)(Vg_UserMsg,
1011 "badly formed extended line op encountered!\n");
sewardjc134dd92002-06-01 14:21:36 +00001012 return bytes_read;
1013 }
1014
1015 len += bytes_read;
1016 op_code = * data ++;
1017
sewardjb642dc22002-10-12 17:27:16 +00001018 if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
sewardjc134dd92002-06-01 14:21:36 +00001019
1020 switch (op_code)
1021 {
1022 case DW_LNE_end_sequence:
sewardj08a50f62002-06-17 02:21:20 +00001023 if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",
1024 si->offset, state_machine_regs.address );
sewardjd84606d2002-06-18 01:04:57 +00001025 state_machine_regs.end_sequence = 1; /* JRS: added for compliance
1026 with spec; is pointless due to reset_state_machine below
1027 */
sewardjb642dc22002-10-12 17:27:16 +00001028 if (state_machine_regs.is_stmt) {
1029 if (state_machine_regs.last_address)
1030 addLineInfo (si, (*fnames)[state_machine_regs.file],
1031 si->offset + state_machine_regs.last_address,
1032 si->offset + state_machine_regs.address,
1033 state_machine_regs.line, 0);
1034 }
sewardjc134dd92002-06-01 14:21:36 +00001035 reset_state_machine (is_stmt);
1036 break;
1037
1038 case DW_LNE_set_address:
1039 /* XXX: Pointer size could be 8 */
sewardj08a50f62002-06-17 02:21:20 +00001040 vg_assert(pointer_size == 4);
sewardjc134dd92002-06-01 14:21:36 +00001041 adr = *((Addr *)data);
sewardj08a50f62002-06-17 02:21:20 +00001042 if (0) VG_(printf)("smr.a := %p\n", adr );
sewardjc134dd92002-06-01 14:21:36 +00001043 state_machine_regs.address = adr;
1044 break;
1045
1046 case DW_LNE_define_file:
sewardjc134dd92002-06-01 14:21:36 +00001047 ++ state_machine_regs.last_file_entry;
1048 name = data;
1049 if (*fnames == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001050 *fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
sewardjc134dd92002-06-01 14:21:36 +00001051 else
njn25e49d8e72002-09-23 09:36:25 +00001052 *fnames = VG_(arena_realloc)(
1053 VG_AR_SYMTAB, *fnames, /*alignment*/4,
sewardj08a50f62002-06-17 02:21:20 +00001054 sizeof(UInt)
1055 * (state_machine_regs.last_file_entry + 1));
sewardjc134dd92002-06-01 14:21:36 +00001056 (*fnames)[state_machine_regs.last_file_entry] = addStr (si,name);
1057 data += VG_(strlen) ((char *) data) + 1;
1058 read_leb128 (data, & bytes_read, 0);
1059 data += bytes_read;
1060 read_leb128 (data, & bytes_read, 0);
1061 data += bytes_read;
sewardj08a50f62002-06-17 02:21:20 +00001062 read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001063 break;
1064
1065 default:
1066 break;
1067 }
1068
1069 return len;
1070}
1071
1072
sewardjb51f2e62002-06-01 23:11:19 +00001073static
1074void read_debuginfo_dwarf2 ( SegInfo* si, UChar* dwarf2, Int dwarf2_sz )
sewardjc134dd92002-06-01 14:21:36 +00001075{
1076 DWARF2_External_LineInfo * external;
1077 DWARF2_Internal_LineInfo info;
1078 UChar * standard_opcodes;
sewardjb51f2e62002-06-01 23:11:19 +00001079 UChar * data = dwarf2;
1080 UChar * end = dwarf2 + dwarf2_sz;
sewardjc134dd92002-06-01 14:21:36 +00001081 UChar * end_of_sequence;
sewardj08a50f62002-06-17 02:21:20 +00001082 UInt * fnames = NULL;
sewardjc134dd92002-06-01 14:21:36 +00001083
sewardjd84606d2002-06-18 01:04:57 +00001084 /* Fails due to gcc padding ...
1085 vg_assert(sizeof(DWARF2_External_LineInfo)
1086 == sizeof(DWARF2_Internal_LineInfo));
1087 */
sewardjc134dd92002-06-01 14:21:36 +00001088
1089 while (data < end)
1090 {
1091 external = (DWARF2_External_LineInfo *) data;
1092
1093 /* Check the length of the block. */
sewardj08a50f62002-06-17 02:21:20 +00001094 info.li_length = * ((UInt *)(external->li_length));
sewardjc134dd92002-06-01 14:21:36 +00001095
1096 if (info.li_length == 0xffffffff)
1097 {
sewardjb51f2e62002-06-01 23:11:19 +00001098 vg_symerr("64-bit DWARF line info is not supported yet.");
sewardjc134dd92002-06-01 14:21:36 +00001099 break;
1100 }
1101
sewardjb51f2e62002-06-01 23:11:19 +00001102 if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
sewardjc134dd92002-06-01 14:21:36 +00001103 {
sewardj08a50f62002-06-17 02:21:20 +00001104 vg_symerr("DWARF line info appears to be corrupt "
1105 "- the section is too small");
sewardjb51f2e62002-06-01 23:11:19 +00001106 return;
sewardjc134dd92002-06-01 14:21:36 +00001107 }
1108
1109 /* Check its version number. */
sewardj08a50f62002-06-17 02:21:20 +00001110 info.li_version = * ((UShort *) (external->li_version));
sewardjc134dd92002-06-01 14:21:36 +00001111 if (info.li_version != 2)
1112 {
sewardj08a50f62002-06-17 02:21:20 +00001113 vg_symerr("Only DWARF version 2 line info "
1114 "is currently supported.");
sewardjb51f2e62002-06-01 23:11:19 +00001115 return;
sewardjc134dd92002-06-01 14:21:36 +00001116 }
1117
sewardjd84606d2002-06-18 01:04:57 +00001118 info.li_prologue_length = * ((UInt *) (external->li_prologue_length));
1119 info.li_min_insn_length = * ((UChar *)(external->li_min_insn_length));
1120 info.li_default_is_stmt = * ((UChar *)(external->li_default_is_stmt));
1121
1122 /* JRS: changed (UInt*) to (UChar*) */
1123 info.li_line_base = * ((UChar *)(external->li_line_base));
1124
1125 info.li_line_range = * ((UChar *)(external->li_line_range));
1126 info.li_opcode_base = * ((UChar *)(external->li_opcode_base));
sewardjc134dd92002-06-01 14:21:36 +00001127
sewardjb642dc22002-10-12 17:27:16 +00001128 if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
1129 info.li_line_base, info.li_line_range, info.li_opcode_base);
1130
sewardjc134dd92002-06-01 14:21:36 +00001131 /* Sign extend the line base field. */
1132 info.li_line_base <<= 24;
1133 info.li_line_base >>= 24;
1134
sewardj08a50f62002-06-17 02:21:20 +00001135 end_of_sequence = data + info.li_length
1136 + sizeof (external->li_length);
sewardjc134dd92002-06-01 14:21:36 +00001137
1138 reset_state_machine (info.li_default_is_stmt);
1139
1140 /* Read the contents of the Opcodes table. */
1141 standard_opcodes = data + sizeof (* external);
1142
sewardjc134dd92002-06-01 14:21:36 +00001143 /* Read the contents of the Directory table. */
1144 data = standard_opcodes + info.li_opcode_base - 1;
1145
sewardj08a50f62002-06-17 02:21:20 +00001146 if (* data == 0)
1147 {
1148 }
sewardjc134dd92002-06-01 14:21:36 +00001149 else
1150 {
sewardj08a50f62002-06-17 02:21:20 +00001151 /* We ignore the directory table, since gcc gives the entire
1152 path as part of the filename */
sewardjc134dd92002-06-01 14:21:36 +00001153 while (* data != 0)
1154 {
1155 data += VG_(strlen) ((char *) data) + 1;
1156 }
1157 }
1158
1159 /* Skip the NUL at the end of the table. */
sewardjd84606d2002-06-18 01:04:57 +00001160 if (*data != 0) {
1161 vg_symerr("can't find NUL at end of DWARF2 directory table");
1162 return;
1163 }
sewardjc134dd92002-06-01 14:21:36 +00001164 data ++;
1165
1166 /* Read the contents of the File Name table. */
sewardj08a50f62002-06-17 02:21:20 +00001167 if (* data == 0)
1168 {
1169 }
sewardjc134dd92002-06-01 14:21:36 +00001170 else
1171 {
sewardjc134dd92002-06-01 14:21:36 +00001172 while (* data != 0)
1173 {
1174 UChar * name;
1175 Int bytes_read;
1176
sewardj08a50f62002-06-17 02:21:20 +00001177 ++ state_machine_regs.last_file_entry;
sewardjc134dd92002-06-01 14:21:36 +00001178 name = data;
sewardj08a50f62002-06-17 02:21:20 +00001179 /* Since we don't have realloc (0, ....) == malloc (...)
1180 semantics, we need to malloc the first time. */
sewardjc134dd92002-06-01 14:21:36 +00001181
1182 if (fnames == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001183 fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
sewardjc134dd92002-06-01 14:21:36 +00001184 else
njn25e49d8e72002-09-23 09:36:25 +00001185 fnames = VG_(arena_realloc)(VG_AR_SYMTAB, fnames, /*alignment*/4,
sewardj08a50f62002-06-17 02:21:20 +00001186 sizeof(UInt)
1187 * (state_machine_regs.last_file_entry + 1));
1188 data += VG_(strlen) ((Char *) data) + 1;
sewardjc134dd92002-06-01 14:21:36 +00001189 fnames[state_machine_regs.last_file_entry] = addStr (si,name);
1190
1191 read_leb128 (data, & bytes_read, 0);
1192 data += bytes_read;
1193 read_leb128 (data, & bytes_read, 0);
1194 data += bytes_read;
1195 read_leb128 (data, & bytes_read, 0);
1196 data += bytes_read;
1197 }
1198 }
1199
1200 /* Skip the NUL at the end of the table. */
sewardjd84606d2002-06-18 01:04:57 +00001201 if (*data != 0) {
1202 vg_symerr("can't find NUL at end of DWARF2 file name table");
1203 return;
1204 }
sewardjc134dd92002-06-01 14:21:36 +00001205 data ++;
1206
1207 /* Now display the statements. */
1208
1209 while (data < end_of_sequence)
1210 {
1211 UChar op_code;
1212 Int adv;
1213 Int bytes_read;
1214
1215 op_code = * data ++;
1216
sewardjb642dc22002-10-12 17:27:16 +00001217 if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
1218
sewardjc134dd92002-06-01 14:21:36 +00001219 if (op_code >= info.li_opcode_base)
1220 {
1221 Int advAddr;
1222 op_code -= info.li_opcode_base;
sewardj08a50f62002-06-17 02:21:20 +00001223 adv = (op_code / info.li_line_range)
1224 * info.li_min_insn_length;
sewardjc134dd92002-06-01 14:21:36 +00001225 advAddr = adv;
1226 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001227 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001228 adv = (op_code % info.li_line_range) + info.li_line_base;
sewardj08a50f62002-06-17 02:21:20 +00001229 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1230 si->offset, state_machine_regs.address );
sewardjb642dc22002-10-12 17:27:16 +00001231 if (state_machine_regs.is_stmt) {
1232 /* only add a statement if there was a previous boundary */
1233 if (state_machine_regs.last_address)
1234 addLineInfo (si, fnames[state_machine_regs.file],
1235 si->offset + state_machine_regs.last_address,
1236 si->offset + state_machine_regs.address,
sewardj08a50f62002-06-17 02:21:20 +00001237 state_machine_regs.line, 0);
sewardjb642dc22002-10-12 17:27:16 +00001238 state_machine_regs.last_address = state_machine_regs.address;
1239 }
sewardjc134dd92002-06-01 14:21:36 +00001240 state_machine_regs.line += adv;
1241 }
1242 else switch (op_code)
1243 {
1244 case DW_LNS_extended_op:
sewardj08a50f62002-06-17 02:21:20 +00001245 data += process_extended_line_op (
1246 si, &fnames, data,
1247 info.li_default_is_stmt, sizeof (Addr));
sewardjc134dd92002-06-01 14:21:36 +00001248 break;
1249
1250 case DW_LNS_copy:
sewardj08a50f62002-06-17 02:21:20 +00001251 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
1252 si->offset, state_machine_regs.address );
sewardjb642dc22002-10-12 17:27:16 +00001253 if (state_machine_regs.is_stmt) {
1254 /* only add a statement if there was a previous boundary */
1255 if (state_machine_regs.last_address)
1256 addLineInfo (si, fnames[state_machine_regs.file],
1257 si->offset + state_machine_regs.last_address,
1258 si->offset + state_machine_regs.address,
sewardj08a50f62002-06-17 02:21:20 +00001259 state_machine_regs.line , 0);
sewardjb642dc22002-10-12 17:27:16 +00001260 state_machine_regs.last_address = state_machine_regs.address;
1261 }
sewardjd84606d2002-06-18 01:04:57 +00001262 state_machine_regs.basic_block = 0; /* JRS added */
sewardjc134dd92002-06-01 14:21:36 +00001263 break;
1264
1265 case DW_LNS_advance_pc:
sewardj08a50f62002-06-17 02:21:20 +00001266 adv = info.li_min_insn_length
1267 * read_leb128 (data, & bytes_read, 0);
sewardjc134dd92002-06-01 14:21:36 +00001268 data += bytes_read;
1269 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001270 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001271 break;
1272
1273 case DW_LNS_advance_line:
1274 adv = read_leb128 (data, & bytes_read, 1);
1275 data += bytes_read;
1276 state_machine_regs.line += adv;
1277 break;
1278
1279 case DW_LNS_set_file:
1280 adv = read_leb128 (data, & bytes_read, 0);
1281 data += bytes_read;
1282 state_machine_regs.file = adv;
1283 break;
1284
1285 case DW_LNS_set_column:
1286 adv = read_leb128 (data, & bytes_read, 0);
1287 data += bytes_read;
1288 state_machine_regs.column = adv;
1289 break;
1290
1291 case DW_LNS_negate_stmt:
1292 adv = state_machine_regs.is_stmt;
1293 adv = ! adv;
1294 state_machine_regs.is_stmt = adv;
1295 break;
1296
1297 case DW_LNS_set_basic_block:
1298 state_machine_regs.basic_block = 1;
1299 break;
1300
1301 case DW_LNS_const_add_pc:
1302 adv = (((255 - info.li_opcode_base) / info.li_line_range)
1303 * info.li_min_insn_length);
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_fixed_advance_pc:
1309 /* XXX: Need something to get 2 bytes */
1310 adv = *((UShort *)data);
1311 data += 2;
1312 state_machine_regs.address += adv;
sewardj08a50f62002-06-17 02:21:20 +00001313 if (0) VG_(printf)("smr.a += %p\n", adv );
sewardjc134dd92002-06-01 14:21:36 +00001314 break;
1315
1316 case DW_LNS_set_prologue_end:
1317 break;
1318
1319 case DW_LNS_set_epilogue_begin:
1320 break;
1321
1322 case DW_LNS_set_isa:
1323 adv = read_leb128 (data, & bytes_read, 0);
1324 data += bytes_read;
1325 break;
1326
1327 default:
1328 {
1329 int j;
1330 for (j = standard_opcodes[op_code - 1]; j > 0 ; --j)
1331 {
1332 read_leb128 (data, &bytes_read, 0);
1333 data += bytes_read;
1334 }
1335 }
1336 break;
1337 }
1338 }
njn25e49d8e72002-09-23 09:36:25 +00001339 VG_(arena_free)(VG_AR_SYMTAB, fnames);
sewardjc134dd92002-06-01 14:21:36 +00001340 fnames = NULL;
1341 }
sewardjc134dd92002-06-01 14:21:36 +00001342}
1343
sewardjb51f2e62002-06-01 23:11:19 +00001344
1345/*------------------------------------------------------------*/
1346/*--- Read info from a .so/exe file. ---*/
1347/*------------------------------------------------------------*/
1348
sewardjde4a1d02002-03-22 01:27:54 +00001349/* Read the symbols from the object/exe specified by the SegInfo into
1350 the tables within the supplied SegInfo. */
1351static
sewardj8fe15a32002-10-20 19:29:21 +00001352Bool vg_read_lib_symbols ( SegInfo* si )
sewardjde4a1d02002-03-22 01:27:54 +00001353{
1354 Elf32_Ehdr* ehdr; /* The ELF header */
1355 Elf32_Shdr* shdr; /* The section table */
1356 UChar* sh_strtab; /* The section table's string table */
sewardjb51f2e62002-06-01 23:11:19 +00001357 UChar* stab; /* The .stab table */
sewardjde4a1d02002-03-22 01:27:54 +00001358 UChar* stabstr; /* The .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001359 UChar* dwarf2; /* The DWARF2 location info table */
sewardjde4a1d02002-03-22 01:27:54 +00001360 Int stab_sz; /* Size in bytes of the .stab table */
1361 Int stabstr_sz; /* Size in bytes of the .stab string table */
sewardjb51f2e62002-06-01 23:11:19 +00001362 Int dwarf2_sz; /* Size in bytes of the DWARF2 srcloc table*/
sewardjde4a1d02002-03-22 01:27:54 +00001363 Int fd;
1364 Int i;
1365 Bool ok;
1366 Addr oimage;
1367 Int n_oimage;
sewardjb3586202002-05-09 17:38:13 +00001368 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001369
sewardjde4a1d02002-03-22 01:27:54 +00001370 oimage = (Addr)NULL;
1371 if (VG_(clo_verbosity) > 1)
njne0ee0712002-05-03 16:41:05 +00001372 VG_(message)(Vg_UserMsg, "Reading syms from %s", si->filename );
sewardjde4a1d02002-03-22 01:27:54 +00001373
1374 /* mmap the object image aboard, so that we can read symbols and
1375 line number info out of it. It will be munmapped immediately
1376 thereafter; it is only aboard transiently. */
1377
sewardjb3586202002-05-09 17:38:13 +00001378 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001379 if (i != 0) {
1380 vg_symerr("Can't stat .so/.exe (to determine its size)?!");
sewardj8fe15a32002-10-20 19:29:21 +00001381 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001382 }
1383 n_oimage = stat_buf.st_size;
1384
njn25e49d8e72002-09-23 09:36:25 +00001385 fd = VG_(open)(si->filename, VKI_O_RDONLY, 0);
sewardjde4a1d02002-03-22 01:27:54 +00001386 if (fd == -1) {
1387 vg_symerr("Can't open .so/.exe to read symbols?!");
sewardj8fe15a32002-10-20 19:29:21 +00001388 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001389 }
1390
sewardjb3586202002-05-09 17:38:13 +00001391 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
1392 VKI_PROT_READ, VKI_MAP_PRIVATE, fd, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001393 if (oimage == ((Addr)(-1))) {
1394 VG_(message)(Vg_UserMsg,
1395 "mmap failed on %s", si->filename );
1396 VG_(close)(fd);
sewardj8fe15a32002-10-20 19:29:21 +00001397 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001398 }
1399
1400 VG_(close)(fd);
1401
1402 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1403 Now verify that it is a valid ELF .so or executable image.
1404 */
1405 ok = (n_oimage >= sizeof(Elf32_Ehdr));
1406 ehdr = (Elf32_Ehdr*)oimage;
1407
1408 if (ok) {
1409 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
1410 && ehdr->e_ident[EI_MAG1] == 'E'
1411 && ehdr->e_ident[EI_MAG2] == 'L'
1412 && ehdr->e_ident[EI_MAG3] == 'F');
1413 ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
1414 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
1415 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
1416 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
1417 ok &= (ehdr->e_machine == EM_386);
1418 ok &= (ehdr->e_version == EV_CURRENT);
1419 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
1420 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
sewardj8fe15a32002-10-20 19:29:21 +00001421 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
sewardjde4a1d02002-03-22 01:27:54 +00001422 }
1423
1424 if (!ok) {
1425 vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
1426 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001427 return False;
1428 }
1429
1430 /* Walk the LOAD headers in the phdr and update the SegInfo to
1431 include them all, so that this segment also contains data and
1432 bss memory. Also computes correct symbol offset value for this
1433 ELF file. */
1434 if (ehdr->e_phoff + ehdr->e_phnum*sizeof(Elf32_Phdr) > n_oimage) {
1435 vg_symerr("ELF program header is beyond image end?!");
1436 VG_(munmap) ( (void*)oimage, n_oimage );
1437 return False;
1438 }
1439 {
1440 Bool offset_set = False;
1441 Elf32_Addr prev_addr = 0;
1442
1443 si->offset = 0;
1444
1445 for(i = 0; i < ehdr->e_phnum; i++) {
1446 Elf32_Phdr *o_phdr;
1447 Elf32_Addr mapped, mapped_end;
1448
1449 o_phdr = &((Elf32_Phdr *)(oimage + ehdr->e_phoff))[i];
1450
1451 if (o_phdr->p_type != PT_LOAD)
1452 continue;
1453
1454 if (!offset_set) {
1455 offset_set = True;
1456 si->offset = si->start - o_phdr->p_vaddr;
1457 }
1458
1459 if (o_phdr->p_vaddr < prev_addr) {
1460 vg_symerr("ELF Phdrs are out of order!?");
1461 VG_(munmap) ( (void*)oimage, n_oimage );
1462 return False;
1463 }
1464 prev_addr = o_phdr->p_vaddr;
1465
1466 mapped = o_phdr->p_vaddr + si->offset;
1467 mapped_end = mapped + o_phdr->p_memsz;
1468
1469 if (si->data_start == 0 &&
1470 (o_phdr->p_flags & (PF_R|PF_W|PF_X)) == (PF_R|PF_W)) {
1471 si->data_start = mapped;
1472 si->data_size = o_phdr->p_filesz;
1473 si->bss_start = mapped + o_phdr->p_filesz;
1474 if (o_phdr->p_memsz > o_phdr->p_filesz)
1475 si->bss_size = o_phdr->p_memsz - o_phdr->p_filesz;
1476 else
1477 si->bss_size = 0;
1478 }
1479
1480 mapped = mapped & ~(VKI_BYTES_PER_PAGE-1);
1481 mapped_end = (mapped_end + VKI_BYTES_PER_PAGE - 1) & ~(VKI_BYTES_PER_PAGE-1);
1482
1483 if (VG_(needs).data_syms &&
1484 (mapped >= si->start && mapped <= (si->start+si->size)) &&
1485 (mapped_end > (si->start+si->size))) {
1486 UInt newsz = mapped_end - si->start;
1487 if (newsz > si->size) {
1488 if (0)
1489 VG_(printf)("extending mapping %p..%p %d -> ..%p %d\n",
1490 si->start, si->start+si->size, si->size,
1491 si->start+newsz, newsz);
1492 si->size = newsz;
1493 }
1494 }
1495 }
sewardjde4a1d02002-03-22 01:27:54 +00001496 }
1497
1498 if (VG_(clo_trace_symtab))
1499 VG_(printf)(
1500 "shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
1501 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
1502
1503 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
1504 vg_symerr("ELF section header is beyond image end?!");
1505 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001506 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001507 }
1508
1509 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
1510 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1511
1512 /* try and read the object's symbol table */
1513 {
1514 UChar* o_strtab = NULL;
1515 Elf32_Sym* o_symtab = NULL;
1516 UInt o_strtab_sz = 0;
1517 UInt o_symtab_sz = 0;
1518
1519 UChar* o_got = NULL;
1520 UChar* o_plt = NULL;
1521 UInt o_got_sz = 0;
1522 UInt o_plt_sz = 0;
1523
1524 Bool snaffle_it;
1525 Addr sym_addr;
1526
1527 /* find the .stabstr and .stab sections */
1528 for (i = 0; i < ehdr->e_shnum; i++) {
sewardj48115152002-10-02 10:20:30 +00001529
1530 /* As a fallback position, we look first for the dynamic
1531 symbols of a library to increase the chances that we can
1532 say something helpful even if the standard and debug
1533 symbols are missing. */
1534
1535 if (0 == VG_(strcmp)(".dynsym",sh_strtab + shdr[i].sh_name)) {
1536 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1537 o_symtab_sz = shdr[i].sh_size;
1538 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1539 /* check image overrun here */
1540 }
1541 if (0 == VG_(strcmp)(".dynstr",sh_strtab + shdr[i].sh_name)) {
1542 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1543 o_strtab_sz = shdr[i].sh_size;
1544 /* check image overrun here */
1545 }
1546
1547 /* now look for the main symbol and string tables. */
sewardjde4a1d02002-03-22 01:27:54 +00001548 if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
1549 o_symtab = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
1550 o_symtab_sz = shdr[i].sh_size;
1551 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1552 /* check image overrun here */
1553 }
1554 if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
1555 o_strtab = (UChar*)(oimage + shdr[i].sh_offset);
1556 o_strtab_sz = shdr[i].sh_size;
1557 /* check image overrun here */
1558 }
1559
1560 /* find out where the .got and .plt sections will be in the
1561 executable image, not in the object image transiently loaded.
1562 */
1563 if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
1564 o_got = (UChar*)(si->offset
sewardj47104382002-10-20 18:35:48 +00001565 + shdr[i].sh_addr);
sewardjde4a1d02002-03-22 01:27:54 +00001566 o_got_sz = shdr[i].sh_size;
sewardj47104382002-10-20 18:35:48 +00001567 si->got_start= (Addr)o_got;
1568 si->got_size = o_got_sz;
sewardjde4a1d02002-03-22 01:27:54 +00001569 /* check image overrun here */
1570 }
1571 if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
1572 o_plt = (UChar*)(si->offset
sewardj47104382002-10-20 18:35:48 +00001573 + shdr[i].sh_addr);
sewardjde4a1d02002-03-22 01:27:54 +00001574 o_plt_sz = shdr[i].sh_size;
sewardj47104382002-10-20 18:35:48 +00001575 si->plt_start= (Addr)o_plt;
1576 si->plt_size = o_plt_sz;
sewardjde4a1d02002-03-22 01:27:54 +00001577 /* check image overrun here */
1578 }
1579
1580 }
1581
1582 if (VG_(clo_trace_symtab)) {
1583 if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
1584 o_plt, o_plt + o_plt_sz - 1 );
1585 if (o_got) VG_(printf)( "GOT: %p .. %p\n",
1586 o_got, o_got + o_got_sz - 1 );
1587 }
1588
1589 if (o_strtab == NULL || o_symtab == NULL) {
1590 vg_symerr(" object doesn't have a symbol table");
1591 } else {
1592 /* Perhaps should start at i = 1; ELF docs suggest that entry
1593 0 always denotes `unknown symbol'. */
1594 for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
sewardj8fe15a32002-10-20 19:29:21 +00001595# if 1
1596 if (VG_(clo_trace_symtab)) {
1597 VG_(printf)("raw symbol: ");
1598 switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
sewardjde4a1d02002-03-22 01:27:54 +00001599 case STB_LOCAL: VG_(printf)("LOC "); break;
1600 case STB_GLOBAL: VG_(printf)("GLO "); break;
1601 case STB_WEAK: VG_(printf)("WEA "); break;
1602 case STB_LOPROC: VG_(printf)("lop "); break;
1603 case STB_HIPROC: VG_(printf)("hip "); break;
1604 default: VG_(printf)("??? "); break;
sewardj8fe15a32002-10-20 19:29:21 +00001605 }
1606 switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
sewardjde4a1d02002-03-22 01:27:54 +00001607 case STT_NOTYPE: VG_(printf)("NOT "); break;
1608 case STT_OBJECT: VG_(printf)("OBJ "); break;
1609 case STT_FUNC: VG_(printf)("FUN "); break;
1610 case STT_SECTION: VG_(printf)("SEC "); break;
1611 case STT_FILE: VG_(printf)("FIL "); break;
1612 case STT_LOPROC: VG_(printf)("lop "); break;
1613 case STT_HIPROC: VG_(printf)("hip "); break;
1614 default: VG_(printf)("??? "); break;
sewardj8fe15a32002-10-20 19:29:21 +00001615 }
1616 VG_(printf)(
1617 ": value %p, size %d, name %s\n",
1618 si->offset+(UChar*)o_symtab[i].st_value,
1619 o_symtab[i].st_size,
1620 o_symtab[i].st_name
1621 ? ((Char*)o_strtab+o_symtab[i].st_name)
1622 : (Char*)"NONAME");
1623 }
sewardjde4a1d02002-03-22 01:27:54 +00001624# endif
1625
1626 /* Figure out if we're interested in the symbol.
1627 Firstly, is it of the right flavour?
1628 */
1629 snaffle_it
1630 = ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
1631 ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
1632 ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
1633 &&
sewardj8fe15a32002-10-20 19:29:21 +00001634 (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC ||
1635 (VG_(needs).data_syms && ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT))
sewardjde4a1d02002-03-22 01:27:54 +00001636 );
1637
1638 /* Secondly, if it's apparently in a GOT or PLT, it's really
1639 a reference to a symbol defined elsewhere, so ignore it.
1640 */
1641 sym_addr = si->offset
1642 + (UInt)o_symtab[i].st_value;
1643 if (o_got != NULL
1644 && sym_addr >= (Addr)o_got
1645 && sym_addr < (Addr)(o_got+o_got_sz)) {
1646 snaffle_it = False;
1647 if (VG_(clo_trace_symtab)) {
1648 VG_(printf)( "in GOT: %s\n",
1649 o_strtab+o_symtab[i].st_name);
1650 }
1651 }
1652 if (o_plt != NULL
1653 && sym_addr >= (Addr)o_plt
1654 && sym_addr < (Addr)(o_plt+o_plt_sz)) {
1655 snaffle_it = False;
1656 if (VG_(clo_trace_symtab)) {
1657 VG_(printf)( "in PLT: %s\n",
1658 o_strtab+o_symtab[i].st_name);
1659 }
1660 }
1661
1662 /* Don't bother if nameless, or zero-sized. */
1663 if (snaffle_it
1664 && (o_symtab[i].st_name == (Elf32_Word)NULL
1665 || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
1666 /* equivalent but cheaper ... */
1667 * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
1668 || o_symtab[i].st_size == 0)) {
1669 snaffle_it = False;
1670 if (VG_(clo_trace_symtab)) {
1671 VG_(printf)( "size=0: %s\n",
1672 o_strtab+o_symtab[i].st_name);
1673 }
1674 }
1675
1676# if 0
1677 /* Avoid _dl_ junk. (Why?) */
1678 /* 01-02-24: disabled until I find out if it really helps. */
1679 if (snaffle_it
1680 && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
1681 || VG_(strncmp)("_r_debug",
1682 o_strtab+o_symtab[i].st_name, 8) == 0)) {
1683 snaffle_it = False;
1684 if (VG_(clo_trace_symtab)) {
1685 VG_(printf)( "_dl_ junk: %s\n",
1686 o_strtab+o_symtab[i].st_name);
1687 }
1688 }
1689# endif
1690
1691 /* This seems to significantly reduce the number of junk
1692 symbols, and particularly reduces the number of
1693 overlapping address ranges. Don't ask me why ... */
1694 if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
1695 snaffle_it = False;
1696 if (VG_(clo_trace_symtab)) {
1697 VG_(printf)( "valu=0: %s\n",
1698 o_strtab+o_symtab[i].st_name);
1699 }
1700 }
1701
1702 /* If no part of the symbol falls within the mapped range,
1703 ignore it. */
1704 if (sym_addr+o_symtab[i].st_size <= si->start
1705 || sym_addr >= si->start+si->size) {
1706 snaffle_it = False;
1707 }
1708
1709 if (snaffle_it) {
1710 /* it's an interesting symbol; record ("snaffle") it. */
1711 RiSym sym;
1712 Char* t0 = o_symtab[i].st_name
1713 ? (Char*)(o_strtab+o_symtab[i].st_name)
1714 : (Char*)"NONAME";
1715 Int nmoff = addStr ( si, t0 );
1716 vg_assert(nmoff >= 0
1717 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
1718 vg_assert( (Int)o_symtab[i].st_value >= 0);
sewardj8fe15a32002-10-20 19:29:21 +00001719 /* VG_(printf)("%p + %d: %p %s\n", si->start,
1720 (Int)o_symtab[i].st_value, sym_addr, t0 ); */
sewardjde4a1d02002-03-22 01:27:54 +00001721 sym.addr = sym_addr;
1722 sym.size = o_symtab[i].st_size;
1723 sym.nmoff = nmoff;
1724 addSym ( si, &sym );
1725 }
1726 }
1727 }
1728 }
1729
sewardjb51f2e62002-06-01 23:11:19 +00001730 /* Reading of the stabs and/or dwarf2 debug format information, if
1731 any. */
sewardjde4a1d02002-03-22 01:27:54 +00001732 stabstr = NULL;
1733 stab = NULL;
sewardjb51f2e62002-06-01 23:11:19 +00001734 dwarf2 = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001735 stabstr_sz = 0;
1736 stab_sz = 0;
sewardjb51f2e62002-06-01 23:11:19 +00001737 dwarf2_sz = 0;
1738
1739 /* find the .stabstr / .stab / .debug_line sections */
sewardjde4a1d02002-03-22 01:27:54 +00001740 for (i = 0; i < ehdr->e_shnum; i++) {
1741 if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001742 stab = (UChar*)(oimage + shdr[i].sh_offset);
sewardjde4a1d02002-03-22 01:27:54 +00001743 stab_sz = shdr[i].sh_size;
1744 }
1745 if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
1746 stabstr = (UChar*)(oimage + shdr[i].sh_offset);
1747 stabstr_sz = shdr[i].sh_size;
1748 }
sewardjc134dd92002-06-01 14:21:36 +00001749 if (0 == VG_(strcmp)(".debug_line",sh_strtab + shdr[i].sh_name)) {
sewardjb51f2e62002-06-01 23:11:19 +00001750 dwarf2 = (UChar *)(oimage + shdr[i].sh_offset);
1751 dwarf2_sz = shdr[i].sh_size;
sewardjc134dd92002-06-01 14:21:36 +00001752 }
sewardjde4a1d02002-03-22 01:27:54 +00001753 }
1754
sewardjb51f2e62002-06-01 23:11:19 +00001755 if ((stab == NULL || stabstr == NULL) && dwarf2 == NULL) {
sewardjde4a1d02002-03-22 01:27:54 +00001756 vg_symerr(" object doesn't have any debug info");
1757 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001758 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001759 }
1760
1761 if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
1762 || stabstr_sz + (UChar*)stabstr
1763 > n_oimage + (UChar*)oimage ) {
sewardjb51f2e62002-06-01 23:11:19 +00001764 vg_symerr(" ELF (stabs) debug data is beyond image end?!");
sewardjde4a1d02002-03-22 01:27:54 +00001765 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001766 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001767 }
1768
sewardjb51f2e62002-06-01 23:11:19 +00001769 if ( dwarf2_sz + (UChar*)dwarf2 > n_oimage + (UChar*)oimage ) {
1770 vg_symerr(" ELF (dwarf2) debug data is beyond image end?!");
1771 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001772 return False;
sewardjb51f2e62002-06-01 23:11:19 +00001773 }
sewardjde4a1d02002-03-22 01:27:54 +00001774
sewardjb51f2e62002-06-01 23:11:19 +00001775 /* Looks plausible. Go on and read debug data. */
1776 if (stab != NULL && stabstr != NULL) {
1777 read_debuginfo_stabs ( si, stab, stab_sz, stabstr, stabstr_sz );
1778 }
sewardjde4a1d02002-03-22 01:27:54 +00001779
sewardjb51f2e62002-06-01 23:11:19 +00001780 if (dwarf2 != NULL) {
1781 read_debuginfo_dwarf2 ( si, dwarf2, dwarf2_sz );
1782 }
sewardjde4a1d02002-03-22 01:27:54 +00001783
1784 /* Last, but not least, heave the oimage back overboard. */
1785 VG_(munmap) ( (void*)oimage, n_oimage );
sewardj8fe15a32002-10-20 19:29:21 +00001786
1787 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001788}
1789
1790
1791/*------------------------------------------------------------*/
1792/*--- Main entry point for symbols table reading. ---*/
1793/*------------------------------------------------------------*/
1794
1795/* The root structure for the entire symbol table system. It is a
1796 linked list of SegInfos. Note that this entire mechanism assumes
1797 that what we read from /proc/self/maps doesn't contain overlapping
1798 address ranges, and as a result the SegInfos in this list describe
1799 disjoint address ranges.
1800*/
1801static SegInfo* segInfo = NULL;
1802
1803
njn25e49d8e72002-09-23 09:36:25 +00001804void VG_(read_symtab_callback) (
sewardjde4a1d02002-03-22 01:27:54 +00001805 Addr start, UInt size,
1806 Char rr, Char ww, Char xx,
1807 UInt foffset, UChar* filename )
1808{
1809 SegInfo* si;
1810
1811 /* Stay sane ... */
1812 if (size == 0)
1813 return;
1814
1815 /* We're only interested in collecting symbols in executable
1816 segments which are associated with a real file. Hence: */
1817 if (filename == NULL || xx != 'x')
1818 return;
1819 if (0 == VG_(strcmp)(filename, "/dev/zero"))
1820 return;
sewardj8fe15a32002-10-20 19:29:21 +00001821 if (foffset != 0)
1822 return;
sewardjde4a1d02002-03-22 01:27:54 +00001823
1824 /* Perhaps we already have this one? If so, skip. */
1825 for (si = segInfo; si != NULL; si = si->next) {
1826 /*
1827 if (0==VG_(strcmp)(si->filename, filename))
1828 VG_(printf)("same fnames: %c%c%c (%p, %d) (%p, %d) %s\n",
1829 rr,ww,xx,si->start,si->size,start,size,filename);
1830 */
1831 /* For some reason the observed size of a mapping can change, so
1832 we don't use that to determine uniqueness. */
1833 if (si->start == start
1834 /* && si->size == size */
1835 && 0==VG_(strcmp)(si->filename, filename)) {
1836 return;
1837 }
1838 }
1839
1840 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001841 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001842
sewardj8fe15a32002-10-20 19:29:21 +00001843 VG_(memset)(si, 0, sizeof(*si));
sewardjde4a1d02002-03-22 01:27:54 +00001844 si->start = start;
1845 si->size = size;
1846 si->foffset = foffset;
njn25e49d8e72002-09-23 09:36:25 +00001847 si->filename = VG_(arena_malloc)(VG_AR_SYMTAB, 1 + VG_(strlen)(filename));
sewardjde4a1d02002-03-22 01:27:54 +00001848 VG_(strcpy)(si->filename, filename);
1849
1850 si->symtab = NULL;
1851 si->symtab_size = si->symtab_used = 0;
1852 si->loctab = NULL;
1853 si->loctab_size = si->loctab_used = 0;
1854 si->strtab = NULL;
1855 si->strtab_size = si->strtab_used = 0;
1856
sewardjde4a1d02002-03-22 01:27:54 +00001857 /* And actually fill it up. */
sewardj8fe15a32002-10-20 19:29:21 +00001858 if (!vg_read_lib_symbols ( si ) && 0) {
1859 /* XXX this interacts badly with the prevN optimization in
1860 addStr(). Since this frees the si, the si pointer value can
1861 be recycled, which confuses the curr_si == si test. For now,
1862 this code is disabled, and everything is included in the
1863 segment list, even if it is a bad ELF file. Ironically,
1864 running this under valgrind itself hides the problem, because
1865 it doesn't recycle pointers... */
1866 freeSegInfo( si );
1867 } else {
1868 si->next = segInfo;
1869 segInfo = si;
1870
1871 canonicaliseSymtab ( si );
1872 canonicaliseLoctab ( si );
1873 }
sewardjde4a1d02002-03-22 01:27:54 +00001874}
1875
1876
1877/* This one really is the Head Honcho. Update the symbol tables to
1878 reflect the current state of /proc/self/maps. Rather than re-read
1879 everything, just read the entries which are not already in segInfo.
1880 So we can call here repeatedly, after every mmap of a non-anonymous
1881 segment with execute permissions, for example, to pick up new
1882 libraries as they are dlopen'd. Conversely, when the client does
1883 munmap(), vg_symtab_notify_munmap() throws away any symbol tables
1884 which happen to correspond to the munmap()d area. */
njn25e49d8e72002-09-23 09:36:25 +00001885void VG_(maybe_read_symbols) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001886{
njn25e49d8e72002-09-23 09:36:25 +00001887 if (!VG_(using_debug_info))
1888 return;
sewardjde4a1d02002-03-22 01:27:54 +00001889
njn25e49d8e72002-09-23 09:36:25 +00001890 VGP_PUSHCC(VgpReadSyms);
1891 VG_(read_procselfmaps) ( VG_(read_symtab_callback) );
1892 VGP_POPCC(VgpReadSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001893}
1894
sewardjde4a1d02002-03-22 01:27:54 +00001895/* When an munmap() call happens, check to see whether it corresponds
1896 to a segment for a .so, and if so discard the relevant SegInfo.
1897 This might not be a very clever idea from the point of view of
1898 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001899 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001900*/
njn25e49d8e72002-09-23 09:36:25 +00001901void VG_(maybe_unload_symbols) ( Addr start, UInt length )
sewardjde4a1d02002-03-22 01:27:54 +00001902{
1903 SegInfo *prev, *curr;
1904
njn25e49d8e72002-09-23 09:36:25 +00001905 if (!VG_(using_debug_info))
1906 return;
1907
sewardjde4a1d02002-03-22 01:27:54 +00001908 prev = NULL;
1909 curr = segInfo;
1910 while (True) {
1911 if (curr == NULL) break;
1912 if (start == curr->start) break;
1913 prev = curr;
1914 curr = curr->next;
1915 }
sewardj18d75132002-05-16 11:06:21 +00001916 if (curr == NULL)
njn25e49d8e72002-09-23 09:36:25 +00001917 return;
sewardjde4a1d02002-03-22 01:27:54 +00001918
1919 VG_(message)(Vg_UserMsg,
1920 "discard syms in %s due to munmap()",
1921 curr->filename ? curr->filename : (UChar*)"???");
1922
1923 vg_assert(prev == NULL || prev->next == curr);
1924
1925 if (prev == NULL) {
1926 segInfo = curr->next;
1927 } else {
1928 prev->next = curr->next;
1929 }
1930
1931 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001932 return;
sewardjde4a1d02002-03-22 01:27:54 +00001933}
1934
1935
1936/*------------------------------------------------------------*/
1937/*--- Use of symbol table & location info to create ---*/
1938/*--- plausible-looking stack dumps. ---*/
1939/*------------------------------------------------------------*/
1940
njn25e49d8e72002-09-23 09:36:25 +00001941static __inline__ void ensure_debug_info_inited ( void )
1942{
1943 if (!VG_(using_debug_info)) {
1944 VG_(using_debug_info) = True;
1945 VG_(maybe_read_symbols)();
1946 }
1947}
1948
sewardjde4a1d02002-03-22 01:27:54 +00001949/* Find a symbol-table index containing the specified pointer, or -1
1950 if not found. Binary search. */
1951
njn25e49d8e72002-09-23 09:36:25 +00001952static Int search_one_symtab ( SegInfo* si, Addr ptr,
1953 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001954{
1955 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001956 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001957 lo = 0,
1958 hi = si->symtab_used-1;
1959 while (True) {
1960 /* current unsearched space is from lo to hi, inclusive. */
1961 if (lo > hi) return -1; /* not found */
1962 mid = (lo + hi) / 2;
1963 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001964 size = ( match_anywhere_in_fun
1965 ? si->symtab[mid].size
1966 : 1);
1967 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001968
1969 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1970 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1971 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1972 return mid;
1973 }
1974}
1975
1976
1977/* Search all symtabs that we know about to locate ptr. If found, set
1978 *psi to the relevant SegInfo, and *symno to the symtab entry number
1979 within that. If not found, *psi is set to NULL. */
1980
njn25e49d8e72002-09-23 09:36:25 +00001981static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1982 /*OUT*/Int* symno,
1983 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001984{
1985 Int sno;
1986 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001987
1988 ensure_debug_info_inited();
1989 VGP_PUSHCC(VgpSearchSyms);
1990
sewardjde4a1d02002-03-22 01:27:54 +00001991 for (si = segInfo; si != NULL; si = si->next) {
1992 if (si->start <= ptr && ptr < si->start+si->size) {
njn25e49d8e72002-09-23 09:36:25 +00001993 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001994 if (sno == -1) goto not_found;
1995 *symno = sno;
1996 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001997 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001998 return;
1999 }
2000 }
2001 not_found:
2002 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002003 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00002004}
2005
2006
2007/* Find a location-table index containing the specified pointer, or -1
2008 if not found. Binary search. */
2009
2010static Int search_one_loctab ( SegInfo* si, Addr ptr )
2011{
2012 Addr a_mid_lo, a_mid_hi;
2013 Int mid,
2014 lo = 0,
2015 hi = si->loctab_used-1;
2016 while (True) {
2017 /* current unsearched space is from lo to hi, inclusive. */
2018 if (lo > hi) return -1; /* not found */
2019 mid = (lo + hi) / 2;
2020 a_mid_lo = si->loctab[mid].addr;
2021 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
2022
2023 if (ptr < a_mid_lo) { hi = mid-1; continue; }
2024 if (ptr > a_mid_hi) { lo = mid+1; continue; }
2025 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
2026 return mid;
2027 }
2028}
2029
2030
2031/* Search all loctabs that we know about to locate ptr. If found, set
2032 *psi to the relevant SegInfo, and *locno to the loctab entry number
2033 within that. If not found, *psi is set to NULL.
2034*/
njn25e49d8e72002-09-23 09:36:25 +00002035static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
2036 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00002037{
2038 Int lno;
2039 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00002040
2041 VGP_PUSHCC(VgpSearchSyms);
2042
2043 ensure_debug_info_inited();
sewardjde4a1d02002-03-22 01:27:54 +00002044 for (si = segInfo; si != NULL; si = si->next) {
2045 if (si->start <= ptr && ptr < si->start+si->size) {
2046 lno = search_one_loctab ( si, ptr );
2047 if (lno == -1) goto not_found;
2048 *locno = lno;
2049 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00002050 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00002051 return;
2052 }
2053 }
2054 not_found:
2055 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00002056 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00002057}
2058
2059
2060/* The whole point of this whole big deal: map a code address to a
2061 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00002062 Caller supplies buf and nbuf. If demangle is False, don't do
sewardjde4a1d02002-03-22 01:27:54 +00002063 demangling, regardless of vg_clo_demangle -- probably because the
2064 call has come from vg_what_fn_or_object_is_this. */
njn25e49d8e72002-09-23 09:36:25 +00002065static
2066Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
2067 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00002068{
2069 SegInfo* si;
2070 Int sno;
njn25e49d8e72002-09-23 09:36:25 +00002071 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00002072 if (si == NULL)
2073 return False;
njn25e49d8e72002-09-23 09:36:25 +00002074 if (demangle) {
2075 VG_(demangle) ( & si->strtab[si->symtab[sno].nmoff], buf, nbuf );
2076 } else {
sewardjde4a1d02002-03-22 01:27:54 +00002077 VG_(strncpy_safely)
2078 ( buf, & si->strtab[si->symtab[sno].nmoff], nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00002079 }
2080 return True;
2081}
2082
njn25e49d8e72002-09-23 09:36:25 +00002083/* This is available to skins... always demangle C++ names */
2084Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
2085{
2086 return get_fnname ( /*demangle*/True, a, buf, nbuf,
2087 /*match_anywhere_in_fun*/True );
2088}
sewardjde4a1d02002-03-22 01:27:54 +00002089
njn25e49d8e72002-09-23 09:36:25 +00002090/* This is available to skins... always demangle C++ names,
2091 only succeed if 'a' matches first instruction of function. */
2092Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
2093{
2094 return get_fnname ( /*demangle*/True, a, buf, nbuf,
2095 /*match_anywhere_in_fun*/False );
2096}
2097
2098/* This is only available to core... don't demangle C++ names */
2099Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
2100{
2101 return get_fnname ( /*demangle*/False, a, buf, nbuf,
2102 /*match_anywhere_in_fun*/True );
2103}
2104
2105/* Map a code address to the name of a shared object file or the executable.
2106 Returns False if no idea; otherwise True. Doesn't require debug info.
2107 Caller supplies buf and nbuf. */
2108Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00002109{
2110 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00002111
2112 ensure_debug_info_inited();
sewardjde4a1d02002-03-22 01:27:54 +00002113 for (si = segInfo; si != NULL; si = si->next) {
2114 if (si->start <= a && a < si->start+si->size) {
2115 VG_(strncpy_safely)(buf, si->filename, nbuf);
2116 return True;
2117 }
2118 }
2119 return False;
2120}
2121
njn25e49d8e72002-09-23 09:36:25 +00002122
2123/* Map a code address to a filename. Returns True if successful. */
2124Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00002125{
njn25e49d8e72002-09-23 09:36:25 +00002126 SegInfo* si;
2127 Int locno;
2128 search_all_loctabs ( a, &si, &locno );
2129 if (si == NULL)
2130 return False;
2131 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
2132 n_filename);
2133 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002134}
2135
njn25e49d8e72002-09-23 09:36:25 +00002136/* Map a code address to a line number. Returns True if successful. */
2137Bool VG_(get_linenum)( Addr a, UInt* lineno )
2138{
2139 SegInfo* si;
2140 Int locno;
2141 search_all_loctabs ( a, &si, &locno );
2142 if (si == NULL)
2143 return False;
2144 *lineno = si->loctab[locno].lineno;
2145
2146 return True;
2147}
sewardjde4a1d02002-03-22 01:27:54 +00002148
2149/* Map a code address to a (filename, line number) pair.
2150 Returns True if successful.
2151*/
njn25e49d8e72002-09-23 09:36:25 +00002152Bool VG_(get_filename_linenum)( Addr a,
2153 Char* filename, Int n_filename,
2154 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00002155{
2156 SegInfo* si;
2157 Int locno;
2158 search_all_loctabs ( a, &si, &locno );
2159 if (si == NULL)
2160 return False;
2161 VG_(strncpy_safely)(filename, & si->strtab[si->loctab[locno].fnmoff],
2162 n_filename);
2163 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00002164
sewardjde4a1d02002-03-22 01:27:54 +00002165 return True;
2166}
2167
2168
2169/* Print a mini stack dump, showing the current location. */
2170void VG_(mini_stack_dump) ( ExeContext* ec )
2171{
2172
2173#define APPEND(str) \
2174 { UChar* sss; \
2175 for (sss = str; n < M_VG_ERRTXT-1 && *sss != 0; n++,sss++) \
2176 buf[n] = *sss; \
2177 buf[n] = 0; \
2178 }
2179
2180 Bool know_fnname;
2181 Bool know_objname;
2182 Bool know_srcloc;
2183 UInt lineno;
2184 UChar ibuf[20];
sewardj04b91062002-06-05 21:22:04 +00002185 UInt i, n;
sewardjde4a1d02002-03-22 01:27:54 +00002186
2187 UChar buf[M_VG_ERRTXT];
2188 UChar buf_fn[M_VG_ERRTXT];
2189 UChar buf_obj[M_VG_ERRTXT];
2190 UChar buf_srcloc[M_VG_ERRTXT];
2191
2192 Int stop_at = VG_(clo_backtrace_size);
2193
njn49ef4622002-10-04 15:15:08 +00002194 vg_assert(stop_at > 0);
sewardjde4a1d02002-03-22 01:27:54 +00002195
njn49ef4622002-10-04 15:15:08 +00002196 i = 0;
2197 do {
2198 n = 0;
njn25e49d8e72002-09-23 09:36:25 +00002199 know_fnname = VG_(get_fnname) (ec->eips[i], buf_fn, M_VG_ERRTXT);
2200 know_objname = VG_(get_objname)(ec->eips[i], buf_obj, M_VG_ERRTXT);
2201 know_srcloc = VG_(get_filename_linenum)(ec->eips[i],
2202 buf_srcloc, M_VG_ERRTXT,
2203 &lineno);
njn49ef4622002-10-04 15:15:08 +00002204 if (i == 0) APPEND(" at ") else APPEND(" by ");
2205
2206 VG_(sprintf)(ibuf,"0x%x: ", ec->eips[i]);
sewardj04b91062002-06-05 21:22:04 +00002207 APPEND(ibuf);
sewardjde4a1d02002-03-22 01:27:54 +00002208 if (know_fnname) {
njn49ef4622002-10-04 15:15:08 +00002209 APPEND(buf_fn);
sewardjde4a1d02002-03-22 01:27:54 +00002210 if (!know_srcloc && know_objname) {
2211 APPEND(" (in ");
2212 APPEND(buf_obj);
2213 APPEND(")");
2214 }
njn49ef4622002-10-04 15:15:08 +00002215 } else if (know_objname && !know_srcloc) {
2216 APPEND("(within ");
2217 APPEND(buf_obj);
2218 APPEND(")");
sewardjde4a1d02002-03-22 01:27:54 +00002219 } else {
njn49ef4622002-10-04 15:15:08 +00002220 APPEND("???");
2221 }
sewardjde4a1d02002-03-22 01:27:54 +00002222 if (know_srcloc) {
2223 APPEND(" (");
2224 APPEND(buf_srcloc);
2225 APPEND(":");
2226 VG_(sprintf)(ibuf,"%d",lineno);
2227 APPEND(ibuf);
2228 APPEND(")");
2229 }
2230 VG_(message)(Vg_UserMsg, "%s", buf);
njn49ef4622002-10-04 15:15:08 +00002231 i++;
2232
2233 } while (i < stop_at && ec->eips[i] != 0);
sewardjde4a1d02002-03-22 01:27:54 +00002234}
2235
2236#undef APPEND
2237
sewardj47104382002-10-20 18:35:48 +00002238/*------------------------------------------------------------*/
2239/*--- SegInfo accessor functions ---*/
2240/*------------------------------------------------------------*/
2241
2242const SegInfo* VG_(next_seginfo)(const SegInfo* seg)
2243{
2244 ensure_debug_info_inited();
2245
2246 if (seg == NULL)
2247 return segInfo;
2248 return seg->next;
2249}
2250
2251Addr VG_(seg_start)(const SegInfo* seg)
2252{
2253 return seg->start;
2254}
2255
2256UInt VG_(seg_size)(const SegInfo* seg)
2257{
2258 return seg->size;
2259}
2260
2261const UChar* VG_(seg_filename)(const SegInfo* seg)
2262{
2263 return seg->filename;
2264}
2265
2266UInt VG_(seg_sym_offset)(const SegInfo* seg)
2267{
2268 return seg->offset;
2269}
2270
2271VgSectKind VG_(seg_sect_kind)(Addr a)
2272{
2273 SegInfo* seg;
2274 VgSectKind ret = Vg_SectUnknown;
2275
2276 ensure_debug_info_inited();
2277
2278 for(seg = segInfo; seg != NULL; seg = seg->next) {
2279 if (a >= seg->start && a < (seg->start + seg->size)) {
2280 if (0)
sewardj8fe15a32002-10-20 19:29:21 +00002281 VG_(printf)("addr=%p seg=%p %s got=%p %d plt=%p %d data=%p %d bss=%p %d\n",
sewardj47104382002-10-20 18:35:48 +00002282 a, seg, seg->filename,
2283 seg->got_start, seg->got_size,
sewardj8fe15a32002-10-20 19:29:21 +00002284 seg->plt_start, seg->plt_size,
2285 seg->data_start, seg->data_size,
2286 seg->bss_start, seg->bss_size);
sewardj47104382002-10-20 18:35:48 +00002287 ret = Vg_SectText;
2288
sewardj8fe15a32002-10-20 19:29:21 +00002289 if (a >= seg->data_start && a < (seg->data_start + seg->data_size))
2290 ret = Vg_SectData;
2291 else if (a >= seg->bss_start && a < (seg->bss_start + seg->bss_size))
2292 ret = Vg_SectBSS;
2293 else if (a >= seg->plt_start && a < (seg->plt_start + seg->plt_size))
sewardj47104382002-10-20 18:35:48 +00002294 ret = Vg_SectPLT;
2295 else if (a >= seg->got_start && a < (seg->got_start + seg->got_size))
2296 ret = Vg_SectGOT;
2297 }
2298 }
2299
2300 return ret;
2301}
2302
sewardjde4a1d02002-03-22 01:27:54 +00002303/*--------------------------------------------------------------------*/
2304/*--- end vg_symtab2.c ---*/
2305/*--------------------------------------------------------------------*/