blob: 74a5174cebc469b4cc9638bc9925a08112d894d7 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001
sewardjde4a1d02002-03-22 01:27:54 +00002/*--------------------------------------------------------------------*/
3/*--- Management of symbols and debugging information. ---*/
4/*--- vg_symtab2.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
nethercotef1e5e152004-09-01 23:58:16 +000032#include "core.h"
jsgfcb1d1c02003-10-14 21:55:10 +000033#include "vg_symtypes.h"
34#include "vg_symtab2.h"
sewardjde4a1d02002-03-22 01:27:54 +000035
36#include <elf.h> /* ELF defns */
sewardjde4a1d02002-03-22 01:27:54 +000037
sewardjb5f6f512005-03-10 23:59:00 +000038static SegInfo* segInfo = NULL;
39
sewardj7a21c612005-02-18 09:38:08 +000040/*------------------------------------------------------------*/
41/*--- 32/64-bit parameterisation ---*/
42/*------------------------------------------------------------*/
43
44/* For all the ELF macros and types which specify '32' or '64',
45 select the correct variant for this platform and give it
46 an 'XX' name. Then use the 'XX' variant consistently in
47 the rest of this file.
48*/
49#if VGA_WORD_SIZE == 4
50# define ElfXX_Ehdr Elf32_Ehdr
51# define ElfXX_Shdr Elf32_Shdr
52# define ElfXX_Phdr Elf32_Phdr
53# define ElfXX_Sym Elf32_Sym
54# define ElfXX_Word Elf32_Word
55# define ElfXX_Addr Elf32_Addr
56# define ElfXX_Dyn Elf32_Dyn
57# define ELFXX_ST_BIND ELF32_ST_BIND
58# define ELFXX_ST_TYPE ELF32_ST_TYPE
59
60#elif VGA_WORD_SIZE == 8
61# define ElfXX_Ehdr Elf64_Ehdr
62# define ElfXX_Shdr Elf64_Shdr
63# define ElfXX_Phdr Elf64_Phdr
64# define ElfXX_Sym Elf64_Sym
65# define ElfXX_Word Elf64_Word
66# define ElfXX_Addr Elf64_Addr
67# define ElfXX_Dyn Elf64_Dyn
68# define ELFXX_ST_BIND ELF64_ST_BIND
69# define ELFXX_ST_TYPE ELF64_ST_TYPE
70
71#else
72# error "VGA_WORD_SIZE should be 4 or 8"
73#endif
74
75
76/*------------------------------------------------------------*/
77/*--- ---*/
78/*------------------------------------------------------------*/
79
rjwalshe4e779d2004-04-16 23:02:29 +000080static Bool
nethercoteb1e1ad42004-08-03 23:44:12 +000081intercept_demangle(const Char*, Char*, Int);
njn9aae6742002-04-30 13:44:01 +000082
sewardjde4a1d02002-03-22 01:27:54 +000083/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
84 dlopen()ed libraries, which is something that KDE3 does a lot.
sewardjde4a1d02002-03-22 01:27:54 +000085
njn25e49d8e72002-09-23 09:36:25 +000086 Stabs reader greatly improved by Nick Nethercote, Apr 02.
sewardjde4a1d02002-03-22 01:27:54 +000087*/
88
sewardjde4a1d02002-03-22 01:27:54 +000089static void freeSegInfo ( SegInfo* si )
90{
jsgfcb1d1c02003-10-14 21:55:10 +000091 struct strchunk *chunk, *next;
sewardjde4a1d02002-03-22 01:27:54 +000092 vg_assert(si != NULL);
njn25e49d8e72002-09-23 09:36:25 +000093 if (si->filename) VG_(arena_free)(VG_AR_SYMTAB, si->filename);
94 if (si->symtab) VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
95 if (si->loctab) VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
jsgfcb1d1c02003-10-14 21:55:10 +000096 if (si->scopetab) VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
97
98 for(chunk = si->strchunks; chunk != NULL; chunk = next) {
99 next = chunk->next;
100 VG_(arena_free)(VG_AR_SYMTAB, chunk);
101 }
njn25e49d8e72002-09-23 09:36:25 +0000102 VG_(arena_free)(VG_AR_SYMTAB, si);
sewardjde4a1d02002-03-22 01:27:54 +0000103}
104
105
106/*------------------------------------------------------------*/
107/*--- Adding stuff ---*/
108/*------------------------------------------------------------*/
109
110/* Add a str to the string table, including terminating zero, and
jsgfcb1d1c02003-10-14 21:55:10 +0000111 return pointer to the string in vg_strtab. Unless it's been seen
112 recently, in which case we find the old pointer and return that.
113 This avoids the most egregious duplications.
sewardjde4a1d02002-03-22 01:27:54 +0000114
jsgfcb1d1c02003-10-14 21:55:10 +0000115 JSGF: changed from returning an index to a pointer, and changed to
116 a chunking memory allocator rather than reallocating, so the
117 pointers are stable.
118*/
119
120Char *VG_(addStr) ( SegInfo* si, Char* str, Int len )
sewardjde4a1d02002-03-22 01:27:54 +0000121{
jsgfcb1d1c02003-10-14 21:55:10 +0000122# define EMPTY NULL
njn25e49d8e72002-09-23 09:36:25 +0000123# define NN 5
124
125 /* prevN[0] has the most recent, prevN[NN-1] the least recent */
jsgfcb1d1c02003-10-14 21:55:10 +0000126 static Char *prevN[NN] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
njn25e49d8e72002-09-23 09:36:25 +0000127 static SegInfo* curr_si = NULL;
jsgfcb1d1c02003-10-14 21:55:10 +0000128 struct strchunk *chunk;
129 Int i, space_needed;
njn25e49d8e72002-09-23 09:36:25 +0000130
jsgfcb1d1c02003-10-14 21:55:10 +0000131 if (len == -1)
132 len = VG_(strlen)(str);
njn25e49d8e72002-09-23 09:36:25 +0000133
134 /* Avoid gratuitous duplication: if we saw `str' within the last NN,
135 * within this segment, return that index. Saves about 200KB in glibc,
136 * extra time taken is too small to measure. --NJN 2002-Aug-30 */
137 if (curr_si == si) {
138 for (i = NN-1; i >= 0; i--) {
sewardjcda419b2002-10-01 08:59:36 +0000139 if (EMPTY != prevN[i]
jsgfcb1d1c02003-10-14 21:55:10 +0000140 && NULL != si->strchunks
jsgfa065a9c2003-10-14 22:07:31 +0000141 && 0 == VG_(memcmp)(str, prevN[i], len+1)) {
njn25e49d8e72002-09-23 09:36:25 +0000142 return prevN[i];
143 }
144 }
145 } else {
146 /* New segment */
147 curr_si = si;
sewardjcda419b2002-10-01 08:59:36 +0000148 for (i = 0; i < NN; i++) prevN[i] = EMPTY;
njn25e49d8e72002-09-23 09:36:25 +0000149 }
150 /* Shuffle prevous ones along, put new one in. */
jsgfcb1d1c02003-10-14 21:55:10 +0000151 for (i = NN-1; i > 0; i--)
152 prevN[i] = prevN[i-1];
njn25e49d8e72002-09-23 09:36:25 +0000153
154# undef EMPTY
155
jsgfcb1d1c02003-10-14 21:55:10 +0000156 space_needed = 1 + len;
njn25e49d8e72002-09-23 09:36:25 +0000157
jsgfcb1d1c02003-10-14 21:55:10 +0000158 if (si->strchunks == NULL ||
159 (si->strchunks->strtab_used + space_needed) > STRCHUNKSIZE) {
160 chunk = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*chunk));
161 chunk->strtab_used = 0;
162 chunk->next = si->strchunks;
163 si->strchunks = chunk;
sewardjde4a1d02002-03-22 01:27:54 +0000164 }
jsgfcb1d1c02003-10-14 21:55:10 +0000165 chunk = si->strchunks;
sewardjde4a1d02002-03-22 01:27:54 +0000166
jsgfcb1d1c02003-10-14 21:55:10 +0000167 prevN[0] = &chunk->strtab[chunk->strtab_used];
168 VG_(memcpy)(prevN[0], str, len);
169 chunk->strtab[chunk->strtab_used+len] = '\0';
170 chunk->strtab_used += space_needed;
sewardjde4a1d02002-03-22 01:27:54 +0000171
jsgfcb1d1c02003-10-14 21:55:10 +0000172 return prevN[0];
sewardjde4a1d02002-03-22 01:27:54 +0000173}
174
175/* Add a symbol to the symbol table. */
176
177static __inline__
178void addSym ( SegInfo* si, RiSym* sym )
179{
sewardj05bcdcb2003-05-18 10:05:38 +0000180 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000181 RiSym* new_tab;
182
183 /* Ignore zero-sized syms. */
184 if (sym->size == 0) return;
185
186 if (si->symtab_used == si->symtab_size) {
187 new_sz = 2 * si->symtab_size;
188 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000189 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
sewardjde4a1d02002-03-22 01:27:54 +0000190 if (si->symtab != NULL) {
191 for (i = 0; i < si->symtab_used; i++)
192 new_tab[i] = si->symtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000193 VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
sewardjde4a1d02002-03-22 01:27:54 +0000194 }
195 si->symtab = new_tab;
196 si->symtab_size = new_sz;
197 }
198
199 si->symtab[si->symtab_used] = *sym;
200 si->symtab_used++;
201 vg_assert(si->symtab_used <= si->symtab_size);
202}
203
204/* Add a location to the location table. */
205
206static __inline__
207void addLoc ( SegInfo* si, RiLoc* loc )
208{
sewardj05bcdcb2003-05-18 10:05:38 +0000209 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000210 RiLoc* new_tab;
211
njne0ee0712002-05-03 16:41:05 +0000212 /* Zero-sized locs should have been ignored earlier */
213 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000214
215 if (si->loctab_used == si->loctab_size) {
216 new_sz = 2 * si->loctab_size;
217 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000218 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
sewardjde4a1d02002-03-22 01:27:54 +0000219 if (si->loctab != NULL) {
220 for (i = 0; i < si->loctab_used; i++)
221 new_tab[i] = si->loctab[i];
njn25e49d8e72002-09-23 09:36:25 +0000222 VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
sewardjde4a1d02002-03-22 01:27:54 +0000223 }
224 si->loctab = new_tab;
225 si->loctab_size = new_sz;
226 }
227
228 si->loctab[si->loctab_used] = *loc;
229 si->loctab_used++;
230 vg_assert(si->loctab_used <= si->loctab_size);
231}
232
233
sewardjb51f2e62002-06-01 23:11:19 +0000234/* Top-level place to call to add a source-location mapping entry. */
235
jsgfcb1d1c02003-10-14 21:55:10 +0000236void VG_(addLineInfo) ( SegInfo* si,
237 Char* filename,
238 Addr this,
239 Addr next,
240 Int lineno,
241 Int entry /* only needed for debug printing */
242 )
sewardjb51f2e62002-06-01 23:11:19 +0000243{
jsgfcb1d1c02003-10-14 21:55:10 +0000244 static const Bool debug = False;
sewardjb51f2e62002-06-01 23:11:19 +0000245 RiLoc loc;
246 Int size = next - this;
247
248 /* Ignore zero-sized locs */
249 if (this == next) return;
250
jsgfcb1d1c02003-10-14 21:55:10 +0000251 if (debug)
252 VG_(printf)(" src %s line %d %p-%p\n", filename, lineno, this, next);
253
sewardjb51f2e62002-06-01 23:11:19 +0000254 /* Maximum sanity checking. Some versions of GNU as do a shabby
255 * job with stabs entries; if anything looks suspicious, revert to
256 * a size of 1. This should catch the instruction of interest
257 * (since if using asm-level debug info, one instruction will
258 * correspond to one line, unlike with C-level debug info where
259 * multiple instructions can map to the one line), but avoid
260 * catching any other instructions bogusly. */
thughesc1c57952004-11-01 17:36:15 +0000261 if (this > next) {
262 if (VG_(clo_verbosity) > 2) {
263 VG_(message)(Vg_DebugMsg,
264 "warning: line info addresses out of order "
265 "at entry %d: 0x%x 0x%x", entry, this, next);
266 }
sewardjb51f2e62002-06-01 23:11:19 +0000267 size = 1;
268 }
269
270 if (size > MAX_LOC_SIZE) {
sewardjd84606d2002-06-18 01:04:57 +0000271 if (0)
sewardjb51f2e62002-06-01 23:11:19 +0000272 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000273 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000274 "at entry %d: %d", entry, size);
275 size = 1;
276 }
277
sewardj08a50f62002-06-17 02:21:20 +0000278 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000279 if (this >= si->start + si->size || next-1 < si->start) {
sewardjd84606d2002-06-18 01:04:57 +0000280 if (0)
sewardj08a50f62002-06-17 02:21:20 +0000281 VG_(message)(Vg_DebugMsg,
282 "warning: ignoring line info entry falling "
283 "outside current SegInfo: %p %p %p %p",
284 si->start, si->start + si->size,
285 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000286 return;
287 }
288
289 vg_assert(lineno >= 0);
290 if (lineno > MAX_LINENO) {
291 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000292 "warning: ignoring line info entry with "
293 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000294 VG_(message)(Vg_UserMsg,
295 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000296 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000297 return;
298 }
sewardjb51f2e62002-06-01 23:11:19 +0000299
300 loc.addr = this;
301 loc.size = (UShort)size;
302 loc.lineno = lineno;
jsgfcb1d1c02003-10-14 21:55:10 +0000303 loc.filename = filename;
sewardjb642dc22002-10-12 17:27:16 +0000304
305 if (0) VG_(message)(Vg_DebugMsg,
306 "addLoc: addr %p, size %d, line %d, file %s",
jsgfcb1d1c02003-10-14 21:55:10 +0000307 this,size,lineno,filename);
sewardjb642dc22002-10-12 17:27:16 +0000308
sewardjb51f2e62002-06-01 23:11:19 +0000309 addLoc ( si, &loc );
310}
311
jsgfcb1d1c02003-10-14 21:55:10 +0000312static __inline__
313void addScopeRange ( SegInfo* si, ScopeRange *range )
314{
315 Int new_sz, i;
316 ScopeRange* new_tab;
317
318 /* Zero-sized scopes should have been ignored earlier */
319 vg_assert(range->size > 0);
320
321 if (si->scopetab_used == si->scopetab_size) {
322 new_sz = 2 * si->scopetab_size;
323 if (new_sz == 0) new_sz = 500;
324 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(*new_tab) );
325 if (si->scopetab != NULL) {
326 for (i = 0; i < si->scopetab_used; i++)
327 new_tab[i] = si->scopetab[i];
328 VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
329 }
330 si->scopetab = new_tab;
331 si->scopetab_size = new_sz;
332 }
333
334 si->scopetab[si->scopetab_used] = *range;
335 si->scopetab_used++;
336 vg_assert(si->scopetab_used <= si->scopetab_size);
337}
338
339
340/* Top-level place to call to add a source-location mapping entry. */
341
342void VG_(addScopeInfo) ( SegInfo* si,
343 Addr this,
344 Addr next,
345 Scope *scope)
346{
347 static const Bool debug = False;
348 Int size = next - this;
349 ScopeRange range;
350
fitzhardinge83d8a712004-02-05 22:58:37 +0000351 /* Ignore zero-sized or negative scopes */
352 if (size <= 0) {
jsgfcb1d1c02003-10-14 21:55:10 +0000353 if (debug)
354 VG_(printf)("ignoring zero-sized range, scope %p at %p\n", scope, this);
355 return;
356 }
357
358 if (debug)
359 VG_(printf)("adding scope range %p-%p (size=%d) scope %p (%d)\n",
360 this, next, next-this, scope, scope->depth);
361
362 range.addr = this;
363 range.size = size;
364 range.scope = scope;
365
366 addScopeRange ( si, &range );
367}
368
sewardjde4a1d02002-03-22 01:27:54 +0000369/*------------------------------------------------------------*/
370/*--- Helpers ---*/
371/*------------------------------------------------------------*/
372
373/* Non-fatal -- use vg_panic if terminal. */
jsgfcb1d1c02003-10-14 21:55:10 +0000374void VG_(symerr) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000375{
376 if (VG_(clo_verbosity) > 1)
377 VG_(message)(Vg_UserMsg,"%s", msg );
378}
379
380
381/* Print a symbol. */
382static
383void printSym ( SegInfo* si, Int i )
384{
385 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
386 i,
387 si->symtab[i].addr,
388 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
jsgfcb1d1c02003-10-14 21:55:10 +0000389 si->symtab[i].name );
sewardjde4a1d02002-03-22 01:27:54 +0000390}
391
nethercote80f76782003-11-13 22:34:00 +0000392#define TRACE_SYMTAB(format, args...) \
393 if (VG_(clo_trace_symtab)) { VG_(printf)(format, ## args); }
394
sewardjde4a1d02002-03-22 01:27:54 +0000395
396#if 0
397/* Print the entire sym tab. */
398static __attribute__ ((unused))
399void printSymtab ( void )
400{
401 Int i;
402 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
403 for (i = 0; i < vg_symtab_used; i++)
404 printSym(i);
405 VG_(printf)("------ BEGIN vg_symtab ------\n");
406}
407#endif
408
409#if 0
410/* Paranoid strcat. */
411static
412void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
413{
414 UInt i = 0, j = 0;
415 while (True) {
416 if (i >= maxlen) return;
417 if (dst[i] == 0) break;
418 i++;
419 }
420 while (True) {
421 if (i >= maxlen) return;
422 dst[i] = src[j];
423 if (src[j] == 0) return;
424 i++; j++;
425 }
426}
427#endif
428
sewardjb51f2e62002-06-01 23:11:19 +0000429
sewardjde4a1d02002-03-22 01:27:54 +0000430/*------------------------------------------------------------*/
431/*--- Canonicalisers ---*/
432/*------------------------------------------------------------*/
433
434/* Sort the symtab by starting address, and emit warnings if any
nethercote80f76782003-11-13 22:34:00 +0000435 symbols have overlapping address ranges. We use that old chestnut,
436 shellsort. Mash the table around so as to establish the property
437 that addresses are in order and the ranges to not overlap. This
438 facilitates using binary search to map addresses to symbols when we
439 come to query the table.
sewardjde4a1d02002-03-22 01:27:54 +0000440*/
jsgfcb1d1c02003-10-14 21:55:10 +0000441static Int compare_RiSym(void *va, void *vb) {
442 RiSym *a = (RiSym *)va;
443 RiSym *b = (RiSym *)vb;
444
nethercote05fdfac2004-08-01 20:24:46 +0000445 if (a->addr < b->addr) return -1;
446 if (a->addr > b->addr) return 1;
447 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000448}
449
fitzhardinge1c76dc42003-12-15 09:00:21 +0000450/* Two symbols have the same address. Which name do we prefer?
451
sewardjb5f6f512005-03-10 23:59:00 +0000452 The general rule is to prefer the shorter symbol name. If the
453 symbol contains a '@', which means its versioned, then the length
454 up to the '@' is used for length comparison purposes (so
455 "foo@GLIBC_2.4.2" is considered shorter than "foobar"), but if two
456 symbols have the same length, the one with the version string is
457 preferred. If all else fails, use alphabetical ordering.
fitzhardinge1c76dc42003-12-15 09:00:21 +0000458 */
459static RiSym *prefersym(RiSym *a, RiSym *b)
460{
sewardjb5f6f512005-03-10 23:59:00 +0000461 Int lena, lenb; /* full length */
462 Int vlena, vlenb; /* length without version */
463 const Char *vpa, *vpb;
fitzhardingeefda47f2003-12-15 23:31:52 +0000464
sewardjb5f6f512005-03-10 23:59:00 +0000465 vlena = lena = VG_(strlen)(a->name);
466 vlenb = lenb = VG_(strlen)(b->name);
fitzhardinge1c76dc42003-12-15 09:00:21 +0000467
sewardjb5f6f512005-03-10 23:59:00 +0000468 vpa = VG_(strchr)(a->name, '@');
469 vpb = VG_(strchr)(b->name, '@');
fitzhardinge1c76dc42003-12-15 09:00:21 +0000470
sewardjb5f6f512005-03-10 23:59:00 +0000471 if (vpa)
472 vlena = vpa - a->name;
473 if (vpb)
474 vlenb = vpb - b->name;
fitzhardingeefda47f2003-12-15 23:31:52 +0000475
sewardjb5f6f512005-03-10 23:59:00 +0000476 /* Select the shortest unversioned name */
477 if (vlena < vlenb)
478 return a;
479 else if (vlenb < vlena)
fitzhardinge1c76dc42003-12-15 09:00:21 +0000480 return b;
481
sewardjb5f6f512005-03-10 23:59:00 +0000482 /* Equal lengths; select the versioned name */
483 if (vpa && !vpb)
484 return a;
485 if (vpb && !vpa)
486 return b;
487
488 /* Either both versioned or neither is versioned; select them
489 alphabetically */
490 if (VG_(strcmp)(a->name, b->name) < 0)
491 return a;
492 else
493 return b;
fitzhardinge1c76dc42003-12-15 09:00:21 +0000494}
495
sewardjde4a1d02002-03-22 01:27:54 +0000496static
497void canonicaliseSymtab ( SegInfo* si )
498{
jsgfcb1d1c02003-10-14 21:55:10 +0000499 Int i, j, n_merged, n_truncated;
sewardjde4a1d02002-03-22 01:27:54 +0000500 Addr s1, s2, e1, e2;
501
502# define SWAP(ty,aa,bb) \
503 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
504
jsgfcb1d1c02003-10-14 21:55:10 +0000505 if (si->symtab_used == 0)
506 return;
sewardjde4a1d02002-03-22 01:27:54 +0000507
nethercote3acbb5d2003-11-13 21:50:45 +0000508 VG_(ssort)(si->symtab, si->symtab_used, sizeof(*si->symtab), compare_RiSym);
sewardjde4a1d02002-03-22 01:27:54 +0000509
rjwalshe4e779d2004-04-16 23:02:29 +0000510 for (i = 0; i < si->symtab_used; i++) {
511 if(VG_(strncmp)(si->symtab[i].name, VG_INTERCEPT_PREFIX,
512 VG_INTERCEPT_PREFIX_LEN) == 0) {
513 int len = VG_(strlen)(si->symtab[i].name);
sewardjb5f6f512005-03-10 23:59:00 +0000514 char *buf = VG_(arena_malloc)(VG_AR_SYMTAB, len), *colon;
nethercoteb1e1ad42004-08-03 23:44:12 +0000515 intercept_demangle(si->symtab[i].name, buf, len);
rjwalshe4e779d2004-04-16 23:02:29 +0000516 colon = buf + VG_(strlen)(buf) - 1;
517 while(*colon != ':') colon--;
518 VG_(strncpy_safely)(si->symtab[i].name, colon+1, len);
sewardjb5f6f512005-03-10 23:59:00 +0000519 VG_(arena_free)(VG_AR_SYMTAB, buf);
rjwalshe4e779d2004-04-16 23:02:29 +0000520 }
521 }
522
sewardjde4a1d02002-03-22 01:27:54 +0000523 cleanup_more:
524
525 /* If two symbols have identical address ranges, favour the
fitzhardinge98abfc72003-12-16 02:05:15 +0000526 one with the longer name (unless the extra length is junk)
sewardjde4a1d02002-03-22 01:27:54 +0000527 */
528 do {
529 n_merged = 0;
530 j = si->symtab_used;
531 si->symtab_used = 0;
532 for (i = 0; i < j; i++) {
533 if (i < j-1
534 && si->symtab[i].addr == si->symtab[i+1].addr
535 && si->symtab[i].size == si->symtab[i+1].size) {
536 n_merged++;
537 /* merge the two into one */
fitzhardinge1c76dc42003-12-15 09:00:21 +0000538 si->symtab[si->symtab_used++] = *prefersym(&si->symtab[i], &si->symtab[i+1]);
sewardjde4a1d02002-03-22 01:27:54 +0000539 i++;
540 } else {
541 si->symtab[si->symtab_used++] = si->symtab[i];
542 }
543 }
nethercote80f76782003-11-13 22:34:00 +0000544 TRACE_SYMTAB( "%d merged\n", n_merged);
sewardjde4a1d02002-03-22 01:27:54 +0000545 }
546 while (n_merged > 0);
547
548 /* Detect and "fix" overlapping address ranges. */
549 n_truncated = 0;
550
sewardj05bcdcb2003-05-18 10:05:38 +0000551 for (i = 0; i < ((Int)si->symtab_used) -1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000552
553 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
554
555 /* Check for common (no overlap) case. */
556 if (si->symtab[i].addr + si->symtab[i].size
557 <= si->symtab[i+1].addr)
558 continue;
559
560 /* There's an overlap. Truncate one or the other. */
561 if (VG_(clo_trace_symtab)) {
562 VG_(printf)("overlapping address ranges in symbol table\n\t");
563 printSym(si,i);
564 VG_(printf)("\t");
565 printSym(si,i+1);
566 VG_(printf)("\n");
567 }
568
569 /* Truncate one or the other. */
570 s1 = si->symtab[i].addr;
571 s2 = si->symtab[i+1].addr;
572 e1 = s1 + si->symtab[i].size - 1;
573 e2 = s2 + si->symtab[i+1].size - 1;
574 if (s1 < s2) {
575 e1 = s2-1;
576 } else {
577 vg_assert(s1 == s2);
578 if (e1 > e2) {
579 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
580 } else
581 if (e1 < e2) {
582 s2 = e1+1;
583 } else {
584 /* e1 == e2. Identical addr ranges. We'll eventually wind
585 up back at cleanup_more, which will take care of it. */
586 }
587 }
588 si->symtab[i].addr = s1;
589 si->symtab[i+1].addr = s2;
590 si->symtab[i].size = e1 - s1 + 1;
591 si->symtab[i+1].size = e2 - s2 + 1;
592 vg_assert(s1 <= s2);
593 vg_assert(si->symtab[i].size > 0);
594 vg_assert(si->symtab[i+1].size > 0);
595 /* It may be that the i+1 entry now needs to be moved further
596 along to maintain the address order requirement. */
597 j = i+1;
sewardj05bcdcb2003-05-18 10:05:38 +0000598 while (j < ((Int)si->symtab_used)-1
sewardjde4a1d02002-03-22 01:27:54 +0000599 && si->symtab[j].addr > si->symtab[j+1].addr) {
600 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
601 j++;
602 }
603 n_truncated++;
604 }
605
606 if (n_truncated > 0) goto cleanup_more;
607
608 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000609 for (i = 0; i < ((Int)si->symtab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000610 /* No zero-sized symbols. */
611 vg_assert(si->symtab[i].size > 0);
612 /* In order. */
613 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
614 /* No overlaps. */
615 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
616 < si->symtab[i+1].addr);
617 }
618# undef SWAP
619}
620
jsgfcb1d1c02003-10-14 21:55:10 +0000621/* Sort the scope range table by starting address. Mash the table
622 around so as to establish the property that addresses are in order
623 and the ranges do not overlap. This facilitates using binary
624 search to map addresses to scopes when we come to query the
625 table.
626*/
627static Int compare_ScopeRange(void *va, void *vb) {
628 ScopeRange *a = (ScopeRange *)va;
629 ScopeRange *b = (ScopeRange *)vb;
630
nethercote05fdfac2004-08-01 20:24:46 +0000631 if (a->addr < b->addr) return -1;
632 if (a->addr > b->addr) return 1;
633 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000634}
635
636static
637void canonicaliseScopetab ( SegInfo* si )
638{
639 Int i,j;
640
641 if (si->scopetab_used == 0)
642 return;
643
644 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000645 VG_(ssort)(si->scopetab, si->scopetab_used, sizeof(*si->scopetab),
646 compare_ScopeRange);
jsgfcb1d1c02003-10-14 21:55:10 +0000647
648 /* If two adjacent entries overlap, truncate the first. */
649 for (i = 0; i < si->scopetab_used-1; i++) {
650 if (si->scopetab[i].addr + si->scopetab[i].size > si->scopetab[i+1].addr) {
651 Int new_size = si->scopetab[i+1].addr - si->scopetab[i].addr;
652
653 if (new_size < 0)
654 si->scopetab[i].size = 0;
655 else
656 si->scopetab[i].size = new_size;
657 }
658 }
659
660 /* Zap any zero-sized entries resulting from the truncation
661 process. */
662 j = 0;
663 for (i = 0; i < si->scopetab_used; i++) {
664 if (si->scopetab[i].size > 0) {
665 si->scopetab[j] = si->scopetab[i];
666 j++;
667 }
668 }
669 si->scopetab_used = j;
670
671 /* Ensure relevant postconditions hold. */
672 for (i = 0; i < si->scopetab_used-1; i++) {
673 /*
674 VG_(printf)("%d (%d) %d 0x%x\n",
675 i, si->scopetab[i+1].confident,
676 si->scopetab[i+1].size, si->scopetab[i+1].addr );
677 */
678 /* No zero-sized symbols. */
679 vg_assert(si->scopetab[i].size > 0);
680 /* In order. */
681 if (si->scopetab[i].addr >= si->scopetab[i+1].addr)
682 VG_(printf)("si->scopetab[%d] = %p,size=%d [%d] = %p,size=%d\n",
683 i, si->scopetab[i].addr, si->scopetab[i].size,
684 i+1, si->scopetab[i+1].addr, si->scopetab[i+1].size);
685 vg_assert(si->scopetab[i].addr < si->scopetab[i+1].addr);
686 /* No overlaps. */
687 vg_assert(si->scopetab[i].addr + si->scopetab[i].size - 1
688 < si->scopetab[i+1].addr);
689 }
690}
sewardjde4a1d02002-03-22 01:27:54 +0000691
692
693/* Sort the location table by starting address. Mash the table around
694 so as to establish the property that addresses are in order and the
695 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000696 addresses to locations when we come to query the table.
697*/
jsgfcb1d1c02003-10-14 21:55:10 +0000698static Int compare_RiLoc(void *va, void *vb) {
699 RiLoc *a = (RiLoc *)va;
700 RiLoc *b = (RiLoc *)vb;
701
nethercote05fdfac2004-08-01 20:24:46 +0000702 if (a->addr < b->addr) return -1;
703 if (a->addr > b->addr) return 1;
704 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000705}
706
sewardjde4a1d02002-03-22 01:27:54 +0000707static
708void canonicaliseLoctab ( SegInfo* si )
709{
jsgfcb1d1c02003-10-14 21:55:10 +0000710 Int i, j;
sewardjde4a1d02002-03-22 01:27:54 +0000711
712# define SWAP(ty,aa,bb) \
713 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
714
jsgfcb1d1c02003-10-14 21:55:10 +0000715 if (si->loctab_used == 0)
716 return;
717
sewardjde4a1d02002-03-22 01:27:54 +0000718 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000719 VG_(ssort)(si->loctab, si->loctab_used, sizeof(*si->loctab), compare_RiLoc);
sewardjde4a1d02002-03-22 01:27:54 +0000720
721 /* If two adjacent entries overlap, truncate the first. */
sewardj05bcdcb2003-05-18 10:05:38 +0000722 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000723 vg_assert(si->loctab[i].size < 10000);
724 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
725 /* Do this in signed int32 because the actual .size fields
726 are unsigned 16s. */
727 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
728 if (new_size < 0) {
729 si->loctab[i].size = 0;
730 } else
731 if (new_size >= 65536) {
732 si->loctab[i].size = 65535;
733 } else {
734 si->loctab[i].size = (UShort)new_size;
735 }
736 }
737 }
738
739 /* Zap any zero-sized entries resulting from the truncation
740 process. */
741 j = 0;
sewardj05bcdcb2003-05-18 10:05:38 +0000742 for (i = 0; i < (Int)si->loctab_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000743 if (si->loctab[i].size > 0) {
744 si->loctab[j] = si->loctab[i];
745 j++;
746 }
747 }
748 si->loctab_used = j;
749
750 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000751 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000752 /*
753 VG_(printf)("%d (%d) %d 0x%x\n",
754 i, si->loctab[i+1].confident,
755 si->loctab[i+1].size, si->loctab[i+1].addr );
756 */
757 /* No zero-sized symbols. */
758 vg_assert(si->loctab[i].size > 0);
759 /* In order. */
760 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
761 /* No overlaps. */
762 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
763 < si->loctab[i+1].addr);
764 }
765# undef SWAP
766}
767
768
769/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000770/*--- Read info from a .so/exe file. ---*/
771/*------------------------------------------------------------*/
772
fitzhardinge98abfc72003-12-16 02:05:15 +0000773Bool VG_(is_object_file)(const void *buf)
774{
775 {
sewardj7a21c612005-02-18 09:38:08 +0000776 ElfXX_Ehdr *ehdr = (ElfXX_Ehdr *)buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000777 Int ok = 1;
778
779 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
780 && ehdr->e_ident[EI_MAG1] == 'E'
781 && ehdr->e_ident[EI_MAG2] == 'L'
782 && ehdr->e_ident[EI_MAG3] == 'F');
nethercotebdaa89f2004-10-09 19:08:08 +0000783 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
784 && ehdr->e_ident[EI_DATA] == VG_ELF_ENDIANNESS
fitzhardinge98abfc72003-12-16 02:05:15 +0000785 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
786 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
nethercotebdaa89f2004-10-09 19:08:08 +0000787 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
fitzhardinge98abfc72003-12-16 02:05:15 +0000788 ok &= (ehdr->e_version == EV_CURRENT);
789 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
790 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
791 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
792
793 if (ok)
794 return True;
795 }
796
797 /* other file formats here? */
798
799 return False;
800}
801
rjwalshe4e779d2004-04-16 23:02:29 +0000802/*
803 * Demangle an intercept symbol into library:func form
804 */
805
806static Bool
nethercoteb1e1ad42004-08-03 23:44:12 +0000807intercept_demangle(const Char* symbol, Char* result, Int nbytes)
rjwalshe4e779d2004-04-16 23:02:29 +0000808{
809 int i, j = 0;
810 int len = VG_(strlen)(symbol);
811
812 for(i = VG_INTERCEPT_PREFIX_LEN; i < len; i++) {
njnca0518d2004-11-26 19:34:36 +0000813 if(symbol[i] == 'J') {
rjwalshe4e779d2004-04-16 23:02:29 +0000814 i++;
njnca0518d2004-11-26 19:34:36 +0000815 vg_assert('J' != symbol[i]);
816 if((symbol[i] >= '0' && symbol[i] <= '9') ||
817 (symbol[i] >= 'a' && symbol[i] <= 'f') ||
818 (symbol[i] >= 'A' && symbol[i] <= 'F'))
819 {
rjwalshe4e779d2004-04-16 23:02:29 +0000820 int x = symbol[i++];
821 int y = symbol[i];
822 if(x >= '0' && x <= '9') {
823 x -= '0';
824 } else if(x >= 'a' && x <= 'f') {
825 x -= 'a';
826 } else if(x >= 'A' && x <= 'F') {
827 x -= 'A';
828 }
829 if(y >= '0' && y <= '9') {
830 y -= '0';
831 } else if(y >= 'a' && y <= 'f') {
832 y = y - 'a' + 10;
833 } else if(y >= 'A' && y <= 'F') {
834 y = y - 'A' + 10;
835 } else {
836 return False;
837 }
838 result[j] = (x << 4) | y;
839 } else {
840 return False;
841 }
842 } else {
843 result[j] = symbol[i];
844 }
845 if(j >= nbytes) {
846 result[j] = '\0';
847 return True;
848 }
849 j++;
850 }
851 result[j] = '\0';
852 return True;
853}
854
855static
sewardj7a21c612005-02-18 09:38:08 +0000856void handle_intercept( SegInfo* si, Char* symbol, ElfXX_Sym* sym)
rjwalshe4e779d2004-04-16 23:02:29 +0000857{
sewardjb5f6f512005-03-10 23:59:00 +0000858 Int len = VG_(strlen)(symbol) + 1 - VG_INTERCEPT_PREFIX_LEN;
859 Char *lib = VG_(arena_malloc)(VG_AR_SYMTAB, len);
rjwalshe4e779d2004-04-16 23:02:29 +0000860 Char *func;
861
nethercoteb1e1ad42004-08-03 23:44:12 +0000862 intercept_demangle(symbol, lib, len);
rjwalshe4e779d2004-04-16 23:02:29 +0000863 func = lib + VG_(strlen)(lib)-1;
864
865 while(*func != ':') func--;
866 *func = '\0';
867
sewardjb5f6f512005-03-10 23:59:00 +0000868 VG_(add_redirect_addr)(lib, func+1, si->offset + sym->st_value);
869 VG_(arena_free)(VG_AR_SYMTAB, lib);
rjwalshe4e779d2004-04-16 23:02:29 +0000870}
871
sewardjb5f6f512005-03-10 23:59:00 +0000872Bool VG_(resolve_redir_allsegs)(CodeRedirect *redir)
rjwalshe4e779d2004-04-16 23:02:29 +0000873{
sewardjb5f6f512005-03-10 23:59:00 +0000874 SegInfo *si;
875
876 for(si = segInfo; si != NULL; si = si->next)
877 if (VG_(resolve_redir)(redir, si))
878 return True;
879
880 return False;
rjwalshe4e779d2004-04-16 23:02:29 +0000881}
882
sewardjb5f6f512005-03-10 23:59:00 +0000883//static
884//void handle_wrapper( SegInfo* si, Char* symbol, ElfXX_Sym* sym)
885//{
886// if (VG_(strcmp)(symbol, STR(VG_WRAPPER(freeres))) == 0)
887// VGA_(intercept_libc_freeres_wrapper)((Addr)(si->offset + sym->st_value));
888// else if (VG_(strcmp)(symbol, STR(VG_WRAPPER(pthread_startfunc_wrapper))) == 0)
889// VG_(pthread_startfunc_wrapper)((Addr)(si->offset + sym->st_value));
890//}
891
nethercote80f76782003-11-13 22:34:00 +0000892/* Read a symbol table (normal or dynamic) */
893static
rjwalshe4e779d2004-04-16 23:02:29 +0000894void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts,
sewardj7a21c612005-02-18 09:38:08 +0000895 ElfXX_Sym* o_symtab, UInt o_symtab_sz,
nethercote80f76782003-11-13 22:34:00 +0000896 UChar* o_strtab, UInt o_strtab_sz )
897{
898 Int i;
899 Addr sym_addr;
900 RiSym risym;
mueller82df83e2003-11-19 22:05:35 +0000901 Char* t0;
902 Char* name;
903
nethercote80f76782003-11-13 22:34:00 +0000904 if (o_strtab == NULL || o_symtab == NULL) {
jseward0edbfb52003-12-12 06:22:06 +0000905 Char buf[80];
906 vg_assert(VG_(strlen)(tab_name) < 40);
907 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
908 VG_(symerr)(buf);
nethercote80f76782003-11-13 22:34:00 +0000909 return;
910 }
911
912 TRACE_SYMTAB("Reading %s (%d entries)\n", tab_name,
sewardj7a21c612005-02-18 09:38:08 +0000913 o_symtab_sz/sizeof(ElfXX_Sym) );
nethercote80f76782003-11-13 22:34:00 +0000914
915 /* Perhaps should start at i = 1; ELF docs suggest that entry
916 0 always denotes `unknown symbol'. */
sewardj7a21c612005-02-18 09:38:08 +0000917 for (i = 1; i < (Int)(o_symtab_sz/sizeof(ElfXX_Sym)); i++) {
918 ElfXX_Sym* sym = & o_symtab[i];
nethercote80f76782003-11-13 22:34:00 +0000919# if 1
920 sym_addr = si->offset + (UInt)sym->st_value;
921
922 if (VG_(clo_trace_symtab)) {
923 VG_(printf)("raw symbol [%d]: ", i);
sewardj7a21c612005-02-18 09:38:08 +0000924 switch (ELFXX_ST_BIND(sym->st_info)) {
nethercote80f76782003-11-13 22:34:00 +0000925 case STB_LOCAL: VG_(printf)("LOC "); break;
926 case STB_GLOBAL: VG_(printf)("GLO "); break;
927 case STB_WEAK: VG_(printf)("WEA "); break;
928 case STB_LOPROC: VG_(printf)("lop "); break;
929 case STB_HIPROC: VG_(printf)("hip "); break;
930 default: VG_(printf)("??? "); break;
931 }
sewardj7a21c612005-02-18 09:38:08 +0000932 switch (ELFXX_ST_TYPE(sym->st_info)) {
nethercote80f76782003-11-13 22:34:00 +0000933 case STT_NOTYPE: VG_(printf)("NOT "); break;
934 case STT_OBJECT: VG_(printf)("OBJ "); break;
935 case STT_FUNC: VG_(printf)("FUN "); break;
936 case STT_SECTION: VG_(printf)("SEC "); break;
937 case STT_FILE: VG_(printf)("FIL "); break;
938 case STT_LOPROC: VG_(printf)("lop "); break;
939 case STT_HIPROC: VG_(printf)("hip "); break;
940 default: VG_(printf)("??? "); break;
941 }
942 VG_(printf)(
943 ": value %p, size %d, name %s\n",
944 sym_addr, sym->st_size,
945 ( sym->st_name
946 ? ((Char*)o_strtab+sym->st_name)
947 : (Char*)"NONAME" ) );
948 }
949# endif
950
rjwalshe4e779d2004-04-16 23:02:29 +0000951 /*
952 * Is this symbol a magic valgrind-intercept symbol? If so,
953 * hand this off to the interceptinator.
954 */
955 if (do_intercepts) {
956 if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
957 VG_INTERCEPT_PREFIX,
958 VG_INTERCEPT_PREFIX_LEN) == 0) {
959 handle_intercept(si, (Char*)o_strtab+sym->st_name, sym);
sewardjb5f6f512005-03-10 23:59:00 +0000960 }
961 //else if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
962 // VG_WRAPPER_PREFIX,
963 // VG_WRAPPER_PREFIX_LEN) == 0) {
964 // handle_wrapper(si, (Char*)o_strtab+sym->st_name, sym);
965 //}
rjwalshe4e779d2004-04-16 23:02:29 +0000966 }
967
nethercote80f76782003-11-13 22:34:00 +0000968 /* Figure out if we're interested in the symbol.
969 Firstly, is it of the right flavour? */
sewardj7a21c612005-02-18 09:38:08 +0000970 if ( ! ( (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL ||
971 ELFXX_ST_BIND(sym->st_info) == STB_LOCAL ||
972 ELFXX_ST_BIND(sym->st_info) == STB_WEAK)
nethercote80f76782003-11-13 22:34:00 +0000973 &&
sewardj7a21c612005-02-18 09:38:08 +0000974 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC ||
nethercote80f76782003-11-13 22:34:00 +0000975 (VG_(needs).data_syms
sewardj7a21c612005-02-18 09:38:08 +0000976 && ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT))
nethercote80f76782003-11-13 22:34:00 +0000977 )
978 )
979 continue;
980
981 /* Secondly, if it's apparently in a GOT or PLT, it's really
982 a reference to a symbol defined elsewhere, so ignore it. */
983 if (si->got_start != 0
984 && sym_addr >= si->got_start
985 && sym_addr < si->got_start + si->got_size) {
986 TRACE_SYMTAB("in GOT: %s\n", o_strtab+sym->st_name);
987 continue;
988 }
989 if (si->plt_start != 0
990 && sym_addr >= si->plt_start
991 && sym_addr < si->plt_start + si->plt_size) {
992 TRACE_SYMTAB("in PLT: %s\n", o_strtab+sym->st_name);
993 continue;
994 }
995
996 /* Don't bother if nameless, or zero-sized. */
sewardj7a21c612005-02-18 09:38:08 +0000997 if (sym->st_name == (ElfXX_Word)NULL
nethercote80f76782003-11-13 22:34:00 +0000998 || /* VG_(strlen)(o_strtab+sym->st_name) == 0 */
999 /* equivalent but cheaper ... */
1000 * ((UChar*)(o_strtab+sym->st_name)) == 0
1001 || sym->st_size == 0) {
1002 TRACE_SYMTAB("size=0: %s\n", o_strtab+sym->st_name);
1003 continue;
1004 }
1005
1006# if 0
1007 /* Avoid _dl_ junk. (Why?) */
1008 /* 01-02-24: disabled until I find out if it really helps. */
1009 if (VG_(strncmp)("_dl_", o_strtab+sym->st_name, 4) == 0
1010 || VG_(strncmp)("_r_debug",
1011 o_strtab+sym->st_name, 8) == 0) {
1012 TRACE_SYMTAB("_dl_ junk: %s\n", o_strtab+sym->st_name);
1013 continue;
1014 }
1015# endif
1016
1017 /* This seems to significantly reduce the number of junk
1018 symbols, and particularly reduces the number of
1019 overlapping address ranges. Don't ask me why ... */
1020 if ((Int)sym->st_value == 0) {
1021 TRACE_SYMTAB( "valu=0: %s\n", o_strtab+sym->st_name);
1022 continue;
1023 }
1024
1025 /* If no part of the symbol falls within the mapped range,
1026 ignore it. */
1027 if (sym_addr+sym->st_size <= si->start
1028 || sym_addr >= si->start+si->size) {
1029 TRACE_SYMTAB( "outside mapped range" );
1030 continue;
1031 }
1032
1033 /* If we reach here, it's an interesting symbol; record it. */
mueller82df83e2003-11-19 22:05:35 +00001034 t0 = sym->st_name
nethercote80f76782003-11-13 22:34:00 +00001035 ? (Char*)(o_strtab+sym->st_name)
1036 : (Char*)"NONAME";
mueller82df83e2003-11-19 22:05:35 +00001037 name = VG_(addStr) ( si, t0, -1 );
nethercote80f76782003-11-13 22:34:00 +00001038 vg_assert(name != NULL
1039 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
nethercote80f76782003-11-13 22:34:00 +00001040 /* VG_(printf)("%p + %d: %p %s\n", si->start,
1041 (Int)sym->st_value, sym_addr, t0 ); */
1042 risym.addr = sym_addr;
1043 risym.size = sym->st_size;
1044 risym.name = name;
1045 addSym ( si, &risym );
1046 }
1047}
1048
thughesc035bd92004-06-13 09:59:02 +00001049/*
1050 * This routine for calculating the CRC for a separate debug file
1051 * is GPLed code borrowed from binutils.
1052 */
1053static UInt
1054calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
1055{
1056 static const UInt crc32_table[256] =
1057 {
1058 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1059 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1060 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1061 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1062 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1063 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1064 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1065 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1066 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1067 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1068 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1069 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1070 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1071 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1072 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1073 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1074 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1075 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1076 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1077 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1078 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1079 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1080 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1081 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1082 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1083 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1084 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1085 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1086 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1087 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1088 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1089 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1090 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1091 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1092 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1093 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1094 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1095 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1096 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1097 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1098 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1099 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1100 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1101 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1102 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1103 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1104 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1105 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1106 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1107 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1108 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1109 0x2d02ef8d
1110 };
1111 const UChar *end;
1112
1113 crc = ~crc & 0xffffffff;
1114 for (end = buf + len; buf < end; ++ buf)
1115 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1116 return ~crc & 0xffffffff;;
1117}
1118
1119/*
1120 * Try and open a separate debug file, ignoring any where the CRC does
1121 * not match the value from the main object file.
1122 */
1123static
1124Addr open_debug_file( Char* name, UInt crc, UInt* size )
1125{
1126 Int fd;
1127 struct vki_stat stat_buf;
1128 Addr addr;
sewardjb5f6f512005-03-10 23:59:00 +00001129 UInt calccrc;
thughesc035bd92004-06-13 09:59:02 +00001130
1131 if ((fd = VG_(open)(name, VKI_O_RDONLY, 0)) < 0)
1132 return 0;
1133
1134 if (VG_(fstat)(fd, &stat_buf) != 0) {
1135 VG_(close)(fd);
1136 return 0;
1137 }
1138
sewardjb5f6f512005-03-10 23:59:00 +00001139 if (VG_(clo_verbosity) > 1)
1140 VG_(message)(Vg_UserMsg, "Reading debug info from %s...", name);
1141
thughesc035bd92004-06-13 09:59:02 +00001142 *size = stat_buf.st_size;
1143
1144 if ((addr = (Addr)VG_(mmap)(NULL, *size, VKI_PROT_READ,
nethercoteb4250ae2004-07-10 16:50:09 +00001145 VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1146 0, fd, 0)) == (Addr)-1)
1147 {
thughesc035bd92004-06-13 09:59:02 +00001148 VG_(close)(fd);
1149 return 0;
1150 }
1151
1152 VG_(close)(fd);
1153
sewardjb5f6f512005-03-10 23:59:00 +00001154 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)addr, *size);
1155 if (calccrc != crc) {
nethercotee567e702004-07-10 17:49:17 +00001156 int res = VG_(munmap)((void*)addr, *size);
1157 vg_assert(0 == res);
sewardjb5f6f512005-03-10 23:59:00 +00001158 if (VG_(clo_verbosity) > 1)
1159 VG_(message)(Vg_UserMsg, "... CRC mismatch (computed %08x wanted %08x)", calccrc, crc);
thughesc035bd92004-06-13 09:59:02 +00001160 return 0;
1161 }
1162
1163 return addr;
1164}
1165
1166/*
nethercoteb1e1ad42004-08-03 23:44:12 +00001167 * Try to find a separate debug file for a given object file.
thughesc035bd92004-06-13 09:59:02 +00001168 */
1169static
1170Addr find_debug_file( Char* objpath, Char* debugname, UInt crc, UInt* size )
1171{
sewardjb5f6f512005-03-10 23:59:00 +00001172 Char *objdir = VG_(arena_strdup)(VG_AR_SYMTAB, objpath);
thughesc035bd92004-06-13 09:59:02 +00001173 Char *objdirptr;
1174 Char *debugpath;
1175 Addr addr = 0;
1176
1177 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1178 *objdirptr = '\0';
1179
sewardjb5f6f512005-03-10 23:59:00 +00001180 debugpath = VG_(arena_malloc)(VG_AR_SYMTAB, VG_(strlen)(objdir) + VG_(strlen)(debugname) + 16);
thughesc035bd92004-06-13 09:59:02 +00001181
1182 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1183
1184 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1185 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1186 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1187 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1188 addr = open_debug_file(debugpath, crc, size);
1189 }
1190 }
1191
sewardjb5f6f512005-03-10 23:59:00 +00001192 VG_(arena_free)(VG_AR_SYMTAB, debugpath);
1193 VG_(arena_free)(VG_AR_SYMTAB, objdir);
thughesc035bd92004-06-13 09:59:02 +00001194
1195 return addr;
1196}
nethercote80f76782003-11-13 22:34:00 +00001197
sewardjde4a1d02002-03-22 01:27:54 +00001198/* Read the symbols from the object/exe specified by the SegInfo into
1199 the tables within the supplied SegInfo. */
1200static
sewardj8fe15a32002-10-20 19:29:21 +00001201Bool vg_read_lib_symbols ( SegInfo* si )
sewardjde4a1d02002-03-22 01:27:54 +00001202{
nethercote80f76782003-11-13 22:34:00 +00001203 Bool res;
sewardj7a21c612005-02-18 09:38:08 +00001204 ElfXX_Ehdr* ehdr; /* The ELF header */
1205 ElfXX_Shdr* shdr; /* The section table */
sewardjde4a1d02002-03-22 01:27:54 +00001206 UChar* sh_strtab; /* The section table's string table */
sewardjde4a1d02002-03-22 01:27:54 +00001207 Int fd;
1208 Int i;
1209 Bool ok;
1210 Addr oimage;
sewardj05bcdcb2003-05-18 10:05:38 +00001211 UInt n_oimage;
thughesc035bd92004-06-13 09:59:02 +00001212 Addr dimage = 0;
1213 UInt n_dimage = 0;
sewardjb3586202002-05-09 17:38:13 +00001214 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001215
sewardjde4a1d02002-03-22 01:27:54 +00001216 oimage = (Addr)NULL;
1217 if (VG_(clo_verbosity) > 1)
fitzhardinge98abfc72003-12-16 02:05:15 +00001218 VG_(message)(Vg_UserMsg, "Reading syms from %s (%p)", si->filename, si->start );
sewardjde4a1d02002-03-22 01:27:54 +00001219
1220 /* mmap the object image aboard, so that we can read symbols and
1221 line number info out of it. It will be munmapped immediately
1222 thereafter; it is only aboard transiently. */
1223
sewardjb3586202002-05-09 17:38:13 +00001224 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001225 if (i != 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00001226 VG_(symerr)("Can't stat .so/.exe (to determine its size)?!");
sewardj8fe15a32002-10-20 19:29:21 +00001227 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001228 }
1229 n_oimage = stat_buf.st_size;
1230
njn25e49d8e72002-09-23 09:36:25 +00001231 fd = VG_(open)(si->filename, VKI_O_RDONLY, 0);
jsgff3c3f1a2003-10-14 22:13:28 +00001232 if (fd < 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00001233 VG_(symerr)("Can't open .so/.exe to read symbols?!");
sewardj8fe15a32002-10-20 19:29:21 +00001234 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001235 }
1236
sewardjb3586202002-05-09 17:38:13 +00001237 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
nethercoteb4250ae2004-07-10 16:50:09 +00001238 VKI_PROT_READ, VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1239 0, fd, 0 );
fitzhardinge98abfc72003-12-16 02:05:15 +00001240
nethercote80f76782003-11-13 22:34:00 +00001241 VG_(close)(fd);
1242
sewardjde4a1d02002-03-22 01:27:54 +00001243 if (oimage == ((Addr)(-1))) {
1244 VG_(message)(Vg_UserMsg,
nethercote132be6f2004-06-27 12:30:15 +00001245 "warning: mmap failed on %s", si->filename );
1246 VG_(message)(Vg_UserMsg,
1247 " no symbols or debug info loaded" );
sewardj8fe15a32002-10-20 19:29:21 +00001248 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001249 }
1250
sewardjde4a1d02002-03-22 01:27:54 +00001251 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1252 Now verify that it is a valid ELF .so or executable image.
1253 */
nethercote80f76782003-11-13 22:34:00 +00001254 res = False;
sewardj7a21c612005-02-18 09:38:08 +00001255 ok = (n_oimage >= sizeof(ElfXX_Ehdr));
1256 ehdr = (ElfXX_Ehdr*)oimage;
sewardjde4a1d02002-03-22 01:27:54 +00001257
fitzhardinge98abfc72003-12-16 02:05:15 +00001258 if (ok)
1259 ok &= VG_(is_object_file)(ehdr);
sewardjde4a1d02002-03-22 01:27:54 +00001260
1261 if (!ok) {
jsgfcb1d1c02003-10-14 21:55:10 +00001262 VG_(symerr)("Invalid ELF header, or missing stringtab/sectiontab.");
nethercote80f76782003-11-13 22:34:00 +00001263 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001264 }
1265
1266 /* Walk the LOAD headers in the phdr and update the SegInfo to
1267 include them all, so that this segment also contains data and
1268 bss memory. Also computes correct symbol offset value for this
1269 ELF file. */
sewardj7a21c612005-02-18 09:38:08 +00001270 if (ehdr->e_phoff + ehdr->e_phnum*sizeof(ElfXX_Phdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001271 VG_(symerr)("ELF program header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001272 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001273 }
1274 {
1275 Bool offset_set = False;
sewardj7a21c612005-02-18 09:38:08 +00001276 ElfXX_Addr prev_addr = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001277 Addr baseaddr = 0;
sewardj8fe15a32002-10-20 19:29:21 +00001278
1279 si->offset = 0;
1280
nethercote80f76782003-11-13 22:34:00 +00001281 for (i = 0; i < ehdr->e_phnum; i++) {
sewardj7a21c612005-02-18 09:38:08 +00001282 ElfXX_Phdr *o_phdr;
1283 ElfXX_Addr mapped, mapped_end;
sewardj8fe15a32002-10-20 19:29:21 +00001284
sewardj7a21c612005-02-18 09:38:08 +00001285 o_phdr = &((ElfXX_Phdr *)(oimage + ehdr->e_phoff))[i];
sewardj8fe15a32002-10-20 19:29:21 +00001286
fitzhardinge98abfc72003-12-16 02:05:15 +00001287 if (o_phdr->p_type == PT_DYNAMIC && si->soname == NULL) {
sewardj7a21c612005-02-18 09:38:08 +00001288 const ElfXX_Dyn *dyn = (const ElfXX_Dyn *)(oimage + o_phdr->p_offset);
fitzhardinge98abfc72003-12-16 02:05:15 +00001289 Int stroff = -1;
1290 Char *strtab = NULL;
1291 Int j;
1292
1293 for(j = 0; dyn[j].d_tag != DT_NULL; j++) {
1294 switch(dyn[j].d_tag) {
1295 case DT_SONAME:
1296 stroff = dyn[j].d_un.d_val;
1297 break;
1298
1299 case DT_STRTAB:
1300 strtab = (Char *)oimage + dyn[j].d_un.d_ptr - baseaddr;
1301 break;
1302 }
1303 }
1304
1305 if (stroff != -1 && strtab != 0) {
1306 TRACE_SYMTAB("soname=%s\n", strtab+stroff);
1307 si->soname = VG_(arena_strdup)(VG_AR_SYMTAB, strtab+stroff);
1308 }
1309 }
1310
sewardj8fe15a32002-10-20 19:29:21 +00001311 if (o_phdr->p_type != PT_LOAD)
1312 continue;
1313
1314 if (!offset_set) {
1315 offset_set = True;
1316 si->offset = si->start - o_phdr->p_vaddr;
fitzhardinge98abfc72003-12-16 02:05:15 +00001317 baseaddr = o_phdr->p_vaddr;
sewardj8fe15a32002-10-20 19:29:21 +00001318 }
1319
1320 if (o_phdr->p_vaddr < prev_addr) {
jsgfcb1d1c02003-10-14 21:55:10 +00001321 VG_(symerr)("ELF Phdrs are out of order!?");
nethercote80f76782003-11-13 22:34:00 +00001322 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001323 }
1324 prev_addr = o_phdr->p_vaddr;
1325
1326 mapped = o_phdr->p_vaddr + si->offset;
1327 mapped_end = mapped + o_phdr->p_memsz;
1328
1329 if (si->data_start == 0 &&
1330 (o_phdr->p_flags & (PF_R|PF_W|PF_X)) == (PF_R|PF_W)) {
1331 si->data_start = mapped;
1332 si->data_size = o_phdr->p_filesz;
1333 si->bss_start = mapped + o_phdr->p_filesz;
1334 if (o_phdr->p_memsz > o_phdr->p_filesz)
1335 si->bss_size = o_phdr->p_memsz - o_phdr->p_filesz;
1336 else
1337 si->bss_size = 0;
1338 }
1339
nethercote73b526f2004-10-31 18:48:21 +00001340 mapped = mapped & ~(VKI_PAGE_SIZE-1);
1341 mapped_end = (mapped_end + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE-1);
sewardj8fe15a32002-10-20 19:29:21 +00001342
sewardj1024cf72005-02-28 14:39:21 +00001343#if 0
1344 /* 20050228: disabled this until VG_(next_segment) can be
1345 reinstated in some clean incarnation of the low level
1346 memory manager. */
sewardj8fe15a32002-10-20 19:29:21 +00001347 if (VG_(needs).data_syms &&
1348 (mapped >= si->start && mapped <= (si->start+si->size)) &&
1349 (mapped_end > (si->start+si->size))) {
1350 UInt newsz = mapped_end - si->start;
1351 if (newsz > si->size) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001352 Segment *seg;
1353
sewardj8fe15a32002-10-20 19:29:21 +00001354 if (0)
1355 VG_(printf)("extending mapping %p..%p %d -> ..%p %d\n",
1356 si->start, si->start+si->size, si->size,
1357 si->start+newsz, newsz);
fitzhardinge98abfc72003-12-16 02:05:15 +00001358
sewardjb5f6f512005-03-10 23:59:00 +00001359 for(seg = VG_(find_segment_containing)(si->start);
fitzhardinge98abfc72003-12-16 02:05:15 +00001360 seg != NULL && VG_(seg_overlaps)(seg, si->start, si->size);
1361 seg = VG_(next_segment)(seg)) {
1362 if (seg->symtab == si)
1363 continue;
1364
1365 if (seg->symtab != NULL)
nethercote8991d5a2004-11-03 17:07:46 +00001366 VG_(symtab_decref)(seg->symtab, seg->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001367
1368 VG_(symtab_incref)(si);
1369 seg->symtab = si;
1370
1371 if (0)
1372 VG_(printf)("adding symtab %p (%p-%p) to segment %p (%p-%p)\n",
1373 si, si->start, si->start+newsz,
1374 seg, seg->addr, seg->addr+seg->len);
1375 }
1376
sewardj8fe15a32002-10-20 19:29:21 +00001377 si->size = newsz;
1378 }
1379 }
sewardj1024cf72005-02-28 14:39:21 +00001380#endif
1381
sewardj8fe15a32002-10-20 19:29:21 +00001382 }
sewardjde4a1d02002-03-22 01:27:54 +00001383 }
1384
nethercote80f76782003-11-13 22:34:00 +00001385 TRACE_SYMTAB("shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
sewardj7a21c612005-02-18 09:38:08 +00001386 ehdr->e_shoff, ehdr->e_shnum, sizeof(ElfXX_Shdr), n_oimage );
sewardjde4a1d02002-03-22 01:27:54 +00001387
sewardj7a21c612005-02-18 09:38:08 +00001388 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(ElfXX_Shdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001389 VG_(symerr)("ELF section header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001390 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001391 }
1392
sewardj7a21c612005-02-18 09:38:08 +00001393 shdr = (ElfXX_Shdr*)(oimage + ehdr->e_shoff);
sewardjde4a1d02002-03-22 01:27:54 +00001394 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1395
nethercote80f76782003-11-13 22:34:00 +00001396 /* Find interesting sections, read the symbol table(s), read any debug
1397 information */
sewardjde4a1d02002-03-22 01:27:54 +00001398 {
nethercote80f76782003-11-13 22:34:00 +00001399 /* Pointers to start of sections */
1400 UChar* o_strtab = NULL; /* .strtab */
sewardj7a21c612005-02-18 09:38:08 +00001401 ElfXX_Sym* o_symtab = NULL; /* .symtab */
nethercote80f76782003-11-13 22:34:00 +00001402 UChar* o_dynstr = NULL; /* .dynstr */
sewardj7a21c612005-02-18 09:38:08 +00001403 ElfXX_Sym* o_dynsym = NULL; /* .dynsym */
thughesc035bd92004-06-13 09:59:02 +00001404 Char* debuglink = NULL; /* .gnu_debuglink */
nethercote80f76782003-11-13 22:34:00 +00001405 UChar* stab = NULL; /* .stab (stabs) */
1406 UChar* stabstr = NULL; /* .stabstr (stabs) */
1407 UChar* debug_line = NULL; /* .debug_line (dwarf2) */
jseward8b3131a2003-12-13 23:16:26 +00001408 UChar* dwarf1d = NULL; /* .debug (dwarf1) */
1409 UChar* dwarf1l = NULL; /* .line (dwarf1) */
sewardjde4a1d02002-03-22 01:27:54 +00001410
nethercote80f76782003-11-13 22:34:00 +00001411 /* Section sizes, in bytes */
1412 UInt o_strtab_sz = 0;
1413 UInt o_symtab_sz = 0;
1414 UInt o_dynstr_sz = 0;
1415 UInt o_dynsym_sz = 0;
thughesc035bd92004-06-13 09:59:02 +00001416 UInt debuglink_sz = 0;
nethercote80f76782003-11-13 22:34:00 +00001417 UInt stab_sz = 0;
1418 UInt stabstr_sz = 0;
1419 UInt debug_line_sz = 0;
jseward8b3131a2003-12-13 23:16:26 +00001420 UInt dwarf1d_sz = 0;
1421 UInt dwarf1l_sz = 0;
1422
1423 Bool has_debuginfo = False;
sewardjde4a1d02002-03-22 01:27:54 +00001424
nethercote80f76782003-11-13 22:34:00 +00001425 /* Find all interesting sections */
sewardjde4a1d02002-03-22 01:27:54 +00001426 for (i = 0; i < ehdr->e_shnum; i++) {
jseward8b3131a2003-12-13 23:16:26 +00001427# define FIND(sec_name, sec_data, sec_size, in_exec, type) \
nethercote80f76782003-11-13 22:34:00 +00001428 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1429 if (0 != sec_data) \
1430 VG_(core_panic)("repeated section!\n"); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001431 if (in_exec) \
nethercote80f76782003-11-13 22:34:00 +00001432 sec_data = (type)(si->offset + shdr[i].sh_addr); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001433 else \
nethercote80f76782003-11-13 22:34:00 +00001434 sec_data = (type)(oimage + shdr[i].sh_offset); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001435 sec_size = shdr[i].sh_size; \
nethercote80f76782003-11-13 22:34:00 +00001436 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1437 sec_name, sec_data, sec_data + sec_size - 1); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001438 if ( shdr[i].sh_offset + sec_size > n_oimage ) { \
nethercote80f76782003-11-13 22:34:00 +00001439 VG_(symerr)(" section beyond image end?!"); \
1440 goto out; \
1441 } \
sewardjde4a1d02002-03-22 01:27:54 +00001442 }
1443
nethercote80f76782003-11-13 22:34:00 +00001444 /* Nb: must find where .got and .plt sections will be in the
1445 * executable image, not in the object image transiently loaded. */
sewardj7a21c612005-02-18 09:38:08 +00001446 FIND(".dynsym", o_dynsym, o_dynsym_sz, 0, ElfXX_Sym*)
nethercote80f76782003-11-13 22:34:00 +00001447 else FIND(".dynstr", o_dynstr, o_dynstr_sz, 0, UChar*)
sewardj7a21c612005-02-18 09:38:08 +00001448 else FIND(".symtab", o_symtab, o_symtab_sz, 0, ElfXX_Sym*)
nethercote80f76782003-11-13 22:34:00 +00001449 else FIND(".strtab", o_strtab, o_strtab_sz, 0, UChar*)
sewardjde4a1d02002-03-22 01:27:54 +00001450
thughesc035bd92004-06-13 09:59:02 +00001451 else FIND(".gnu_debuglink", debuglink, debuglink_sz, 0, Char*)
1452
nethercote80f76782003-11-13 22:34:00 +00001453 else FIND(".stab", stab, stab_sz, 0, UChar*)
1454 else FIND(".stabstr", stabstr, stabstr_sz, 0, UChar*)
1455 else FIND(".debug_line", debug_line, debug_line_sz, 0, UChar*)
jseward8b3131a2003-12-13 23:16:26 +00001456 else FIND(".debug", dwarf1d, dwarf1d_sz, 0, UChar*)
1457 else FIND(".line", dwarf1l, dwarf1l_sz, 0, UChar*)
nethercote80f76782003-11-13 22:34:00 +00001458
1459 else FIND(".got", si->got_start, si->got_size, 1, Addr)
1460 else FIND(".plt", si->plt_start, si->plt_size, 1, Addr)
1461
jseward8b3131a2003-12-13 23:16:26 +00001462# undef FIND
nethercote80f76782003-11-13 22:34:00 +00001463
1464 /* Check some sizes */
sewardj7a21c612005-02-18 09:38:08 +00001465 vg_assert((o_dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1466 vg_assert((o_symtab_sz % sizeof(ElfXX_Sym)) == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001467 }
1468
rjwalshe4e779d2004-04-16 23:02:29 +00001469 read_symtab(si, "symbol table", False,
nethercote80f76782003-11-13 22:34:00 +00001470 o_symtab, o_symtab_sz,
1471 o_strtab, o_strtab_sz);
sewardjde4a1d02002-03-22 01:27:54 +00001472
rjwalshe4e779d2004-04-16 23:02:29 +00001473 read_symtab(si, "dynamic symbol table", True,
nethercote80f76782003-11-13 22:34:00 +00001474 o_dynsym, o_dynsym_sz,
1475 o_dynstr, o_dynstr_sz);
sewardj9b81a422003-04-26 21:42:09 +00001476
thughesc035bd92004-06-13 09:59:02 +00001477 /* Did we find a debuglink section? */
1478 if (debuglink != NULL) {
sewardjb5f6f512005-03-10 23:59:00 +00001479 UInt crc_offset = ROUNDUP(VG_(strlen)(debuglink)+1, 4);
thughesc035bd92004-06-13 09:59:02 +00001480 UInt crc;
1481
1482 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1483
1484 /* Extract the CRC from the debuglink section */
1485 crc = *(UInt *)(debuglink + crc_offset);
1486
1487 /* See if we can find a matching debug file */
1488 if ((dimage = find_debug_file(si->filename, debuglink, crc, &n_dimage)) != 0) {
sewardj7a21c612005-02-18 09:38:08 +00001489 ehdr = (ElfXX_Ehdr*)dimage;
thughesc035bd92004-06-13 09:59:02 +00001490
sewardj7a21c612005-02-18 09:38:08 +00001491 if (n_dimage >= sizeof(ElfXX_Ehdr) && VG_(is_object_file)(ehdr))
thughesc035bd92004-06-13 09:59:02 +00001492 {
sewardj7a21c612005-02-18 09:38:08 +00001493 shdr = (ElfXX_Shdr*)(dimage + ehdr->e_shoff);
thughesc035bd92004-06-13 09:59:02 +00001494 sh_strtab = (UChar*)(dimage + shdr[ehdr->e_shstrndx].sh_offset);
1495
1496 /* Find all interesting sections */
1497 for (i = 0; i < ehdr->e_shnum; i++) {
1498# define FIND(sec_name, sec_data, sec_size, type) \
1499 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1500 if (0 != sec_data) \
1501 VG_(core_panic)("repeated section!\n"); \
1502 sec_data = (type)(dimage + shdr[i].sh_offset); \
1503 sec_size = shdr[i].sh_size; \
1504 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1505 sec_name, sec_data, sec_data + sec_size - 1); \
1506 if ( shdr[i].sh_offset + sec_size > n_dimage ) { \
1507 VG_(symerr)(" section beyond image end?!"); \
1508 goto out; \
1509 } \
1510 }
1511
1512 /* Nb: must find where .got and .plt sections will be in the
1513 * executable image, not in the object image transiently loaded. */
1514 FIND(".stab", stab, stab_sz, UChar*)
1515 else FIND(".stabstr", stabstr, stabstr_sz, UChar*)
1516 else FIND(".debug_line", debug_line, debug_line_sz, UChar*)
1517 else FIND(".debug", dwarf1d, dwarf1d_sz, UChar*)
1518 else FIND(".line", dwarf1l, dwarf1l_sz, UChar*)
1519
1520# undef FIND
1521
1522 /* Check some sizes */
sewardj7a21c612005-02-18 09:38:08 +00001523 vg_assert((o_dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1524 vg_assert((o_symtab_sz % sizeof(ElfXX_Sym)) == 0);
thughesc035bd92004-06-13 09:59:02 +00001525 }
1526 }
1527 }
1528 }
1529
nethercote80f76782003-11-13 22:34:00 +00001530 /* Read the stabs and/or dwarf2 debug information, if any. */
1531 if (stab != NULL && stabstr != NULL) {
jseward8b3131a2003-12-13 23:16:26 +00001532 has_debuginfo = True;
1533 VG_(read_debuginfo_stabs) ( si, stab, stab_sz,
1534 stabstr, stabstr_sz );
1535 }
sewardj7a21c612005-02-18 09:38:08 +00001536 if (debug_line && VGA_WORD_SIZE==4/*hack*/) {
jseward8b3131a2003-12-13 23:16:26 +00001537 has_debuginfo = True;
nethercote80f76782003-11-13 22:34:00 +00001538 VG_(read_debuginfo_dwarf2) ( si, debug_line, debug_line_sz );
jseward8b3131a2003-12-13 23:16:26 +00001539 }
1540 if (dwarf1d && dwarf1l) {
1541 has_debuginfo = True;
1542 VG_(read_debuginfo_dwarf1) ( si, dwarf1d, dwarf1d_sz,
1543 dwarf1l, dwarf1l_sz );
1544 }
1545 if (!has_debuginfo) {
nethercote80f76782003-11-13 22:34:00 +00001546 VG_(symerr)(" object doesn't have any debug info");
1547 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001548 }
1549 }
nethercote80f76782003-11-13 22:34:00 +00001550 res = True;
sewardjde4a1d02002-03-22 01:27:54 +00001551
nethercotee567e702004-07-10 17:49:17 +00001552 out: {
1553 Int m_res;
thughesc035bd92004-06-13 09:59:02 +00001554 /* Last, but not least, heave the image(s) back overboard. */
nethercotee567e702004-07-10 17:49:17 +00001555 if (dimage) {
1556 m_res = VG_(munmap) ( (void*)dimage, n_dimage );
1557 vg_assert(0 == m_res);
1558 }
1559 m_res = VG_(munmap) ( (void*)oimage, n_oimage );
1560 vg_assert(0 == m_res);
nethercote80f76782003-11-13 22:34:00 +00001561 return res;
nethercotee567e702004-07-10 17:49:17 +00001562 }
sewardjde4a1d02002-03-22 01:27:54 +00001563}
1564
sewardjde4a1d02002-03-22 01:27:54 +00001565/*------------------------------------------------------------*/
1566/*--- Main entry point for symbols table reading. ---*/
1567/*------------------------------------------------------------*/
1568
1569/* The root structure for the entire symbol table system. It is a
1570 linked list of SegInfos. Note that this entire mechanism assumes
1571 that what we read from /proc/self/maps doesn't contain overlapping
1572 address ranges, and as a result the SegInfos in this list describe
1573 disjoint address ranges.
1574*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001575SegInfo *VG_(read_seg_symbols) ( Segment *seg )
sewardjde4a1d02002-03-22 01:27:54 +00001576{
1577 SegInfo* si;
1578
fitzhardinge98abfc72003-12-16 02:05:15 +00001579 vg_assert(seg->symtab == NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001580
njnfa1016e2003-09-25 17:54:11 +00001581 VGP_PUSHCC(VgpReadSyms);
1582
sewardjde4a1d02002-03-22 01:27:54 +00001583 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001584 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001585
sewardj8fe15a32002-10-20 19:29:21 +00001586 VG_(memset)(si, 0, sizeof(*si));
fitzhardinge98abfc72003-12-16 02:05:15 +00001587 si->start = seg->addr;
1588 si->size = seg->len;
1589 si->foffset = seg->offset;
fitzhardinge1a4adf02003-12-22 10:42:59 +00001590 si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00001591
1592 si->ref = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001593
1594 si->symtab = NULL;
1595 si->symtab_size = si->symtab_used = 0;
1596 si->loctab = NULL;
1597 si->loctab_size = si->loctab_used = 0;
jsgfcb1d1c02003-10-14 21:55:10 +00001598 si->strchunks = NULL;
1599 si->scopetab = NULL;
1600 si->scopetab_size = si->scopetab_used = 0;
1601
fitzhardinge98abfc72003-12-16 02:05:15 +00001602 si->seg = seg;
1603
jsgfcb1d1c02003-10-14 21:55:10 +00001604 si->stab_typetab = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001605
nethercote80f76782003-11-13 22:34:00 +00001606 si->plt_start = si->plt_size = 0;
1607 si->got_start = si->got_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001608 si->data_start = si->data_size = 0;
nethercote80f76782003-11-13 22:34:00 +00001609 si->bss_start = si->bss_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001610
sewardjde4a1d02002-03-22 01:27:54 +00001611 /* And actually fill it up. */
sewardj8fe15a32002-10-20 19:29:21 +00001612 if (!vg_read_lib_symbols ( si ) && 0) {
1613 /* XXX this interacts badly with the prevN optimization in
1614 addStr(). Since this frees the si, the si pointer value can
1615 be recycled, which confuses the curr_si == si test. For now,
1616 this code is disabled, and everything is included in the
1617 segment list, even if it is a bad ELF file. Ironically,
1618 running this under valgrind itself hides the problem, because
1619 it doesn't recycle pointers... */
1620 freeSegInfo( si );
1621 } else {
1622 si->next = segInfo;
1623 segInfo = si;
1624
1625 canonicaliseSymtab ( si );
1626 canonicaliseLoctab ( si );
jsgfcb1d1c02003-10-14 21:55:10 +00001627 canonicaliseScopetab ( si );
fitzhardinge98abfc72003-12-16 02:05:15 +00001628
1629 /* do redirects */
sewardjb5f6f512005-03-10 23:59:00 +00001630 VG_(resolve_seg_redirs)( si );
sewardj8fe15a32002-10-20 19:29:21 +00001631 }
njnfa1016e2003-09-25 17:54:11 +00001632 VGP_POPCC(VgpReadSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001633
1634 return si;
sewardjde4a1d02002-03-22 01:27:54 +00001635}
1636
1637
sewardjde4a1d02002-03-22 01:27:54 +00001638/* When an munmap() call happens, check to see whether it corresponds
1639 to a segment for a .so, and if so discard the relevant SegInfo.
1640 This might not be a very clever idea from the point of view of
1641 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001642 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001643*/
nethercote928a5f72004-11-03 18:10:37 +00001644static void unload_symbols ( Addr start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +00001645{
1646 SegInfo *prev, *curr;
1647
sewardjde4a1d02002-03-22 01:27:54 +00001648 prev = NULL;
1649 curr = segInfo;
1650 while (True) {
1651 if (curr == NULL) break;
1652 if (start == curr->start) break;
1653 prev = curr;
1654 curr = curr->next;
1655 }
njnfa1016e2003-09-25 17:54:11 +00001656 if (curr == NULL) {
1657 VGP_POPCC(VgpReadSyms);
njn25e49d8e72002-09-23 09:36:25 +00001658 return;
njnfa1016e2003-09-25 17:54:11 +00001659 }
sewardjde4a1d02002-03-22 01:27:54 +00001660
mueller75c0ed62003-11-19 00:47:00 +00001661 if (VG_(clo_verbosity) > 1)
1662 VG_(message)(Vg_UserMsg,
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 "discard syms at %p-%p in %s due to munmap()",
1664 start, start+length, curr->filename ? curr->filename : (Char *)"???");
sewardjde4a1d02002-03-22 01:27:54 +00001665
1666 vg_assert(prev == NULL || prev->next == curr);
1667
1668 if (prev == NULL) {
1669 segInfo = curr->next;
1670 } else {
1671 prev->next = curr->next;
1672 }
1673
1674 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001675 return;
sewardjde4a1d02002-03-22 01:27:54 +00001676}
1677
nethercote8991d5a2004-11-03 17:07:46 +00001678void VG_(symtab_decref)(SegInfo *si, Addr start)
fitzhardinge98abfc72003-12-16 02:05:15 +00001679{
1680 vg_assert(si->ref >= 1);
1681 if (--si->ref == 0)
nethercote85cdd342004-08-01 22:36:40 +00001682 unload_symbols(si->start, si->size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001683}
1684
1685void VG_(symtab_incref)(SegInfo *si)
1686{
1687 vg_assert(si->ref > 0);
1688 si->ref++;
1689}
sewardjde4a1d02002-03-22 01:27:54 +00001690
1691/*------------------------------------------------------------*/
1692/*--- Use of symbol table & location info to create ---*/
1693/*--- plausible-looking stack dumps. ---*/
1694/*------------------------------------------------------------*/
1695
1696/* Find a symbol-table index containing the specified pointer, or -1
1697 if not found. Binary search. */
1698
njn25e49d8e72002-09-23 09:36:25 +00001699static Int search_one_symtab ( SegInfo* si, Addr ptr,
1700 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001701{
1702 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001703 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001704 lo = 0,
1705 hi = si->symtab_used-1;
1706 while (True) {
1707 /* current unsearched space is from lo to hi, inclusive. */
1708 if (lo > hi) return -1; /* not found */
1709 mid = (lo + hi) / 2;
1710 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001711 size = ( match_anywhere_in_fun
1712 ? si->symtab[mid].size
1713 : 1);
1714 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001715
1716 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1717 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1718 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1719 return mid;
1720 }
1721}
1722
1723
sewardj25c7c3a2003-07-10 00:17:58 +00001724/* SLOW (Linear search). Try and map a symbol name to an address.
1725 Since this is searching in the direction opposite to which the
1726 table is designed we have no option but to do a complete linear
1727 scan of the table. Returns NULL if not found. */
1728
sewardjb5f6f512005-03-10 23:59:00 +00001729Addr VG_(reverse_search_one_symtab) ( const SegInfo* si, const Char* name )
sewardj25c7c3a2003-07-10 00:17:58 +00001730{
1731 UInt i;
1732 for (i = 0; i < si->symtab_used; i++) {
sewardjc8bf5fe2003-07-13 00:53:22 +00001733 if (0)
jsgfcb1d1c02003-10-14 21:55:10 +00001734 VG_(printf)("%p %s\n", si->symtab[i].addr, si->symtab[i].name);
1735 if (0 == VG_(strcmp)(name, si->symtab[i].name))
sewardj25c7c3a2003-07-10 00:17:58 +00001736 return si->symtab[i].addr;
1737 }
1738 return (Addr)NULL;
1739}
1740
1741
sewardjde4a1d02002-03-22 01:27:54 +00001742/* Search all symtabs that we know about to locate ptr. If found, set
1743 *psi to the relevant SegInfo, and *symno to the symtab entry number
1744 within that. If not found, *psi is set to NULL. */
1745
njn25e49d8e72002-09-23 09:36:25 +00001746static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1747 /*OUT*/Int* symno,
1748 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001749{
1750 Int sno;
1751 SegInfo* si;
fitzhardinge98abfc72003-12-16 02:05:15 +00001752 Segment *s;
njn25e49d8e72002-09-23 09:36:25 +00001753
njn25e49d8e72002-09-23 09:36:25 +00001754 VGP_PUSHCC(VgpSearchSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001755
1756 s = VG_(find_segment)(ptr);
1757
sewardjb5f6f512005-03-10 23:59:00 +00001758 if (s == NULL || s->symtab == NULL)
fitzhardinge98abfc72003-12-16 02:05:15 +00001759 goto not_found;
njn25e49d8e72002-09-23 09:36:25 +00001760
fitzhardinge98abfc72003-12-16 02:05:15 +00001761 si = s->symtab;
1762
1763 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
1764 if (sno == -1) goto not_found;
1765
1766 *symno = sno;
1767 *psi = si;
1768 VGP_POPCC(VgpSearchSyms);
1769 return;
1770
sewardjde4a1d02002-03-22 01:27:54 +00001771 not_found:
1772 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001773 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001774}
1775
1776
1777/* Find a location-table index containing the specified pointer, or -1
1778 if not found. Binary search. */
1779
1780static Int search_one_loctab ( SegInfo* si, Addr ptr )
1781{
1782 Addr a_mid_lo, a_mid_hi;
1783 Int mid,
1784 lo = 0,
1785 hi = si->loctab_used-1;
1786 while (True) {
1787 /* current unsearched space is from lo to hi, inclusive. */
1788 if (lo > hi) return -1; /* not found */
1789 mid = (lo + hi) / 2;
1790 a_mid_lo = si->loctab[mid].addr;
1791 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1792
1793 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1794 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1795 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1796 return mid;
1797 }
1798}
1799
1800
1801/* Search all loctabs that we know about to locate ptr. If found, set
1802 *psi to the relevant SegInfo, and *locno to the loctab entry number
1803 within that. If not found, *psi is set to NULL.
1804*/
njn25e49d8e72002-09-23 09:36:25 +00001805static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
1806 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00001807{
1808 Int lno;
1809 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001810
1811 VGP_PUSHCC(VgpSearchSyms);
1812
sewardjde4a1d02002-03-22 01:27:54 +00001813 for (si = segInfo; si != NULL; si = si->next) {
1814 if (si->start <= ptr && ptr < si->start+si->size) {
1815 lno = search_one_loctab ( si, ptr );
1816 if (lno == -1) goto not_found;
1817 *locno = lno;
1818 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001819 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001820 return;
1821 }
1822 }
1823 not_found:
1824 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001825 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001826}
1827
1828
jsgfcb1d1c02003-10-14 21:55:10 +00001829/* Find a scope-table index containing the specified pointer, or -1
1830 if not found. Binary search. */
1831
1832static Int search_one_scopetab ( SegInfo* si, Addr ptr )
1833{
1834 Addr a_mid_lo, a_mid_hi;
1835 Int mid,
1836 lo = 0,
1837 hi = si->scopetab_used-1;
1838 while (True) {
1839 /* current unsearched space is from lo to hi, inclusive. */
1840 if (lo > hi) return -1; /* not found */
1841 mid = (lo + hi) / 2;
1842 a_mid_lo = si->scopetab[mid].addr;
1843 a_mid_hi = ((Addr)si->scopetab[mid].addr) + si->scopetab[mid].size - 1;
1844
1845 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1846 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1847 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1848 return mid;
1849 }
1850}
1851
1852
1853/* Search all scopetabs that we know about to locate ptr. If found, set
1854 *psi to the relevant SegInfo, and *locno to the scopetab entry number
1855 within that. If not found, *psi is set to NULL.
1856*/
1857static void search_all_scopetabs ( Addr ptr,
1858 /*OUT*/SegInfo** psi,
1859 /*OUT*/Int* scopeno )
1860{
1861 Int scno;
1862 SegInfo* si;
1863
1864 VGP_PUSHCC(VgpSearchSyms);
1865
1866 for (si = segInfo; si != NULL; si = si->next) {
1867 if (si->start <= ptr && ptr < si->start+si->size) {
1868 scno = search_one_scopetab ( si, ptr );
1869 if (scno == -1) goto not_found;
1870 *scopeno = scno;
1871 *psi = si;
1872 VGP_POPCC(VgpSearchSyms);
1873 return;
1874 }
1875 }
1876 not_found:
1877 *psi = NULL;
1878 VGP_POPCC(VgpSearchSyms);
1879}
1880
sewardjde4a1d02002-03-22 01:27:54 +00001881/* The whole point of this whole big deal: map a code address to a
1882 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00001883 Caller supplies buf and nbuf. If demangle is False, don't do
sewardjde4a1d02002-03-22 01:27:54 +00001884 demangling, regardless of vg_clo_demangle -- probably because the
1885 call has come from vg_what_fn_or_object_is_this. */
njn25e49d8e72002-09-23 09:36:25 +00001886static
1887Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
sewardj1771e172002-11-13 22:06:35 +00001888 Bool match_anywhere_in_fun, Bool show_offset)
sewardjde4a1d02002-03-22 01:27:54 +00001889{
1890 SegInfo* si;
1891 Int sno;
sewardj1771e172002-11-13 22:06:35 +00001892 Int offset;
1893
njn25e49d8e72002-09-23 09:36:25 +00001894 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001895 if (si == NULL)
1896 return False;
njn25e49d8e72002-09-23 09:36:25 +00001897 if (demangle) {
jsgfcb1d1c02003-10-14 21:55:10 +00001898 VG_(demangle) ( si->symtab[sno].name, buf, nbuf );
njn25e49d8e72002-09-23 09:36:25 +00001899 } else {
sewardjde4a1d02002-03-22 01:27:54 +00001900 VG_(strncpy_safely)
jsgfcb1d1c02003-10-14 21:55:10 +00001901 ( buf, si->symtab[sno].name, nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00001902 }
sewardj1771e172002-11-13 22:06:35 +00001903
1904 offset = a - si->symtab[sno].addr;
1905 if (show_offset && offset != 0) {
1906 Char buf2[12];
1907 Char* symend = buf + VG_(strlen)(buf);
1908 Char* end = buf + nbuf;
1909 Int len;
1910
1911 len = VG_(sprintf)(buf2, "%c%d",
1912 offset < 0 ? '-' : '+',
1913 offset < 0 ? -offset : offset);
sewardj05bcdcb2003-05-18 10:05:38 +00001914 vg_assert(len < (Int)sizeof(buf2));
sewardj1771e172002-11-13 22:06:35 +00001915
1916 if (len < (end - symend)) {
1917 Char *cp = buf2;
1918 VG_(memcpy)(symend, cp, len+1);
1919 }
1920 }
1921
sewardjde4a1d02002-03-22 01:27:54 +00001922 return True;
1923}
1924
nethercote7cc9c232004-01-21 15:08:04 +00001925/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001926 match anywhere in function, but don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001927Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1928{
1929 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001930 /*match_anywhere_in_fun*/True,
1931 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001932}
sewardjde4a1d02002-03-22 01:27:54 +00001933
nethercote7cc9c232004-01-21 15:08:04 +00001934/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001935 match anywhere in function, and show offset if nonzero. */
1936Bool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1937{
1938 return get_fnname ( /*demangle*/True, a, buf, nbuf,
1939 /*match_anywhere_in_fun*/True,
1940 /*show offset?*/True );
1941}
1942
nethercote7cc9c232004-01-21 15:08:04 +00001943/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001944 only succeed if 'a' matches first instruction of function,
1945 and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001946Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1947{
1948 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001949 /*match_anywhere_in_fun*/False,
1950 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001951}
1952
sewardj6e008cb2002-12-15 13:11:39 +00001953/* This is only available to core... don't demangle C++ names,
1954 match anywhere in function, and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001955Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
1956{
1957 return get_fnname ( /*demangle*/False, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001958 /*match_anywhere_in_fun*/True,
1959 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001960}
1961
1962/* Map a code address to the name of a shared object file or the executable.
1963 Returns False if no idea; otherwise True. Doesn't require debug info.
1964 Caller supplies buf and nbuf. */
1965Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001966{
1967 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001968
sewardjde4a1d02002-03-22 01:27:54 +00001969 for (si = segInfo; si != NULL; si = si->next) {
1970 if (si->start <= a && a < si->start+si->size) {
1971 VG_(strncpy_safely)(buf, si->filename, nbuf);
1972 return True;
1973 }
1974 }
1975 return False;
1976}
1977
njnb877d492003-01-28 20:40:57 +00001978/* Map a code address to its SegInfo. Returns NULL if not found. Doesn't
1979 require debug info. */
1980SegInfo* VG_(get_obj) ( Addr a )
1981{
1982 SegInfo* si;
1983
njnb877d492003-01-28 20:40:57 +00001984 for (si = segInfo; si != NULL; si = si->next) {
1985 if (si->start <= a && a < si->start+si->size) {
1986 return si;
1987 }
1988 }
nethercote80f76782003-11-13 22:34:00 +00001989 return NULL;
njnb877d492003-01-28 20:40:57 +00001990}
1991
njn25e49d8e72002-09-23 09:36:25 +00001992
1993/* Map a code address to a filename. Returns True if successful. */
1994Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00001995{
njn25e49d8e72002-09-23 09:36:25 +00001996 SegInfo* si;
1997 Int locno;
1998 search_all_loctabs ( a, &si, &locno );
1999 if (si == NULL)
2000 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00002001 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
njn25e49d8e72002-09-23 09:36:25 +00002002 n_filename);
2003 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002004}
2005
njn25e49d8e72002-09-23 09:36:25 +00002006/* Map a code address to a line number. Returns True if successful. */
2007Bool VG_(get_linenum)( Addr a, UInt* lineno )
2008{
2009 SegInfo* si;
2010 Int locno;
2011 search_all_loctabs ( a, &si, &locno );
2012 if (si == NULL)
2013 return False;
2014 *lineno = si->loctab[locno].lineno;
2015
2016 return True;
2017}
sewardjde4a1d02002-03-22 01:27:54 +00002018
2019/* Map a code address to a (filename, line number) pair.
2020 Returns True if successful.
2021*/
njn25e49d8e72002-09-23 09:36:25 +00002022Bool VG_(get_filename_linenum)( Addr a,
2023 Char* filename, Int n_filename,
2024 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00002025{
2026 SegInfo* si;
2027 Int locno;
2028 search_all_loctabs ( a, &si, &locno );
2029 if (si == NULL)
2030 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00002031 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
sewardjde4a1d02002-03-22 01:27:54 +00002032 n_filename);
2033 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00002034
sewardjde4a1d02002-03-22 01:27:54 +00002035 return True;
2036}
2037
jsgfcb1d1c02003-10-14 21:55:10 +00002038#ifndef TEST
2039
2040/* return a pointer to a register (now for 5 other impossible things
2041 before breakfast) */
2042static UInt *regaddr(ThreadId tid, Int regno)
2043{
2044 UInt *ret = 0;
2045
sewardj2a99cf62004-11-24 10:44:19 +00002046 ret = VGA_(reg_addr_from_tst)(regno, &VG_(threads)[tid].arch);
jsgfcb1d1c02003-10-14 21:55:10 +00002047
2048 if (ret == 0) {
2049 Char file[100];
2050 Int line;
2051 Addr eip = VG_(get_EIP)(tid);
2052
2053 if (!VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
2054 file[0] = 0;
2055 VG_(printf)("mysterious register %d used at %p %s:%d\n",
2056 regno, eip, file, line);
2057 }
2058
2059 return ret;
2060}
2061
2062/* Get a list of all variables in scope, working out from the directly
2063 current one */
2064Variable *VG_(get_scope_variables)(ThreadId tid)
2065{
2066 static const Bool debug = False;
2067 Variable *list, *end;
2068 Addr eip;
2069 SegInfo *si;
2070 Int scopeidx;
2071 Scope *scope;
2072 Int distance;
2073 static const Int maxsyms = 1000;
2074 Int nsyms = maxsyms;
2075
2076 list = end = NULL;
2077
2078 eip = VG_(get_EIP)(tid);
2079
2080 search_all_scopetabs(eip, &si, &scopeidx);
2081
2082 if (debug)
2083 VG_(printf)("eip=%p si=%p (%s; offset=%p) scopeidx=%d\n",
2084 eip, si, si ? si->filename : (Char *)"???",
2085 si ? si->offset : 0x99999, scopeidx);
2086
2087 if (si == NULL)
2088 return NULL; /* nothing in scope (should use global scope at least) */
2089
2090 if (debug) {
2091 ScopeRange *sr = &si->scopetab[scopeidx];
2092 Char file[100];
2093 Int line;
2094
2095 if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file), &line))
2096 file[0] = 0;
2097
2098 VG_(printf)("found scope range %p: eip=%p (%s:%d) size=%d scope=%p\n",
2099 sr, sr->addr, file, line, sr->size, sr->scope);
2100 }
2101
2102 distance = 0;
2103 for(scope = si->scopetab[scopeidx].scope; scope != NULL; scope = scope->outer, distance++) {
2104 UInt i;
2105
2106 for(i = 0; i < scope->nsyms; i++) {
2107 Sym *sym = &scope->syms[i];
2108 Variable *v;
2109
2110 if (nsyms-- == 0) {
2111 VG_(printf)("max %d syms reached\n", maxsyms);
2112 return list;
2113 }
2114
2115 v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
2116
2117 v->next = NULL;
2118 v->distance = distance;
2119 v->type = VG_(st_basetype)(sym->type, False);
2120 v->name = VG_(arena_strdup)(VG_AR_SYMTAB, sym->name);
2121 v->container = NULL;
2122 v->size = VG_(st_sizeof)(sym->type);
2123
2124 if (debug && 0)
mueller5ed88f22004-01-06 16:02:29 +00002125 VG_(printf)("sym->name=%s sym->kind=%d offset=%d\n", sym->name, sym->kind, sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002126 switch(sym->kind) {
2127 UInt reg;
2128
2129 case SyGlobal:
2130 case SyStatic:
mueller5ed88f22004-01-06 16:02:29 +00002131 if (sym->u.addr == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00002132 /* XXX lookup value */
2133 }
mueller5ed88f22004-01-06 16:02:29 +00002134 v->valuep = sym->u.addr;
jsgfcb1d1c02003-10-14 21:55:10 +00002135 break;
2136
2137 case SyReg:
mueller5ed88f22004-01-06 16:02:29 +00002138 v->valuep = (Addr)regaddr(tid, sym->u.regno);
jsgfcb1d1c02003-10-14 21:55:10 +00002139 break;
2140
2141 case SyEBPrel:
2142 case SyESPrel:
nethercotecd656042004-09-11 23:48:22 +00002143 reg = *regaddr(tid, sym->kind == SyESPrel ?
2144 R_STACK_PTR : R_FRAME_PTR);
jsgfcb1d1c02003-10-14 21:55:10 +00002145 if (debug)
mueller5ed88f22004-01-06 16:02:29 +00002146 VG_(printf)("reg=%p+%d=%p\n", reg, sym->u.offset, reg+sym->u.offset);
2147 v->valuep = (Addr)(reg + sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002148 break;
2149
2150 case SyType:
2151 VG_(core_panic)("unexpected typedef in scope");
2152 }
2153
2154 if (v->valuep == 0) {
2155 /* not interesting or useful */
2156 VG_(arena_free)(VG_AR_SYMTAB, v);
2157 continue;
2158 }
2159
2160 /* append to end of list */
2161 if (list == NULL)
2162 list = end = v;
2163 else {
2164 end->next = v;
2165 end = v;
2166 }
2167 }
2168 }
2169
2170 return list;
2171}
2172#endif /* TEST */
2173
njn6c846552003-09-16 07:41:43 +00002174/* Print into buf info on code address, function name and filename */
2175Char* VG_(describe_eip)(Addr eip, Char* buf, Int n_buf)
sewardjde4a1d02002-03-22 01:27:54 +00002176{
njn6c846552003-09-16 07:41:43 +00002177#define APPEND(str) \
2178 { UChar* sss; \
2179 for (sss = str; n < n_buf-1 && *sss != 0; n++,sss++) \
2180 buf[n] = *sss; \
2181 buf[n] = '\0'; \
sewardjde4a1d02002-03-22 01:27:54 +00002182 }
nethercote80f76782003-11-13 22:34:00 +00002183 UInt lineno;
2184 UChar ibuf[20];
2185 UInt n = 0;
nethercote3b38c1d2004-10-18 15:47:18 +00002186 static UChar buf_fn[M_VG_ERRTXT];
2187 static UChar buf_obj[M_VG_ERRTXT];
2188 static UChar buf_srcloc[M_VG_ERRTXT];
nethercote80f76782003-11-13 22:34:00 +00002189 Bool know_fnname = VG_(get_fnname) (eip, buf_fn, M_VG_ERRTXT);
2190 Bool know_objname = VG_(get_objname)(eip, buf_obj, M_VG_ERRTXT);
2191 Bool know_srcloc = VG_(get_filename_linenum)(eip, buf_srcloc, M_VG_ERRTXT,
2192 &lineno);
sewardja4da2f32005-03-02 14:06:08 +00002193 VG_(sprintf)(ibuf,"0x%llx: ", (ULong)eip);
njn6c846552003-09-16 07:41:43 +00002194 APPEND(ibuf);
2195 if (know_fnname) {
2196 APPEND(buf_fn);
2197 if (!know_srcloc && know_objname) {
2198 APPEND(" (in ");
2199 APPEND(buf_obj);
2200 APPEND(")");
2201 }
2202 } else if (know_objname && !know_srcloc) {
2203 APPEND("(within ");
2204 APPEND(buf_obj);
2205 APPEND(")");
2206 } else {
2207 APPEND("???");
2208 }
2209 if (know_srcloc) {
2210 APPEND(" (");
2211 APPEND(buf_srcloc);
2212 APPEND(":");
2213 VG_(sprintf)(ibuf,"%d",lineno);
2214 APPEND(ibuf);
2215 APPEND(")");
2216 }
2217 return buf;
2218
2219#undef APPEND
2220}
2221
2222/* Print a mini stack dump, showing the current location. */
2223void VG_(mini_stack_dump) ( Addr eips[], UInt n_eips )
2224{
2225 UInt i;
nethercote3b38c1d2004-10-18 15:47:18 +00002226 static UChar buf[M_VG_ERRTXT];
nethercote77eba602003-11-13 17:35:04 +00002227 Bool main_done = False;
njn6c846552003-09-16 07:41:43 +00002228
2229 Int stop_at = n_eips;
sewardjde4a1d02002-03-22 01:27:54 +00002230
njn49ef4622002-10-04 15:15:08 +00002231 vg_assert(stop_at > 0);
sewardjde4a1d02002-03-22 01:27:54 +00002232
nethercote77eba602003-11-13 17:35:04 +00002233 /* This loop is the basis for the one in VG_(gen_suppressions)(); if you
2234 change this, change it too! */
njn49ef4622002-10-04 15:15:08 +00002235 i = 0;
2236 do {
njn6c846552003-09-16 07:41:43 +00002237 Addr eip = eips[i];
nethercotefbfc1082004-09-04 15:28:37 +00002238 if (i > 0)
2239 eip -= MIN_INSTR_SIZE; // point to calling line
njn6c846552003-09-16 07:41:43 +00002240 VG_(describe_eip)(eip, buf, M_VG_ERRTXT);
nethercote77eba602003-11-13 17:35:04 +00002241
2242 if ( ! VG_(clo_show_below_main)) {
2243 // Stop after "main"; if main() is recursive, stop after last main().
2244 if (VG_(strstr)(buf, " main ("))
2245 main_done = True;
2246 else if (main_done)
2247 break;
2248 }
2249 VG_(message)(Vg_UserMsg, " %s %s", ( i == 0 ? "at" : "by" ), buf);
njn49ef4622002-10-04 15:15:08 +00002250 i++;
2251
njn6c846552003-09-16 07:41:43 +00002252 } while (i < (UInt)stop_at && eips[i] != 0);
sewardjde4a1d02002-03-22 01:27:54 +00002253}
2254
sewardj25c7c3a2003-07-10 00:17:58 +00002255
2256/*------------------------------------------------------------*/
sewardj47104382002-10-20 18:35:48 +00002257/*--- SegInfo accessor functions ---*/
2258/*------------------------------------------------------------*/
2259
2260const SegInfo* VG_(next_seginfo)(const SegInfo* seg)
2261{
sewardj47104382002-10-20 18:35:48 +00002262 if (seg == NULL)
2263 return segInfo;
2264 return seg->next;
2265}
2266
2267Addr VG_(seg_start)(const SegInfo* seg)
2268{
2269 return seg->start;
2270}
2271
nethercote928a5f72004-11-03 18:10:37 +00002272SizeT VG_(seg_size)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002273{
2274 return seg->size;
2275}
2276
2277const UChar* VG_(seg_filename)(const SegInfo* seg)
2278{
2279 return seg->filename;
2280}
2281
nethercote928a5f72004-11-03 18:10:37 +00002282ULong VG_(seg_sym_offset)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002283{
2284 return seg->offset;
2285}
2286
2287VgSectKind VG_(seg_sect_kind)(Addr a)
2288{
2289 SegInfo* seg;
2290 VgSectKind ret = Vg_SectUnknown;
2291
sewardj47104382002-10-20 18:35:48 +00002292 for(seg = segInfo; seg != NULL; seg = seg->next) {
2293 if (a >= seg->start && a < (seg->start + seg->size)) {
2294 if (0)
sewardj8fe15a32002-10-20 19:29:21 +00002295 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 +00002296 a, seg, seg->filename,
2297 seg->got_start, seg->got_size,
sewardj8fe15a32002-10-20 19:29:21 +00002298 seg->plt_start, seg->plt_size,
2299 seg->data_start, seg->data_size,
2300 seg->bss_start, seg->bss_size);
sewardj47104382002-10-20 18:35:48 +00002301 ret = Vg_SectText;
2302
sewardj8fe15a32002-10-20 19:29:21 +00002303 if (a >= seg->data_start && a < (seg->data_start + seg->data_size))
2304 ret = Vg_SectData;
2305 else if (a >= seg->bss_start && a < (seg->bss_start + seg->bss_size))
2306 ret = Vg_SectBSS;
2307 else if (a >= seg->plt_start && a < (seg->plt_start + seg->plt_size))
sewardj47104382002-10-20 18:35:48 +00002308 ret = Vg_SectPLT;
2309 else if (a >= seg->got_start && a < (seg->got_start + seg->got_size))
2310 ret = Vg_SectGOT;
2311 }
2312 }
2313
2314 return ret;
2315}
2316
sewardjde4a1d02002-03-22 01:27:54 +00002317/*--------------------------------------------------------------------*/
2318/*--- end vg_symtab2.c ---*/
2319/*--------------------------------------------------------------------*/