blob: 874ab227fb5480305cb6f9467c2881ef60ece84f [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001/*--------------------------------------------------------------------*/
2/*--- Management of symbols and debugging information. ---*/
3/*--- vg_symtab2.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercotef1e5e152004-09-01 23:58:16 +000031#include "core.h"
jsgfcb1d1c02003-10-14 21:55:10 +000032#include "vg_symtypes.h"
33#include "vg_symtab2.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
35#include <elf.h> /* ELF defns */
sewardjde4a1d02002-03-22 01:27:54 +000036
rjwalshe4e779d2004-04-16 23:02:29 +000037static Bool
nethercoteb1e1ad42004-08-03 23:44:12 +000038intercept_demangle(const Char*, Char*, Int);
njn9aae6742002-04-30 13:44:01 +000039
sewardjde4a1d02002-03-22 01:27:54 +000040/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
41 dlopen()ed libraries, which is something that KDE3 does a lot.
sewardjde4a1d02002-03-22 01:27:54 +000042
njn25e49d8e72002-09-23 09:36:25 +000043 Stabs reader greatly improved by Nick Nethercote, Apr 02.
sewardjde4a1d02002-03-22 01:27:54 +000044*/
45
sewardjde4a1d02002-03-22 01:27:54 +000046static void freeSegInfo ( SegInfo* si )
47{
jsgfcb1d1c02003-10-14 21:55:10 +000048 struct strchunk *chunk, *next;
sewardjde4a1d02002-03-22 01:27:54 +000049 vg_assert(si != NULL);
njn25e49d8e72002-09-23 09:36:25 +000050 if (si->filename) VG_(arena_free)(VG_AR_SYMTAB, si->filename);
51 if (si->symtab) VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
52 if (si->loctab) VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
jsgfcb1d1c02003-10-14 21:55:10 +000053 if (si->scopetab) VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
54
55 for(chunk = si->strchunks; chunk != NULL; chunk = next) {
56 next = chunk->next;
57 VG_(arena_free)(VG_AR_SYMTAB, chunk);
58 }
njn25e49d8e72002-09-23 09:36:25 +000059 VG_(arena_free)(VG_AR_SYMTAB, si);
sewardjde4a1d02002-03-22 01:27:54 +000060}
61
62
63/*------------------------------------------------------------*/
64/*--- Adding stuff ---*/
65/*------------------------------------------------------------*/
66
67/* Add a str to the string table, including terminating zero, and
jsgfcb1d1c02003-10-14 21:55:10 +000068 return pointer to the string in vg_strtab. Unless it's been seen
69 recently, in which case we find the old pointer and return that.
70 This avoids the most egregious duplications.
sewardjde4a1d02002-03-22 01:27:54 +000071
jsgfcb1d1c02003-10-14 21:55:10 +000072 JSGF: changed from returning an index to a pointer, and changed to
73 a chunking memory allocator rather than reallocating, so the
74 pointers are stable.
75*/
76
77Char *VG_(addStr) ( SegInfo* si, Char* str, Int len )
sewardjde4a1d02002-03-22 01:27:54 +000078{
jsgfcb1d1c02003-10-14 21:55:10 +000079# define EMPTY NULL
njn25e49d8e72002-09-23 09:36:25 +000080# define NN 5
81
82 /* prevN[0] has the most recent, prevN[NN-1] the least recent */
jsgfcb1d1c02003-10-14 21:55:10 +000083 static Char *prevN[NN] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
njn25e49d8e72002-09-23 09:36:25 +000084 static SegInfo* curr_si = NULL;
jsgfcb1d1c02003-10-14 21:55:10 +000085 struct strchunk *chunk;
86 Int i, space_needed;
njn25e49d8e72002-09-23 09:36:25 +000087
jsgfcb1d1c02003-10-14 21:55:10 +000088 if (len == -1)
89 len = VG_(strlen)(str);
njn25e49d8e72002-09-23 09:36:25 +000090
91 /* Avoid gratuitous duplication: if we saw `str' within the last NN,
92 * within this segment, return that index. Saves about 200KB in glibc,
93 * extra time taken is too small to measure. --NJN 2002-Aug-30 */
94 if (curr_si == si) {
95 for (i = NN-1; i >= 0; i--) {
sewardjcda419b2002-10-01 08:59:36 +000096 if (EMPTY != prevN[i]
jsgfcb1d1c02003-10-14 21:55:10 +000097 && NULL != si->strchunks
jsgfa065a9c2003-10-14 22:07:31 +000098 && 0 == VG_(memcmp)(str, prevN[i], len+1)) {
njn25e49d8e72002-09-23 09:36:25 +000099 return prevN[i];
100 }
101 }
102 } else {
103 /* New segment */
104 curr_si = si;
sewardjcda419b2002-10-01 08:59:36 +0000105 for (i = 0; i < NN; i++) prevN[i] = EMPTY;
njn25e49d8e72002-09-23 09:36:25 +0000106 }
107 /* Shuffle prevous ones along, put new one in. */
jsgfcb1d1c02003-10-14 21:55:10 +0000108 for (i = NN-1; i > 0; i--)
109 prevN[i] = prevN[i-1];
njn25e49d8e72002-09-23 09:36:25 +0000110
111# undef EMPTY
112
jsgfcb1d1c02003-10-14 21:55:10 +0000113 space_needed = 1 + len;
njn25e49d8e72002-09-23 09:36:25 +0000114
jsgfcb1d1c02003-10-14 21:55:10 +0000115 if (si->strchunks == NULL ||
116 (si->strchunks->strtab_used + space_needed) > STRCHUNKSIZE) {
117 chunk = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*chunk));
118 chunk->strtab_used = 0;
119 chunk->next = si->strchunks;
120 si->strchunks = chunk;
sewardjde4a1d02002-03-22 01:27:54 +0000121 }
jsgfcb1d1c02003-10-14 21:55:10 +0000122 chunk = si->strchunks;
sewardjde4a1d02002-03-22 01:27:54 +0000123
jsgfcb1d1c02003-10-14 21:55:10 +0000124 prevN[0] = &chunk->strtab[chunk->strtab_used];
125 VG_(memcpy)(prevN[0], str, len);
126 chunk->strtab[chunk->strtab_used+len] = '\0';
127 chunk->strtab_used += space_needed;
sewardjde4a1d02002-03-22 01:27:54 +0000128
jsgfcb1d1c02003-10-14 21:55:10 +0000129 return prevN[0];
sewardjde4a1d02002-03-22 01:27:54 +0000130}
131
132/* Add a symbol to the symbol table. */
133
134static __inline__
135void addSym ( SegInfo* si, RiSym* sym )
136{
sewardj05bcdcb2003-05-18 10:05:38 +0000137 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000138 RiSym* new_tab;
139
140 /* Ignore zero-sized syms. */
141 if (sym->size == 0) return;
142
143 if (si->symtab_used == si->symtab_size) {
144 new_sz = 2 * si->symtab_size;
145 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000146 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiSym) );
sewardjde4a1d02002-03-22 01:27:54 +0000147 if (si->symtab != NULL) {
148 for (i = 0; i < si->symtab_used; i++)
149 new_tab[i] = si->symtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000150 VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
sewardjde4a1d02002-03-22 01:27:54 +0000151 }
152 si->symtab = new_tab;
153 si->symtab_size = new_sz;
154 }
155
156 si->symtab[si->symtab_used] = *sym;
157 si->symtab_used++;
158 vg_assert(si->symtab_used <= si->symtab_size);
159}
160
161/* Add a location to the location table. */
162
163static __inline__
164void addLoc ( SegInfo* si, RiLoc* loc )
165{
sewardj05bcdcb2003-05-18 10:05:38 +0000166 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000167 RiLoc* new_tab;
168
njne0ee0712002-05-03 16:41:05 +0000169 /* Zero-sized locs should have been ignored earlier */
170 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000171
172 if (si->loctab_used == si->loctab_size) {
173 new_sz = 2 * si->loctab_size;
174 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000175 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
sewardjde4a1d02002-03-22 01:27:54 +0000176 if (si->loctab != NULL) {
177 for (i = 0; i < si->loctab_used; i++)
178 new_tab[i] = si->loctab[i];
njn25e49d8e72002-09-23 09:36:25 +0000179 VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
sewardjde4a1d02002-03-22 01:27:54 +0000180 }
181 si->loctab = new_tab;
182 si->loctab_size = new_sz;
183 }
184
185 si->loctab[si->loctab_used] = *loc;
186 si->loctab_used++;
187 vg_assert(si->loctab_used <= si->loctab_size);
188}
189
190
sewardjb51f2e62002-06-01 23:11:19 +0000191/* Top-level place to call to add a source-location mapping entry. */
192
jsgfcb1d1c02003-10-14 21:55:10 +0000193void VG_(addLineInfo) ( SegInfo* si,
194 Char* filename,
195 Addr this,
196 Addr next,
197 Int lineno,
198 Int entry /* only needed for debug printing */
199 )
sewardjb51f2e62002-06-01 23:11:19 +0000200{
jsgfcb1d1c02003-10-14 21:55:10 +0000201 static const Bool debug = False;
sewardjb51f2e62002-06-01 23:11:19 +0000202 RiLoc loc;
203 Int size = next - this;
204
205 /* Ignore zero-sized locs */
206 if (this == next) return;
207
jsgfcb1d1c02003-10-14 21:55:10 +0000208 if (debug)
209 VG_(printf)(" src %s line %d %p-%p\n", filename, lineno, this, next);
210
sewardjb51f2e62002-06-01 23:11:19 +0000211 /* Maximum sanity checking. Some versions of GNU as do a shabby
212 * job with stabs entries; if anything looks suspicious, revert to
213 * a size of 1. This should catch the instruction of interest
214 * (since if using asm-level debug info, one instruction will
215 * correspond to one line, unlike with C-level debug info where
216 * multiple instructions can map to the one line), but avoid
217 * catching any other instructions bogusly. */
thughesc1c57952004-11-01 17:36:15 +0000218 if (this > next) {
219 if (VG_(clo_verbosity) > 2) {
220 VG_(message)(Vg_DebugMsg,
221 "warning: line info addresses out of order "
222 "at entry %d: 0x%x 0x%x", entry, this, next);
223 }
sewardjb51f2e62002-06-01 23:11:19 +0000224 size = 1;
225 }
226
227 if (size > MAX_LOC_SIZE) {
sewardjd84606d2002-06-18 01:04:57 +0000228 if (0)
sewardjb51f2e62002-06-01 23:11:19 +0000229 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000230 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000231 "at entry %d: %d", entry, size);
232 size = 1;
233 }
234
sewardj08a50f62002-06-17 02:21:20 +0000235 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000236 if (this >= si->start + si->size || next-1 < si->start) {
sewardjd84606d2002-06-18 01:04:57 +0000237 if (0)
sewardj08a50f62002-06-17 02:21:20 +0000238 VG_(message)(Vg_DebugMsg,
239 "warning: ignoring line info entry falling "
240 "outside current SegInfo: %p %p %p %p",
241 si->start, si->start + si->size,
242 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000243 return;
244 }
245
246 vg_assert(lineno >= 0);
247 if (lineno > MAX_LINENO) {
248 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000249 "warning: ignoring line info entry with "
250 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000251 VG_(message)(Vg_UserMsg,
252 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000253 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000254 return;
255 }
sewardjb51f2e62002-06-01 23:11:19 +0000256
257 loc.addr = this;
258 loc.size = (UShort)size;
259 loc.lineno = lineno;
jsgfcb1d1c02003-10-14 21:55:10 +0000260 loc.filename = filename;
sewardjb642dc22002-10-12 17:27:16 +0000261
262 if (0) VG_(message)(Vg_DebugMsg,
263 "addLoc: addr %p, size %d, line %d, file %s",
jsgfcb1d1c02003-10-14 21:55:10 +0000264 this,size,lineno,filename);
sewardjb642dc22002-10-12 17:27:16 +0000265
sewardjb51f2e62002-06-01 23:11:19 +0000266 addLoc ( si, &loc );
267}
268
jsgfcb1d1c02003-10-14 21:55:10 +0000269static __inline__
270void addScopeRange ( SegInfo* si, ScopeRange *range )
271{
272 Int new_sz, i;
273 ScopeRange* new_tab;
274
275 /* Zero-sized scopes should have been ignored earlier */
276 vg_assert(range->size > 0);
277
278 if (si->scopetab_used == si->scopetab_size) {
279 new_sz = 2 * si->scopetab_size;
280 if (new_sz == 0) new_sz = 500;
281 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(*new_tab) );
282 if (si->scopetab != NULL) {
283 for (i = 0; i < si->scopetab_used; i++)
284 new_tab[i] = si->scopetab[i];
285 VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
286 }
287 si->scopetab = new_tab;
288 si->scopetab_size = new_sz;
289 }
290
291 si->scopetab[si->scopetab_used] = *range;
292 si->scopetab_used++;
293 vg_assert(si->scopetab_used <= si->scopetab_size);
294}
295
296
297/* Top-level place to call to add a source-location mapping entry. */
298
299void VG_(addScopeInfo) ( SegInfo* si,
300 Addr this,
301 Addr next,
302 Scope *scope)
303{
304 static const Bool debug = False;
305 Int size = next - this;
306 ScopeRange range;
307
fitzhardinge83d8a712004-02-05 22:58:37 +0000308 /* Ignore zero-sized or negative scopes */
309 if (size <= 0) {
jsgfcb1d1c02003-10-14 21:55:10 +0000310 if (debug)
311 VG_(printf)("ignoring zero-sized range, scope %p at %p\n", scope, this);
312 return;
313 }
314
315 if (debug)
316 VG_(printf)("adding scope range %p-%p (size=%d) scope %p (%d)\n",
317 this, next, next-this, scope, scope->depth);
318
319 range.addr = this;
320 range.size = size;
321 range.scope = scope;
322
323 addScopeRange ( si, &range );
324}
325
sewardjde4a1d02002-03-22 01:27:54 +0000326/*------------------------------------------------------------*/
327/*--- Helpers ---*/
328/*------------------------------------------------------------*/
329
330/* Non-fatal -- use vg_panic if terminal. */
jsgfcb1d1c02003-10-14 21:55:10 +0000331void VG_(symerr) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000332{
333 if (VG_(clo_verbosity) > 1)
334 VG_(message)(Vg_UserMsg,"%s", msg );
335}
336
337
338/* Print a symbol. */
339static
340void printSym ( SegInfo* si, Int i )
341{
342 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
343 i,
344 si->symtab[i].addr,
345 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
jsgfcb1d1c02003-10-14 21:55:10 +0000346 si->symtab[i].name );
sewardjde4a1d02002-03-22 01:27:54 +0000347}
348
nethercote80f76782003-11-13 22:34:00 +0000349#define TRACE_SYMTAB(format, args...) \
350 if (VG_(clo_trace_symtab)) { VG_(printf)(format, ## args); }
351
sewardjde4a1d02002-03-22 01:27:54 +0000352
353#if 0
354/* Print the entire sym tab. */
355static __attribute__ ((unused))
356void printSymtab ( void )
357{
358 Int i;
359 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
360 for (i = 0; i < vg_symtab_used; i++)
361 printSym(i);
362 VG_(printf)("------ BEGIN vg_symtab ------\n");
363}
364#endif
365
366#if 0
367/* Paranoid strcat. */
368static
369void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
370{
371 UInt i = 0, j = 0;
372 while (True) {
373 if (i >= maxlen) return;
374 if (dst[i] == 0) break;
375 i++;
376 }
377 while (True) {
378 if (i >= maxlen) return;
379 dst[i] = src[j];
380 if (src[j] == 0) return;
381 i++; j++;
382 }
383}
384#endif
385
sewardjb51f2e62002-06-01 23:11:19 +0000386
sewardjde4a1d02002-03-22 01:27:54 +0000387/*------------------------------------------------------------*/
388/*--- Canonicalisers ---*/
389/*------------------------------------------------------------*/
390
391/* Sort the symtab by starting address, and emit warnings if any
nethercote80f76782003-11-13 22:34:00 +0000392 symbols have overlapping address ranges. We use that old chestnut,
393 shellsort. Mash the table around so as to establish the property
394 that addresses are in order and the ranges to not overlap. This
395 facilitates using binary search to map addresses to symbols when we
396 come to query the table.
sewardjde4a1d02002-03-22 01:27:54 +0000397*/
jsgfcb1d1c02003-10-14 21:55:10 +0000398static Int compare_RiSym(void *va, void *vb) {
399 RiSym *a = (RiSym *)va;
400 RiSym *b = (RiSym *)vb;
401
nethercote05fdfac2004-08-01 20:24:46 +0000402 if (a->addr < b->addr) return -1;
403 if (a->addr > b->addr) return 1;
404 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000405}
406
fitzhardinge1c76dc42003-12-15 09:00:21 +0000407/* Two symbols have the same address. Which name do we prefer?
408
409 In general we prefer the longer name, but if the choice is between
410 __libc_X and X, then choose X (similarly with __GI__ and __
411 prefixes).
412 */
413static RiSym *prefersym(RiSym *a, RiSym *b)
414{
415 Int pfx;
fitzhardingeefda47f2003-12-15 23:31:52 +0000416 Int lena, lenb;
417 Int i;
418 static const struct {
419 const Char *prefix;
420 Int len;
421 } prefixes[] = {
422#define PFX(x) { x, sizeof(x)-1 }
423 /* order from longest to shortest */
424 PFX("__GI___libc_"),
425 PFX("__GI___"),
426 PFX("__libc_"),
427 PFX("__GI__"),
428 PFX("__GI_"),
429 PFX("__"),
430#undef PFX
431 };
432
433 lena = VG_(strlen)(a->name);
434 lenb = VG_(strlen)(b->name);
fitzhardinge1c76dc42003-12-15 09:00:21 +0000435
436 /* rearrange so that a is the long one */
fitzhardingeefda47f2003-12-15 23:31:52 +0000437 if (lena < lenb) {
fitzhardinge1c76dc42003-12-15 09:00:21 +0000438 RiSym *t;
fitzhardingeefda47f2003-12-15 23:31:52 +0000439 Int lt;
fitzhardinge1c76dc42003-12-15 09:00:21 +0000440
441 t = a;
442 a = b;
443 b = t;
fitzhardingeefda47f2003-12-15 23:31:52 +0000444
445 lt = lena;
446 lena = lenb;
447 lenb = lt;
fitzhardinge1c76dc42003-12-15 09:00:21 +0000448 }
449
rjwalshe4e779d2004-04-16 23:02:29 +0000450 /* Ugh. If we get a "free", always choose it. This is because
451 normally, this function would choose "cfree" over free. cfree is
452 an alias for free. If there's any more symbols like this, we may
453 want to consider making this mechanism more generic.
454 */
455 if(VG_(strcmp)(a->name, "free") == 0)
456 return a;
457
458 if(VG_(strcmp)(b->name, "free") == 0)
459 return b;
460
fitzhardingeefda47f2003-12-15 23:31:52 +0000461 for(i = pfx = 0; i < sizeof(prefixes)/sizeof(*prefixes); i++) {
462 Int pfxlen = prefixes[i].len;
463
464 if (pfxlen < lena &&
465 VG_(memcmp)(a->name, prefixes[i].prefix, pfxlen) == 0) {
466 pfx = pfxlen;
467 break;
468 }
469 }
fitzhardinge1c76dc42003-12-15 09:00:21 +0000470
471 if (pfx != 0 && VG_(strcmp)(a->name + pfx, b->name) == 0)
472 return b;
473
474 return a;
475}
476
sewardjde4a1d02002-03-22 01:27:54 +0000477static
478void canonicaliseSymtab ( SegInfo* si )
479{
jsgfcb1d1c02003-10-14 21:55:10 +0000480 Int i, j, n_merged, n_truncated;
sewardjde4a1d02002-03-22 01:27:54 +0000481 Addr s1, s2, e1, e2;
482
483# define SWAP(ty,aa,bb) \
484 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
485
jsgfcb1d1c02003-10-14 21:55:10 +0000486 if (si->symtab_used == 0)
487 return;
sewardjde4a1d02002-03-22 01:27:54 +0000488
nethercote3acbb5d2003-11-13 21:50:45 +0000489 VG_(ssort)(si->symtab, si->symtab_used, sizeof(*si->symtab), compare_RiSym);
sewardjde4a1d02002-03-22 01:27:54 +0000490
rjwalshe4e779d2004-04-16 23:02:29 +0000491 for (i = 0; i < si->symtab_used; i++) {
492 if(VG_(strncmp)(si->symtab[i].name, VG_INTERCEPT_PREFIX,
493 VG_INTERCEPT_PREFIX_LEN) == 0) {
494 int len = VG_(strlen)(si->symtab[i].name);
495 char *buf = VG_(malloc)(len), *colon;
nethercoteb1e1ad42004-08-03 23:44:12 +0000496 intercept_demangle(si->symtab[i].name, buf, len);
rjwalshe4e779d2004-04-16 23:02:29 +0000497 colon = buf + VG_(strlen)(buf) - 1;
498 while(*colon != ':') colon--;
499 VG_(strncpy_safely)(si->symtab[i].name, colon+1, len);
500 }
501 }
502
sewardjde4a1d02002-03-22 01:27:54 +0000503 cleanup_more:
504
505 /* If two symbols have identical address ranges, favour the
fitzhardinge98abfc72003-12-16 02:05:15 +0000506 one with the longer name (unless the extra length is junk)
sewardjde4a1d02002-03-22 01:27:54 +0000507 */
508 do {
509 n_merged = 0;
510 j = si->symtab_used;
511 si->symtab_used = 0;
512 for (i = 0; i < j; i++) {
513 if (i < j-1
514 && si->symtab[i].addr == si->symtab[i+1].addr
515 && si->symtab[i].size == si->symtab[i+1].size) {
516 n_merged++;
517 /* merge the two into one */
fitzhardinge1c76dc42003-12-15 09:00:21 +0000518 si->symtab[si->symtab_used++] = *prefersym(&si->symtab[i], &si->symtab[i+1]);
sewardjde4a1d02002-03-22 01:27:54 +0000519 i++;
520 } else {
521 si->symtab[si->symtab_used++] = si->symtab[i];
522 }
523 }
nethercote80f76782003-11-13 22:34:00 +0000524 TRACE_SYMTAB( "%d merged\n", n_merged);
sewardjde4a1d02002-03-22 01:27:54 +0000525 }
526 while (n_merged > 0);
527
528 /* Detect and "fix" overlapping address ranges. */
529 n_truncated = 0;
530
sewardj05bcdcb2003-05-18 10:05:38 +0000531 for (i = 0; i < ((Int)si->symtab_used) -1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000532
533 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
534
535 /* Check for common (no overlap) case. */
536 if (si->symtab[i].addr + si->symtab[i].size
537 <= si->symtab[i+1].addr)
538 continue;
539
540 /* There's an overlap. Truncate one or the other. */
541 if (VG_(clo_trace_symtab)) {
542 VG_(printf)("overlapping address ranges in symbol table\n\t");
543 printSym(si,i);
544 VG_(printf)("\t");
545 printSym(si,i+1);
546 VG_(printf)("\n");
547 }
548
549 /* Truncate one or the other. */
550 s1 = si->symtab[i].addr;
551 s2 = si->symtab[i+1].addr;
552 e1 = s1 + si->symtab[i].size - 1;
553 e2 = s2 + si->symtab[i+1].size - 1;
554 if (s1 < s2) {
555 e1 = s2-1;
556 } else {
557 vg_assert(s1 == s2);
558 if (e1 > e2) {
559 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
560 } else
561 if (e1 < e2) {
562 s2 = e1+1;
563 } else {
564 /* e1 == e2. Identical addr ranges. We'll eventually wind
565 up back at cleanup_more, which will take care of it. */
566 }
567 }
568 si->symtab[i].addr = s1;
569 si->symtab[i+1].addr = s2;
570 si->symtab[i].size = e1 - s1 + 1;
571 si->symtab[i+1].size = e2 - s2 + 1;
572 vg_assert(s1 <= s2);
573 vg_assert(si->symtab[i].size > 0);
574 vg_assert(si->symtab[i+1].size > 0);
575 /* It may be that the i+1 entry now needs to be moved further
576 along to maintain the address order requirement. */
577 j = i+1;
sewardj05bcdcb2003-05-18 10:05:38 +0000578 while (j < ((Int)si->symtab_used)-1
sewardjde4a1d02002-03-22 01:27:54 +0000579 && si->symtab[j].addr > si->symtab[j+1].addr) {
580 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
581 j++;
582 }
583 n_truncated++;
584 }
585
586 if (n_truncated > 0) goto cleanup_more;
587
588 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000589 for (i = 0; i < ((Int)si->symtab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000590 /* No zero-sized symbols. */
591 vg_assert(si->symtab[i].size > 0);
592 /* In order. */
593 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
594 /* No overlaps. */
595 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
596 < si->symtab[i+1].addr);
597 }
598# undef SWAP
599}
600
jsgfcb1d1c02003-10-14 21:55:10 +0000601/* Sort the scope range table by starting address. Mash the table
602 around so as to establish the property that addresses are in order
603 and the ranges do not overlap. This facilitates using binary
604 search to map addresses to scopes when we come to query the
605 table.
606*/
607static Int compare_ScopeRange(void *va, void *vb) {
608 ScopeRange *a = (ScopeRange *)va;
609 ScopeRange *b = (ScopeRange *)vb;
610
nethercote05fdfac2004-08-01 20:24:46 +0000611 if (a->addr < b->addr) return -1;
612 if (a->addr > b->addr) return 1;
613 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000614}
615
616static
617void canonicaliseScopetab ( SegInfo* si )
618{
619 Int i,j;
620
621 if (si->scopetab_used == 0)
622 return;
623
624 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000625 VG_(ssort)(si->scopetab, si->scopetab_used, sizeof(*si->scopetab),
626 compare_ScopeRange);
jsgfcb1d1c02003-10-14 21:55:10 +0000627
628 /* If two adjacent entries overlap, truncate the first. */
629 for (i = 0; i < si->scopetab_used-1; i++) {
630 if (si->scopetab[i].addr + si->scopetab[i].size > si->scopetab[i+1].addr) {
631 Int new_size = si->scopetab[i+1].addr - si->scopetab[i].addr;
632
633 if (new_size < 0)
634 si->scopetab[i].size = 0;
635 else
636 si->scopetab[i].size = new_size;
637 }
638 }
639
640 /* Zap any zero-sized entries resulting from the truncation
641 process. */
642 j = 0;
643 for (i = 0; i < si->scopetab_used; i++) {
644 if (si->scopetab[i].size > 0) {
645 si->scopetab[j] = si->scopetab[i];
646 j++;
647 }
648 }
649 si->scopetab_used = j;
650
651 /* Ensure relevant postconditions hold. */
652 for (i = 0; i < si->scopetab_used-1; i++) {
653 /*
654 VG_(printf)("%d (%d) %d 0x%x\n",
655 i, si->scopetab[i+1].confident,
656 si->scopetab[i+1].size, si->scopetab[i+1].addr );
657 */
658 /* No zero-sized symbols. */
659 vg_assert(si->scopetab[i].size > 0);
660 /* In order. */
661 if (si->scopetab[i].addr >= si->scopetab[i+1].addr)
662 VG_(printf)("si->scopetab[%d] = %p,size=%d [%d] = %p,size=%d\n",
663 i, si->scopetab[i].addr, si->scopetab[i].size,
664 i+1, si->scopetab[i+1].addr, si->scopetab[i+1].size);
665 vg_assert(si->scopetab[i].addr < si->scopetab[i+1].addr);
666 /* No overlaps. */
667 vg_assert(si->scopetab[i].addr + si->scopetab[i].size - 1
668 < si->scopetab[i+1].addr);
669 }
670}
sewardjde4a1d02002-03-22 01:27:54 +0000671
672
673/* Sort the location table by starting address. Mash the table around
674 so as to establish the property that addresses are in order and the
675 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000676 addresses to locations when we come to query the table.
677*/
jsgfcb1d1c02003-10-14 21:55:10 +0000678static Int compare_RiLoc(void *va, void *vb) {
679 RiLoc *a = (RiLoc *)va;
680 RiLoc *b = (RiLoc *)vb;
681
nethercote05fdfac2004-08-01 20:24:46 +0000682 if (a->addr < b->addr) return -1;
683 if (a->addr > b->addr) return 1;
684 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000685}
686
sewardjde4a1d02002-03-22 01:27:54 +0000687static
688void canonicaliseLoctab ( SegInfo* si )
689{
jsgfcb1d1c02003-10-14 21:55:10 +0000690 Int i, j;
sewardjde4a1d02002-03-22 01:27:54 +0000691
692# define SWAP(ty,aa,bb) \
693 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
694
jsgfcb1d1c02003-10-14 21:55:10 +0000695 if (si->loctab_used == 0)
696 return;
697
sewardjde4a1d02002-03-22 01:27:54 +0000698 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000699 VG_(ssort)(si->loctab, si->loctab_used, sizeof(*si->loctab), compare_RiLoc);
sewardjde4a1d02002-03-22 01:27:54 +0000700
701 /* If two adjacent entries overlap, truncate the first. */
sewardj05bcdcb2003-05-18 10:05:38 +0000702 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000703 vg_assert(si->loctab[i].size < 10000);
704 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
705 /* Do this in signed int32 because the actual .size fields
706 are unsigned 16s. */
707 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
708 if (new_size < 0) {
709 si->loctab[i].size = 0;
710 } else
711 if (new_size >= 65536) {
712 si->loctab[i].size = 65535;
713 } else {
714 si->loctab[i].size = (UShort)new_size;
715 }
716 }
717 }
718
719 /* Zap any zero-sized entries resulting from the truncation
720 process. */
721 j = 0;
sewardj05bcdcb2003-05-18 10:05:38 +0000722 for (i = 0; i < (Int)si->loctab_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000723 if (si->loctab[i].size > 0) {
724 si->loctab[j] = si->loctab[i];
725 j++;
726 }
727 }
728 si->loctab_used = j;
729
730 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000731 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000732 /*
733 VG_(printf)("%d (%d) %d 0x%x\n",
734 i, si->loctab[i+1].confident,
735 si->loctab[i+1].size, si->loctab[i+1].addr );
736 */
737 /* No zero-sized symbols. */
738 vg_assert(si->loctab[i].size > 0);
739 /* In order. */
740 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
741 /* No overlaps. */
742 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
743 < si->loctab[i+1].addr);
744 }
745# undef SWAP
746}
747
748
749/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000750/*--- Read info from a .so/exe file. ---*/
751/*------------------------------------------------------------*/
752
fitzhardinge98abfc72003-12-16 02:05:15 +0000753Bool VG_(is_object_file)(const void *buf)
754{
755 {
756 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buf;
757 Int ok = 1;
758
759 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
760 && ehdr->e_ident[EI_MAG1] == 'E'
761 && ehdr->e_ident[EI_MAG2] == 'L'
762 && ehdr->e_ident[EI_MAG3] == 'F');
nethercotebdaa89f2004-10-09 19:08:08 +0000763 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
764 && ehdr->e_ident[EI_DATA] == VG_ELF_ENDIANNESS
fitzhardinge98abfc72003-12-16 02:05:15 +0000765 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
766 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
nethercotebdaa89f2004-10-09 19:08:08 +0000767 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
fitzhardinge98abfc72003-12-16 02:05:15 +0000768 ok &= (ehdr->e_version == EV_CURRENT);
769 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
770 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
771 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
772
773 if (ok)
774 return True;
775 }
776
777 /* other file formats here? */
778
779 return False;
780}
781
rjwalshe4e779d2004-04-16 23:02:29 +0000782/*
783 * Demangle an intercept symbol into library:func form
784 */
785
786static Bool
nethercoteb1e1ad42004-08-03 23:44:12 +0000787intercept_demangle(const Char* symbol, Char* result, Int nbytes)
rjwalshe4e779d2004-04-16 23:02:29 +0000788{
789 int i, j = 0;
790 int len = VG_(strlen)(symbol);
791
792 for(i = VG_INTERCEPT_PREFIX_LEN; i < len; i++) {
793 if(symbol[i] == '$') {
794 i++;
795 if(symbol[i] == '$') {
796 result[j] = '$';
797 } else if((symbol[i] >= '0' && symbol[i] <= '9') ||
798 (symbol[i] >= 'a' && symbol[i] <= 'f') ||
799 (symbol[i] >= 'A' && symbol[i] <= 'F')) {
800 int x = symbol[i++];
801 int y = symbol[i];
802 if(x >= '0' && x <= '9') {
803 x -= '0';
804 } else if(x >= 'a' && x <= 'f') {
805 x -= 'a';
806 } else if(x >= 'A' && x <= 'F') {
807 x -= 'A';
808 }
809 if(y >= '0' && y <= '9') {
810 y -= '0';
811 } else if(y >= 'a' && y <= 'f') {
812 y = y - 'a' + 10;
813 } else if(y >= 'A' && y <= 'F') {
814 y = y - 'A' + 10;
815 } else {
816 return False;
817 }
818 result[j] = (x << 4) | y;
819 } else {
820 return False;
821 }
822 } else {
823 result[j] = symbol[i];
824 }
825 if(j >= nbytes) {
826 result[j] = '\0';
827 return True;
828 }
829 j++;
830 }
831 result[j] = '\0';
832 return True;
833}
834
nethercote85cdd342004-08-01 22:36:40 +0000835// Forward declaration
836static void add_redirect_addr(const Char *from_lib, const Char *from_sym,
837 Addr to_addr);
838
rjwalshe4e779d2004-04-16 23:02:29 +0000839static
840void handle_intercept( SegInfo* si, Char* symbol, Elf32_Sym* sym)
841{
842 int len = VG_(strlen)(symbol) + 1 - VG_INTERCEPT_PREFIX_LEN;
843 char *lib = VG_(malloc)(len);
844 Char *func;
845
nethercoteb1e1ad42004-08-03 23:44:12 +0000846 intercept_demangle(symbol, lib, len);
rjwalshe4e779d2004-04-16 23:02:29 +0000847 func = lib + VG_(strlen)(lib)-1;
848
849 while(*func != ':') func--;
850 *func = '\0';
851
nethercote85cdd342004-08-01 22:36:40 +0000852 add_redirect_addr(lib, func+1, si->offset + sym->st_value);
rjwalshe4e779d2004-04-16 23:02:29 +0000853 VG_(free)(lib);
854}
855
856static
857void handle_wrapper( SegInfo* si, Char* symbol, Elf32_Sym* sym)
858{
859 VG_(intercept_libc_freeres_wrapper)((Addr)(si->offset + sym->st_value));
860}
861
nethercote80f76782003-11-13 22:34:00 +0000862/* Read a symbol table (normal or dynamic) */
863static
rjwalshe4e779d2004-04-16 23:02:29 +0000864void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts,
nethercote80f76782003-11-13 22:34:00 +0000865 Elf32_Sym* o_symtab, UInt o_symtab_sz,
866 UChar* o_strtab, UInt o_strtab_sz )
867{
868 Int i;
869 Addr sym_addr;
870 RiSym risym;
mueller82df83e2003-11-19 22:05:35 +0000871 Char* t0;
872 Char* name;
873
nethercote80f76782003-11-13 22:34:00 +0000874 if (o_strtab == NULL || o_symtab == NULL) {
jseward0edbfb52003-12-12 06:22:06 +0000875 Char buf[80];
876 vg_assert(VG_(strlen)(tab_name) < 40);
877 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
878 VG_(symerr)(buf);
nethercote80f76782003-11-13 22:34:00 +0000879 return;
880 }
881
882 TRACE_SYMTAB("Reading %s (%d entries)\n", tab_name,
883 o_symtab_sz/sizeof(Elf32_Sym) );
884
885 /* Perhaps should start at i = 1; ELF docs suggest that entry
886 0 always denotes `unknown symbol'. */
887 for (i = 1; i < (Int)(o_symtab_sz/sizeof(Elf32_Sym)); i++) {
888 Elf32_Sym* sym = & o_symtab[i];
889# if 1
890 sym_addr = si->offset + (UInt)sym->st_value;
891
892 if (VG_(clo_trace_symtab)) {
893 VG_(printf)("raw symbol [%d]: ", i);
894 switch (ELF32_ST_BIND(sym->st_info)) {
895 case STB_LOCAL: VG_(printf)("LOC "); break;
896 case STB_GLOBAL: VG_(printf)("GLO "); break;
897 case STB_WEAK: VG_(printf)("WEA "); break;
898 case STB_LOPROC: VG_(printf)("lop "); break;
899 case STB_HIPROC: VG_(printf)("hip "); break;
900 default: VG_(printf)("??? "); break;
901 }
902 switch (ELF32_ST_TYPE(sym->st_info)) {
903 case STT_NOTYPE: VG_(printf)("NOT "); break;
904 case STT_OBJECT: VG_(printf)("OBJ "); break;
905 case STT_FUNC: VG_(printf)("FUN "); break;
906 case STT_SECTION: VG_(printf)("SEC "); break;
907 case STT_FILE: VG_(printf)("FIL "); break;
908 case STT_LOPROC: VG_(printf)("lop "); break;
909 case STT_HIPROC: VG_(printf)("hip "); break;
910 default: VG_(printf)("??? "); break;
911 }
912 VG_(printf)(
913 ": value %p, size %d, name %s\n",
914 sym_addr, sym->st_size,
915 ( sym->st_name
916 ? ((Char*)o_strtab+sym->st_name)
917 : (Char*)"NONAME" ) );
918 }
919# endif
920
rjwalshe4e779d2004-04-16 23:02:29 +0000921 /*
922 * Is this symbol a magic valgrind-intercept symbol? If so,
923 * hand this off to the interceptinator.
924 */
925 if (do_intercepts) {
926 if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
927 VG_INTERCEPT_PREFIX,
928 VG_INTERCEPT_PREFIX_LEN) == 0) {
929 handle_intercept(si, (Char*)o_strtab+sym->st_name, sym);
930 } else if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
931 VG_WRAPPER_PREFIX,
932 VG_WRAPPER_PREFIX_LEN) == 0) {
933 handle_wrapper(si, (Char*)o_strtab+sym->st_name, sym);
934 }
935 }
936
nethercote80f76782003-11-13 22:34:00 +0000937 /* Figure out if we're interested in the symbol.
938 Firstly, is it of the right flavour? */
939 if ( ! ( (ELF32_ST_BIND(sym->st_info) == STB_GLOBAL ||
940 ELF32_ST_BIND(sym->st_info) == STB_LOCAL ||
941 ELF32_ST_BIND(sym->st_info) == STB_WEAK)
942 &&
943 (ELF32_ST_TYPE(sym->st_info) == STT_FUNC ||
944 (VG_(needs).data_syms
945 && ELF32_ST_TYPE(sym->st_info) == STT_OBJECT))
946 )
947 )
948 continue;
949
950 /* Secondly, if it's apparently in a GOT or PLT, it's really
951 a reference to a symbol defined elsewhere, so ignore it. */
952 if (si->got_start != 0
953 && sym_addr >= si->got_start
954 && sym_addr < si->got_start + si->got_size) {
955 TRACE_SYMTAB("in GOT: %s\n", o_strtab+sym->st_name);
956 continue;
957 }
958 if (si->plt_start != 0
959 && sym_addr >= si->plt_start
960 && sym_addr < si->plt_start + si->plt_size) {
961 TRACE_SYMTAB("in PLT: %s\n", o_strtab+sym->st_name);
962 continue;
963 }
964
965 /* Don't bother if nameless, or zero-sized. */
966 if (sym->st_name == (Elf32_Word)NULL
967 || /* VG_(strlen)(o_strtab+sym->st_name) == 0 */
968 /* equivalent but cheaper ... */
969 * ((UChar*)(o_strtab+sym->st_name)) == 0
970 || sym->st_size == 0) {
971 TRACE_SYMTAB("size=0: %s\n", o_strtab+sym->st_name);
972 continue;
973 }
974
975# if 0
976 /* Avoid _dl_ junk. (Why?) */
977 /* 01-02-24: disabled until I find out if it really helps. */
978 if (VG_(strncmp)("_dl_", o_strtab+sym->st_name, 4) == 0
979 || VG_(strncmp)("_r_debug",
980 o_strtab+sym->st_name, 8) == 0) {
981 TRACE_SYMTAB("_dl_ junk: %s\n", o_strtab+sym->st_name);
982 continue;
983 }
984# endif
985
986 /* This seems to significantly reduce the number of junk
987 symbols, and particularly reduces the number of
988 overlapping address ranges. Don't ask me why ... */
989 if ((Int)sym->st_value == 0) {
990 TRACE_SYMTAB( "valu=0: %s\n", o_strtab+sym->st_name);
991 continue;
992 }
993
994 /* If no part of the symbol falls within the mapped range,
995 ignore it. */
996 if (sym_addr+sym->st_size <= si->start
997 || sym_addr >= si->start+si->size) {
998 TRACE_SYMTAB( "outside mapped range" );
999 continue;
1000 }
1001
1002 /* If we reach here, it's an interesting symbol; record it. */
mueller82df83e2003-11-19 22:05:35 +00001003 t0 = sym->st_name
nethercote80f76782003-11-13 22:34:00 +00001004 ? (Char*)(o_strtab+sym->st_name)
1005 : (Char*)"NONAME";
mueller82df83e2003-11-19 22:05:35 +00001006 name = VG_(addStr) ( si, t0, -1 );
nethercote80f76782003-11-13 22:34:00 +00001007 vg_assert(name != NULL
1008 /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
nethercote80f76782003-11-13 22:34:00 +00001009 /* VG_(printf)("%p + %d: %p %s\n", si->start,
1010 (Int)sym->st_value, sym_addr, t0 ); */
1011 risym.addr = sym_addr;
1012 risym.size = sym->st_size;
1013 risym.name = name;
1014 addSym ( si, &risym );
1015 }
1016}
1017
thughesc035bd92004-06-13 09:59:02 +00001018/*
1019 * This routine for calculating the CRC for a separate debug file
1020 * is GPLed code borrowed from binutils.
1021 */
1022static UInt
1023calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
1024{
1025 static const UInt crc32_table[256] =
1026 {
1027 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1028 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1029 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1030 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1031 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1032 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1033 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1034 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1035 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1036 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1037 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1038 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1039 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1040 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1041 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1042 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1043 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1044 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1045 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1046 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1047 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1048 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1049 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1050 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1051 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1052 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1053 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1054 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1055 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1056 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1057 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1058 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1059 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1060 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1061 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1062 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1063 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1064 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1065 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1066 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1067 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1068 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1069 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1070 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1071 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1072 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1073 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1074 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1075 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1076 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1077 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1078 0x2d02ef8d
1079 };
1080 const UChar *end;
1081
1082 crc = ~crc & 0xffffffff;
1083 for (end = buf + len; buf < end; ++ buf)
1084 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1085 return ~crc & 0xffffffff;;
1086}
1087
1088/*
1089 * Try and open a separate debug file, ignoring any where the CRC does
1090 * not match the value from the main object file.
1091 */
1092static
1093Addr open_debug_file( Char* name, UInt crc, UInt* size )
1094{
1095 Int fd;
1096 struct vki_stat stat_buf;
1097 Addr addr;
1098
1099 if ((fd = VG_(open)(name, VKI_O_RDONLY, 0)) < 0)
1100 return 0;
1101
1102 if (VG_(fstat)(fd, &stat_buf) != 0) {
1103 VG_(close)(fd);
1104 return 0;
1105 }
1106
1107 *size = stat_buf.st_size;
1108
1109 if ((addr = (Addr)VG_(mmap)(NULL, *size, VKI_PROT_READ,
nethercoteb4250ae2004-07-10 16:50:09 +00001110 VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1111 0, fd, 0)) == (Addr)-1)
1112 {
thughesc035bd92004-06-13 09:59:02 +00001113 VG_(close)(fd);
1114 return 0;
1115 }
1116
1117 VG_(close)(fd);
1118
1119 if (calc_gnu_debuglink_crc32(0, (UChar*)addr, *size) != crc) {
nethercotee567e702004-07-10 17:49:17 +00001120 int res = VG_(munmap)((void*)addr, *size);
1121 vg_assert(0 == res);
thughesc035bd92004-06-13 09:59:02 +00001122 return 0;
1123 }
1124
1125 return addr;
1126}
1127
1128/*
nethercoteb1e1ad42004-08-03 23:44:12 +00001129 * Try to find a separate debug file for a given object file.
thughesc035bd92004-06-13 09:59:02 +00001130 */
1131static
1132Addr find_debug_file( Char* objpath, Char* debugname, UInt crc, UInt* size )
1133{
1134 Char *objdir = VG_(strdup)(objpath);
1135 Char *objdirptr;
1136 Char *debugpath;
1137 Addr addr = 0;
1138
1139 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1140 *objdirptr = '\0';
1141
1142 debugpath = VG_(malloc)(VG_(strlen)(objdir) + VG_(strlen)(debugname) + 16);
1143
1144 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1145
1146 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1147 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1148 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1149 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1150 addr = open_debug_file(debugpath, crc, size);
1151 }
1152 }
1153
1154 VG_(free)(debugpath);
1155 VG_(free)(objdir);
1156
1157 return addr;
1158}
nethercote80f76782003-11-13 22:34:00 +00001159
sewardjde4a1d02002-03-22 01:27:54 +00001160/* Read the symbols from the object/exe specified by the SegInfo into
1161 the tables within the supplied SegInfo. */
1162static
sewardj8fe15a32002-10-20 19:29:21 +00001163Bool vg_read_lib_symbols ( SegInfo* si )
sewardjde4a1d02002-03-22 01:27:54 +00001164{
nethercote80f76782003-11-13 22:34:00 +00001165 Bool res;
sewardjde4a1d02002-03-22 01:27:54 +00001166 Elf32_Ehdr* ehdr; /* The ELF header */
1167 Elf32_Shdr* shdr; /* The section table */
1168 UChar* sh_strtab; /* The section table's string table */
sewardjde4a1d02002-03-22 01:27:54 +00001169 Int fd;
1170 Int i;
1171 Bool ok;
1172 Addr oimage;
sewardj05bcdcb2003-05-18 10:05:38 +00001173 UInt n_oimage;
thughesc035bd92004-06-13 09:59:02 +00001174 Addr dimage = 0;
1175 UInt n_dimage = 0;
sewardjb3586202002-05-09 17:38:13 +00001176 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001177
sewardjde4a1d02002-03-22 01:27:54 +00001178 oimage = (Addr)NULL;
1179 if (VG_(clo_verbosity) > 1)
fitzhardinge98abfc72003-12-16 02:05:15 +00001180 VG_(message)(Vg_UserMsg, "Reading syms from %s (%p)", si->filename, si->start );
sewardjde4a1d02002-03-22 01:27:54 +00001181
1182 /* mmap the object image aboard, so that we can read symbols and
1183 line number info out of it. It will be munmapped immediately
1184 thereafter; it is only aboard transiently. */
1185
sewardjb3586202002-05-09 17:38:13 +00001186 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001187 if (i != 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00001188 VG_(symerr)("Can't stat .so/.exe (to determine its size)?!");
sewardj8fe15a32002-10-20 19:29:21 +00001189 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001190 }
1191 n_oimage = stat_buf.st_size;
1192
njn25e49d8e72002-09-23 09:36:25 +00001193 fd = VG_(open)(si->filename, VKI_O_RDONLY, 0);
jsgff3c3f1a2003-10-14 22:13:28 +00001194 if (fd < 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00001195 VG_(symerr)("Can't open .so/.exe to read symbols?!");
sewardj8fe15a32002-10-20 19:29:21 +00001196 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001197 }
1198
sewardjb3586202002-05-09 17:38:13 +00001199 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
nethercoteb4250ae2004-07-10 16:50:09 +00001200 VKI_PROT_READ, VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1201 0, fd, 0 );
fitzhardinge98abfc72003-12-16 02:05:15 +00001202
nethercote80f76782003-11-13 22:34:00 +00001203 VG_(close)(fd);
1204
sewardjde4a1d02002-03-22 01:27:54 +00001205 if (oimage == ((Addr)(-1))) {
1206 VG_(message)(Vg_UserMsg,
nethercote132be6f2004-06-27 12:30:15 +00001207 "warning: mmap failed on %s", si->filename );
1208 VG_(message)(Vg_UserMsg,
1209 " no symbols or debug info loaded" );
sewardj8fe15a32002-10-20 19:29:21 +00001210 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001211 }
1212
sewardjde4a1d02002-03-22 01:27:54 +00001213 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1214 Now verify that it is a valid ELF .so or executable image.
1215 */
nethercote80f76782003-11-13 22:34:00 +00001216 res = False;
sewardjde4a1d02002-03-22 01:27:54 +00001217 ok = (n_oimage >= sizeof(Elf32_Ehdr));
1218 ehdr = (Elf32_Ehdr*)oimage;
1219
fitzhardinge98abfc72003-12-16 02:05:15 +00001220 if (ok)
1221 ok &= VG_(is_object_file)(ehdr);
sewardjde4a1d02002-03-22 01:27:54 +00001222
1223 if (!ok) {
jsgfcb1d1c02003-10-14 21:55:10 +00001224 VG_(symerr)("Invalid ELF header, or missing stringtab/sectiontab.");
nethercote80f76782003-11-13 22:34:00 +00001225 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001226 }
1227
1228 /* Walk the LOAD headers in the phdr and update the SegInfo to
1229 include them all, so that this segment also contains data and
1230 bss memory. Also computes correct symbol offset value for this
1231 ELF file. */
1232 if (ehdr->e_phoff + ehdr->e_phnum*sizeof(Elf32_Phdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001233 VG_(symerr)("ELF program header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001234 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001235 }
1236 {
1237 Bool offset_set = False;
1238 Elf32_Addr prev_addr = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001239 Addr baseaddr = 0;
sewardj8fe15a32002-10-20 19:29:21 +00001240
1241 si->offset = 0;
1242
nethercote80f76782003-11-13 22:34:00 +00001243 for (i = 0; i < ehdr->e_phnum; i++) {
sewardj8fe15a32002-10-20 19:29:21 +00001244 Elf32_Phdr *o_phdr;
1245 Elf32_Addr mapped, mapped_end;
1246
1247 o_phdr = &((Elf32_Phdr *)(oimage + ehdr->e_phoff))[i];
1248
fitzhardinge98abfc72003-12-16 02:05:15 +00001249 if (o_phdr->p_type == PT_DYNAMIC && si->soname == NULL) {
1250 const Elf32_Dyn *dyn = (const Elf32_Dyn *)(oimage + o_phdr->p_offset);
1251 Int stroff = -1;
1252 Char *strtab = NULL;
1253 Int j;
1254
1255 for(j = 0; dyn[j].d_tag != DT_NULL; j++) {
1256 switch(dyn[j].d_tag) {
1257 case DT_SONAME:
1258 stroff = dyn[j].d_un.d_val;
1259 break;
1260
1261 case DT_STRTAB:
1262 strtab = (Char *)oimage + dyn[j].d_un.d_ptr - baseaddr;
1263 break;
1264 }
1265 }
1266
1267 if (stroff != -1 && strtab != 0) {
1268 TRACE_SYMTAB("soname=%s\n", strtab+stroff);
1269 si->soname = VG_(arena_strdup)(VG_AR_SYMTAB, strtab+stroff);
1270 }
1271 }
1272
sewardj8fe15a32002-10-20 19:29:21 +00001273 if (o_phdr->p_type != PT_LOAD)
1274 continue;
1275
1276 if (!offset_set) {
1277 offset_set = True;
1278 si->offset = si->start - o_phdr->p_vaddr;
fitzhardinge98abfc72003-12-16 02:05:15 +00001279 baseaddr = o_phdr->p_vaddr;
sewardj8fe15a32002-10-20 19:29:21 +00001280 }
1281
1282 if (o_phdr->p_vaddr < prev_addr) {
jsgfcb1d1c02003-10-14 21:55:10 +00001283 VG_(symerr)("ELF Phdrs are out of order!?");
nethercote80f76782003-11-13 22:34:00 +00001284 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001285 }
1286 prev_addr = o_phdr->p_vaddr;
1287
1288 mapped = o_phdr->p_vaddr + si->offset;
1289 mapped_end = mapped + o_phdr->p_memsz;
1290
1291 if (si->data_start == 0 &&
1292 (o_phdr->p_flags & (PF_R|PF_W|PF_X)) == (PF_R|PF_W)) {
1293 si->data_start = mapped;
1294 si->data_size = o_phdr->p_filesz;
1295 si->bss_start = mapped + o_phdr->p_filesz;
1296 if (o_phdr->p_memsz > o_phdr->p_filesz)
1297 si->bss_size = o_phdr->p_memsz - o_phdr->p_filesz;
1298 else
1299 si->bss_size = 0;
1300 }
1301
nethercote73b526f2004-10-31 18:48:21 +00001302 mapped = mapped & ~(VKI_PAGE_SIZE-1);
1303 mapped_end = (mapped_end + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE-1);
sewardj8fe15a32002-10-20 19:29:21 +00001304
1305 if (VG_(needs).data_syms &&
1306 (mapped >= si->start && mapped <= (si->start+si->size)) &&
1307 (mapped_end > (si->start+si->size))) {
1308 UInt newsz = mapped_end - si->start;
1309 if (newsz > si->size) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001310 Segment *seg;
1311
sewardj8fe15a32002-10-20 19:29:21 +00001312 if (0)
1313 VG_(printf)("extending mapping %p..%p %d -> ..%p %d\n",
1314 si->start, si->start+si->size, si->size,
1315 si->start+newsz, newsz);
fitzhardinge98abfc72003-12-16 02:05:15 +00001316
1317 for(seg = VG_(find_segment)(si->start);
1318 seg != NULL && VG_(seg_overlaps)(seg, si->start, si->size);
1319 seg = VG_(next_segment)(seg)) {
1320 if (seg->symtab == si)
1321 continue;
1322
1323 if (seg->symtab != NULL)
nethercote8991d5a2004-11-03 17:07:46 +00001324 VG_(symtab_decref)(seg->symtab, seg->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001325
1326 VG_(symtab_incref)(si);
1327 seg->symtab = si;
1328
1329 if (0)
1330 VG_(printf)("adding symtab %p (%p-%p) to segment %p (%p-%p)\n",
1331 si, si->start, si->start+newsz,
1332 seg, seg->addr, seg->addr+seg->len);
1333 }
1334
sewardj8fe15a32002-10-20 19:29:21 +00001335 si->size = newsz;
1336 }
1337 }
1338 }
sewardjde4a1d02002-03-22 01:27:54 +00001339 }
1340
nethercote80f76782003-11-13 22:34:00 +00001341 TRACE_SYMTAB("shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
1342 ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );
sewardjde4a1d02002-03-22 01:27:54 +00001343
1344 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
jsgfcb1d1c02003-10-14 21:55:10 +00001345 VG_(symerr)("ELF section header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001346 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001347 }
1348
1349 shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
1350 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1351
nethercote80f76782003-11-13 22:34:00 +00001352 /* Find interesting sections, read the symbol table(s), read any debug
1353 information */
sewardjde4a1d02002-03-22 01:27:54 +00001354 {
nethercote80f76782003-11-13 22:34:00 +00001355 /* Pointers to start of sections */
1356 UChar* o_strtab = NULL; /* .strtab */
1357 Elf32_Sym* o_symtab = NULL; /* .symtab */
1358 UChar* o_dynstr = NULL; /* .dynstr */
1359 Elf32_Sym* o_dynsym = NULL; /* .dynsym */
thughesc035bd92004-06-13 09:59:02 +00001360 Char* debuglink = NULL; /* .gnu_debuglink */
nethercote80f76782003-11-13 22:34:00 +00001361 UChar* stab = NULL; /* .stab (stabs) */
1362 UChar* stabstr = NULL; /* .stabstr (stabs) */
1363 UChar* debug_line = NULL; /* .debug_line (dwarf2) */
jseward8b3131a2003-12-13 23:16:26 +00001364 UChar* dwarf1d = NULL; /* .debug (dwarf1) */
1365 UChar* dwarf1l = NULL; /* .line (dwarf1) */
sewardjde4a1d02002-03-22 01:27:54 +00001366
nethercote80f76782003-11-13 22:34:00 +00001367 /* Section sizes, in bytes */
1368 UInt o_strtab_sz = 0;
1369 UInt o_symtab_sz = 0;
1370 UInt o_dynstr_sz = 0;
1371 UInt o_dynsym_sz = 0;
thughesc035bd92004-06-13 09:59:02 +00001372 UInt debuglink_sz = 0;
nethercote80f76782003-11-13 22:34:00 +00001373 UInt stab_sz = 0;
1374 UInt stabstr_sz = 0;
1375 UInt debug_line_sz = 0;
jseward8b3131a2003-12-13 23:16:26 +00001376 UInt dwarf1d_sz = 0;
1377 UInt dwarf1l_sz = 0;
1378
1379 Bool has_debuginfo = False;
sewardjde4a1d02002-03-22 01:27:54 +00001380
nethercote80f76782003-11-13 22:34:00 +00001381 /* Find all interesting sections */
sewardjde4a1d02002-03-22 01:27:54 +00001382 for (i = 0; i < ehdr->e_shnum; i++) {
jseward8b3131a2003-12-13 23:16:26 +00001383# define FIND(sec_name, sec_data, sec_size, in_exec, type) \
nethercote80f76782003-11-13 22:34:00 +00001384 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1385 if (0 != sec_data) \
1386 VG_(core_panic)("repeated section!\n"); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001387 if (in_exec) \
nethercote80f76782003-11-13 22:34:00 +00001388 sec_data = (type)(si->offset + shdr[i].sh_addr); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001389 else \
nethercote80f76782003-11-13 22:34:00 +00001390 sec_data = (type)(oimage + shdr[i].sh_offset); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001391 sec_size = shdr[i].sh_size; \
nethercote80f76782003-11-13 22:34:00 +00001392 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1393 sec_name, sec_data, sec_data + sec_size - 1); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001394 if ( shdr[i].sh_offset + sec_size > n_oimage ) { \
nethercote80f76782003-11-13 22:34:00 +00001395 VG_(symerr)(" section beyond image end?!"); \
1396 goto out; \
1397 } \
sewardjde4a1d02002-03-22 01:27:54 +00001398 }
1399
nethercote80f76782003-11-13 22:34:00 +00001400 /* Nb: must find where .got and .plt sections will be in the
1401 * executable image, not in the object image transiently loaded. */
1402 FIND(".dynsym", o_dynsym, o_dynsym_sz, 0, Elf32_Sym*)
1403 else FIND(".dynstr", o_dynstr, o_dynstr_sz, 0, UChar*)
1404 else FIND(".symtab", o_symtab, o_symtab_sz, 0, Elf32_Sym*)
1405 else FIND(".strtab", o_strtab, o_strtab_sz, 0, UChar*)
sewardjde4a1d02002-03-22 01:27:54 +00001406
thughesc035bd92004-06-13 09:59:02 +00001407 else FIND(".gnu_debuglink", debuglink, debuglink_sz, 0, Char*)
1408
nethercote80f76782003-11-13 22:34:00 +00001409 else FIND(".stab", stab, stab_sz, 0, UChar*)
1410 else FIND(".stabstr", stabstr, stabstr_sz, 0, UChar*)
1411 else FIND(".debug_line", debug_line, debug_line_sz, 0, UChar*)
jseward8b3131a2003-12-13 23:16:26 +00001412 else FIND(".debug", dwarf1d, dwarf1d_sz, 0, UChar*)
1413 else FIND(".line", dwarf1l, dwarf1l_sz, 0, UChar*)
nethercote80f76782003-11-13 22:34:00 +00001414
1415 else FIND(".got", si->got_start, si->got_size, 1, Addr)
1416 else FIND(".plt", si->plt_start, si->plt_size, 1, Addr)
1417
jseward8b3131a2003-12-13 23:16:26 +00001418# undef FIND
nethercote80f76782003-11-13 22:34:00 +00001419
1420 /* Check some sizes */
1421 vg_assert((o_dynsym_sz % sizeof(Elf32_Sym)) == 0);
1422 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001423 }
1424
rjwalshe4e779d2004-04-16 23:02:29 +00001425 read_symtab(si, "symbol table", False,
nethercote80f76782003-11-13 22:34:00 +00001426 o_symtab, o_symtab_sz,
1427 o_strtab, o_strtab_sz);
sewardjde4a1d02002-03-22 01:27:54 +00001428
rjwalshe4e779d2004-04-16 23:02:29 +00001429 read_symtab(si, "dynamic symbol table", True,
nethercote80f76782003-11-13 22:34:00 +00001430 o_dynsym, o_dynsym_sz,
1431 o_dynstr, o_dynstr_sz);
sewardj9b81a422003-04-26 21:42:09 +00001432
thughesc035bd92004-06-13 09:59:02 +00001433 /* Did we find a debuglink section? */
1434 if (debuglink != NULL) {
1435 UInt crc_offset = (VG_(strlen)(debuglink) + 4) & ~3;
1436 UInt crc;
1437
1438 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1439
1440 /* Extract the CRC from the debuglink section */
1441 crc = *(UInt *)(debuglink + crc_offset);
1442
1443 /* See if we can find a matching debug file */
1444 if ((dimage = find_debug_file(si->filename, debuglink, crc, &n_dimage)) != 0) {
1445 ehdr = (Elf32_Ehdr*)dimage;
1446
1447 if (n_dimage >= sizeof(Elf32_Ehdr) && VG_(is_object_file)(ehdr))
1448 {
1449 shdr = (Elf32_Shdr*)(dimage + ehdr->e_shoff);
1450 sh_strtab = (UChar*)(dimage + shdr[ehdr->e_shstrndx].sh_offset);
1451
1452 /* Find all interesting sections */
1453 for (i = 0; i < ehdr->e_shnum; i++) {
1454# define FIND(sec_name, sec_data, sec_size, type) \
1455 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1456 if (0 != sec_data) \
1457 VG_(core_panic)("repeated section!\n"); \
1458 sec_data = (type)(dimage + shdr[i].sh_offset); \
1459 sec_size = shdr[i].sh_size; \
1460 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1461 sec_name, sec_data, sec_data + sec_size - 1); \
1462 if ( shdr[i].sh_offset + sec_size > n_dimage ) { \
1463 VG_(symerr)(" section beyond image end?!"); \
1464 goto out; \
1465 } \
1466 }
1467
1468 /* Nb: must find where .got and .plt sections will be in the
1469 * executable image, not in the object image transiently loaded. */
1470 FIND(".stab", stab, stab_sz, UChar*)
1471 else FIND(".stabstr", stabstr, stabstr_sz, UChar*)
1472 else FIND(".debug_line", debug_line, debug_line_sz, UChar*)
1473 else FIND(".debug", dwarf1d, dwarf1d_sz, UChar*)
1474 else FIND(".line", dwarf1l, dwarf1l_sz, UChar*)
1475
1476# undef FIND
1477
1478 /* Check some sizes */
1479 vg_assert((o_dynsym_sz % sizeof(Elf32_Sym)) == 0);
1480 vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
1481 }
1482 }
1483 }
1484 }
1485
nethercote80f76782003-11-13 22:34:00 +00001486 /* Read the stabs and/or dwarf2 debug information, if any. */
1487 if (stab != NULL && stabstr != NULL) {
jseward8b3131a2003-12-13 23:16:26 +00001488 has_debuginfo = True;
1489 VG_(read_debuginfo_stabs) ( si, stab, stab_sz,
1490 stabstr, stabstr_sz );
1491 }
1492 if (debug_line) {
1493 has_debuginfo = True;
nethercote80f76782003-11-13 22:34:00 +00001494 VG_(read_debuginfo_dwarf2) ( si, debug_line, debug_line_sz );
jseward8b3131a2003-12-13 23:16:26 +00001495 }
1496 if (dwarf1d && dwarf1l) {
1497 has_debuginfo = True;
1498 VG_(read_debuginfo_dwarf1) ( si, dwarf1d, dwarf1d_sz,
1499 dwarf1l, dwarf1l_sz );
1500 }
1501 if (!has_debuginfo) {
nethercote80f76782003-11-13 22:34:00 +00001502 VG_(symerr)(" object doesn't have any debug info");
1503 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001504 }
1505 }
nethercote80f76782003-11-13 22:34:00 +00001506 res = True;
sewardjde4a1d02002-03-22 01:27:54 +00001507
nethercotee567e702004-07-10 17:49:17 +00001508 out: {
1509 Int m_res;
thughesc035bd92004-06-13 09:59:02 +00001510 /* Last, but not least, heave the image(s) back overboard. */
nethercotee567e702004-07-10 17:49:17 +00001511 if (dimage) {
1512 m_res = VG_(munmap) ( (void*)dimage, n_dimage );
1513 vg_assert(0 == m_res);
1514 }
1515 m_res = VG_(munmap) ( (void*)oimage, n_oimage );
1516 vg_assert(0 == m_res);
nethercote80f76782003-11-13 22:34:00 +00001517 return res;
nethercotee567e702004-07-10 17:49:17 +00001518 }
sewardjde4a1d02002-03-22 01:27:54 +00001519}
1520
sewardjde4a1d02002-03-22 01:27:54 +00001521/*------------------------------------------------------------*/
1522/*--- Main entry point for symbols table reading. ---*/
1523/*------------------------------------------------------------*/
1524
1525/* The root structure for the entire symbol table system. It is a
1526 linked list of SegInfos. Note that this entire mechanism assumes
1527 that what we read from /proc/self/maps doesn't contain overlapping
1528 address ranges, and as a result the SegInfos in this list describe
1529 disjoint address ranges.
1530*/
1531static SegInfo* segInfo = NULL;
1532
fitzhardinge98abfc72003-12-16 02:05:15 +00001533static void resolve_seg_redirs(SegInfo *si);
1534
1535SegInfo *VG_(read_seg_symbols) ( Segment *seg )
sewardjde4a1d02002-03-22 01:27:54 +00001536{
1537 SegInfo* si;
1538
fitzhardinge98abfc72003-12-16 02:05:15 +00001539 vg_assert(seg->symtab == NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001540
njnfa1016e2003-09-25 17:54:11 +00001541 VGP_PUSHCC(VgpReadSyms);
1542
sewardjde4a1d02002-03-22 01:27:54 +00001543 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001544 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001545
sewardj8fe15a32002-10-20 19:29:21 +00001546 VG_(memset)(si, 0, sizeof(*si));
fitzhardinge98abfc72003-12-16 02:05:15 +00001547 si->start = seg->addr;
1548 si->size = seg->len;
1549 si->foffset = seg->offset;
fitzhardinge1a4adf02003-12-22 10:42:59 +00001550 si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00001551
1552 si->ref = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001553
1554 si->symtab = NULL;
1555 si->symtab_size = si->symtab_used = 0;
1556 si->loctab = NULL;
1557 si->loctab_size = si->loctab_used = 0;
jsgfcb1d1c02003-10-14 21:55:10 +00001558 si->strchunks = NULL;
1559 si->scopetab = NULL;
1560 si->scopetab_size = si->scopetab_used = 0;
1561
fitzhardinge98abfc72003-12-16 02:05:15 +00001562 si->seg = seg;
1563
jsgfcb1d1c02003-10-14 21:55:10 +00001564 si->stab_typetab = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001565
nethercote80f76782003-11-13 22:34:00 +00001566 si->plt_start = si->plt_size = 0;
1567 si->got_start = si->got_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001568 si->data_start = si->data_size = 0;
nethercote80f76782003-11-13 22:34:00 +00001569 si->bss_start = si->bss_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001570
sewardjde4a1d02002-03-22 01:27:54 +00001571 /* And actually fill it up. */
sewardj8fe15a32002-10-20 19:29:21 +00001572 if (!vg_read_lib_symbols ( si ) && 0) {
1573 /* XXX this interacts badly with the prevN optimization in
1574 addStr(). Since this frees the si, the si pointer value can
1575 be recycled, which confuses the curr_si == si test. For now,
1576 this code is disabled, and everything is included in the
1577 segment list, even if it is a bad ELF file. Ironically,
1578 running this under valgrind itself hides the problem, because
1579 it doesn't recycle pointers... */
1580 freeSegInfo( si );
1581 } else {
1582 si->next = segInfo;
1583 segInfo = si;
1584
1585 canonicaliseSymtab ( si );
1586 canonicaliseLoctab ( si );
jsgfcb1d1c02003-10-14 21:55:10 +00001587 canonicaliseScopetab ( si );
fitzhardinge98abfc72003-12-16 02:05:15 +00001588
1589 /* do redirects */
1590 resolve_seg_redirs( si );
sewardj8fe15a32002-10-20 19:29:21 +00001591 }
njnfa1016e2003-09-25 17:54:11 +00001592 VGP_POPCC(VgpReadSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001593
1594 return si;
sewardjde4a1d02002-03-22 01:27:54 +00001595}
1596
1597
sewardjde4a1d02002-03-22 01:27:54 +00001598/* When an munmap() call happens, check to see whether it corresponds
1599 to a segment for a .so, and if so discard the relevant SegInfo.
1600 This might not be a very clever idea from the point of view of
1601 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001602 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001603*/
nethercote928a5f72004-11-03 18:10:37 +00001604static void unload_symbols ( Addr start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +00001605{
1606 SegInfo *prev, *curr;
1607
sewardjde4a1d02002-03-22 01:27:54 +00001608 prev = NULL;
1609 curr = segInfo;
1610 while (True) {
1611 if (curr == NULL) break;
1612 if (start == curr->start) break;
1613 prev = curr;
1614 curr = curr->next;
1615 }
njnfa1016e2003-09-25 17:54:11 +00001616 if (curr == NULL) {
1617 VGP_POPCC(VgpReadSyms);
njn25e49d8e72002-09-23 09:36:25 +00001618 return;
njnfa1016e2003-09-25 17:54:11 +00001619 }
sewardjde4a1d02002-03-22 01:27:54 +00001620
mueller75c0ed62003-11-19 00:47:00 +00001621 if (VG_(clo_verbosity) > 1)
1622 VG_(message)(Vg_UserMsg,
fitzhardinge98abfc72003-12-16 02:05:15 +00001623 "discard syms at %p-%p in %s due to munmap()",
1624 start, start+length, curr->filename ? curr->filename : (Char *)"???");
sewardjde4a1d02002-03-22 01:27:54 +00001625
1626 vg_assert(prev == NULL || prev->next == curr);
1627
1628 if (prev == NULL) {
1629 segInfo = curr->next;
1630 } else {
1631 prev->next = curr->next;
1632 }
1633
1634 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001635 return;
sewardjde4a1d02002-03-22 01:27:54 +00001636}
1637
nethercote8991d5a2004-11-03 17:07:46 +00001638void VG_(symtab_decref)(SegInfo *si, Addr start)
fitzhardinge98abfc72003-12-16 02:05:15 +00001639{
1640 vg_assert(si->ref >= 1);
1641 if (--si->ref == 0)
nethercote85cdd342004-08-01 22:36:40 +00001642 unload_symbols(si->start, si->size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001643}
1644
1645void VG_(symtab_incref)(SegInfo *si)
1646{
1647 vg_assert(si->ref > 0);
1648 si->ref++;
1649}
sewardjde4a1d02002-03-22 01:27:54 +00001650
1651/*------------------------------------------------------------*/
1652/*--- Use of symbol table & location info to create ---*/
1653/*--- plausible-looking stack dumps. ---*/
1654/*------------------------------------------------------------*/
1655
1656/* Find a symbol-table index containing the specified pointer, or -1
1657 if not found. Binary search. */
1658
njn25e49d8e72002-09-23 09:36:25 +00001659static Int search_one_symtab ( SegInfo* si, Addr ptr,
1660 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001661{
1662 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001663 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001664 lo = 0,
1665 hi = si->symtab_used-1;
1666 while (True) {
1667 /* current unsearched space is from lo to hi, inclusive. */
1668 if (lo > hi) return -1; /* not found */
1669 mid = (lo + hi) / 2;
1670 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001671 size = ( match_anywhere_in_fun
1672 ? si->symtab[mid].size
1673 : 1);
1674 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001675
1676 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1677 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1678 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1679 return mid;
1680 }
1681}
1682
1683
sewardj25c7c3a2003-07-10 00:17:58 +00001684/* SLOW (Linear search). Try and map a symbol name to an address.
1685 Since this is searching in the direction opposite to which the
1686 table is designed we have no option but to do a complete linear
1687 scan of the table. Returns NULL if not found. */
1688
fitzhardinge98abfc72003-12-16 02:05:15 +00001689static Addr reverse_search_one_symtab ( const SegInfo* si,
1690 const Char* name )
sewardj25c7c3a2003-07-10 00:17:58 +00001691{
1692 UInt i;
1693 for (i = 0; i < si->symtab_used; i++) {
sewardjc8bf5fe2003-07-13 00:53:22 +00001694 if (0)
jsgfcb1d1c02003-10-14 21:55:10 +00001695 VG_(printf)("%p %s\n", si->symtab[i].addr, si->symtab[i].name);
1696 if (0 == VG_(strcmp)(name, si->symtab[i].name))
sewardj25c7c3a2003-07-10 00:17:58 +00001697 return si->symtab[i].addr;
1698 }
1699 return (Addr)NULL;
1700}
1701
1702
sewardjde4a1d02002-03-22 01:27:54 +00001703/* Search all symtabs that we know about to locate ptr. If found, set
1704 *psi to the relevant SegInfo, and *symno to the symtab entry number
1705 within that. If not found, *psi is set to NULL. */
1706
njn25e49d8e72002-09-23 09:36:25 +00001707static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1708 /*OUT*/Int* symno,
1709 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001710{
1711 Int sno;
1712 SegInfo* si;
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 Segment *s;
njn25e49d8e72002-09-23 09:36:25 +00001714
njn25e49d8e72002-09-23 09:36:25 +00001715 VGP_PUSHCC(VgpSearchSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001716
1717 s = VG_(find_segment)(ptr);
1718
1719 if (s == NULL || !VG_(seg_overlaps)(s, ptr, 0) || s->symtab == NULL)
1720 goto not_found;
njn25e49d8e72002-09-23 09:36:25 +00001721
fitzhardinge98abfc72003-12-16 02:05:15 +00001722 si = s->symtab;
1723
1724 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
1725 if (sno == -1) goto not_found;
1726
1727 *symno = sno;
1728 *psi = si;
1729 VGP_POPCC(VgpSearchSyms);
1730 return;
1731
sewardjde4a1d02002-03-22 01:27:54 +00001732 not_found:
1733 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001734 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001735}
1736
1737
1738/* Find a location-table index containing the specified pointer, or -1
1739 if not found. Binary search. */
1740
1741static Int search_one_loctab ( SegInfo* si, Addr ptr )
1742{
1743 Addr a_mid_lo, a_mid_hi;
1744 Int mid,
1745 lo = 0,
1746 hi = si->loctab_used-1;
1747 while (True) {
1748 /* current unsearched space is from lo to hi, inclusive. */
1749 if (lo > hi) return -1; /* not found */
1750 mid = (lo + hi) / 2;
1751 a_mid_lo = si->loctab[mid].addr;
1752 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1753
1754 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1755 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1756 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1757 return mid;
1758 }
1759}
1760
1761
1762/* Search all loctabs that we know about to locate ptr. If found, set
1763 *psi to the relevant SegInfo, and *locno to the loctab entry number
1764 within that. If not found, *psi is set to NULL.
1765*/
njn25e49d8e72002-09-23 09:36:25 +00001766static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
1767 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00001768{
1769 Int lno;
1770 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001771
1772 VGP_PUSHCC(VgpSearchSyms);
1773
sewardjde4a1d02002-03-22 01:27:54 +00001774 for (si = segInfo; si != NULL; si = si->next) {
1775 if (si->start <= ptr && ptr < si->start+si->size) {
1776 lno = search_one_loctab ( si, ptr );
1777 if (lno == -1) goto not_found;
1778 *locno = lno;
1779 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001780 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001781 return;
1782 }
1783 }
1784 not_found:
1785 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001786 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001787}
1788
1789
jsgfcb1d1c02003-10-14 21:55:10 +00001790/* Find a scope-table index containing the specified pointer, or -1
1791 if not found. Binary search. */
1792
1793static Int search_one_scopetab ( SegInfo* si, Addr ptr )
1794{
1795 Addr a_mid_lo, a_mid_hi;
1796 Int mid,
1797 lo = 0,
1798 hi = si->scopetab_used-1;
1799 while (True) {
1800 /* current unsearched space is from lo to hi, inclusive. */
1801 if (lo > hi) return -1; /* not found */
1802 mid = (lo + hi) / 2;
1803 a_mid_lo = si->scopetab[mid].addr;
1804 a_mid_hi = ((Addr)si->scopetab[mid].addr) + si->scopetab[mid].size - 1;
1805
1806 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1807 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1808 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1809 return mid;
1810 }
1811}
1812
1813
1814/* Search all scopetabs that we know about to locate ptr. If found, set
1815 *psi to the relevant SegInfo, and *locno to the scopetab entry number
1816 within that. If not found, *psi is set to NULL.
1817*/
1818static void search_all_scopetabs ( Addr ptr,
1819 /*OUT*/SegInfo** psi,
1820 /*OUT*/Int* scopeno )
1821{
1822 Int scno;
1823 SegInfo* si;
1824
1825 VGP_PUSHCC(VgpSearchSyms);
1826
1827 for (si = segInfo; si != NULL; si = si->next) {
1828 if (si->start <= ptr && ptr < si->start+si->size) {
1829 scno = search_one_scopetab ( si, ptr );
1830 if (scno == -1) goto not_found;
1831 *scopeno = scno;
1832 *psi = si;
1833 VGP_POPCC(VgpSearchSyms);
1834 return;
1835 }
1836 }
1837 not_found:
1838 *psi = NULL;
1839 VGP_POPCC(VgpSearchSyms);
1840}
1841
sewardjde4a1d02002-03-22 01:27:54 +00001842/* The whole point of this whole big deal: map a code address to a
1843 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00001844 Caller supplies buf and nbuf. If demangle is False, don't do
sewardjde4a1d02002-03-22 01:27:54 +00001845 demangling, regardless of vg_clo_demangle -- probably because the
1846 call has come from vg_what_fn_or_object_is_this. */
njn25e49d8e72002-09-23 09:36:25 +00001847static
1848Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
sewardj1771e172002-11-13 22:06:35 +00001849 Bool match_anywhere_in_fun, Bool show_offset)
sewardjde4a1d02002-03-22 01:27:54 +00001850{
1851 SegInfo* si;
1852 Int sno;
sewardj1771e172002-11-13 22:06:35 +00001853 Int offset;
1854
njn25e49d8e72002-09-23 09:36:25 +00001855 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001856 if (si == NULL)
1857 return False;
njn25e49d8e72002-09-23 09:36:25 +00001858 if (demangle) {
jsgfcb1d1c02003-10-14 21:55:10 +00001859 VG_(demangle) ( si->symtab[sno].name, buf, nbuf );
njn25e49d8e72002-09-23 09:36:25 +00001860 } else {
sewardjde4a1d02002-03-22 01:27:54 +00001861 VG_(strncpy_safely)
jsgfcb1d1c02003-10-14 21:55:10 +00001862 ( buf, si->symtab[sno].name, nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00001863 }
sewardj1771e172002-11-13 22:06:35 +00001864
1865 offset = a - si->symtab[sno].addr;
1866 if (show_offset && offset != 0) {
1867 Char buf2[12];
1868 Char* symend = buf + VG_(strlen)(buf);
1869 Char* end = buf + nbuf;
1870 Int len;
1871
1872 len = VG_(sprintf)(buf2, "%c%d",
1873 offset < 0 ? '-' : '+',
1874 offset < 0 ? -offset : offset);
sewardj05bcdcb2003-05-18 10:05:38 +00001875 vg_assert(len < (Int)sizeof(buf2));
sewardj1771e172002-11-13 22:06:35 +00001876
1877 if (len < (end - symend)) {
1878 Char *cp = buf2;
1879 VG_(memcpy)(symend, cp, len+1);
1880 }
1881 }
1882
sewardjde4a1d02002-03-22 01:27:54 +00001883 return True;
1884}
1885
nethercote7cc9c232004-01-21 15:08:04 +00001886/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001887 match anywhere in function, but don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001888Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
1889{
1890 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001891 /*match_anywhere_in_fun*/True,
1892 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001893}
sewardjde4a1d02002-03-22 01:27:54 +00001894
nethercote7cc9c232004-01-21 15:08:04 +00001895/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001896 match anywhere in function, and show offset if nonzero. */
1897Bool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
1898{
1899 return get_fnname ( /*demangle*/True, a, buf, nbuf,
1900 /*match_anywhere_in_fun*/True,
1901 /*show offset?*/True );
1902}
1903
nethercote7cc9c232004-01-21 15:08:04 +00001904/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001905 only succeed if 'a' matches first instruction of function,
1906 and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001907Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
1908{
1909 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001910 /*match_anywhere_in_fun*/False,
1911 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001912}
1913
sewardj6e008cb2002-12-15 13:11:39 +00001914/* This is only available to core... don't demangle C++ names,
1915 match anywhere in function, and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001916Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
1917{
1918 return get_fnname ( /*demangle*/False, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00001919 /*match_anywhere_in_fun*/True,
1920 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00001921}
1922
1923/* Map a code address to the name of a shared object file or the executable.
1924 Returns False if no idea; otherwise True. Doesn't require debug info.
1925 Caller supplies buf and nbuf. */
1926Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00001927{
1928 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001929
sewardjde4a1d02002-03-22 01:27:54 +00001930 for (si = segInfo; si != NULL; si = si->next) {
1931 if (si->start <= a && a < si->start+si->size) {
1932 VG_(strncpy_safely)(buf, si->filename, nbuf);
1933 return True;
1934 }
1935 }
1936 return False;
1937}
1938
njnb877d492003-01-28 20:40:57 +00001939/* Map a code address to its SegInfo. Returns NULL if not found. Doesn't
1940 require debug info. */
1941SegInfo* VG_(get_obj) ( Addr a )
1942{
1943 SegInfo* si;
1944
njnb877d492003-01-28 20:40:57 +00001945 for (si = segInfo; si != NULL; si = si->next) {
1946 if (si->start <= a && a < si->start+si->size) {
1947 return si;
1948 }
1949 }
nethercote80f76782003-11-13 22:34:00 +00001950 return NULL;
njnb877d492003-01-28 20:40:57 +00001951}
1952
njn25e49d8e72002-09-23 09:36:25 +00001953
1954/* Map a code address to a filename. Returns True if successful. */
1955Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00001956{
njn25e49d8e72002-09-23 09:36:25 +00001957 SegInfo* si;
1958 Int locno;
1959 search_all_loctabs ( a, &si, &locno );
1960 if (si == NULL)
1961 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00001962 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
njn25e49d8e72002-09-23 09:36:25 +00001963 n_filename);
1964 return True;
sewardjde4a1d02002-03-22 01:27:54 +00001965}
1966
njn25e49d8e72002-09-23 09:36:25 +00001967/* Map a code address to a line number. Returns True if successful. */
1968Bool VG_(get_linenum)( Addr a, UInt* lineno )
1969{
1970 SegInfo* si;
1971 Int locno;
1972 search_all_loctabs ( a, &si, &locno );
1973 if (si == NULL)
1974 return False;
1975 *lineno = si->loctab[locno].lineno;
1976
1977 return True;
1978}
sewardjde4a1d02002-03-22 01:27:54 +00001979
1980/* Map a code address to a (filename, line number) pair.
1981 Returns True if successful.
1982*/
njn25e49d8e72002-09-23 09:36:25 +00001983Bool VG_(get_filename_linenum)( Addr a,
1984 Char* filename, Int n_filename,
1985 UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00001986{
1987 SegInfo* si;
1988 Int locno;
1989 search_all_loctabs ( a, &si, &locno );
1990 if (si == NULL)
1991 return False;
jsgfcb1d1c02003-10-14 21:55:10 +00001992 VG_(strncpy_safely)(filename, si->loctab[locno].filename,
sewardjde4a1d02002-03-22 01:27:54 +00001993 n_filename);
1994 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00001995
sewardjde4a1d02002-03-22 01:27:54 +00001996 return True;
1997}
1998
jsgfcb1d1c02003-10-14 21:55:10 +00001999#ifndef TEST
2000
2001/* return a pointer to a register (now for 5 other impossible things
2002 before breakfast) */
2003static UInt *regaddr(ThreadId tid, Int regno)
2004{
2005 UInt *ret = 0;
2006
nethercotecd656042004-09-11 23:48:22 +00002007 if (VG_(is_running_thread)(tid))
2008 ret = VGA_(reg_addr_from_BB)(regno);
2009 else
2010 ret = VGA_(reg_addr_from_tst)(regno, &VG_(threads)[tid].arch);
jsgfcb1d1c02003-10-14 21:55:10 +00002011
2012 if (ret == 0) {
2013 Char file[100];
2014 Int line;
2015 Addr eip = VG_(get_EIP)(tid);
2016
2017 if (!VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
2018 file[0] = 0;
2019 VG_(printf)("mysterious register %d used at %p %s:%d\n",
2020 regno, eip, file, line);
2021 }
2022
2023 return ret;
2024}
2025
2026/* Get a list of all variables in scope, working out from the directly
2027 current one */
2028Variable *VG_(get_scope_variables)(ThreadId tid)
2029{
2030 static const Bool debug = False;
2031 Variable *list, *end;
2032 Addr eip;
2033 SegInfo *si;
2034 Int scopeidx;
2035 Scope *scope;
2036 Int distance;
2037 static const Int maxsyms = 1000;
2038 Int nsyms = maxsyms;
2039
2040 list = end = NULL;
2041
2042 eip = VG_(get_EIP)(tid);
2043
2044 search_all_scopetabs(eip, &si, &scopeidx);
2045
2046 if (debug)
2047 VG_(printf)("eip=%p si=%p (%s; offset=%p) scopeidx=%d\n",
2048 eip, si, si ? si->filename : (Char *)"???",
2049 si ? si->offset : 0x99999, scopeidx);
2050
2051 if (si == NULL)
2052 return NULL; /* nothing in scope (should use global scope at least) */
2053
2054 if (debug) {
2055 ScopeRange *sr = &si->scopetab[scopeidx];
2056 Char file[100];
2057 Int line;
2058
2059 if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file), &line))
2060 file[0] = 0;
2061
2062 VG_(printf)("found scope range %p: eip=%p (%s:%d) size=%d scope=%p\n",
2063 sr, sr->addr, file, line, sr->size, sr->scope);
2064 }
2065
2066 distance = 0;
2067 for(scope = si->scopetab[scopeidx].scope; scope != NULL; scope = scope->outer, distance++) {
2068 UInt i;
2069
2070 for(i = 0; i < scope->nsyms; i++) {
2071 Sym *sym = &scope->syms[i];
2072 Variable *v;
2073
2074 if (nsyms-- == 0) {
2075 VG_(printf)("max %d syms reached\n", maxsyms);
2076 return list;
2077 }
2078
2079 v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
2080
2081 v->next = NULL;
2082 v->distance = distance;
2083 v->type = VG_(st_basetype)(sym->type, False);
2084 v->name = VG_(arena_strdup)(VG_AR_SYMTAB, sym->name);
2085 v->container = NULL;
2086 v->size = VG_(st_sizeof)(sym->type);
2087
2088 if (debug && 0)
mueller5ed88f22004-01-06 16:02:29 +00002089 VG_(printf)("sym->name=%s sym->kind=%d offset=%d\n", sym->name, sym->kind, sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002090 switch(sym->kind) {
2091 UInt reg;
2092
2093 case SyGlobal:
2094 case SyStatic:
mueller5ed88f22004-01-06 16:02:29 +00002095 if (sym->u.addr == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00002096 /* XXX lookup value */
2097 }
mueller5ed88f22004-01-06 16:02:29 +00002098 v->valuep = sym->u.addr;
jsgfcb1d1c02003-10-14 21:55:10 +00002099 break;
2100
2101 case SyReg:
mueller5ed88f22004-01-06 16:02:29 +00002102 v->valuep = (Addr)regaddr(tid, sym->u.regno);
jsgfcb1d1c02003-10-14 21:55:10 +00002103 break;
2104
2105 case SyEBPrel:
2106 case SyESPrel:
nethercotecd656042004-09-11 23:48:22 +00002107 reg = *regaddr(tid, sym->kind == SyESPrel ?
2108 R_STACK_PTR : R_FRAME_PTR);
jsgfcb1d1c02003-10-14 21:55:10 +00002109 if (debug)
mueller5ed88f22004-01-06 16:02:29 +00002110 VG_(printf)("reg=%p+%d=%p\n", reg, sym->u.offset, reg+sym->u.offset);
2111 v->valuep = (Addr)(reg + sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002112 break;
2113
2114 case SyType:
2115 VG_(core_panic)("unexpected typedef in scope");
2116 }
2117
2118 if (v->valuep == 0) {
2119 /* not interesting or useful */
2120 VG_(arena_free)(VG_AR_SYMTAB, v);
2121 continue;
2122 }
2123
2124 /* append to end of list */
2125 if (list == NULL)
2126 list = end = v;
2127 else {
2128 end->next = v;
2129 end = v;
2130 }
2131 }
2132 }
2133
2134 return list;
2135}
2136#endif /* TEST */
2137
njn6c846552003-09-16 07:41:43 +00002138/* Print into buf info on code address, function name and filename */
2139Char* VG_(describe_eip)(Addr eip, Char* buf, Int n_buf)
sewardjde4a1d02002-03-22 01:27:54 +00002140{
njn6c846552003-09-16 07:41:43 +00002141#define APPEND(str) \
2142 { UChar* sss; \
2143 for (sss = str; n < n_buf-1 && *sss != 0; n++,sss++) \
2144 buf[n] = *sss; \
2145 buf[n] = '\0'; \
sewardjde4a1d02002-03-22 01:27:54 +00002146 }
nethercote80f76782003-11-13 22:34:00 +00002147 UInt lineno;
2148 UChar ibuf[20];
2149 UInt n = 0;
nethercote3b38c1d2004-10-18 15:47:18 +00002150 static UChar buf_fn[M_VG_ERRTXT];
2151 static UChar buf_obj[M_VG_ERRTXT];
2152 static UChar buf_srcloc[M_VG_ERRTXT];
nethercote80f76782003-11-13 22:34:00 +00002153 Bool know_fnname = VG_(get_fnname) (eip, buf_fn, M_VG_ERRTXT);
2154 Bool know_objname = VG_(get_objname)(eip, buf_obj, M_VG_ERRTXT);
2155 Bool know_srcloc = VG_(get_filename_linenum)(eip, buf_srcloc, M_VG_ERRTXT,
2156 &lineno);
njn6c846552003-09-16 07:41:43 +00002157 VG_(sprintf)(ibuf,"0x%x: ", eip);
2158 APPEND(ibuf);
2159 if (know_fnname) {
2160 APPEND(buf_fn);
2161 if (!know_srcloc && know_objname) {
2162 APPEND(" (in ");
2163 APPEND(buf_obj);
2164 APPEND(")");
2165 }
2166 } else if (know_objname && !know_srcloc) {
2167 APPEND("(within ");
2168 APPEND(buf_obj);
2169 APPEND(")");
2170 } else {
2171 APPEND("???");
2172 }
2173 if (know_srcloc) {
2174 APPEND(" (");
2175 APPEND(buf_srcloc);
2176 APPEND(":");
2177 VG_(sprintf)(ibuf,"%d",lineno);
2178 APPEND(ibuf);
2179 APPEND(")");
2180 }
2181 return buf;
2182
2183#undef APPEND
2184}
2185
2186/* Print a mini stack dump, showing the current location. */
2187void VG_(mini_stack_dump) ( Addr eips[], UInt n_eips )
2188{
2189 UInt i;
nethercote3b38c1d2004-10-18 15:47:18 +00002190 static UChar buf[M_VG_ERRTXT];
nethercote77eba602003-11-13 17:35:04 +00002191 Bool main_done = False;
njn6c846552003-09-16 07:41:43 +00002192
2193 Int stop_at = n_eips;
sewardjde4a1d02002-03-22 01:27:54 +00002194
njn49ef4622002-10-04 15:15:08 +00002195 vg_assert(stop_at > 0);
sewardjde4a1d02002-03-22 01:27:54 +00002196
nethercote77eba602003-11-13 17:35:04 +00002197 /* This loop is the basis for the one in VG_(gen_suppressions)(); if you
2198 change this, change it too! */
njn49ef4622002-10-04 15:15:08 +00002199 i = 0;
2200 do {
njn6c846552003-09-16 07:41:43 +00002201 Addr eip = eips[i];
nethercotefbfc1082004-09-04 15:28:37 +00002202 if (i > 0)
2203 eip -= MIN_INSTR_SIZE; // point to calling line
njn6c846552003-09-16 07:41:43 +00002204 VG_(describe_eip)(eip, buf, M_VG_ERRTXT);
nethercote77eba602003-11-13 17:35:04 +00002205
2206 if ( ! VG_(clo_show_below_main)) {
2207 // Stop after "main"; if main() is recursive, stop after last main().
2208 if (VG_(strstr)(buf, " main ("))
2209 main_done = True;
2210 else if (main_done)
2211 break;
2212 }
2213 VG_(message)(Vg_UserMsg, " %s %s", ( i == 0 ? "at" : "by" ), buf);
njn49ef4622002-10-04 15:15:08 +00002214 i++;
2215
njn6c846552003-09-16 07:41:43 +00002216 } while (i < (UInt)stop_at && eips[i] != 0);
sewardjde4a1d02002-03-22 01:27:54 +00002217}
2218
sewardj25c7c3a2003-07-10 00:17:58 +00002219
2220/*------------------------------------------------------------*/
fitzhardinge98abfc72003-12-16 02:05:15 +00002221/*--- General purpose redirection. ---*/
sewardj25c7c3a2003-07-10 00:17:58 +00002222/*------------------------------------------------------------*/
2223
jsewardbdce5e02003-12-21 23:32:43 +00002224/* Set to True for debug printing. */
2225static const Bool verbose_redir = False;
2226
2227
fitzhardinge98abfc72003-12-16 02:05:15 +00002228/* resolved redirections, indexed by from_addr */
2229typedef struct _CodeRedirect {
2230 const Char *from_lib; /* library qualifier pattern */
2231 const Char *from_sym; /* symbol */
2232 Addr from_addr; /* old addr */
sewardj25c7c3a2003-07-10 00:17:58 +00002233
fitzhardinge98abfc72003-12-16 02:05:15 +00002234 const Char *to_lib; /* library qualifier pattern */
2235 const Char *to_sym; /* symbol */
2236 Addr to_addr; /* new addr */
2237
2238 struct _CodeRedirect *next; /* next pointer on unresolved list */
2239} CodeRedirect;
2240
2241static Int addrcmp(const void *ap, const void *bp)
sewardj25c7c3a2003-07-10 00:17:58 +00002242{
fitzhardinge98abfc72003-12-16 02:05:15 +00002243 Addr a = *(Addr *)ap;
2244 Addr b = *(Addr *)bp;
2245 Int ret;
sewardj25c7c3a2003-07-10 00:17:58 +00002246
fitzhardinge98abfc72003-12-16 02:05:15 +00002247 if (a == b)
2248 ret = 0;
2249 else
2250 ret = (a < b) ? -1 : 1;
sewardj25c7c3a2003-07-10 00:17:58 +00002251
fitzhardinge98abfc72003-12-16 02:05:15 +00002252 return ret;
2253}
sewardj25c7c3a2003-07-10 00:17:58 +00002254
fitzhardinge98abfc72003-12-16 02:05:15 +00002255static Char *straddr(void *p)
2256{
2257 static Char buf[16];
sewardj25c7c3a2003-07-10 00:17:58 +00002258
fitzhardinge98abfc72003-12-16 02:05:15 +00002259 VG_(sprintf)(buf, "%p", *(Addr *)p);
sewardj25c7c3a2003-07-10 00:17:58 +00002260
fitzhardinge98abfc72003-12-16 02:05:15 +00002261 return buf;
2262}
sewardj25c7c3a2003-07-10 00:17:58 +00002263
fitzhardinge98abfc72003-12-16 02:05:15 +00002264static SkipList sk_resolved_redir = SKIPLIST_INIT(CodeRedirect, from_addr,
2265 addrcmp, straddr, VG_AR_SYMTAB);
2266static CodeRedirect *unresolved_redir = NULL;
2267
2268static Bool match_lib(const Char *pattern, const SegInfo *si)
2269{
2270 /* pattern == NULL matches everything, otherwise use globbing
2271
2272 If the pattern starts with:
2273 file:, then match filename
2274 soname:, then match soname
2275 something else, match filename
2276 */
2277 const Char *name = si->filename;
2278
2279 if (pattern == NULL)
2280 return True;
2281
2282 if (VG_(strncmp)(pattern, "file:", 5) == 0) {
2283 pattern += 5;
2284 name = si->filename;
2285 }
2286 if (VG_(strncmp)(pattern, "soname:", 7) == 0) {
2287 pattern += 7;
2288 name = si->soname;
sewardj25c7c3a2003-07-10 00:17:58 +00002289 }
2290
fitzhardinge98abfc72003-12-16 02:05:15 +00002291 if (name == NULL)
2292 return False;
2293
2294 return VG_(string_match)(pattern, name);
2295}
sewardj25c7c3a2003-07-10 00:17:58 +00002296
fitzhardinge98abfc72003-12-16 02:05:15 +00002297/* Resolve a redir using si if possible, and add it to the resolved
2298 list */
2299static Bool resolve_redir(CodeRedirect *redir, const SegInfo *si)
2300{
2301 Bool resolved;
sewardj25c7c3a2003-07-10 00:17:58 +00002302
fitzhardinge98abfc72003-12-16 02:05:15 +00002303 vg_assert(si != NULL);
2304 vg_assert(si->seg != NULL);
sewardj25c7c3a2003-07-10 00:17:58 +00002305
fitzhardinge98abfc72003-12-16 02:05:15 +00002306 /* no redirection from Valgrind segments */
2307 if (si->seg->flags & SF_VALGRIND)
2308 return False;
2309
2310 resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
2311
jsewardbdce5e02003-12-21 23:32:43 +00002312 if (0 && verbose_redir)
2313 VG_(printf)(" consider FROM binding %s:%s -> %s:%s in %s(%s)\n",
fitzhardinge98abfc72003-12-16 02:05:15 +00002314 redir->from_lib, redir->from_sym,
2315 redir->to_lib, redir->to_sym,
2316 si->filename, si->soname);
2317
2318 vg_assert(!resolved);
2319
2320 if (redir->from_addr == 0) {
2321 vg_assert(redir->from_sym != NULL);
2322
2323 if (match_lib(redir->from_lib, si)) {
2324 redir->from_addr = reverse_search_one_symtab(si, redir->from_sym);
jsewardbdce5e02003-12-21 23:32:43 +00002325 if (verbose_redir && redir->from_addr != 0)
2326 VG_(printf)(" bind FROM: %p = %s:%s\n",
2327 redir->from_addr,redir->from_lib, redir->from_sym );
fitzhardinge98abfc72003-12-16 02:05:15 +00002328 }
2329 }
2330
2331 if (redir->to_addr == 0) {
2332 vg_assert(redir->to_sym != NULL);
2333
2334 if (match_lib(redir->to_lib, si)) {
2335 redir->to_addr = reverse_search_one_symtab(si, redir->to_sym);
jsewardbdce5e02003-12-21 23:32:43 +00002336 if (verbose_redir && redir->to_addr != 0)
2337 VG_(printf)(" bind TO: %p = %s:%s\n",
2338 redir->to_addr,redir->to_lib, redir->to_sym );
2339
fitzhardinge98abfc72003-12-16 02:05:15 +00002340 }
2341 }
2342
2343 resolved = (redir->from_addr != 0) && (redir->to_addr != 0);
2344
jsewardbdce5e02003-12-21 23:32:43 +00002345 if (0 && verbose_redir)
fitzhardinge98abfc72003-12-16 02:05:15 +00002346 VG_(printf)("resolve_redir: %s:%s from=%p %s:%s to=%p\n",
2347 redir->from_lib, redir->from_sym, redir->from_addr,
2348 redir->to_lib, redir->to_sym, redir->to_addr);
2349
2350 if (resolved) {
jsewardbdce5e02003-12-21 23:32:43 +00002351 if (VG_(clo_verbosity) > 2 || verbose_redir) {
2352 VG_(message)(Vg_DebugMsg, " redir resolved (%s:%s=%p -> ",
fitzhardinge98abfc72003-12-16 02:05:15 +00002353 redir->from_lib, redir->from_sym, redir->from_addr);
jsewardbdce5e02003-12-21 23:32:43 +00002354 VG_(message)(Vg_DebugMsg, " %s:%s=%p)",
fitzhardinge98abfc72003-12-16 02:05:15 +00002355 redir->to_lib, redir->to_sym, redir->to_addr);
2356 }
2357
jsewarda053a842003-12-22 00:50:52 +00002358 if (VG_(search_transtab)(redir->from_addr) != 0) {
2359 /* For some given (from, to) redir, the "from" function got
2360 called before the .so containing "to" became available. We
2361 know this because there is already a translation for the
2362 entry point of the original "from". So the redirect will
2363 never actually take effect unless that translation is
2364 discarded.
2365
2366 Note, we only really need to discard the first bb of the
2367 old entry point, and so we avoid the problem of having to
2368 figure out how big that bb was -- since it is at least 1
2369 byte of original code, we can just pass 1 as the original
2370 size to invalidate_translations() and it will indeed get
2371 rid of the translation.
2372
2373 Note, this is potentially expensive -- discarding
2374 translations causes complete unchaining.
2375 */
2376 if (VG_(clo_verbosity) > 2) {
2377 VG_(message)(Vg_UserMsg,
2378 "Discarding translation due to redirect of already called function" );
2379 VG_(message)(Vg_UserMsg,
2380 " %s (%p -> %p)",
2381 redir->from_sym, redir->from_addr, redir->to_addr );
2382 }
2383 VG_(invalidate_translations)(redir->from_addr, 1, True);
2384 }
fitzhardinge98abfc72003-12-16 02:05:15 +00002385
2386 VG_(SkipList_Insert)(&sk_resolved_redir, redir);
2387 }
2388
2389 return resolved;
2390}
2391
2392/* Go through the complete redir list, resolving as much as possible with this SegInfo.
2393
2394 This should be called when a new SegInfo symtab is loaded.
2395 */
2396static void resolve_seg_redirs(SegInfo *si)
2397{
2398 CodeRedirect **prevp = &unresolved_redir;
2399 CodeRedirect *redir, *next;
2400
jsewardbdce5e02003-12-21 23:32:43 +00002401 if (verbose_redir)
2402 VG_(printf)("Considering redirs to/from %s(soname=%s)\n",
2403 si->filename, si->soname);
2404
fitzhardinge98abfc72003-12-16 02:05:15 +00002405 /* visit each unresolved redir - if it becomes resolved, then
2406 remove it from the unresolved list */
2407 for(redir = unresolved_redir; redir != NULL; redir = next) {
2408 next = redir->next;
2409
2410 if (resolve_redir(redir, si)) {
2411 *prevp = next;
2412 redir->next = NULL;
2413 } else
2414 prevp = &redir->next;
2415 }
2416}
2417
2418static Bool resolve_redir_allsegs(CodeRedirect *redir)
2419{
2420 SegInfo *si;
2421
2422 for(si = segInfo; si != NULL; si = si->next)
2423 if (resolve_redir(redir, si))
2424 return True;
2425
2426 return False;
2427}
2428
2429/* Redirect a lib/symbol reference to a function at lib/symbol */
nethercote85cdd342004-08-01 22:36:40 +00002430static void add_redirect_sym(const Char *from_lib, const Char *from_sym,
2431 const Char *to_lib, const Char *to_sym)
fitzhardinge98abfc72003-12-16 02:05:15 +00002432{
2433 CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
2434
2435 redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
2436 redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
2437 redir->from_addr = 0;
2438
2439 redir->to_lib = VG_(arena_strdup)(VG_AR_SYMTAB, to_lib);
2440 redir->to_sym = VG_(arena_strdup)(VG_AR_SYMTAB, to_sym);
2441 redir->to_addr = 0;
2442
jseward5348e562003-12-21 23:54:59 +00002443 if (VG_(clo_verbosity) >= 2)
2444 VG_(message)(Vg_UserMsg,
2445 "REDIRECT %s(%s) to %s(%s)",
2446 from_lib, from_sym, to_lib, to_sym);
2447
fitzhardinge98abfc72003-12-16 02:05:15 +00002448 if (!resolve_redir_allsegs(redir)) {
2449 /* can't resolve immediately; add to list */
2450 redir->next = unresolved_redir;
2451 unresolved_redir = redir;
2452 }
2453}
2454
2455/* Redirect a lib/symbol reference to a function at lib/symbol */
nethercote85cdd342004-08-01 22:36:40 +00002456static void add_redirect_addr(const Char *from_lib, const Char *from_sym,
2457 Addr to_addr)
fitzhardinge98abfc72003-12-16 02:05:15 +00002458{
2459 CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redir);
2460
2461 redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
2462 redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
2463 redir->from_addr = 0;
2464
2465 redir->to_lib = NULL;
2466 redir->to_sym = NULL;
2467 redir->to_addr = to_addr;
2468
2469 if (!resolve_redir_allsegs(redir)) {
2470 /* can't resolve immediately; add to list */
2471 redir->next = unresolved_redir;
2472 unresolved_redir = redir;
2473 }
2474}
2475
2476Addr VG_(code_redirect)(Addr a)
2477{
2478 CodeRedirect *r = VG_(SkipList_Find)(&sk_resolved_redir, &a);
2479
2480 if (r == NULL || r->from_addr != a)
2481 return a;
2482
2483 vg_assert(r->to_addr != 0);
2484
2485 return r->to_addr;
2486}
2487
2488void VG_(setup_code_redirect_table) ( void )
2489{
2490 static const struct {
2491 const Char *from, *to;
2492 } redirects[] = {
2493 { "__GI___errno_location", "__errno_location" },
2494 { "__errno_location", "__errno_location" },
2495 { "__GI___h_errno_location", "__h_errno_location" },
2496 { "__h_errno_location", "__h_errno_location" },
2497 { "__GI___res_state", "__res_state" },
2498 { "__res_state", "__res_state" },
2499 };
2500 Int i;
2501
2502 for(i = 0; i < sizeof(redirects)/sizeof(*redirects); i++) {
nethercote85cdd342004-08-01 22:36:40 +00002503 add_redirect_sym("soname:libc.so.6", redirects[i].from,
2504 "soname:libpthread.so.0", redirects[i].to);
sewardj25c7c3a2003-07-10 00:17:58 +00002505 }
jsewardbdce5e02003-12-21 23:32:43 +00002506
thughes266c6162004-03-22 19:46:29 +00002507 /* Redirect _dl_sysinfo_int80, which is glibc's default system call
2508 routine, to the routine in our trampoline page so that the
2509 special sysinfo unwind hack in vg_execontext.c will kick in.
2510 */
nethercote85cdd342004-08-01 22:36:40 +00002511 add_redirect_addr("soname:ld-linux.so.2", "_dl_sysinfo_int80",
2512 VG_(client_trampoline_code)+VG_(tramp_syscall_offset));
thughes266c6162004-03-22 19:46:29 +00002513
jseward5348e562003-12-21 23:54:59 +00002514 /* Overenthusiastic use of PLT bypassing by the glibc people also
2515 means we need to patch the following functions to our own
2516 implementations of said, in mac_replace_strmem.c.
2517 */
nethercote85cdd342004-08-01 22:36:40 +00002518 add_redirect_sym("soname:libc.so.6", "stpcpy",
2519 "*vgpreload_memcheck.so*", "stpcpy");
2520 add_redirect_sym("soname:libc.so.6", "strnlen",
2521 "*vgpreload_memcheck.so*", "strnlen");
2522 add_redirect_sym("soname:ld-linux.so.2", "stpcpy",
2523 "*vgpreload_memcheck.so*", "stpcpy");
2524 add_redirect_sym("soname:ld-linux.so.2", "strchr",
2525 "*vgpreload_memcheck.so*", "strchr");
sewardj25c7c3a2003-07-10 00:17:58 +00002526}
2527
sewardj47104382002-10-20 18:35:48 +00002528/*------------------------------------------------------------*/
2529/*--- SegInfo accessor functions ---*/
2530/*------------------------------------------------------------*/
2531
2532const SegInfo* VG_(next_seginfo)(const SegInfo* seg)
2533{
sewardj47104382002-10-20 18:35:48 +00002534 if (seg == NULL)
2535 return segInfo;
2536 return seg->next;
2537}
2538
2539Addr VG_(seg_start)(const SegInfo* seg)
2540{
2541 return seg->start;
2542}
2543
nethercote928a5f72004-11-03 18:10:37 +00002544SizeT VG_(seg_size)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002545{
2546 return seg->size;
2547}
2548
2549const UChar* VG_(seg_filename)(const SegInfo* seg)
2550{
2551 return seg->filename;
2552}
2553
nethercote928a5f72004-11-03 18:10:37 +00002554ULong VG_(seg_sym_offset)(const SegInfo* seg)
sewardj47104382002-10-20 18:35:48 +00002555{
2556 return seg->offset;
2557}
2558
2559VgSectKind VG_(seg_sect_kind)(Addr a)
2560{
2561 SegInfo* seg;
2562 VgSectKind ret = Vg_SectUnknown;
2563
sewardj47104382002-10-20 18:35:48 +00002564 for(seg = segInfo; seg != NULL; seg = seg->next) {
2565 if (a >= seg->start && a < (seg->start + seg->size)) {
2566 if (0)
sewardj8fe15a32002-10-20 19:29:21 +00002567 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 +00002568 a, seg, seg->filename,
2569 seg->got_start, seg->got_size,
sewardj8fe15a32002-10-20 19:29:21 +00002570 seg->plt_start, seg->plt_size,
2571 seg->data_start, seg->data_size,
2572 seg->bss_start, seg->bss_size);
sewardj47104382002-10-20 18:35:48 +00002573 ret = Vg_SectText;
2574
sewardj8fe15a32002-10-20 19:29:21 +00002575 if (a >= seg->data_start && a < (seg->data_start + seg->data_size))
2576 ret = Vg_SectData;
2577 else if (a >= seg->bss_start && a < (seg->bss_start + seg->bss_size))
2578 ret = Vg_SectBSS;
2579 else if (a >= seg->plt_start && a < (seg->plt_start + seg->plt_size))
sewardj47104382002-10-20 18:35:48 +00002580 ret = Vg_SectPLT;
2581 else if (a >= seg->got_start && a < (seg->got_start + seg->got_size))
2582 ret = Vg_SectGOT;
2583 }
2584 }
2585
2586 return ret;
2587}
2588
sewardjde4a1d02002-03-22 01:27:54 +00002589/*--------------------------------------------------------------------*/
2590/*--- end vg_symtab2.c ---*/
2591/*--------------------------------------------------------------------*/