blob: 179c582fdaab459dc15c208ee375eab1b827c61d [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
njn53612422005-03-12 16:22:54 +000011 Copyright (C) 2000-2005 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)
njn1fd5eb22005-03-13 05:43:23 +0000377 VG_(message)(Vg_DebugMsg,"%s", msg );
sewardjde4a1d02002-03-22 01:27:54 +0000378}
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
njna1685902005-03-16 04:09:21 +0000726 are only 12 bits. */
sewardjde4a1d02002-03-22 01:27:54 +0000727 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
njna1685902005-03-16 04:09:21 +0000731 if (new_size > MAX_LOC_SIZE) {
732 si->loctab[i].size = MAX_LOC_SIZE;
sewardjde4a1d02002-03-22 01:27:54 +0000733 } 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');
njn35172bc2005-03-26 00:04:03 +0000783 ok &= (ehdr->e_ident[EI_CLASS] == VGA_ELF_CLASS
784 && ehdr->e_ident[EI_DATA] == VGA_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);
njn35172bc2005-03-26 00:04:03 +0000787 ok &= (ehdr->e_machine == VGA_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)
njn1fd5eb22005-03-13 05:43:23 +00001140 VG_(message)(Vg_DebugMsg, "Reading debug info from %s...", name);
sewardjb5f6f512005-03-10 23:59:00 +00001141
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)
njn1fd5eb22005-03-13 05:43:23 +00001159 VG_(message)(Vg_DebugMsg, "... 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)
njn1fd5eb22005-03-13 05:43:23 +00001218 VG_(message)(Vg_DebugMsg, "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))) {
njn1fd5eb22005-03-13 05:43:23 +00001244 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", si->filename );
1245 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded" );
sewardj8fe15a32002-10-20 19:29:21 +00001246 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001247 }
1248
sewardjde4a1d02002-03-22 01:27:54 +00001249 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1250 Now verify that it is a valid ELF .so or executable image.
1251 */
nethercote80f76782003-11-13 22:34:00 +00001252 res = False;
sewardj7a21c612005-02-18 09:38:08 +00001253 ok = (n_oimage >= sizeof(ElfXX_Ehdr));
1254 ehdr = (ElfXX_Ehdr*)oimage;
sewardjde4a1d02002-03-22 01:27:54 +00001255
fitzhardinge98abfc72003-12-16 02:05:15 +00001256 if (ok)
1257 ok &= VG_(is_object_file)(ehdr);
sewardjde4a1d02002-03-22 01:27:54 +00001258
1259 if (!ok) {
jsgfcb1d1c02003-10-14 21:55:10 +00001260 VG_(symerr)("Invalid ELF header, or missing stringtab/sectiontab.");
nethercote80f76782003-11-13 22:34:00 +00001261 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001262 }
1263
1264 /* Walk the LOAD headers in the phdr and update the SegInfo to
1265 include them all, so that this segment also contains data and
1266 bss memory. Also computes correct symbol offset value for this
1267 ELF file. */
sewardj7a21c612005-02-18 09:38:08 +00001268 if (ehdr->e_phoff + ehdr->e_phnum*sizeof(ElfXX_Phdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001269 VG_(symerr)("ELF program header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001270 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001271 }
1272 {
1273 Bool offset_set = False;
sewardj7a21c612005-02-18 09:38:08 +00001274 ElfXX_Addr prev_addr = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001275 Addr baseaddr = 0;
sewardj8fe15a32002-10-20 19:29:21 +00001276
1277 si->offset = 0;
1278
nethercote80f76782003-11-13 22:34:00 +00001279 for (i = 0; i < ehdr->e_phnum; i++) {
sewardj7a21c612005-02-18 09:38:08 +00001280 ElfXX_Phdr *o_phdr;
1281 ElfXX_Addr mapped, mapped_end;
sewardj8fe15a32002-10-20 19:29:21 +00001282
sewardj7a21c612005-02-18 09:38:08 +00001283 o_phdr = &((ElfXX_Phdr *)(oimage + ehdr->e_phoff))[i];
sewardj8fe15a32002-10-20 19:29:21 +00001284
fitzhardinge98abfc72003-12-16 02:05:15 +00001285 if (o_phdr->p_type == PT_DYNAMIC && si->soname == NULL) {
sewardj7a21c612005-02-18 09:38:08 +00001286 const ElfXX_Dyn *dyn = (const ElfXX_Dyn *)(oimage + o_phdr->p_offset);
fitzhardinge98abfc72003-12-16 02:05:15 +00001287 Int stroff = -1;
1288 Char *strtab = NULL;
1289 Int j;
1290
1291 for(j = 0; dyn[j].d_tag != DT_NULL; j++) {
1292 switch(dyn[j].d_tag) {
1293 case DT_SONAME:
1294 stroff = dyn[j].d_un.d_val;
1295 break;
1296
1297 case DT_STRTAB:
1298 strtab = (Char *)oimage + dyn[j].d_un.d_ptr - baseaddr;
1299 break;
1300 }
1301 }
1302
1303 if (stroff != -1 && strtab != 0) {
1304 TRACE_SYMTAB("soname=%s\n", strtab+stroff);
1305 si->soname = VG_(arena_strdup)(VG_AR_SYMTAB, strtab+stroff);
1306 }
1307 }
1308
sewardj8fe15a32002-10-20 19:29:21 +00001309 if (o_phdr->p_type != PT_LOAD)
1310 continue;
1311
1312 if (!offset_set) {
1313 offset_set = True;
1314 si->offset = si->start - o_phdr->p_vaddr;
fitzhardinge98abfc72003-12-16 02:05:15 +00001315 baseaddr = o_phdr->p_vaddr;
sewardj8fe15a32002-10-20 19:29:21 +00001316 }
1317
1318 if (o_phdr->p_vaddr < prev_addr) {
jsgfcb1d1c02003-10-14 21:55:10 +00001319 VG_(symerr)("ELF Phdrs are out of order!?");
nethercote80f76782003-11-13 22:34:00 +00001320 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001321 }
1322 prev_addr = o_phdr->p_vaddr;
1323
1324 mapped = o_phdr->p_vaddr + si->offset;
1325 mapped_end = mapped + o_phdr->p_memsz;
1326
1327 if (si->data_start == 0 &&
1328 (o_phdr->p_flags & (PF_R|PF_W|PF_X)) == (PF_R|PF_W)) {
1329 si->data_start = mapped;
1330 si->data_size = o_phdr->p_filesz;
1331 si->bss_start = mapped + o_phdr->p_filesz;
1332 if (o_phdr->p_memsz > o_phdr->p_filesz)
1333 si->bss_size = o_phdr->p_memsz - o_phdr->p_filesz;
1334 else
1335 si->bss_size = 0;
1336 }
1337
nethercote73b526f2004-10-31 18:48:21 +00001338 mapped = mapped & ~(VKI_PAGE_SIZE-1);
1339 mapped_end = (mapped_end + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE-1);
sewardj8fe15a32002-10-20 19:29:21 +00001340
sewardj1024cf72005-02-28 14:39:21 +00001341#if 0
1342 /* 20050228: disabled this until VG_(next_segment) can be
1343 reinstated in some clean incarnation of the low level
1344 memory manager. */
sewardj8fe15a32002-10-20 19:29:21 +00001345 if (VG_(needs).data_syms &&
1346 (mapped >= si->start && mapped <= (si->start+si->size)) &&
1347 (mapped_end > (si->start+si->size))) {
1348 UInt newsz = mapped_end - si->start;
1349 if (newsz > si->size) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001350 Segment *seg;
1351
sewardj8fe15a32002-10-20 19:29:21 +00001352 if (0)
1353 VG_(printf)("extending mapping %p..%p %d -> ..%p %d\n",
1354 si->start, si->start+si->size, si->size,
1355 si->start+newsz, newsz);
fitzhardinge98abfc72003-12-16 02:05:15 +00001356
sewardjb5f6f512005-03-10 23:59:00 +00001357 for(seg = VG_(find_segment_containing)(si->start);
fitzhardinge98abfc72003-12-16 02:05:15 +00001358 seg != NULL && VG_(seg_overlaps)(seg, si->start, si->size);
1359 seg = VG_(next_segment)(seg)) {
1360 if (seg->symtab == si)
1361 continue;
1362
1363 if (seg->symtab != NULL)
nethercote8991d5a2004-11-03 17:07:46 +00001364 VG_(symtab_decref)(seg->symtab, seg->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001365
1366 VG_(symtab_incref)(si);
1367 seg->symtab = si;
1368
1369 if (0)
1370 VG_(printf)("adding symtab %p (%p-%p) to segment %p (%p-%p)\n",
1371 si, si->start, si->start+newsz,
1372 seg, seg->addr, seg->addr+seg->len);
1373 }
1374
sewardj8fe15a32002-10-20 19:29:21 +00001375 si->size = newsz;
1376 }
1377 }
sewardj1024cf72005-02-28 14:39:21 +00001378#endif
1379
sewardj8fe15a32002-10-20 19:29:21 +00001380 }
sewardjde4a1d02002-03-22 01:27:54 +00001381 }
1382
nethercote80f76782003-11-13 22:34:00 +00001383 TRACE_SYMTAB("shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
sewardj7a21c612005-02-18 09:38:08 +00001384 ehdr->e_shoff, ehdr->e_shnum, sizeof(ElfXX_Shdr), n_oimage );
sewardjde4a1d02002-03-22 01:27:54 +00001385
sewardj7a21c612005-02-18 09:38:08 +00001386 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(ElfXX_Shdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001387 VG_(symerr)("ELF section header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001388 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001389 }
1390
sewardj7a21c612005-02-18 09:38:08 +00001391 shdr = (ElfXX_Shdr*)(oimage + ehdr->e_shoff);
sewardjde4a1d02002-03-22 01:27:54 +00001392 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1393
nethercote80f76782003-11-13 22:34:00 +00001394 /* Find interesting sections, read the symbol table(s), read any debug
1395 information */
sewardjde4a1d02002-03-22 01:27:54 +00001396 {
nethercote80f76782003-11-13 22:34:00 +00001397 /* Pointers to start of sections */
1398 UChar* o_strtab = NULL; /* .strtab */
sewardj7a21c612005-02-18 09:38:08 +00001399 ElfXX_Sym* o_symtab = NULL; /* .symtab */
nethercote80f76782003-11-13 22:34:00 +00001400 UChar* o_dynstr = NULL; /* .dynstr */
sewardj7a21c612005-02-18 09:38:08 +00001401 ElfXX_Sym* o_dynsym = NULL; /* .dynsym */
thughesc035bd92004-06-13 09:59:02 +00001402 Char* debuglink = NULL; /* .gnu_debuglink */
nethercote80f76782003-11-13 22:34:00 +00001403 UChar* stab = NULL; /* .stab (stabs) */
1404 UChar* stabstr = NULL; /* .stabstr (stabs) */
1405 UChar* debug_line = NULL; /* .debug_line (dwarf2) */
jseward8b3131a2003-12-13 23:16:26 +00001406 UChar* dwarf1d = NULL; /* .debug (dwarf1) */
1407 UChar* dwarf1l = NULL; /* .line (dwarf1) */
sewardjde4a1d02002-03-22 01:27:54 +00001408
nethercote80f76782003-11-13 22:34:00 +00001409 /* Section sizes, in bytes */
1410 UInt o_strtab_sz = 0;
1411 UInt o_symtab_sz = 0;
1412 UInt o_dynstr_sz = 0;
1413 UInt o_dynsym_sz = 0;
thughesc035bd92004-06-13 09:59:02 +00001414 UInt debuglink_sz = 0;
nethercote80f76782003-11-13 22:34:00 +00001415 UInt stab_sz = 0;
1416 UInt stabstr_sz = 0;
1417 UInt debug_line_sz = 0;
jseward8b3131a2003-12-13 23:16:26 +00001418 UInt dwarf1d_sz = 0;
1419 UInt dwarf1l_sz = 0;
1420
1421 Bool has_debuginfo = False;
sewardjde4a1d02002-03-22 01:27:54 +00001422
nethercote80f76782003-11-13 22:34:00 +00001423 /* Find all interesting sections */
sewardjde4a1d02002-03-22 01:27:54 +00001424 for (i = 0; i < ehdr->e_shnum; i++) {
jseward8b3131a2003-12-13 23:16:26 +00001425# define FIND(sec_name, sec_data, sec_size, in_exec, type) \
nethercote80f76782003-11-13 22:34:00 +00001426 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1427 if (0 != sec_data) \
1428 VG_(core_panic)("repeated section!\n"); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001429 if (in_exec) \
nethercote80f76782003-11-13 22:34:00 +00001430 sec_data = (type)(si->offset + shdr[i].sh_addr); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001431 else \
nethercote80f76782003-11-13 22:34:00 +00001432 sec_data = (type)(oimage + shdr[i].sh_offset); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001433 sec_size = shdr[i].sh_size; \
nethercote80f76782003-11-13 22:34:00 +00001434 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1435 sec_name, sec_data, sec_data + sec_size - 1); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001436 if ( shdr[i].sh_offset + sec_size > n_oimage ) { \
nethercote80f76782003-11-13 22:34:00 +00001437 VG_(symerr)(" section beyond image end?!"); \
1438 goto out; \
1439 } \
sewardjde4a1d02002-03-22 01:27:54 +00001440 }
1441
nethercote80f76782003-11-13 22:34:00 +00001442 /* Nb: must find where .got and .plt sections will be in the
1443 * executable image, not in the object image transiently loaded. */
sewardj7a21c612005-02-18 09:38:08 +00001444 FIND(".dynsym", o_dynsym, o_dynsym_sz, 0, ElfXX_Sym*)
nethercote80f76782003-11-13 22:34:00 +00001445 else FIND(".dynstr", o_dynstr, o_dynstr_sz, 0, UChar*)
sewardj7a21c612005-02-18 09:38:08 +00001446 else FIND(".symtab", o_symtab, o_symtab_sz, 0, ElfXX_Sym*)
nethercote80f76782003-11-13 22:34:00 +00001447 else FIND(".strtab", o_strtab, o_strtab_sz, 0, UChar*)
sewardjde4a1d02002-03-22 01:27:54 +00001448
thughesc035bd92004-06-13 09:59:02 +00001449 else FIND(".gnu_debuglink", debuglink, debuglink_sz, 0, Char*)
1450
nethercote80f76782003-11-13 22:34:00 +00001451 else FIND(".stab", stab, stab_sz, 0, UChar*)
1452 else FIND(".stabstr", stabstr, stabstr_sz, 0, UChar*)
1453 else FIND(".debug_line", debug_line, debug_line_sz, 0, UChar*)
jseward8b3131a2003-12-13 23:16:26 +00001454 else FIND(".debug", dwarf1d, dwarf1d_sz, 0, UChar*)
1455 else FIND(".line", dwarf1l, dwarf1l_sz, 0, UChar*)
nethercote80f76782003-11-13 22:34:00 +00001456
1457 else FIND(".got", si->got_start, si->got_size, 1, Addr)
1458 else FIND(".plt", si->plt_start, si->plt_size, 1, Addr)
1459
jseward8b3131a2003-12-13 23:16:26 +00001460# undef FIND
nethercote80f76782003-11-13 22:34:00 +00001461
1462 /* Check some sizes */
sewardj7a21c612005-02-18 09:38:08 +00001463 vg_assert((o_dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1464 vg_assert((o_symtab_sz % sizeof(ElfXX_Sym)) == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001465 }
1466
rjwalshe4e779d2004-04-16 23:02:29 +00001467 read_symtab(si, "symbol table", False,
nethercote80f76782003-11-13 22:34:00 +00001468 o_symtab, o_symtab_sz,
1469 o_strtab, o_strtab_sz);
sewardjde4a1d02002-03-22 01:27:54 +00001470
rjwalshe4e779d2004-04-16 23:02:29 +00001471 read_symtab(si, "dynamic symbol table", True,
nethercote80f76782003-11-13 22:34:00 +00001472 o_dynsym, o_dynsym_sz,
1473 o_dynstr, o_dynstr_sz);
sewardj9b81a422003-04-26 21:42:09 +00001474
thughesc035bd92004-06-13 09:59:02 +00001475 /* Did we find a debuglink section? */
1476 if (debuglink != NULL) {
sewardjb5f6f512005-03-10 23:59:00 +00001477 UInt crc_offset = ROUNDUP(VG_(strlen)(debuglink)+1, 4);
thughesc035bd92004-06-13 09:59:02 +00001478 UInt crc;
1479
1480 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1481
1482 /* Extract the CRC from the debuglink section */
1483 crc = *(UInt *)(debuglink + crc_offset);
1484
1485 /* See if we can find a matching debug file */
1486 if ((dimage = find_debug_file(si->filename, debuglink, crc, &n_dimage)) != 0) {
sewardj7a21c612005-02-18 09:38:08 +00001487 ehdr = (ElfXX_Ehdr*)dimage;
thughesc035bd92004-06-13 09:59:02 +00001488
sewardj7a21c612005-02-18 09:38:08 +00001489 if (n_dimage >= sizeof(ElfXX_Ehdr) && VG_(is_object_file)(ehdr))
thughesc035bd92004-06-13 09:59:02 +00001490 {
sewardj7a21c612005-02-18 09:38:08 +00001491 shdr = (ElfXX_Shdr*)(dimage + ehdr->e_shoff);
thughesc035bd92004-06-13 09:59:02 +00001492 sh_strtab = (UChar*)(dimage + shdr[ehdr->e_shstrndx].sh_offset);
1493
1494 /* Find all interesting sections */
1495 for (i = 0; i < ehdr->e_shnum; i++) {
1496# define FIND(sec_name, sec_data, sec_size, type) \
1497 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1498 if (0 != sec_data) \
1499 VG_(core_panic)("repeated section!\n"); \
1500 sec_data = (type)(dimage + shdr[i].sh_offset); \
1501 sec_size = shdr[i].sh_size; \
1502 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1503 sec_name, sec_data, sec_data + sec_size - 1); \
1504 if ( shdr[i].sh_offset + sec_size > n_dimage ) { \
1505 VG_(symerr)(" section beyond image end?!"); \
1506 goto out; \
1507 } \
1508 }
1509
1510 /* Nb: must find where .got and .plt sections will be in the
1511 * executable image, not in the object image transiently loaded. */
1512 FIND(".stab", stab, stab_sz, UChar*)
1513 else FIND(".stabstr", stabstr, stabstr_sz, UChar*)
1514 else FIND(".debug_line", debug_line, debug_line_sz, UChar*)
1515 else FIND(".debug", dwarf1d, dwarf1d_sz, UChar*)
1516 else FIND(".line", dwarf1l, dwarf1l_sz, UChar*)
1517
1518# undef FIND
1519
1520 /* Check some sizes */
sewardj7a21c612005-02-18 09:38:08 +00001521 vg_assert((o_dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1522 vg_assert((o_symtab_sz % sizeof(ElfXX_Sym)) == 0);
thughesc035bd92004-06-13 09:59:02 +00001523 }
1524 }
1525 }
1526 }
1527
nethercote80f76782003-11-13 22:34:00 +00001528 /* Read the stabs and/or dwarf2 debug information, if any. */
1529 if (stab != NULL && stabstr != NULL) {
jseward8b3131a2003-12-13 23:16:26 +00001530 has_debuginfo = True;
1531 VG_(read_debuginfo_stabs) ( si, stab, stab_sz,
1532 stabstr, stabstr_sz );
1533 }
sewardj7a21c612005-02-18 09:38:08 +00001534 if (debug_line && VGA_WORD_SIZE==4/*hack*/) {
jseward8b3131a2003-12-13 23:16:26 +00001535 has_debuginfo = True;
nethercote80f76782003-11-13 22:34:00 +00001536 VG_(read_debuginfo_dwarf2) ( si, debug_line, debug_line_sz );
jseward8b3131a2003-12-13 23:16:26 +00001537 }
1538 if (dwarf1d && dwarf1l) {
1539 has_debuginfo = True;
1540 VG_(read_debuginfo_dwarf1) ( si, dwarf1d, dwarf1d_sz,
1541 dwarf1l, dwarf1l_sz );
1542 }
1543 if (!has_debuginfo) {
nethercote80f76782003-11-13 22:34:00 +00001544 VG_(symerr)(" object doesn't have any debug info");
1545 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001546 }
1547 }
nethercote80f76782003-11-13 22:34:00 +00001548 res = True;
sewardjde4a1d02002-03-22 01:27:54 +00001549
nethercotee567e702004-07-10 17:49:17 +00001550 out: {
1551 Int m_res;
thughesc035bd92004-06-13 09:59:02 +00001552 /* Last, but not least, heave the image(s) back overboard. */
nethercotee567e702004-07-10 17:49:17 +00001553 if (dimage) {
1554 m_res = VG_(munmap) ( (void*)dimage, n_dimage );
1555 vg_assert(0 == m_res);
1556 }
1557 m_res = VG_(munmap) ( (void*)oimage, n_oimage );
1558 vg_assert(0 == m_res);
nethercote80f76782003-11-13 22:34:00 +00001559 return res;
nethercotee567e702004-07-10 17:49:17 +00001560 }
sewardjde4a1d02002-03-22 01:27:54 +00001561}
1562
sewardjde4a1d02002-03-22 01:27:54 +00001563/*------------------------------------------------------------*/
1564/*--- Main entry point for symbols table reading. ---*/
1565/*------------------------------------------------------------*/
1566
1567/* The root structure for the entire symbol table system. It is a
1568 linked list of SegInfos. Note that this entire mechanism assumes
1569 that what we read from /proc/self/maps doesn't contain overlapping
1570 address ranges, and as a result the SegInfos in this list describe
1571 disjoint address ranges.
1572*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001573SegInfo *VG_(read_seg_symbols) ( Segment *seg )
sewardjde4a1d02002-03-22 01:27:54 +00001574{
1575 SegInfo* si;
1576
fitzhardinge98abfc72003-12-16 02:05:15 +00001577 vg_assert(seg->symtab == NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001578
njnfa1016e2003-09-25 17:54:11 +00001579 VGP_PUSHCC(VgpReadSyms);
1580
sewardjde4a1d02002-03-22 01:27:54 +00001581 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001582 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001583
sewardj8fe15a32002-10-20 19:29:21 +00001584 VG_(memset)(si, 0, sizeof(*si));
fitzhardinge98abfc72003-12-16 02:05:15 +00001585 si->start = seg->addr;
1586 si->size = seg->len;
1587 si->foffset = seg->offset;
fitzhardinge1a4adf02003-12-22 10:42:59 +00001588 si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00001589
1590 si->ref = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001591
1592 si->symtab = NULL;
1593 si->symtab_size = si->symtab_used = 0;
1594 si->loctab = NULL;
1595 si->loctab_size = si->loctab_used = 0;
jsgfcb1d1c02003-10-14 21:55:10 +00001596 si->strchunks = NULL;
1597 si->scopetab = NULL;
1598 si->scopetab_size = si->scopetab_used = 0;
1599
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 si->seg = seg;
1601
jsgfcb1d1c02003-10-14 21:55:10 +00001602 si->stab_typetab = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001603
nethercote80f76782003-11-13 22:34:00 +00001604 si->plt_start = si->plt_size = 0;
1605 si->got_start = si->got_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001606 si->data_start = si->data_size = 0;
nethercote80f76782003-11-13 22:34:00 +00001607 si->bss_start = si->bss_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001608
sewardjde4a1d02002-03-22 01:27:54 +00001609 /* And actually fill it up. */
sewardj8fe15a32002-10-20 19:29:21 +00001610 if (!vg_read_lib_symbols ( si ) && 0) {
1611 /* XXX this interacts badly with the prevN optimization in
1612 addStr(). Since this frees the si, the si pointer value can
1613 be recycled, which confuses the curr_si == si test. For now,
1614 this code is disabled, and everything is included in the
1615 segment list, even if it is a bad ELF file. Ironically,
1616 running this under valgrind itself hides the problem, because
1617 it doesn't recycle pointers... */
1618 freeSegInfo( si );
1619 } else {
1620 si->next = segInfo;
1621 segInfo = si;
1622
1623 canonicaliseSymtab ( si );
1624 canonicaliseLoctab ( si );
jsgfcb1d1c02003-10-14 21:55:10 +00001625 canonicaliseScopetab ( si );
fitzhardinge98abfc72003-12-16 02:05:15 +00001626
1627 /* do redirects */
sewardjb5f6f512005-03-10 23:59:00 +00001628 VG_(resolve_seg_redirs)( si );
sewardj8fe15a32002-10-20 19:29:21 +00001629 }
njnfa1016e2003-09-25 17:54:11 +00001630 VGP_POPCC(VgpReadSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001631
1632 return si;
sewardjde4a1d02002-03-22 01:27:54 +00001633}
1634
1635
sewardjde4a1d02002-03-22 01:27:54 +00001636/* When an munmap() call happens, check to see whether it corresponds
1637 to a segment for a .so, and if so discard the relevant SegInfo.
1638 This might not be a very clever idea from the point of view of
1639 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001640 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001641*/
nethercote928a5f72004-11-03 18:10:37 +00001642static void unload_symbols ( Addr start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +00001643{
1644 SegInfo *prev, *curr;
1645
sewardjde4a1d02002-03-22 01:27:54 +00001646 prev = NULL;
1647 curr = segInfo;
1648 while (True) {
1649 if (curr == NULL) break;
1650 if (start == curr->start) break;
1651 prev = curr;
1652 curr = curr->next;
1653 }
njnfa1016e2003-09-25 17:54:11 +00001654 if (curr == NULL) {
1655 VGP_POPCC(VgpReadSyms);
njn25e49d8e72002-09-23 09:36:25 +00001656 return;
njnfa1016e2003-09-25 17:54:11 +00001657 }
sewardjde4a1d02002-03-22 01:27:54 +00001658
mueller75c0ed62003-11-19 00:47:00 +00001659 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +00001660 VG_(message)(Vg_DebugMsg,
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 "discard syms at %p-%p in %s due to munmap()",
1662 start, start+length, curr->filename ? curr->filename : (Char *)"???");
sewardjde4a1d02002-03-22 01:27:54 +00001663
1664 vg_assert(prev == NULL || prev->next == curr);
1665
1666 if (prev == NULL) {
1667 segInfo = curr->next;
1668 } else {
1669 prev->next = curr->next;
1670 }
1671
1672 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001673 return;
sewardjde4a1d02002-03-22 01:27:54 +00001674}
1675
nethercote8991d5a2004-11-03 17:07:46 +00001676void VG_(symtab_decref)(SegInfo *si, Addr start)
fitzhardinge98abfc72003-12-16 02:05:15 +00001677{
1678 vg_assert(si->ref >= 1);
1679 if (--si->ref == 0)
nethercote85cdd342004-08-01 22:36:40 +00001680 unload_symbols(si->start, si->size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001681}
1682
1683void VG_(symtab_incref)(SegInfo *si)
1684{
1685 vg_assert(si->ref > 0);
1686 si->ref++;
1687}
sewardjde4a1d02002-03-22 01:27:54 +00001688
1689/*------------------------------------------------------------*/
1690/*--- Use of symbol table & location info to create ---*/
1691/*--- plausible-looking stack dumps. ---*/
1692/*------------------------------------------------------------*/
1693
1694/* Find a symbol-table index containing the specified pointer, or -1
1695 if not found. Binary search. */
1696
njn25e49d8e72002-09-23 09:36:25 +00001697static Int search_one_symtab ( SegInfo* si, Addr ptr,
1698 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001699{
1700 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001701 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001702 lo = 0,
1703 hi = si->symtab_used-1;
1704 while (True) {
1705 /* current unsearched space is from lo to hi, inclusive. */
1706 if (lo > hi) return -1; /* not found */
1707 mid = (lo + hi) / 2;
1708 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001709 size = ( match_anywhere_in_fun
1710 ? si->symtab[mid].size
1711 : 1);
1712 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001713
1714 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1715 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1716 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1717 return mid;
1718 }
1719}
1720
1721
sewardj25c7c3a2003-07-10 00:17:58 +00001722/* SLOW (Linear search). Try and map a symbol name to an address.
1723 Since this is searching in the direction opposite to which the
1724 table is designed we have no option but to do a complete linear
1725 scan of the table. Returns NULL if not found. */
1726
sewardjb5f6f512005-03-10 23:59:00 +00001727Addr VG_(reverse_search_one_symtab) ( const SegInfo* si, const Char* name )
sewardj25c7c3a2003-07-10 00:17:58 +00001728{
1729 UInt i;
1730 for (i = 0; i < si->symtab_used; i++) {
sewardjc8bf5fe2003-07-13 00:53:22 +00001731 if (0)
jsgfcb1d1c02003-10-14 21:55:10 +00001732 VG_(printf)("%p %s\n", si->symtab[i].addr, si->symtab[i].name);
1733 if (0 == VG_(strcmp)(name, si->symtab[i].name))
sewardj25c7c3a2003-07-10 00:17:58 +00001734 return si->symtab[i].addr;
1735 }
1736 return (Addr)NULL;
1737}
1738
1739
sewardjde4a1d02002-03-22 01:27:54 +00001740/* Search all symtabs that we know about to locate ptr. If found, set
1741 *psi to the relevant SegInfo, and *symno to the symtab entry number
1742 within that. If not found, *psi is set to NULL. */
1743
njn25e49d8e72002-09-23 09:36:25 +00001744static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1745 /*OUT*/Int* symno,
1746 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001747{
1748 Int sno;
1749 SegInfo* si;
fitzhardinge98abfc72003-12-16 02:05:15 +00001750 Segment *s;
njn25e49d8e72002-09-23 09:36:25 +00001751
njn25e49d8e72002-09-23 09:36:25 +00001752 VGP_PUSHCC(VgpSearchSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001753
1754 s = VG_(find_segment)(ptr);
1755
sewardjb5f6f512005-03-10 23:59:00 +00001756 if (s == NULL || s->symtab == NULL)
fitzhardinge98abfc72003-12-16 02:05:15 +00001757 goto not_found;
njn25e49d8e72002-09-23 09:36:25 +00001758
fitzhardinge98abfc72003-12-16 02:05:15 +00001759 si = s->symtab;
1760
1761 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
1762 if (sno == -1) goto not_found;
1763
1764 *symno = sno;
1765 *psi = si;
1766 VGP_POPCC(VgpSearchSyms);
1767 return;
1768
sewardjde4a1d02002-03-22 01:27:54 +00001769 not_found:
1770 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001771 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001772}
1773
1774
1775/* Find a location-table index containing the specified pointer, or -1
1776 if not found. Binary search. */
1777
1778static Int search_one_loctab ( SegInfo* si, Addr ptr )
1779{
1780 Addr a_mid_lo, a_mid_hi;
1781 Int mid,
1782 lo = 0,
1783 hi = si->loctab_used-1;
1784 while (True) {
1785 /* current unsearched space is from lo to hi, inclusive. */
1786 if (lo > hi) return -1; /* not found */
1787 mid = (lo + hi) / 2;
1788 a_mid_lo = si->loctab[mid].addr;
1789 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1790
1791 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1792 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1793 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1794 return mid;
1795 }
1796}
1797
1798
1799/* Search all loctabs that we know about to locate ptr. If found, set
1800 *psi to the relevant SegInfo, and *locno to the loctab entry number
1801 within that. If not found, *psi is set to NULL.
1802*/
njn25e49d8e72002-09-23 09:36:25 +00001803static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
1804 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00001805{
1806 Int lno;
1807 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001808
1809 VGP_PUSHCC(VgpSearchSyms);
1810
sewardjde4a1d02002-03-22 01:27:54 +00001811 for (si = segInfo; si != NULL; si = si->next) {
1812 if (si->start <= ptr && ptr < si->start+si->size) {
1813 lno = search_one_loctab ( si, ptr );
1814 if (lno == -1) goto not_found;
1815 *locno = lno;
1816 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001817 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001818 return;
1819 }
1820 }
1821 not_found:
1822 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001823 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001824}
1825
1826
jsgfcb1d1c02003-10-14 21:55:10 +00001827/* Find a scope-table index containing the specified pointer, or -1
1828 if not found. Binary search. */
1829
1830static Int search_one_scopetab ( SegInfo* si, Addr ptr )
1831{
1832 Addr a_mid_lo, a_mid_hi;
1833 Int mid,
1834 lo = 0,
1835 hi = si->scopetab_used-1;
1836 while (True) {
1837 /* current unsearched space is from lo to hi, inclusive. */
1838 if (lo > hi) return -1; /* not found */
1839 mid = (lo + hi) / 2;
1840 a_mid_lo = si->scopetab[mid].addr;
1841 a_mid_hi = ((Addr)si->scopetab[mid].addr) + si->scopetab[mid].size - 1;
1842
1843 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1844 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1845 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1846 return mid;
1847 }
1848}
1849
1850
1851/* Search all scopetabs that we know about to locate ptr. If found, set
1852 *psi to the relevant SegInfo, and *locno to the scopetab entry number
1853 within that. If not found, *psi is set to NULL.
1854*/
1855static void search_all_scopetabs ( Addr ptr,
1856 /*OUT*/SegInfo** psi,
1857 /*OUT*/Int* scopeno )
1858{
1859 Int scno;
1860 SegInfo* si;
1861
1862 VGP_PUSHCC(VgpSearchSyms);
1863
1864 for (si = segInfo; si != NULL; si = si->next) {
1865 if (si->start <= ptr && ptr < si->start+si->size) {
1866 scno = search_one_scopetab ( si, ptr );
1867 if (scno == -1) goto not_found;
1868 *scopeno = scno;
1869 *psi = si;
1870 VGP_POPCC(VgpSearchSyms);
1871 return;
1872 }
1873 }
1874 not_found:
1875 *psi = NULL;
1876 VGP_POPCC(VgpSearchSyms);
1877}
1878
sewardjde4a1d02002-03-22 01:27:54 +00001879/* The whole point of this whole big deal: map a code address to a
1880 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00001881 Caller supplies buf and nbuf. If demangle is False, don't do
sewardjde4a1d02002-03-22 01:27:54 +00001882 demangling, regardless of vg_clo_demangle -- probably because the
1883 call has come from vg_what_fn_or_object_is_this. */
njn25e49d8e72002-09-23 09:36:25 +00001884static
1885Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
sewardj1771e172002-11-13 22:06:35 +00001886 Bool match_anywhere_in_fun, Bool show_offset)
sewardjde4a1d02002-03-22 01:27:54 +00001887{
1888 SegInfo* si;
1889 Int sno;
sewardj1771e172002-11-13 22:06:35 +00001890 Int offset;
1891
njn25e49d8e72002-09-23 09:36:25 +00001892 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001893 if (si == NULL)
1894 return False;
njn25e49d8e72002-09-23 09:36:25 +00001895 if (demangle) {
jsgfcb1d1c02003-10-14 21:55:10 +00001896 VG_(demangle) ( si->symtab[sno].name, buf, nbuf );
njn25e49d8e72002-09-23 09:36:25 +00001897 } else {
sewardjde4a1d02002-03-22 01:27:54 +00001898 VG_(strncpy_safely)
jsgfcb1d1c02003-10-14 21:55:10 +00001899 ( buf, si->symtab[sno].name, nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00001900 }
sewardj1771e172002-11-13 22:06:35 +00001901
1902 offset = a - si->symtab[sno].addr;
1903 if (show_offset && offset != 0) {
1904 Char buf2[12];
1905 Char* symend = buf + VG_(strlen)(buf);
1906 Char* end = buf + nbuf;
1907 Int len;
1908
1909 len = VG_(sprintf)(buf2, "%c%d",
1910 offset < 0 ? '-' : '+',
1911 offset < 0 ? -offset : offset);
sewardj05bcdcb2003-05-18 10:05:38 +00001912 vg_assert(len < (Int)sizeof(buf2));
sewardj1771e172002-11-13 22:06:35 +00001913
1914 if (len < (end - symend)) {
1915 Char *cp = buf2;
1916 VG_(memcpy)(symend, cp, len+1);
1917 }
1918 }
1919
sewardjde4a1d02002-03-22 01:27:54 +00001920 return True;
1921}
1922
nethercote7cc9c232004-01-21 15:08:04 +00001923/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001924 match anywhere in function, but don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001925Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1926{
1927 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001928 /*match_anywhere_in_fun*/True,
1929 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001930}
sewardjde4a1d02002-03-22 01:27:54 +00001931
nethercote7cc9c232004-01-21 15:08:04 +00001932/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001933 match anywhere in function, and show offset if nonzero. */
1934Bool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1935{
1936 return get_fnname ( /*demangle*/True, a, buf, nbuf,
1937 /*match_anywhere_in_fun*/True,
1938 /*show offset?*/True );
1939}
1940
nethercote7cc9c232004-01-21 15:08:04 +00001941/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001942 only succeed if 'a' matches first instruction of function,
1943 and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001944Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1945{
1946 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001947 /*match_anywhere_in_fun*/False,
1948 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001949}
1950
sewardj6e008cb2002-12-15 13:11:39 +00001951/* This is only available to core... don't demangle C++ names,
1952 match anywhere in function, and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001953Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
1954{
1955 return get_fnname ( /*demangle*/False, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001956 /*match_anywhere_in_fun*/True,
1957 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001958}
1959
1960/* Map a code address to the name of a shared object file or the executable.
1961 Returns False if no idea; otherwise True. Doesn't require debug info.
1962 Caller supplies buf and nbuf. */
1963Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001964{
1965 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001966
sewardjde4a1d02002-03-22 01:27:54 +00001967 for (si = segInfo; si != NULL; si = si->next) {
1968 if (si->start <= a && a < si->start+si->size) {
1969 VG_(strncpy_safely)(buf, si->filename, nbuf);
1970 return True;
1971 }
1972 }
1973 return False;
1974}
1975
njnb877d492003-01-28 20:40:57 +00001976/* Map a code address to its SegInfo. Returns NULL if not found. Doesn't
1977 require debug info. */
1978SegInfo* VG_(get_obj) ( Addr a )
1979{
1980 SegInfo* si;
1981
njnb877d492003-01-28 20:40:57 +00001982 for (si = segInfo; si != NULL; si = si->next) {
1983 if (si->start <= a && a < si->start+si->size) {
1984 return si;
1985 }
1986 }
nethercote80f76782003-11-13 22:34:00 +00001987 return NULL;
njnb877d492003-01-28 20:40:57 +00001988}
1989
njn25e49d8e72002-09-23 09:36:25 +00001990
1991/* Map a code address to a filename. Returns True if successful. */
1992Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00001993{
njn25e49d8e72002-09-23 09:36:25 +00001994 SegInfo* si;
1995 Int locno;
1996 search_all_loctabs ( a, &si, &locno );
1997 if (si == NULL)
1998 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00001999 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
njn25e49d8e72002-09-23 09:36:25 +00002000 n_filename);
2001 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002002}
2003
njn25e49d8e72002-09-23 09:36:25 +00002004/* Map a code address to a line number. Returns True if successful. */
2005Bool VG_(get_linenum)( Addr a, UInt* lineno )
2006{
2007 SegInfo* si;
2008 Int locno;
2009 search_all_loctabs ( a, &si, &locno );
2010 if (si == NULL)
2011 return False;
2012 *lineno = si->loctab[locno].lineno;
2013
2014 return True;
2015}
sewardjde4a1d02002-03-22 01:27:54 +00002016
2017/* Map a code address to a (filename, line number) pair.
2018 Returns True if successful.
2019*/
njn25e49d8e72002-09-23 09:36:25 +00002020Bool VG_(get_filename_linenum)( Addr a,
2021 Char* filename, Int n_filename,
2022 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00002023{
2024 SegInfo* si;
2025 Int locno;
2026 search_all_loctabs ( a, &si, &locno );
2027 if (si == NULL)
2028 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00002029 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
sewardjde4a1d02002-03-22 01:27:54 +00002030 n_filename);
2031 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00002032
sewardjde4a1d02002-03-22 01:27:54 +00002033 return True;
2034}
2035
jsgfcb1d1c02003-10-14 21:55:10 +00002036#ifndef TEST
2037
2038/* return a pointer to a register (now for 5 other impossible things
2039 before breakfast) */
2040static UInt *regaddr(ThreadId tid, Int regno)
2041{
2042 UInt *ret = 0;
2043
sewardj2a99cf62004-11-24 10:44:19 +00002044 ret = VGA_(reg_addr_from_tst)(regno, &VG_(threads)[tid].arch);
jsgfcb1d1c02003-10-14 21:55:10 +00002045
2046 if (ret == 0) {
2047 Char file[100];
2048 Int line;
njn67516132005-03-22 04:02:43 +00002049 Addr eip = VG_(get_IP)(tid);
jsgfcb1d1c02003-10-14 21:55:10 +00002050
2051 if (!VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
2052 file[0] = 0;
2053 VG_(printf)("mysterious register %d used at %p %s:%d\n",
2054 regno, eip, file, line);
2055 }
2056
2057 return ret;
2058}
2059
2060/* Get a list of all variables in scope, working out from the directly
2061 current one */
2062Variable *VG_(get_scope_variables)(ThreadId tid)
2063{
2064 static const Bool debug = False;
2065 Variable *list, *end;
2066 Addr eip;
2067 SegInfo *si;
2068 Int scopeidx;
2069 Scope *scope;
2070 Int distance;
2071 static const Int maxsyms = 1000;
2072 Int nsyms = maxsyms;
2073
2074 list = end = NULL;
2075
njn67516132005-03-22 04:02:43 +00002076 eip = VG_(get_IP)(tid);
jsgfcb1d1c02003-10-14 21:55:10 +00002077
2078 search_all_scopetabs(eip, &si, &scopeidx);
2079
2080 if (debug)
2081 VG_(printf)("eip=%p si=%p (%s; offset=%p) scopeidx=%d\n",
2082 eip, si, si ? si->filename : (Char *)"???",
2083 si ? si->offset : 0x99999, scopeidx);
2084
2085 if (si == NULL)
2086 return NULL; /* nothing in scope (should use global scope at least) */
2087
2088 if (debug) {
2089 ScopeRange *sr = &si->scopetab[scopeidx];
2090 Char file[100];
2091 Int line;
2092
2093 if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file), &line))
2094 file[0] = 0;
2095
2096 VG_(printf)("found scope range %p: eip=%p (%s:%d) size=%d scope=%p\n",
2097 sr, sr->addr, file, line, sr->size, sr->scope);
2098 }
2099
2100 distance = 0;
2101 for(scope = si->scopetab[scopeidx].scope; scope != NULL; scope = scope->outer, distance++) {
2102 UInt i;
2103
2104 for(i = 0; i < scope->nsyms; i++) {
2105 Sym *sym = &scope->syms[i];
2106 Variable *v;
2107
2108 if (nsyms-- == 0) {
2109 VG_(printf)("max %d syms reached\n", maxsyms);
2110 return list;
2111 }
2112
2113 v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
2114
2115 v->next = NULL;
2116 v->distance = distance;
2117 v->type = VG_(st_basetype)(sym->type, False);
2118 v->name = VG_(arena_strdup)(VG_AR_SYMTAB, sym->name);
2119 v->container = NULL;
2120 v->size = VG_(st_sizeof)(sym->type);
2121
2122 if (debug && 0)
mueller5ed88f22004-01-06 16:02:29 +00002123 VG_(printf)("sym->name=%s sym->kind=%d offset=%d\n", sym->name, sym->kind, sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002124 switch(sym->kind) {
2125 UInt reg;
2126
2127 case SyGlobal:
2128 case SyStatic:
mueller5ed88f22004-01-06 16:02:29 +00002129 if (sym->u.addr == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00002130 /* XXX lookup value */
2131 }
mueller5ed88f22004-01-06 16:02:29 +00002132 v->valuep = sym->u.addr;
jsgfcb1d1c02003-10-14 21:55:10 +00002133 break;
2134
2135 case SyReg:
mueller5ed88f22004-01-06 16:02:29 +00002136 v->valuep = (Addr)regaddr(tid, sym->u.regno);
jsgfcb1d1c02003-10-14 21:55:10 +00002137 break;
2138
2139 case SyEBPrel:
2140 case SyESPrel:
nethercotecd656042004-09-11 23:48:22 +00002141 reg = *regaddr(tid, sym->kind == SyESPrel ?
2142 R_STACK_PTR : R_FRAME_PTR);
jsgfcb1d1c02003-10-14 21:55:10 +00002143 if (debug)
mueller5ed88f22004-01-06 16:02:29 +00002144 VG_(printf)("reg=%p+%d=%p\n", reg, sym->u.offset, reg+sym->u.offset);
2145 v->valuep = (Addr)(reg + sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002146 break;
2147
2148 case SyType:
2149 VG_(core_panic)("unexpected typedef in scope");
2150 }
2151
2152 if (v->valuep == 0) {
2153 /* not interesting or useful */
2154 VG_(arena_free)(VG_AR_SYMTAB, v);
2155 continue;
2156 }
2157
2158 /* append to end of list */
2159 if (list == NULL)
2160 list = end = v;
2161 else {
2162 end->next = v;
2163 end = v;
2164 }
2165 }
2166 }
2167
2168 return list;
2169}
2170#endif /* TEST */
2171
njn6c846552003-09-16 07:41:43 +00002172/* Print into buf info on code address, function name and filename */
njnd01fef72005-03-25 23:35:48 +00002173Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
sewardjde4a1d02002-03-22 01:27:54 +00002174{
njn6c846552003-09-16 07:41:43 +00002175#define APPEND(str) \
2176 { UChar* sss; \
2177 for (sss = str; n < n_buf-1 && *sss != 0; n++,sss++) \
2178 buf[n] = *sss; \
2179 buf[n] = '\0'; \
sewardjde4a1d02002-03-22 01:27:54 +00002180 }
nethercote80f76782003-11-13 22:34:00 +00002181 UInt lineno;
2182 UChar ibuf[20];
2183 UInt n = 0;
njn47b209a2005-03-25 23:47:16 +00002184 static UChar buf_fn[VG_ERRTXT_LEN];
2185 static UChar buf_obj[VG_ERRTXT_LEN];
2186 static UChar buf_srcloc[VG_ERRTXT_LEN];
2187 Bool know_fnname = VG_(get_fnname) (eip, buf_fn, VG_ERRTXT_LEN);
2188 Bool know_objname = VG_(get_objname)(eip, buf_obj, VG_ERRTXT_LEN);
2189 Bool know_srcloc = VG_(get_filename_linenum)(eip, buf_srcloc,
2190 VG_ERRTXT_LEN, &lineno);
sewardja4da2f32005-03-02 14:06:08 +00002191 VG_(sprintf)(ibuf,"0x%llx: ", (ULong)eip);
njn6c846552003-09-16 07:41:43 +00002192 APPEND(ibuf);
2193 if (know_fnname) {
2194 APPEND(buf_fn);
2195 if (!know_srcloc && know_objname) {
2196 APPEND(" (in ");
2197 APPEND(buf_obj);
2198 APPEND(")");
2199 }
2200 } else if (know_objname && !know_srcloc) {
2201 APPEND("(within ");
2202 APPEND(buf_obj);
2203 APPEND(")");
2204 } else {
2205 APPEND("???");
2206 }
2207 if (know_srcloc) {
2208 APPEND(" (");
2209 APPEND(buf_srcloc);
2210 APPEND(":");
2211 VG_(sprintf)(ibuf,"%d",lineno);
2212 APPEND(ibuf);
2213 APPEND(")");
2214 }
2215 return buf;
2216
2217#undef APPEND
2218}
2219
sewardj25c7c3a2003-07-10 00:17:58 +00002220/*------------------------------------------------------------*/
sewardj47104382002-10-20 18:35:48 +00002221/*--- SegInfo accessor functions ---*/
2222/*------------------------------------------------------------*/
2223
2224const SegInfo* VG_(next_seginfo)(const SegInfo* seg)
2225{
sewardj47104382002-10-20 18:35:48 +00002226 if (seg == NULL)
2227 return segInfo;
2228 return seg->next;
2229}
2230
2231Addr VG_(seg_start)(const SegInfo* seg)
2232{
2233 return seg->start;
2234}
2235
nethercote928a5f72004-11-03 18:10:37 +00002236SizeT VG_(seg_size)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002237{
2238 return seg->size;
2239}
2240
2241const UChar* VG_(seg_filename)(const SegInfo* seg)
2242{
2243 return seg->filename;
2244}
2245
nethercote928a5f72004-11-03 18:10:37 +00002246ULong VG_(seg_sym_offset)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002247{
2248 return seg->offset;
2249}
2250
2251VgSectKind VG_(seg_sect_kind)(Addr a)
2252{
2253 SegInfo* seg;
2254 VgSectKind ret = Vg_SectUnknown;
2255
sewardj47104382002-10-20 18:35:48 +00002256 for(seg = segInfo; seg != NULL; seg = seg->next) {
2257 if (a >= seg->start && a < (seg->start + seg->size)) {
2258 if (0)
sewardj8fe15a32002-10-20 19:29:21 +00002259 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 +00002260 a, seg, seg->filename,
2261 seg->got_start, seg->got_size,
sewardj8fe15a32002-10-20 19:29:21 +00002262 seg->plt_start, seg->plt_size,
2263 seg->data_start, seg->data_size,
2264 seg->bss_start, seg->bss_size);
sewardj47104382002-10-20 18:35:48 +00002265 ret = Vg_SectText;
2266
sewardj8fe15a32002-10-20 19:29:21 +00002267 if (a >= seg->data_start && a < (seg->data_start + seg->data_size))
2268 ret = Vg_SectData;
2269 else if (a >= seg->bss_start && a < (seg->bss_start + seg->bss_size))
2270 ret = Vg_SectBSS;
2271 else if (a >= seg->plt_start && a < (seg->plt_start + seg->plt_size))
sewardj47104382002-10-20 18:35:48 +00002272 ret = Vg_SectPLT;
2273 else if (a >= seg->got_start && a < (seg->got_start + seg->got_size))
2274 ret = Vg_SectGOT;
2275 }
2276 }
2277
2278 return ret;
2279}
2280
sewardjde4a1d02002-03-22 01:27:54 +00002281/*--------------------------------------------------------------------*/
2282/*--- end vg_symtab2.c ---*/
2283/*--------------------------------------------------------------------*/