blob: 8624f121080868bfe30a0ec62e1dddf2a96fb88f [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001
sewardjde4a1d02002-03-22 01:27:54 +00002/*--------------------------------------------------------------------*/
3/*--- Management of symbols and debugging information. ---*/
njnea27e462005-05-31 02:38:09 +00004/*--- symtab.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn53612422005-03-12 16:22:54 +000011 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
33#include "pub_core_threadstate.h"
njn899ce732005-06-21 00:28:11 +000034#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
njnf4c50162005-06-20 14:18:12 +000035#include "pub_core_aspacemgr.h" // For Segment type
36#include "pub_core_debuginfo.h"
njn94b1e2e2005-05-10 05:00:55 +000037#include "pub_core_demangle.h"
njn97405b22005-06-02 03:39:33 +000038#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000039#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000040#include "pub_core_libcfile.h"
njne9befc62005-06-11 15:51:30 +000041#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000042#include "pub_core_libcprint.h"
njnf536bbb2005-06-13 04:21:38 +000043#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000044#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000045#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000046#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000047#include "pub_core_redir.h"
njnf4c50162005-06-20 14:18:12 +000048#include "pub_core_tooliface.h" // For VG_(needs).data_syms
njnea27e462005-05-31 02:38:09 +000049#include "priv_symtab.h"
sewardj55f9d1a2005-04-25 11:11:44 +000050
njn43b9a8a2005-05-10 04:37:01 +000051#include <elf.h> /* ELF defns */
sewardjde4a1d02002-03-22 01:27:54 +000052
njn16eeb4e2005-06-16 03:56:58 +000053static SegInfo* segInfo_list = NULL;
sewardjb5f6f512005-03-10 23:59:00 +000054
sewardj7a21c612005-02-18 09:38:08 +000055/*------------------------------------------------------------*/
56/*--- 32/64-bit parameterisation ---*/
57/*------------------------------------------------------------*/
58
59/* For all the ELF macros and types which specify '32' or '64',
60 select the correct variant for this platform and give it
61 an 'XX' name. Then use the 'XX' variant consistently in
62 the rest of this file.
63*/
njna37029a2005-05-15 03:56:26 +000064#if VG_WORDSIZE == 4
sewardj7a21c612005-02-18 09:38:08 +000065# define ElfXX_Ehdr Elf32_Ehdr
66# define ElfXX_Shdr Elf32_Shdr
67# define ElfXX_Phdr Elf32_Phdr
68# define ElfXX_Sym Elf32_Sym
69# define ElfXX_Word Elf32_Word
70# define ElfXX_Addr Elf32_Addr
71# define ElfXX_Dyn Elf32_Dyn
72# define ELFXX_ST_BIND ELF32_ST_BIND
73# define ELFXX_ST_TYPE ELF32_ST_TYPE
74
njna37029a2005-05-15 03:56:26 +000075#elif VG_WORDSIZE == 8
sewardj7a21c612005-02-18 09:38:08 +000076# define ElfXX_Ehdr Elf64_Ehdr
77# define ElfXX_Shdr Elf64_Shdr
78# define ElfXX_Phdr Elf64_Phdr
79# define ElfXX_Sym Elf64_Sym
80# define ElfXX_Word Elf64_Word
81# define ElfXX_Addr Elf64_Addr
82# define ElfXX_Dyn Elf64_Dyn
83# define ELFXX_ST_BIND ELF64_ST_BIND
84# define ELFXX_ST_TYPE ELF64_ST_TYPE
85
86#else
njna37029a2005-05-15 03:56:26 +000087# error "VG_WORDSIZE should be 4 or 8"
sewardj7a21c612005-02-18 09:38:08 +000088#endif
89
90
91/*------------------------------------------------------------*/
92/*--- ---*/
93/*------------------------------------------------------------*/
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
96 dlopen()ed libraries, which is something that KDE3 does a lot.
sewardjde4a1d02002-03-22 01:27:54 +000097
njn25e49d8e72002-09-23 09:36:25 +000098 Stabs reader greatly improved by Nick Nethercote, Apr 02.
sewardjde4a1d02002-03-22 01:27:54 +000099*/
100
sewardjde4a1d02002-03-22 01:27:54 +0000101static void freeSegInfo ( SegInfo* si )
102{
jsgfcb1d1c02003-10-14 21:55:10 +0000103 struct strchunk *chunk, *next;
sewardjde4a1d02002-03-22 01:27:54 +0000104 vg_assert(si != NULL);
njn25e49d8e72002-09-23 09:36:25 +0000105 if (si->filename) VG_(arena_free)(VG_AR_SYMTAB, si->filename);
106 if (si->symtab) VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
107 if (si->loctab) VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
jsgfcb1d1c02003-10-14 21:55:10 +0000108 if (si->scopetab) VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
sewardj5c638c22005-04-30 07:55:58 +0000109 if (si->cfisi) VG_(arena_free)(VG_AR_SYMTAB, si->cfisi);
jsgfcb1d1c02003-10-14 21:55:10 +0000110
111 for(chunk = si->strchunks; chunk != NULL; chunk = next) {
112 next = chunk->next;
113 VG_(arena_free)(VG_AR_SYMTAB, chunk);
114 }
njn25e49d8e72002-09-23 09:36:25 +0000115 VG_(arena_free)(VG_AR_SYMTAB, si);
sewardjde4a1d02002-03-22 01:27:54 +0000116}
117
118
119/*------------------------------------------------------------*/
120/*--- Adding stuff ---*/
121/*------------------------------------------------------------*/
122
123/* Add a str to the string table, including terminating zero, and
jsgfcb1d1c02003-10-14 21:55:10 +0000124 return pointer to the string in vg_strtab. Unless it's been seen
125 recently, in which case we find the old pointer and return that.
126 This avoids the most egregious duplications.
sewardjde4a1d02002-03-22 01:27:54 +0000127
jsgfcb1d1c02003-10-14 21:55:10 +0000128 JSGF: changed from returning an index to a pointer, and changed to
129 a chunking memory allocator rather than reallocating, so the
130 pointers are stable.
131*/
132
sewardj7eb7c582005-06-23 01:02:53 +0000133Char* ML_(addStr) ( SegInfo* si, Char* str, Int len )
sewardjde4a1d02002-03-22 01:27:54 +0000134{
jsgfcb1d1c02003-10-14 21:55:10 +0000135 struct strchunk *chunk;
njn16eeb4e2005-06-16 03:56:58 +0000136 Int space_needed;
137 Char* p;
njn25e49d8e72002-09-23 09:36:25 +0000138
jsgfcb1d1c02003-10-14 21:55:10 +0000139 if (len == -1)
140 len = VG_(strlen)(str);
njn25e49d8e72002-09-23 09:36:25 +0000141
jsgfcb1d1c02003-10-14 21:55:10 +0000142 space_needed = 1 + len;
njn25e49d8e72002-09-23 09:36:25 +0000143
njn16eeb4e2005-06-16 03:56:58 +0000144 // Allocate a new strtab chunk if necessary
jsgfcb1d1c02003-10-14 21:55:10 +0000145 if (si->strchunks == NULL ||
146 (si->strchunks->strtab_used + space_needed) > STRCHUNKSIZE) {
147 chunk = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*chunk));
148 chunk->strtab_used = 0;
149 chunk->next = si->strchunks;
150 si->strchunks = chunk;
sewardjde4a1d02002-03-22 01:27:54 +0000151 }
jsgfcb1d1c02003-10-14 21:55:10 +0000152 chunk = si->strchunks;
sewardjde4a1d02002-03-22 01:27:54 +0000153
njn16eeb4e2005-06-16 03:56:58 +0000154 p = &chunk->strtab[chunk->strtab_used];
155 VG_(memcpy)(p, str, len);
jsgfcb1d1c02003-10-14 21:55:10 +0000156 chunk->strtab[chunk->strtab_used+len] = '\0';
157 chunk->strtab_used += space_needed;
sewardjde4a1d02002-03-22 01:27:54 +0000158
njn16eeb4e2005-06-16 03:56:58 +0000159 return p;
sewardjde4a1d02002-03-22 01:27:54 +0000160}
161
162/* Add a symbol to the symbol table. */
sewardjde4a1d02002-03-22 01:27:54 +0000163static __inline__
164void addSym ( SegInfo* si, RiSym* sym )
165{
sewardj05bcdcb2003-05-18 10:05:38 +0000166 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000167 RiSym* new_tab;
168
169 /* Ignore zero-sized syms. */
170 if (sym->size == 0) return;
171
172 if (si->symtab_used == si->symtab_size) {
173 new_sz = 2 * si->symtab_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(RiSym) );
sewardjde4a1d02002-03-22 01:27:54 +0000176 if (si->symtab != NULL) {
177 for (i = 0; i < si->symtab_used; i++)
178 new_tab[i] = si->symtab[i];
njn25e49d8e72002-09-23 09:36:25 +0000179 VG_(arena_free)(VG_AR_SYMTAB, si->symtab);
sewardjde4a1d02002-03-22 01:27:54 +0000180 }
181 si->symtab = new_tab;
182 si->symtab_size = new_sz;
183 }
184
185 si->symtab[si->symtab_used] = *sym;
186 si->symtab_used++;
187 vg_assert(si->symtab_used <= si->symtab_size);
188}
189
190/* Add a location to the location table. */
191
192static __inline__
193void addLoc ( SegInfo* si, RiLoc* loc )
194{
sewardj05bcdcb2003-05-18 10:05:38 +0000195 UInt new_sz, i;
sewardjde4a1d02002-03-22 01:27:54 +0000196 RiLoc* new_tab;
197
njne0ee0712002-05-03 16:41:05 +0000198 /* Zero-sized locs should have been ignored earlier */
199 vg_assert(loc->size > 0);
sewardjde4a1d02002-03-22 01:27:54 +0000200
201 if (si->loctab_used == si->loctab_size) {
202 new_sz = 2 * si->loctab_size;
203 if (new_sz == 0) new_sz = 500;
njn25e49d8e72002-09-23 09:36:25 +0000204 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(RiLoc) );
sewardjde4a1d02002-03-22 01:27:54 +0000205 if (si->loctab != NULL) {
206 for (i = 0; i < si->loctab_used; i++)
207 new_tab[i] = si->loctab[i];
njn25e49d8e72002-09-23 09:36:25 +0000208 VG_(arena_free)(VG_AR_SYMTAB, si->loctab);
sewardjde4a1d02002-03-22 01:27:54 +0000209 }
210 si->loctab = new_tab;
211 si->loctab_size = new_sz;
212 }
213
214 si->loctab[si->loctab_used] = *loc;
215 si->loctab_used++;
216 vg_assert(si->loctab_used <= si->loctab_size);
217}
218
219
sewardjb51f2e62002-06-01 23:11:19 +0000220/* Top-level place to call to add a source-location mapping entry. */
221
sewardj7eb7c582005-06-23 01:02:53 +0000222void ML_(addLineInfo) ( SegInfo* si,
jsgfcb1d1c02003-10-14 21:55:10 +0000223 Char* filename,
sewardj7cee6f92005-06-13 17:39:06 +0000224 Char* dirname, /* NULL == directory is unknown */
jsgfcb1d1c02003-10-14 21:55:10 +0000225 Addr this,
226 Addr next,
227 Int lineno,
228 Int entry /* only needed for debug printing */
sewardj7cee6f92005-06-13 17:39:06 +0000229 )
sewardjb51f2e62002-06-01 23:11:19 +0000230{
jsgfcb1d1c02003-10-14 21:55:10 +0000231 static const Bool debug = False;
sewardjb51f2e62002-06-01 23:11:19 +0000232 RiLoc loc;
233 Int size = next - this;
234
235 /* Ignore zero-sized locs */
236 if (this == next) return;
237
jsgfcb1d1c02003-10-14 21:55:10 +0000238 if (debug)
sewardj7cee6f92005-06-13 17:39:06 +0000239 VG_(printf)( " src %s %s line %d %p-%p\n",
240 dirname ? dirname : (Char*)"(unknown)",
241 filename, lineno, this, next );
jsgfcb1d1c02003-10-14 21:55:10 +0000242
sewardjb51f2e62002-06-01 23:11:19 +0000243 /* Maximum sanity checking. Some versions of GNU as do a shabby
244 * job with stabs entries; if anything looks suspicious, revert to
245 * a size of 1. This should catch the instruction of interest
246 * (since if using asm-level debug info, one instruction will
247 * correspond to one line, unlike with C-level debug info where
248 * multiple instructions can map to the one line), but avoid
249 * catching any other instructions bogusly. */
thughesc1c57952004-11-01 17:36:15 +0000250 if (this > next) {
251 if (VG_(clo_verbosity) > 2) {
252 VG_(message)(Vg_DebugMsg,
253 "warning: line info addresses out of order "
254 "at entry %d: 0x%x 0x%x", entry, this, next);
255 }
sewardjb51f2e62002-06-01 23:11:19 +0000256 size = 1;
257 }
258
259 if (size > MAX_LOC_SIZE) {
sewardjd84606d2002-06-18 01:04:57 +0000260 if (0)
sewardjb51f2e62002-06-01 23:11:19 +0000261 VG_(message)(Vg_DebugMsg,
sewardj08a50f62002-06-17 02:21:20 +0000262 "warning: line info address range too large "
sewardjb51f2e62002-06-01 23:11:19 +0000263 "at entry %d: %d", entry, size);
264 size = 1;
265 }
266
sewardj08a50f62002-06-17 02:21:20 +0000267 /* vg_assert(this < si->start + si->size && next-1 >= si->start); */
njne306ffe2002-06-08 13:34:17 +0000268 if (this >= si->start + si->size || next-1 < si->start) {
sewardjd84606d2002-06-18 01:04:57 +0000269 if (0)
sewardj08a50f62002-06-17 02:21:20 +0000270 VG_(message)(Vg_DebugMsg,
271 "warning: ignoring line info entry falling "
272 "outside current SegInfo: %p %p %p %p",
273 si->start, si->start + si->size,
274 this, next-1);
njne306ffe2002-06-08 13:34:17 +0000275 return;
276 }
277
278 vg_assert(lineno >= 0);
279 if (lineno > MAX_LINENO) {
280 VG_(message)(Vg_UserMsg,
sewardj08a50f62002-06-17 02:21:20 +0000281 "warning: ignoring line info entry with "
282 "huge line number (%d)", lineno);
njne306ffe2002-06-08 13:34:17 +0000283 VG_(message)(Vg_UserMsg,
284 " Can't handle line numbers "
sewardj08a50f62002-06-17 02:21:20 +0000285 "greater than %d, sorry", MAX_LINENO);
njne306ffe2002-06-08 13:34:17 +0000286 return;
287 }
sewardjb51f2e62002-06-01 23:11:19 +0000288
289 loc.addr = this;
290 loc.size = (UShort)size;
291 loc.lineno = lineno;
jsgfcb1d1c02003-10-14 21:55:10 +0000292 loc.filename = filename;
sewardj7cee6f92005-06-13 17:39:06 +0000293 loc.dirname = dirname;
sewardjb642dc22002-10-12 17:27:16 +0000294
295 if (0) VG_(message)(Vg_DebugMsg,
296 "addLoc: addr %p, size %d, line %d, file %s",
jsgfcb1d1c02003-10-14 21:55:10 +0000297 this,size,lineno,filename);
sewardjb642dc22002-10-12 17:27:16 +0000298
sewardjb51f2e62002-06-01 23:11:19 +0000299 addLoc ( si, &loc );
300}
301
jsgfcb1d1c02003-10-14 21:55:10 +0000302static __inline__
303void addScopeRange ( SegInfo* si, ScopeRange *range )
304{
305 Int new_sz, i;
306 ScopeRange* new_tab;
307
308 /* Zero-sized scopes should have been ignored earlier */
309 vg_assert(range->size > 0);
310
311 if (si->scopetab_used == si->scopetab_size) {
312 new_sz = 2 * si->scopetab_size;
313 if (new_sz == 0) new_sz = 500;
314 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(*new_tab) );
315 if (si->scopetab != NULL) {
316 for (i = 0; i < si->scopetab_used; i++)
317 new_tab[i] = si->scopetab[i];
318 VG_(arena_free)(VG_AR_SYMTAB, si->scopetab);
319 }
320 si->scopetab = new_tab;
321 si->scopetab_size = new_sz;
322 }
323
324 si->scopetab[si->scopetab_used] = *range;
325 si->scopetab_used++;
326 vg_assert(si->scopetab_used <= si->scopetab_size);
327}
328
329
330/* Top-level place to call to add a source-location mapping entry. */
331
sewardj7eb7c582005-06-23 01:02:53 +0000332void ML_(addScopeInfo) ( SegInfo* si,
jsgfcb1d1c02003-10-14 21:55:10 +0000333 Addr this,
334 Addr next,
335 Scope *scope)
336{
337 static const Bool debug = False;
338 Int size = next - this;
339 ScopeRange range;
340
fitzhardinge83d8a712004-02-05 22:58:37 +0000341 /* Ignore zero-sized or negative scopes */
342 if (size <= 0) {
jsgfcb1d1c02003-10-14 21:55:10 +0000343 if (debug)
344 VG_(printf)("ignoring zero-sized range, scope %p at %p\n", scope, this);
345 return;
346 }
347
348 if (debug)
349 VG_(printf)("adding scope range %p-%p (size=%d) scope %p (%d)\n",
350 this, next, next-this, scope, scope->depth);
351
352 range.addr = this;
353 range.size = size;
354 range.scope = scope;
355
356 addScopeRange ( si, &range );
357}
358
sewardj35165532005-04-30 18:47:48 +0000359
360/* Top-level place to call to add a CFI summary record. The supplied
361 CfiSI is copied. */
sewardj7eb7c582005-06-23 01:02:53 +0000362void ML_(addCfiSI) ( SegInfo* si, CfiSI* cfisi )
sewardj35165532005-04-30 18:47:48 +0000363{
364 static const Bool debug = False;
365
366 if (debug) {
367 VG_(printf)("adding CfiSI: ");
sewardj7eb7c582005-06-23 01:02:53 +0000368 ML_(ppCfiSI)(cfisi);
sewardj35165532005-04-30 18:47:48 +0000369 }
370
sewardj6b2eefa2005-05-20 02:10:45 +0000371 vg_assert(cfisi->len > 0 && cfisi->len < 2000000);
sewardjbf603752005-05-02 00:36:27 +0000372
sewardj35165532005-04-30 18:47:48 +0000373 UInt new_sz, i;
374 CfiSI* new_tab;
375
sewardjc4f204f2005-05-03 15:23:00 +0000376 /* Rule out ones which are completely outside the segment. These
377 probably indicate some kind of bug, but for the meantime ignore
378 them. */
379 if ( cfisi->base + cfisi->len - 1 < si->start
380 || si->start + si->size - 1 < cfisi->base ) {
sewardj55022aa2005-05-03 16:05:00 +0000381 static Int complaints = 3;
382 if (VG_(clo_trace_cfi) || complaints > 0) {
383 complaints--;
sewardjbe18a592005-05-06 17:01:21 +0000384 if (VG_(clo_verbosity) > 1) {
385 VG_(message)(
386 Vg_DebugMsg,
387 "warning: CfiSI %p .. %p outside segment %p .. %p",
388 cfisi->base,
389 cfisi->base + cfisi->len - 1,
390 si->start,
391 si->start + si->size - 1
392 );
393 }
sewardj55022aa2005-05-03 16:05:00 +0000394 if (VG_(clo_trace_cfi))
sewardj7eb7c582005-06-23 01:02:53 +0000395 ML_(ppCfiSI)(cfisi);
sewardjc4f204f2005-05-03 15:23:00 +0000396 }
397 return;
398 }
399
sewardj35165532005-04-30 18:47:48 +0000400 if (si->cfisi_used == si->cfisi_size) {
401 new_sz = 2 * si->cfisi_size;
402 if (new_sz == 0) new_sz = 20;
403 new_tab = VG_(arena_malloc)(VG_AR_SYMTAB, new_sz * sizeof(CfiSI) );
404 if (si->cfisi != NULL) {
405 for (i = 0; i < si->cfisi_used; i++)
406 new_tab[i] = si->cfisi[i];
407 VG_(arena_free)(VG_AR_SYMTAB, si->cfisi);
408 }
409 si->cfisi = new_tab;
410 si->cfisi_size = new_sz;
411 }
412
413 si->cfisi[si->cfisi_used] = *cfisi;
414 si->cfisi_used++;
415 vg_assert(si->cfisi_used <= si->cfisi_size);
416}
417
418
sewardjde4a1d02002-03-22 01:27:54 +0000419/*------------------------------------------------------------*/
420/*--- Helpers ---*/
421/*------------------------------------------------------------*/
422
423/* Non-fatal -- use vg_panic if terminal. */
sewardj7eb7c582005-06-23 01:02:53 +0000424void ML_(symerr) ( Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000425{
426 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +0000427 VG_(message)(Vg_DebugMsg,"%s", msg );
sewardjde4a1d02002-03-22 01:27:54 +0000428}
429
430
431/* Print a symbol. */
432static
433void printSym ( SegInfo* si, Int i )
434{
435 VG_(printf)( "%5d: %8p .. %8p (%d) %s\n",
436 i,
437 si->symtab[i].addr,
438 si->symtab[i].addr + si->symtab[i].size - 1, si->symtab[i].size,
jsgfcb1d1c02003-10-14 21:55:10 +0000439 si->symtab[i].name );
sewardjde4a1d02002-03-22 01:27:54 +0000440}
441
nethercote80f76782003-11-13 22:34:00 +0000442#define TRACE_SYMTAB(format, args...) \
443 if (VG_(clo_trace_symtab)) { VG_(printf)(format, ## args); }
444
sewardjde4a1d02002-03-22 01:27:54 +0000445
446#if 0
447/* Print the entire sym tab. */
448static __attribute__ ((unused))
449void printSymtab ( void )
450{
451 Int i;
452 VG_(printf)("\n------ BEGIN vg_symtab ------\n");
453 for (i = 0; i < vg_symtab_used; i++)
454 printSym(i);
455 VG_(printf)("------ BEGIN vg_symtab ------\n");
456}
457#endif
458
459#if 0
460/* Paranoid strcat. */
461static
462void safeCopy ( UChar* dst, UInt maxlen, UChar* src )
463{
464 UInt i = 0, j = 0;
465 while (True) {
466 if (i >= maxlen) return;
467 if (dst[i] == 0) break;
468 i++;
469 }
470 while (True) {
471 if (i >= maxlen) return;
472 dst[i] = src[j];
473 if (src[j] == 0) return;
474 i++; j++;
475 }
476}
477#endif
478
sewardjb51f2e62002-06-01 23:11:19 +0000479
sewardjde4a1d02002-03-22 01:27:54 +0000480/*------------------------------------------------------------*/
481/*--- Canonicalisers ---*/
482/*------------------------------------------------------------*/
483
484/* Sort the symtab by starting address, and emit warnings if any
nethercote80f76782003-11-13 22:34:00 +0000485 symbols have overlapping address ranges. We use that old chestnut,
486 shellsort. Mash the table around so as to establish the property
487 that addresses are in order and the ranges to not overlap. This
488 facilitates using binary search to map addresses to symbols when we
489 come to query the table.
sewardjde4a1d02002-03-22 01:27:54 +0000490*/
jsgfcb1d1c02003-10-14 21:55:10 +0000491static Int compare_RiSym(void *va, void *vb) {
492 RiSym *a = (RiSym *)va;
493 RiSym *b = (RiSym *)vb;
494
nethercote05fdfac2004-08-01 20:24:46 +0000495 if (a->addr < b->addr) return -1;
496 if (a->addr > b->addr) return 1;
497 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000498}
499
fitzhardinge1c76dc42003-12-15 09:00:21 +0000500/* Two symbols have the same address. Which name do we prefer?
501
sewardjb5f6f512005-03-10 23:59:00 +0000502 The general rule is to prefer the shorter symbol name. If the
503 symbol contains a '@', which means its versioned, then the length
504 up to the '@' is used for length comparison purposes (so
505 "foo@GLIBC_2.4.2" is considered shorter than "foobar"), but if two
506 symbols have the same length, the one with the version string is
507 preferred. If all else fails, use alphabetical ordering.
njn16eeb4e2005-06-16 03:56:58 +0000508
509 Very occasionally this goes wrong (eg. 'memcmp' and 'bcmp' are aliases
510 in glibc, we choose the 'bcmp' symbol because it's shorter, so we
511 can misdescribe memcmp() as bcmp()). This is hard to avoid. It's
512 mentioned in the FAQ file.
fitzhardinge1c76dc42003-12-15 09:00:21 +0000513 */
514static RiSym *prefersym(RiSym *a, RiSym *b)
515{
sewardjb5f6f512005-03-10 23:59:00 +0000516 Int lena, lenb; /* full length */
517 Int vlena, vlenb; /* length without version */
518 const Char *vpa, *vpb;
fitzhardingeefda47f2003-12-15 23:31:52 +0000519
sewardjb5f6f512005-03-10 23:59:00 +0000520 vlena = lena = VG_(strlen)(a->name);
521 vlenb = lenb = VG_(strlen)(b->name);
fitzhardinge1c76dc42003-12-15 09:00:21 +0000522
sewardjb5f6f512005-03-10 23:59:00 +0000523 vpa = VG_(strchr)(a->name, '@');
524 vpb = VG_(strchr)(b->name, '@');
fitzhardinge1c76dc42003-12-15 09:00:21 +0000525
sewardjb5f6f512005-03-10 23:59:00 +0000526 if (vpa)
527 vlena = vpa - a->name;
528 if (vpb)
529 vlenb = vpb - b->name;
fitzhardingeefda47f2003-12-15 23:31:52 +0000530
njn16eeb4e2005-06-16 03:56:58 +0000531 TRACE_SYMTAB("choosing between '%s' and '%s'\n", a->name, b->name);
532
sewardjb5f6f512005-03-10 23:59:00 +0000533 /* Select the shortest unversioned name */
534 if (vlena < vlenb)
535 return a;
536 else if (vlenb < vlena)
fitzhardinge1c76dc42003-12-15 09:00:21 +0000537 return b;
538
sewardjb5f6f512005-03-10 23:59:00 +0000539 /* Equal lengths; select the versioned name */
540 if (vpa && !vpb)
541 return a;
542 if (vpb && !vpa)
543 return b;
544
545 /* Either both versioned or neither is versioned; select them
546 alphabetically */
547 if (VG_(strcmp)(a->name, b->name) < 0)
548 return a;
549 else
550 return b;
fitzhardinge1c76dc42003-12-15 09:00:21 +0000551}
552
sewardjde4a1d02002-03-22 01:27:54 +0000553static
554void canonicaliseSymtab ( SegInfo* si )
555{
jsgfcb1d1c02003-10-14 21:55:10 +0000556 Int i, j, n_merged, n_truncated;
sewardjde4a1d02002-03-22 01:27:54 +0000557 Addr s1, s2, e1, e2;
558
559# define SWAP(ty,aa,bb) \
560 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
561
jsgfcb1d1c02003-10-14 21:55:10 +0000562 if (si->symtab_used == 0)
563 return;
sewardjde4a1d02002-03-22 01:27:54 +0000564
nethercote3acbb5d2003-11-13 21:50:45 +0000565 VG_(ssort)(si->symtab, si->symtab_used, sizeof(*si->symtab), compare_RiSym);
sewardjde4a1d02002-03-22 01:27:54 +0000566
567 cleanup_more:
568
njn16eeb4e2005-06-16 03:56:58 +0000569 /* If two symbols have identical address ranges, we pick one
570 using prefersym() (see it for details). */
sewardjde4a1d02002-03-22 01:27:54 +0000571 do {
572 n_merged = 0;
573 j = si->symtab_used;
574 si->symtab_used = 0;
575 for (i = 0; i < j; i++) {
576 if (i < j-1
577 && si->symtab[i].addr == si->symtab[i+1].addr
578 && si->symtab[i].size == si->symtab[i+1].size) {
579 n_merged++;
580 /* merge the two into one */
fitzhardinge1c76dc42003-12-15 09:00:21 +0000581 si->symtab[si->symtab_used++] = *prefersym(&si->symtab[i], &si->symtab[i+1]);
sewardjde4a1d02002-03-22 01:27:54 +0000582 i++;
583 } else {
584 si->symtab[si->symtab_used++] = si->symtab[i];
585 }
586 }
nethercote80f76782003-11-13 22:34:00 +0000587 TRACE_SYMTAB( "%d merged\n", n_merged);
sewardjde4a1d02002-03-22 01:27:54 +0000588 }
589 while (n_merged > 0);
590
591 /* Detect and "fix" overlapping address ranges. */
592 n_truncated = 0;
593
sewardj05bcdcb2003-05-18 10:05:38 +0000594 for (i = 0; i < ((Int)si->symtab_used) -1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000595
596 vg_assert(si->symtab[i].addr <= si->symtab[i+1].addr);
597
598 /* Check for common (no overlap) case. */
599 if (si->symtab[i].addr + si->symtab[i].size
600 <= si->symtab[i+1].addr)
601 continue;
602
603 /* There's an overlap. Truncate one or the other. */
604 if (VG_(clo_trace_symtab)) {
605 VG_(printf)("overlapping address ranges in symbol table\n\t");
606 printSym(si,i);
607 VG_(printf)("\t");
608 printSym(si,i+1);
609 VG_(printf)("\n");
610 }
611
612 /* Truncate one or the other. */
613 s1 = si->symtab[i].addr;
614 s2 = si->symtab[i+1].addr;
615 e1 = s1 + si->symtab[i].size - 1;
616 e2 = s2 + si->symtab[i+1].size - 1;
617 if (s1 < s2) {
618 e1 = s2-1;
619 } else {
620 vg_assert(s1 == s2);
621 if (e1 > e2) {
622 s1 = e2+1; SWAP(Addr,s1,s2); SWAP(Addr,e1,e2);
623 } else
624 if (e1 < e2) {
625 s2 = e1+1;
626 } else {
627 /* e1 == e2. Identical addr ranges. We'll eventually wind
628 up back at cleanup_more, which will take care of it. */
629 }
630 }
631 si->symtab[i].addr = s1;
632 si->symtab[i+1].addr = s2;
633 si->symtab[i].size = e1 - s1 + 1;
634 si->symtab[i+1].size = e2 - s2 + 1;
635 vg_assert(s1 <= s2);
636 vg_assert(si->symtab[i].size > 0);
637 vg_assert(si->symtab[i+1].size > 0);
638 /* It may be that the i+1 entry now needs to be moved further
639 along to maintain the address order requirement. */
640 j = i+1;
sewardj05bcdcb2003-05-18 10:05:38 +0000641 while (j < ((Int)si->symtab_used)-1
sewardjde4a1d02002-03-22 01:27:54 +0000642 && si->symtab[j].addr > si->symtab[j+1].addr) {
643 SWAP(RiSym,si->symtab[j],si->symtab[j+1]);
644 j++;
645 }
646 n_truncated++;
647 }
648
649 if (n_truncated > 0) goto cleanup_more;
650
651 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000652 for (i = 0; i < ((Int)si->symtab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000653 /* No zero-sized symbols. */
654 vg_assert(si->symtab[i].size > 0);
655 /* In order. */
656 vg_assert(si->symtab[i].addr < si->symtab[i+1].addr);
657 /* No overlaps. */
658 vg_assert(si->symtab[i].addr + si->symtab[i].size - 1
659 < si->symtab[i+1].addr);
660 }
661# undef SWAP
662}
663
jsgfcb1d1c02003-10-14 21:55:10 +0000664/* Sort the scope range table by starting address. Mash the table
665 around so as to establish the property that addresses are in order
666 and the ranges do not overlap. This facilitates using binary
667 search to map addresses to scopes when we come to query the
668 table.
669*/
670static Int compare_ScopeRange(void *va, void *vb) {
671 ScopeRange *a = (ScopeRange *)va;
672 ScopeRange *b = (ScopeRange *)vb;
673
nethercote05fdfac2004-08-01 20:24:46 +0000674 if (a->addr < b->addr) return -1;
675 if (a->addr > b->addr) return 1;
676 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000677}
678
679static
680void canonicaliseScopetab ( SegInfo* si )
681{
682 Int i,j;
683
684 if (si->scopetab_used == 0)
685 return;
686
687 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000688 VG_(ssort)(si->scopetab, si->scopetab_used, sizeof(*si->scopetab),
689 compare_ScopeRange);
jsgfcb1d1c02003-10-14 21:55:10 +0000690
691 /* If two adjacent entries overlap, truncate the first. */
692 for (i = 0; i < si->scopetab_used-1; i++) {
693 if (si->scopetab[i].addr + si->scopetab[i].size > si->scopetab[i+1].addr) {
694 Int new_size = si->scopetab[i+1].addr - si->scopetab[i].addr;
695
696 if (new_size < 0)
697 si->scopetab[i].size = 0;
698 else
699 si->scopetab[i].size = new_size;
700 }
701 }
702
703 /* Zap any zero-sized entries resulting from the truncation
704 process. */
705 j = 0;
706 for (i = 0; i < si->scopetab_used; i++) {
707 if (si->scopetab[i].size > 0) {
708 si->scopetab[j] = si->scopetab[i];
709 j++;
710 }
711 }
712 si->scopetab_used = j;
713
714 /* Ensure relevant postconditions hold. */
715 for (i = 0; i < si->scopetab_used-1; i++) {
716 /*
717 VG_(printf)("%d (%d) %d 0x%x\n",
718 i, si->scopetab[i+1].confident,
719 si->scopetab[i+1].size, si->scopetab[i+1].addr );
720 */
721 /* No zero-sized symbols. */
722 vg_assert(si->scopetab[i].size > 0);
723 /* In order. */
724 if (si->scopetab[i].addr >= si->scopetab[i+1].addr)
725 VG_(printf)("si->scopetab[%d] = %p,size=%d [%d] = %p,size=%d\n",
726 i, si->scopetab[i].addr, si->scopetab[i].size,
727 i+1, si->scopetab[i+1].addr, si->scopetab[i+1].size);
728 vg_assert(si->scopetab[i].addr < si->scopetab[i+1].addr);
729 /* No overlaps. */
730 vg_assert(si->scopetab[i].addr + si->scopetab[i].size - 1
731 < si->scopetab[i+1].addr);
732 }
733}
sewardjde4a1d02002-03-22 01:27:54 +0000734
735
736/* Sort the location table by starting address. Mash the table around
737 so as to establish the property that addresses are in order and the
738 ranges do not overlap. This facilitates using binary search to map
sewardjb51f2e62002-06-01 23:11:19 +0000739 addresses to locations when we come to query the table.
740*/
jsgfcb1d1c02003-10-14 21:55:10 +0000741static Int compare_RiLoc(void *va, void *vb) {
742 RiLoc *a = (RiLoc *)va;
743 RiLoc *b = (RiLoc *)vb;
744
nethercote05fdfac2004-08-01 20:24:46 +0000745 if (a->addr < b->addr) return -1;
746 if (a->addr > b->addr) return 1;
747 return 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000748}
749
sewardjde4a1d02002-03-22 01:27:54 +0000750static
751void canonicaliseLoctab ( SegInfo* si )
752{
njn16eeb4e2005-06-16 03:56:58 +0000753 Int i, j;
sewardjde4a1d02002-03-22 01:27:54 +0000754
755# define SWAP(ty,aa,bb) \
756 do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0);
757
jsgfcb1d1c02003-10-14 21:55:10 +0000758 if (si->loctab_used == 0)
759 return;
760
sewardjde4a1d02002-03-22 01:27:54 +0000761 /* Sort by start address. */
nethercote3acbb5d2003-11-13 21:50:45 +0000762 VG_(ssort)(si->loctab, si->loctab_used, sizeof(*si->loctab), compare_RiLoc);
sewardjde4a1d02002-03-22 01:27:54 +0000763
764 /* If two adjacent entries overlap, truncate the first. */
sewardj05bcdcb2003-05-18 10:05:38 +0000765 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000766 vg_assert(si->loctab[i].size < 10000);
767 if (si->loctab[i].addr + si->loctab[i].size > si->loctab[i+1].addr) {
768 /* Do this in signed int32 because the actual .size fields
njna1685902005-03-16 04:09:21 +0000769 are only 12 bits. */
sewardjde4a1d02002-03-22 01:27:54 +0000770 Int new_size = si->loctab[i+1].addr - si->loctab[i].addr;
771 if (new_size < 0) {
772 si->loctab[i].size = 0;
773 } else
njna1685902005-03-16 04:09:21 +0000774 if (new_size > MAX_LOC_SIZE) {
775 si->loctab[i].size = MAX_LOC_SIZE;
sewardjde4a1d02002-03-22 01:27:54 +0000776 } else {
777 si->loctab[i].size = (UShort)new_size;
778 }
779 }
780 }
781
782 /* Zap any zero-sized entries resulting from the truncation
783 process. */
784 j = 0;
sewardj05bcdcb2003-05-18 10:05:38 +0000785 for (i = 0; i < (Int)si->loctab_used; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000786 if (si->loctab[i].size > 0) {
787 si->loctab[j] = si->loctab[i];
788 j++;
789 }
790 }
791 si->loctab_used = j;
792
793 /* Ensure relevant postconditions hold. */
sewardj05bcdcb2003-05-18 10:05:38 +0000794 for (i = 0; i < ((Int)si->loctab_used)-1; i++) {
sewardjde4a1d02002-03-22 01:27:54 +0000795 /*
796 VG_(printf)("%d (%d) %d 0x%x\n",
797 i, si->loctab[i+1].confident,
798 si->loctab[i+1].size, si->loctab[i+1].addr );
799 */
800 /* No zero-sized symbols. */
801 vg_assert(si->loctab[i].size > 0);
802 /* In order. */
803 vg_assert(si->loctab[i].addr < si->loctab[i+1].addr);
804 /* No overlaps. */
805 vg_assert(si->loctab[i].addr + si->loctab[i].size - 1
806 < si->loctab[i+1].addr);
807 }
808# undef SWAP
809}
810
811
sewardj3a1c7db2005-05-02 09:43:44 +0000812/* Sort the call-frame-info table by starting address. Mash the table
813 around so as to establish the property that addresses are in order
814 and the ranges do not overlap. This facilitates using binary
815 search to map addresses to locations when we come to query the
816 table.
817
818 Also, set cfisi_minaddr and cfisi_maxaddr to be the min and max of
819 any of the address ranges contained in cfisi[0 .. cfisi_used-1], so
820 as to facilitate rapidly skipping this SegInfo when looking for an
821 address which falls outside that range.
822*/
823static Int compare_CfiSI(void *va, void *vb) {
824 CfiSI *a = (CfiSI*)va;
825 CfiSI *b = (CfiSI*)vb;
826
827 if (a->base < b->base) return -1;
828 if (a->base > b->base) return 1;
829 return 0;
830}
831
sewardjbf603752005-05-02 00:36:27 +0000832static
833void canonicaliseCfiSI ( SegInfo* si )
834{
835 Int i;
836 const Addr minAddr = 0;
837 const Addr maxAddr = ~minAddr;
838
839 /* Set cfisi_minaddr and cfisi_maxaddr to summarise the entire
840 address range contained in cfisi[0 .. cfisi_used-1]. */
841 si->cfisi_minaddr = maxAddr;
842 si->cfisi_maxaddr = minAddr;
843 for (i = 0; i < si->cfisi_used; i++) {
844 Addr here_min = si->cfisi[i].base;
845 Addr here_max = si->cfisi[i].base + si->cfisi[i].len - 1;
846 if (here_min < si->cfisi_minaddr)
847 si->cfisi_minaddr = here_min;
848 if (here_max > si->cfisi_maxaddr)
849 si->cfisi_maxaddr = here_max;
850 }
sewardj520e3492005-05-02 10:39:16 +0000851
852 if (VG_(clo_trace_cfi))
853 VG_(printf)("canonicaliseCfiSI: %d entries, %p .. %p\n",
854 si->cfisi_used,
855 si->cfisi_minaddr, si->cfisi_maxaddr);
sewardj3a1c7db2005-05-02 09:43:44 +0000856
857 /* Sort the cfisi array by base address. */
858 VG_(ssort)(si->cfisi, si->cfisi_used, sizeof(*si->cfisi), compare_CfiSI);
859
860 /* Ensure relevant postconditions hold. */
861 for (i = 0; i < si->cfisi_used; i++) {
862 /* No zero-length ranges. */
863 vg_assert(si->cfisi[i].len > 0);
864 /* Makes sense w.r.t. summary address range */
865 vg_assert(si->cfisi[i].base >= si->cfisi_minaddr);
866 vg_assert(si->cfisi[i].base + si->cfisi[i].len - 1
867 <= si->cfisi_maxaddr);
868
869 if (i < si->cfisi_used - 1) {
sewardjc4f204f2005-05-03 15:23:00 +0000870 /*
871 if (!(si->cfisi[i].base < si->cfisi[i+1].base)) {
872 VG_(printf)("\nOOO cfisis:\n");
873 VG_(ppCfiSI)(&si->cfisi[i]);
874 VG_(ppCfiSI)(&si->cfisi[i+1]);
875 }
876 */
sewardj3a1c7db2005-05-02 09:43:44 +0000877 /* In order. */
878 vg_assert(si->cfisi[i].base < si->cfisi[i+1].base);
879 /* No overlaps. */
880 vg_assert(si->cfisi[i].base + si->cfisi[i].len - 1
881 < si->cfisi[i+1].base);
882 }
883 }
884
sewardjbf603752005-05-02 00:36:27 +0000885}
886
887
sewardjde4a1d02002-03-22 01:27:54 +0000888/*------------------------------------------------------------*/
sewardjb51f2e62002-06-01 23:11:19 +0000889/*--- Read info from a .so/exe file. ---*/
890/*------------------------------------------------------------*/
891
fitzhardinge98abfc72003-12-16 02:05:15 +0000892Bool VG_(is_object_file)(const void *buf)
893{
894 {
sewardj7a21c612005-02-18 09:38:08 +0000895 ElfXX_Ehdr *ehdr = (ElfXX_Ehdr *)buf;
fitzhardinge98abfc72003-12-16 02:05:15 +0000896 Int ok = 1;
897
898 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
899 && ehdr->e_ident[EI_MAG1] == 'E'
900 && ehdr->e_ident[EI_MAG2] == 'L'
901 && ehdr->e_ident[EI_MAG3] == 'F');
njn35172bc2005-03-26 00:04:03 +0000902 ok &= (ehdr->e_ident[EI_CLASS] == VGA_ELF_CLASS
903 && ehdr->e_ident[EI_DATA] == VGA_ELF_ENDIANNESS
fitzhardinge98abfc72003-12-16 02:05:15 +0000904 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
905 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
njn35172bc2005-03-26 00:04:03 +0000906 ok &= (ehdr->e_machine == VGA_ELF_MACHINE);
fitzhardinge98abfc72003-12-16 02:05:15 +0000907 ok &= (ehdr->e_version == EV_CURRENT);
908 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
909 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
910 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
911
912 if (ok)
913 return True;
914 }
915
916 /* other file formats here? */
917
918 return False;
919}
920
njn16eeb4e2005-06-16 03:56:58 +0000921static Bool is_interesting_symbol(SegInfo* si, ElfXX_Sym* sym,
922 Char* sym_name, Addr sym_addr)
rjwalshe4e779d2004-04-16 23:02:29 +0000923{
njn16eeb4e2005-06-16 03:56:58 +0000924 /* Figure out if we're interested in the symbol.
925 Firstly, is it of the right flavour? */
926 if ( ! ( (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL ||
927 ELFXX_ST_BIND(sym->st_info) == STB_LOCAL ||
928 ELFXX_ST_BIND(sym->st_info) == STB_WEAK)
929 &&
930 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC ||
931 (VG_(needs).data_syms
932 && ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT))
933 )
934 )
935 return False;
rjwalshe4e779d2004-04-16 23:02:29 +0000936
njn16eeb4e2005-06-16 03:56:58 +0000937 /* Secondly, if it's apparently in a GOT or PLT, it's really
938 a reference to a symbol defined elsewhere, so ignore it. */
939 if (si->got_start != 0
940 && sym_addr >= si->got_start
941 && sym_addr < si->got_start + si->got_size) {
942 TRACE_SYMTAB("ignore -- in GOT: %s\n", sym_name);
943 return False;
rjwalshe4e779d2004-04-16 23:02:29 +0000944 }
njn16eeb4e2005-06-16 03:56:58 +0000945 if (si->plt_start != 0
946 && sym_addr >= si->plt_start
947 && sym_addr < si->plt_start + si->plt_size) {
948 TRACE_SYMTAB("ignore -- in PLT: %s\n", sym_name);
sewardj9ee81f52005-04-02 17:38:59 +0000949 return False;
950 }
951
njn16eeb4e2005-06-16 03:56:58 +0000952 /* Don't bother if nameless, or zero-sized. */
953 if (sym->st_name == (ElfXX_Word)NULL
954 || /* VG_(strlen)(sym_name) == 0 */
955 /* equivalent but cheaper ... */
956 sym_name[0] == 0
957 || sym->st_size == 0) {
958 TRACE_SYMTAB("ignore -- size=0: %s\n", sym_name);
959 return False;
sewardj9ee81f52005-04-02 17:38:59 +0000960 }
961
njn16eeb4e2005-06-16 03:56:58 +0000962 /* This seems to significantly reduce the number of junk
963 symbols, and particularly reduces the number of
964 overlapping address ranges. Don't ask me why ... */
965 if ((Int)sym->st_value == 0) {
966 TRACE_SYMTAB( "ignore -- valu=0: %s\n", sym_name);
967 return False;
968 }
969
970 /* If no part of the symbol falls within the mapped range,
971 ignore it. */
972 if (sym_addr+sym->st_size <= si->start
973 || sym_addr >= si->start+si->size) {
974 TRACE_SYMTAB( "ignore -- outside mapped range\n" );
975 return False;
976 }
977
978 // It is an interesting symbol!
rjwalshe4e779d2004-04-16 23:02:29 +0000979 return True;
980}
981
nethercote80f76782003-11-13 22:34:00 +0000982/* Read a symbol table (normal or dynamic) */
983static
rjwalshe4e779d2004-04-16 23:02:29 +0000984void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts,
sewardj7a21c612005-02-18 09:38:08 +0000985 ElfXX_Sym* o_symtab, UInt o_symtab_sz,
nethercote80f76782003-11-13 22:34:00 +0000986 UChar* o_strtab, UInt o_strtab_sz )
987{
988 Int i;
989 Addr sym_addr;
njn16eeb4e2005-06-16 03:56:58 +0000990 Char* sym_name;
nethercote80f76782003-11-13 22:34:00 +0000991 RiSym risym;
mueller82df83e2003-11-19 22:05:35 +0000992 Char* name;
njn16eeb4e2005-06-16 03:56:58 +0000993 ElfXX_Sym* sym;
mueller82df83e2003-11-19 22:05:35 +0000994
nethercote80f76782003-11-13 22:34:00 +0000995 if (o_strtab == NULL || o_symtab == NULL) {
jseward0edbfb52003-12-12 06:22:06 +0000996 Char buf[80];
997 vg_assert(VG_(strlen)(tab_name) < 40);
998 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
sewardj7eb7c582005-06-23 01:02:53 +0000999 ML_(symerr)(buf);
nethercote80f76782003-11-13 22:34:00 +00001000 return;
1001 }
1002
1003 TRACE_SYMTAB("Reading %s (%d entries)\n", tab_name,
sewardj7a21c612005-02-18 09:38:08 +00001004 o_symtab_sz/sizeof(ElfXX_Sym) );
nethercote80f76782003-11-13 22:34:00 +00001005
1006 /* Perhaps should start at i = 1; ELF docs suggest that entry
njn02bc4b82005-05-15 17:28:26 +00001007 0 always denotes 'unknown symbol'. */
sewardj7a21c612005-02-18 09:38:08 +00001008 for (i = 1; i < (Int)(o_symtab_sz/sizeof(ElfXX_Sym)); i++) {
njn16eeb4e2005-06-16 03:56:58 +00001009 sym = & o_symtab[i];
1010 sym_name = (Char*)(o_strtab + sym->st_name);
tomf26d0682005-04-02 14:57:43 +00001011 sym_addr = si->offset + sym->st_value;
nethercote80f76782003-11-13 22:34:00 +00001012
1013 if (VG_(clo_trace_symtab)) {
1014 VG_(printf)("raw symbol [%d]: ", i);
sewardj7a21c612005-02-18 09:38:08 +00001015 switch (ELFXX_ST_BIND(sym->st_info)) {
nethercote80f76782003-11-13 22:34:00 +00001016 case STB_LOCAL: VG_(printf)("LOC "); break;
1017 case STB_GLOBAL: VG_(printf)("GLO "); break;
1018 case STB_WEAK: VG_(printf)("WEA "); break;
1019 case STB_LOPROC: VG_(printf)("lop "); break;
1020 case STB_HIPROC: VG_(printf)("hip "); break;
1021 default: VG_(printf)("??? "); break;
1022 }
sewardj7a21c612005-02-18 09:38:08 +00001023 switch (ELFXX_ST_TYPE(sym->st_info)) {
nethercote80f76782003-11-13 22:34:00 +00001024 case STT_NOTYPE: VG_(printf)("NOT "); break;
1025 case STT_OBJECT: VG_(printf)("OBJ "); break;
1026 case STT_FUNC: VG_(printf)("FUN "); break;
1027 case STT_SECTION: VG_(printf)("SEC "); break;
1028 case STT_FILE: VG_(printf)("FIL "); break;
1029 case STT_LOPROC: VG_(printf)("lop "); break;
1030 case STT_HIPROC: VG_(printf)("hip "); break;
1031 default: VG_(printf)("??? "); break;
1032 }
1033 VG_(printf)(
1034 ": value %p, size %d, name %s\n",
1035 sym_addr, sym->st_size,
njn16eeb4e2005-06-16 03:56:58 +00001036 ( sym->st_name ? sym_name : (Char*)"NONAME" ) );
nethercote80f76782003-11-13 22:34:00 +00001037 }
nethercote80f76782003-11-13 22:34:00 +00001038
njn16eeb4e2005-06-16 03:56:58 +00001039 // Record interesting symbols in our symtab.
1040 if ( is_interesting_symbol(si, sym, sym_name, sym_addr) ) {
1041 vg_assert(sym->st_name != 0);
1042 vg_assert(sym_name[0] != 0);
sewardj7eb7c582005-06-23 01:02:53 +00001043 name = ML_(addStr) ( si, sym_name, -1 );
njn16eeb4e2005-06-16 03:56:58 +00001044 vg_assert(name != NULL);
1045
1046 /*
1047 * Is this symbol a magic valgrind-intercept symbol? If so,
1048 * hand this off to the redir module.
1049 *
1050 * Note: this function can change the symbol name just added to
1051 * the string table. Importantly, it never makes it bigger.
1052 */
1053 if (do_intercepts) {
1054 VG_(maybe_redir_or_notify)( name, sym_addr );
1055 }
1056
1057 risym.addr = sym_addr;
1058 risym.size = sym->st_size;
1059 risym.name = name;
1060 addSym ( si, &risym );
rjwalshe4e779d2004-04-16 23:02:29 +00001061 }
nethercote80f76782003-11-13 22:34:00 +00001062 }
1063}
1064
thughesc035bd92004-06-13 09:59:02 +00001065/*
1066 * This routine for calculating the CRC for a separate debug file
1067 * is GPLed code borrowed from binutils.
1068 */
1069static UInt
1070calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
1071{
1072 static const UInt crc32_table[256] =
1073 {
1074 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
1075 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
1076 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
1077 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
1078 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1079 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1080 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1081 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1082 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1083 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1084 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1085 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1086 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1087 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1088 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1089 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1090 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1091 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1092 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1093 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1094 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1095 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1096 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1097 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1098 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1099 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1100 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1101 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1102 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1103 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1104 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1105 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1106 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1107 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1108 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1109 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1110 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1111 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1112 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1113 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1114 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1115 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1116 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1117 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1118 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1119 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1120 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1121 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1122 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1123 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1124 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1125 0x2d02ef8d
1126 };
1127 const UChar *end;
1128
1129 crc = ~crc & 0xffffffff;
1130 for (end = buf + len; buf < end; ++ buf)
1131 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1132 return ~crc & 0xffffffff;;
1133}
1134
1135/*
1136 * Try and open a separate debug file, ignoring any where the CRC does
1137 * not match the value from the main object file.
1138 */
1139static
1140Addr open_debug_file( Char* name, UInt crc, UInt* size )
1141{
1142 Int fd;
1143 struct vki_stat stat_buf;
1144 Addr addr;
sewardjb5f6f512005-03-10 23:59:00 +00001145 UInt calccrc;
thughesc035bd92004-06-13 09:59:02 +00001146
1147 if ((fd = VG_(open)(name, VKI_O_RDONLY, 0)) < 0)
1148 return 0;
1149
1150 if (VG_(fstat)(fd, &stat_buf) != 0) {
1151 VG_(close)(fd);
1152 return 0;
1153 }
1154
sewardjb5f6f512005-03-10 23:59:00 +00001155 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +00001156 VG_(message)(Vg_DebugMsg, "Reading debug info from %s...", name);
sewardjb5f6f512005-03-10 23:59:00 +00001157
thughesc035bd92004-06-13 09:59:02 +00001158 *size = stat_buf.st_size;
1159
1160 if ((addr = (Addr)VG_(mmap)(NULL, *size, VKI_PROT_READ,
nethercoteb4250ae2004-07-10 16:50:09 +00001161 VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1162 0, fd, 0)) == (Addr)-1)
1163 {
thughesc035bd92004-06-13 09:59:02 +00001164 VG_(close)(fd);
1165 return 0;
1166 }
1167
1168 VG_(close)(fd);
1169
sewardjb5f6f512005-03-10 23:59:00 +00001170 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)addr, *size);
1171 if (calccrc != crc) {
nethercotee567e702004-07-10 17:49:17 +00001172 int res = VG_(munmap)((void*)addr, *size);
1173 vg_assert(0 == res);
sewardjb5f6f512005-03-10 23:59:00 +00001174 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +00001175 VG_(message)(Vg_DebugMsg, "... CRC mismatch (computed %08x wanted %08x)", calccrc, crc);
thughesc035bd92004-06-13 09:59:02 +00001176 return 0;
1177 }
1178
1179 return addr;
1180}
1181
1182/*
nethercoteb1e1ad42004-08-03 23:44:12 +00001183 * Try to find a separate debug file for a given object file.
thughesc035bd92004-06-13 09:59:02 +00001184 */
1185static
1186Addr find_debug_file( Char* objpath, Char* debugname, UInt crc, UInt* size )
1187{
sewardjb5f6f512005-03-10 23:59:00 +00001188 Char *objdir = VG_(arena_strdup)(VG_AR_SYMTAB, objpath);
thughesc035bd92004-06-13 09:59:02 +00001189 Char *objdirptr;
1190 Char *debugpath;
1191 Addr addr = 0;
1192
1193 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1194 *objdirptr = '\0';
1195
sewardjb5f6f512005-03-10 23:59:00 +00001196 debugpath = VG_(arena_malloc)(VG_AR_SYMTAB, VG_(strlen)(objdir) + VG_(strlen)(debugname) + 16);
thughesc035bd92004-06-13 09:59:02 +00001197
1198 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1199
1200 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1201 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1202 if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
1203 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1204 addr = open_debug_file(debugpath, crc, size);
1205 }
1206 }
1207
sewardjb5f6f512005-03-10 23:59:00 +00001208 VG_(arena_free)(VG_AR_SYMTAB, debugpath);
1209 VG_(arena_free)(VG_AR_SYMTAB, objdir);
thughesc035bd92004-06-13 09:59:02 +00001210
1211 return addr;
1212}
nethercote80f76782003-11-13 22:34:00 +00001213
sewardjde4a1d02002-03-22 01:27:54 +00001214/* Read the symbols from the object/exe specified by the SegInfo into
1215 the tables within the supplied SegInfo. */
1216static
njn695c16e2005-03-27 03:40:28 +00001217Bool read_lib_symbols ( SegInfo* si )
sewardjde4a1d02002-03-22 01:27:54 +00001218{
nethercote80f76782003-11-13 22:34:00 +00001219 Bool res;
sewardj7a21c612005-02-18 09:38:08 +00001220 ElfXX_Ehdr* ehdr; /* The ELF header */
1221 ElfXX_Shdr* shdr; /* The section table */
sewardjde4a1d02002-03-22 01:27:54 +00001222 UChar* sh_strtab; /* The section table's string table */
sewardjde4a1d02002-03-22 01:27:54 +00001223 Int fd;
1224 Int i;
1225 Bool ok;
1226 Addr oimage;
sewardj05bcdcb2003-05-18 10:05:38 +00001227 UInt n_oimage;
thughesc035bd92004-06-13 09:59:02 +00001228 Addr dimage = 0;
1229 UInt n_dimage = 0;
sewardjb3586202002-05-09 17:38:13 +00001230 struct vki_stat stat_buf;
sewardjde4a1d02002-03-22 01:27:54 +00001231
sewardjde4a1d02002-03-22 01:27:54 +00001232 oimage = (Addr)NULL;
1233 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +00001234 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%p)", si->filename, si->start );
sewardjde4a1d02002-03-22 01:27:54 +00001235
1236 /* mmap the object image aboard, so that we can read symbols and
1237 line number info out of it. It will be munmapped immediately
1238 thereafter; it is only aboard transiently. */
1239
sewardjb3586202002-05-09 17:38:13 +00001240 i = VG_(stat)(si->filename, &stat_buf);
sewardjde4a1d02002-03-22 01:27:54 +00001241 if (i != 0) {
sewardj7eb7c582005-06-23 01:02:53 +00001242 ML_(symerr)("Can't stat .so/.exe (to determine its size)?!");
sewardj8fe15a32002-10-20 19:29:21 +00001243 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001244 }
1245 n_oimage = stat_buf.st_size;
1246
njn25e49d8e72002-09-23 09:36:25 +00001247 fd = VG_(open)(si->filename, VKI_O_RDONLY, 0);
jsgff3c3f1a2003-10-14 22:13:28 +00001248 if (fd < 0) {
sewardj7eb7c582005-06-23 01:02:53 +00001249 ML_(symerr)("Can't open .so/.exe to read symbols?!");
sewardj8fe15a32002-10-20 19:29:21 +00001250 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001251 }
1252
sewardjb3586202002-05-09 17:38:13 +00001253 oimage = (Addr)VG_(mmap)( NULL, n_oimage,
nethercoteb4250ae2004-07-10 16:50:09 +00001254 VKI_PROT_READ, VKI_MAP_PRIVATE|VKI_MAP_NOSYMS,
1255 0, fd, 0 );
fitzhardinge98abfc72003-12-16 02:05:15 +00001256
nethercote80f76782003-11-13 22:34:00 +00001257 VG_(close)(fd);
1258
sewardjde4a1d02002-03-22 01:27:54 +00001259 if (oimage == ((Addr)(-1))) {
njn1fd5eb22005-03-13 05:43:23 +00001260 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", si->filename );
1261 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded" );
sewardj8fe15a32002-10-20 19:29:21 +00001262 return False;
sewardjde4a1d02002-03-22 01:27:54 +00001263 }
1264
sewardjde4a1d02002-03-22 01:27:54 +00001265 /* Ok, the object image is safely in oimage[0 .. n_oimage-1].
1266 Now verify that it is a valid ELF .so or executable image.
1267 */
nethercote80f76782003-11-13 22:34:00 +00001268 res = False;
sewardj7a21c612005-02-18 09:38:08 +00001269 ok = (n_oimage >= sizeof(ElfXX_Ehdr));
1270 ehdr = (ElfXX_Ehdr*)oimage;
sewardjde4a1d02002-03-22 01:27:54 +00001271
fitzhardinge98abfc72003-12-16 02:05:15 +00001272 if (ok)
1273 ok &= VG_(is_object_file)(ehdr);
sewardjde4a1d02002-03-22 01:27:54 +00001274
1275 if (!ok) {
sewardj7eb7c582005-06-23 01:02:53 +00001276 ML_(symerr)("Invalid ELF header, or missing stringtab/sectiontab.");
nethercote80f76782003-11-13 22:34:00 +00001277 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001278 }
1279
1280 /* Walk the LOAD headers in the phdr and update the SegInfo to
1281 include them all, so that this segment also contains data and
1282 bss memory. Also computes correct symbol offset value for this
1283 ELF file. */
sewardj7a21c612005-02-18 09:38:08 +00001284 if (ehdr->e_phoff + ehdr->e_phnum*sizeof(ElfXX_Phdr) > n_oimage) {
sewardj7eb7c582005-06-23 01:02:53 +00001285 ML_(symerr)("ELF program header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001286 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001287 }
1288 {
1289 Bool offset_set = False;
sewardj7a21c612005-02-18 09:38:08 +00001290 ElfXX_Addr prev_addr = 0;
fitzhardinge98abfc72003-12-16 02:05:15 +00001291 Addr baseaddr = 0;
sewardj8fe15a32002-10-20 19:29:21 +00001292
1293 si->offset = 0;
1294
nethercote80f76782003-11-13 22:34:00 +00001295 for (i = 0; i < ehdr->e_phnum; i++) {
sewardj7a21c612005-02-18 09:38:08 +00001296 ElfXX_Phdr *o_phdr;
1297 ElfXX_Addr mapped, mapped_end;
sewardj8fe15a32002-10-20 19:29:21 +00001298
sewardj7a21c612005-02-18 09:38:08 +00001299 o_phdr = &((ElfXX_Phdr *)(oimage + ehdr->e_phoff))[i];
sewardj8fe15a32002-10-20 19:29:21 +00001300
fitzhardinge98abfc72003-12-16 02:05:15 +00001301 if (o_phdr->p_type == PT_DYNAMIC && si->soname == NULL) {
sewardj7a21c612005-02-18 09:38:08 +00001302 const ElfXX_Dyn *dyn = (const ElfXX_Dyn *)(oimage + o_phdr->p_offset);
fitzhardinge98abfc72003-12-16 02:05:15 +00001303 Int stroff = -1;
1304 Char *strtab = NULL;
1305 Int j;
1306
1307 for(j = 0; dyn[j].d_tag != DT_NULL; j++) {
1308 switch(dyn[j].d_tag) {
1309 case DT_SONAME:
1310 stroff = dyn[j].d_un.d_val;
1311 break;
1312
1313 case DT_STRTAB:
1314 strtab = (Char *)oimage + dyn[j].d_un.d_ptr - baseaddr;
1315 break;
1316 }
1317 }
1318
1319 if (stroff != -1 && strtab != 0) {
1320 TRACE_SYMTAB("soname=%s\n", strtab+stroff);
1321 si->soname = VG_(arena_strdup)(VG_AR_SYMTAB, strtab+stroff);
1322 }
1323 }
1324
sewardj8fe15a32002-10-20 19:29:21 +00001325 if (o_phdr->p_type != PT_LOAD)
1326 continue;
1327
1328 if (!offset_set) {
1329 offset_set = True;
1330 si->offset = si->start - o_phdr->p_vaddr;
fitzhardinge98abfc72003-12-16 02:05:15 +00001331 baseaddr = o_phdr->p_vaddr;
sewardj8fe15a32002-10-20 19:29:21 +00001332 }
1333
1334 if (o_phdr->p_vaddr < prev_addr) {
sewardj7eb7c582005-06-23 01:02:53 +00001335 ML_(symerr)("ELF Phdrs are out of order!?");
nethercote80f76782003-11-13 22:34:00 +00001336 goto out;
sewardj8fe15a32002-10-20 19:29:21 +00001337 }
1338 prev_addr = o_phdr->p_vaddr;
1339
1340 mapped = o_phdr->p_vaddr + si->offset;
1341 mapped_end = mapped + o_phdr->p_memsz;
1342
1343 if (si->data_start == 0 &&
1344 (o_phdr->p_flags & (PF_R|PF_W|PF_X)) == (PF_R|PF_W)) {
1345 si->data_start = mapped;
1346 si->data_size = o_phdr->p_filesz;
1347 si->bss_start = mapped + o_phdr->p_filesz;
1348 if (o_phdr->p_memsz > o_phdr->p_filesz)
1349 si->bss_size = o_phdr->p_memsz - o_phdr->p_filesz;
1350 else
1351 si->bss_size = 0;
1352 }
1353
nethercote73b526f2004-10-31 18:48:21 +00001354 mapped = mapped & ~(VKI_PAGE_SIZE-1);
1355 mapped_end = (mapped_end + VKI_PAGE_SIZE - 1) & ~(VKI_PAGE_SIZE-1);
sewardj8fe15a32002-10-20 19:29:21 +00001356
sewardj1024cf72005-02-28 14:39:21 +00001357#if 0
1358 /* 20050228: disabled this until VG_(next_segment) can be
1359 reinstated in some clean incarnation of the low level
1360 memory manager. */
sewardj8fe15a32002-10-20 19:29:21 +00001361 if (VG_(needs).data_syms &&
1362 (mapped >= si->start && mapped <= (si->start+si->size)) &&
1363 (mapped_end > (si->start+si->size))) {
1364 UInt newsz = mapped_end - si->start;
1365 if (newsz > si->size) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001366 Segment *seg;
1367
sewardj8fe15a32002-10-20 19:29:21 +00001368 if (0)
1369 VG_(printf)("extending mapping %p..%p %d -> ..%p %d\n",
1370 si->start, si->start+si->size, si->size,
1371 si->start+newsz, newsz);
fitzhardinge98abfc72003-12-16 02:05:15 +00001372
sewardjb5f6f512005-03-10 23:59:00 +00001373 for(seg = VG_(find_segment_containing)(si->start);
fitzhardinge98abfc72003-12-16 02:05:15 +00001374 seg != NULL && VG_(seg_overlaps)(seg, si->start, si->size);
1375 seg = VG_(next_segment)(seg)) {
1376 if (seg->symtab == si)
1377 continue;
1378
1379 if (seg->symtab != NULL)
njn36ef6ba2005-05-14 18:42:26 +00001380 VG_(seginfo_decref)(seg->symtab, seg->addr);
fitzhardinge98abfc72003-12-16 02:05:15 +00001381
1382 VG_(symtab_incref)(si);
1383 seg->symtab = si;
1384
1385 if (0)
1386 VG_(printf)("adding symtab %p (%p-%p) to segment %p (%p-%p)\n",
1387 si, si->start, si->start+newsz,
1388 seg, seg->addr, seg->addr+seg->len);
1389 }
1390
sewardj8fe15a32002-10-20 19:29:21 +00001391 si->size = newsz;
1392 }
1393 }
sewardj1024cf72005-02-28 14:39:21 +00001394#endif
1395
sewardj8fe15a32002-10-20 19:29:21 +00001396 }
sewardjde4a1d02002-03-22 01:27:54 +00001397 }
1398
nethercote80f76782003-11-13 22:34:00 +00001399 TRACE_SYMTAB("shoff = %d, shnum = %d, size = %d, n_vg_oimage = %d\n",
sewardj7a21c612005-02-18 09:38:08 +00001400 ehdr->e_shoff, ehdr->e_shnum, sizeof(ElfXX_Shdr), n_oimage );
sewardjde4a1d02002-03-22 01:27:54 +00001401
sewardj7a21c612005-02-18 09:38:08 +00001402 if (ehdr->e_shoff + ehdr->e_shnum*sizeof(ElfXX_Shdr) > n_oimage) {
sewardj7eb7c582005-06-23 01:02:53 +00001403 ML_(symerr)("ELF section header is beyond image end?!");
nethercote80f76782003-11-13 22:34:00 +00001404 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001405 }
1406
sewardj7a21c612005-02-18 09:38:08 +00001407 shdr = (ElfXX_Shdr*)(oimage + ehdr->e_shoff);
sewardjde4a1d02002-03-22 01:27:54 +00001408 sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);
1409
nethercote80f76782003-11-13 22:34:00 +00001410 /* Find interesting sections, read the symbol table(s), read any debug
1411 information */
sewardjde4a1d02002-03-22 01:27:54 +00001412 {
nethercote80f76782003-11-13 22:34:00 +00001413 /* Pointers to start of sections */
1414 UChar* o_strtab = NULL; /* .strtab */
sewardj7a21c612005-02-18 09:38:08 +00001415 ElfXX_Sym* o_symtab = NULL; /* .symtab */
nethercote80f76782003-11-13 22:34:00 +00001416 UChar* o_dynstr = NULL; /* .dynstr */
sewardj7a21c612005-02-18 09:38:08 +00001417 ElfXX_Sym* o_dynsym = NULL; /* .dynsym */
thughesc035bd92004-06-13 09:59:02 +00001418 Char* debuglink = NULL; /* .gnu_debuglink */
nethercote80f76782003-11-13 22:34:00 +00001419 UChar* stab = NULL; /* .stab (stabs) */
1420 UChar* stabstr = NULL; /* .stabstr (stabs) */
1421 UChar* debug_line = NULL; /* .debug_line (dwarf2) */
sewardj022bf2f2005-06-14 21:51:14 +00001422 UChar* debug_info = NULL; /* .debug_info (dwarf2) */
1423 UChar* debug_abbv = NULL; /* .debug_abbrev (dwarf2) */
1424 UChar* debug_str = NULL; /* .debug_str (dwarf2) */
jseward8b3131a2003-12-13 23:16:26 +00001425 UChar* dwarf1d = NULL; /* .debug (dwarf1) */
1426 UChar* dwarf1l = NULL; /* .line (dwarf1) */
sewardj5c638c22005-04-30 07:55:58 +00001427 UChar* ehframe = NULL; /* .eh_frame (dwarf2) */
sewardjde4a1d02002-03-22 01:27:54 +00001428
nethercote80f76782003-11-13 22:34:00 +00001429 /* Section sizes, in bytes */
1430 UInt o_strtab_sz = 0;
1431 UInt o_symtab_sz = 0;
1432 UInt o_dynstr_sz = 0;
1433 UInt o_dynsym_sz = 0;
thughesc035bd92004-06-13 09:59:02 +00001434 UInt debuglink_sz = 0;
nethercote80f76782003-11-13 22:34:00 +00001435 UInt stab_sz = 0;
1436 UInt stabstr_sz = 0;
1437 UInt debug_line_sz = 0;
sewardj022bf2f2005-06-14 21:51:14 +00001438 UInt debug_info_sz = 0;
1439 UInt debug_abbv_sz = 0;
1440 UInt debug_str_sz = 0;
jseward8b3131a2003-12-13 23:16:26 +00001441 UInt dwarf1d_sz = 0;
1442 UInt dwarf1l_sz = 0;
sewardj5c638c22005-04-30 07:55:58 +00001443 UInt ehframe_sz = 0;
jseward8b3131a2003-12-13 23:16:26 +00001444
tom2fd38902005-05-01 15:14:01 +00001445 /* Section virtual addresses */
1446 Addr dummy_addr = 0;
1447 Addr ehframe_addr = 0;
1448
jseward8b3131a2003-12-13 23:16:26 +00001449 Bool has_debuginfo = False;
sewardjde4a1d02002-03-22 01:27:54 +00001450
nethercote80f76782003-11-13 22:34:00 +00001451 /* Find all interesting sections */
sewardjde4a1d02002-03-22 01:27:54 +00001452 for (i = 0; i < ehdr->e_shnum; i++) {
tom2fd38902005-05-01 15:14:01 +00001453# define FIND(sec_name, sec_data, sec_size, sec_addr, in_exec, type) \
nethercote80f76782003-11-13 22:34:00 +00001454 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1455 if (0 != sec_data) \
1456 VG_(core_panic)("repeated section!\n"); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001457 if (in_exec) \
nethercote80f76782003-11-13 22:34:00 +00001458 sec_data = (type)(si->offset + shdr[i].sh_addr); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001459 else \
nethercote80f76782003-11-13 22:34:00 +00001460 sec_data = (type)(oimage + shdr[i].sh_offset); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001461 sec_size = shdr[i].sh_size; \
tom2fd38902005-05-01 15:14:01 +00001462 sec_addr = si->offset + shdr[i].sh_addr; \
nethercote80f76782003-11-13 22:34:00 +00001463 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1464 sec_name, sec_data, sec_data + sec_size - 1); \
nethercotefd1ea4c2003-12-01 11:54:09 +00001465 if ( shdr[i].sh_offset + sec_size > n_oimage ) { \
sewardj7eb7c582005-06-23 01:02:53 +00001466 ML_(symerr)(" section beyond image end?!"); \
nethercote80f76782003-11-13 22:34:00 +00001467 goto out; \
1468 } \
sewardjde4a1d02002-03-22 01:27:54 +00001469 }
1470
nethercote80f76782003-11-13 22:34:00 +00001471 /* Nb: must find where .got and .plt sections will be in the
1472 * executable image, not in the object image transiently loaded. */
tom2fd38902005-05-01 15:14:01 +00001473 FIND(".dynsym", o_dynsym, o_dynsym_sz, dummy_addr, 0, ElfXX_Sym*)
1474 else FIND(".dynstr", o_dynstr, o_dynstr_sz, dummy_addr, 0, UChar*)
1475 else FIND(".symtab", o_symtab, o_symtab_sz, dummy_addr, 0, ElfXX_Sym*)
1476 else FIND(".strtab", o_strtab, o_strtab_sz, dummy_addr, 0, UChar*)
sewardjde4a1d02002-03-22 01:27:54 +00001477
tom2fd38902005-05-01 15:14:01 +00001478 else FIND(".gnu_debuglink", debuglink, debuglink_sz, dummy_addr, 0, Char*)
thughesc035bd92004-06-13 09:59:02 +00001479
tom2fd38902005-05-01 15:14:01 +00001480 else FIND(".stab", stab, stab_sz, dummy_addr, 0, UChar*)
1481 else FIND(".stabstr", stabstr, stabstr_sz, dummy_addr, 0, UChar*)
sewardj022bf2f2005-06-14 21:51:14 +00001482
tom2fd38902005-05-01 15:14:01 +00001483 else FIND(".debug_line", debug_line, debug_line_sz, dummy_addr, 0, UChar*)
sewardj022bf2f2005-06-14 21:51:14 +00001484 else FIND(".debug_info", debug_info, debug_info_sz, dummy_addr, 0, UChar*)
1485 else FIND(".debug_abbrev", debug_abbv, debug_abbv_sz, dummy_addr, 0, UChar*)
1486 else FIND(".debug_str", debug_str, debug_str_sz, dummy_addr, 0, UChar*)
1487
tom2fd38902005-05-01 15:14:01 +00001488 else FIND(".debug", dwarf1d, dwarf1d_sz, dummy_addr, 0, UChar*)
1489 else FIND(".line", dwarf1l, dwarf1l_sz, dummy_addr, 0, UChar*)
1490 else FIND(".eh_frame", ehframe, ehframe_sz, ehframe_addr, 0, UChar*)
nethercote80f76782003-11-13 22:34:00 +00001491
tom2fd38902005-05-01 15:14:01 +00001492 else FIND(".got", si->got_start, si->got_size, dummy_addr, 1, Addr)
1493 else FIND(".plt", si->plt_start, si->plt_size, dummy_addr, 1, Addr)
nethercote80f76782003-11-13 22:34:00 +00001494
jseward8b3131a2003-12-13 23:16:26 +00001495# undef FIND
sewardjde4a1d02002-03-22 01:27:54 +00001496 }
njn36ef6ba2005-05-14 18:42:26 +00001497
1498 /* Check some sizes */
1499 vg_assert((o_dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1500 vg_assert((o_symtab_sz % sizeof(ElfXX_Sym)) == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001501
thughesc035bd92004-06-13 09:59:02 +00001502 /* Did we find a debuglink section? */
1503 if (debuglink != NULL) {
njn13bfd852005-06-02 03:52:53 +00001504 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink)+1, 4);
thughesc035bd92004-06-13 09:59:02 +00001505 UInt crc;
1506
1507 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1508
1509 /* Extract the CRC from the debuglink section */
1510 crc = *(UInt *)(debuglink + crc_offset);
1511
1512 /* See if we can find a matching debug file */
1513 if ((dimage = find_debug_file(si->filename, debuglink, crc, &n_dimage)) != 0) {
sewardj7a21c612005-02-18 09:38:08 +00001514 ehdr = (ElfXX_Ehdr*)dimage;
thughesc035bd92004-06-13 09:59:02 +00001515
sewardj7a21c612005-02-18 09:38:08 +00001516 if (n_dimage >= sizeof(ElfXX_Ehdr) && VG_(is_object_file)(ehdr))
thughesc035bd92004-06-13 09:59:02 +00001517 {
sewardj7a21c612005-02-18 09:38:08 +00001518 shdr = (ElfXX_Shdr*)(dimage + ehdr->e_shoff);
thughesc035bd92004-06-13 09:59:02 +00001519 sh_strtab = (UChar*)(dimage + shdr[ehdr->e_shstrndx].sh_offset);
1520
1521 /* Find all interesting sections */
1522 for (i = 0; i < ehdr->e_shnum; i++) {
1523# define FIND(sec_name, sec_data, sec_size, type) \
1524 if (0 == VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)) { \
1525 if (0 != sec_data) \
1526 VG_(core_panic)("repeated section!\n"); \
1527 sec_data = (type)(dimage + shdr[i].sh_offset); \
1528 sec_size = shdr[i].sh_size; \
1529 TRACE_SYMTAB( "%18s: %p .. %p\n", \
1530 sec_name, sec_data, sec_data + sec_size - 1); \
1531 if ( shdr[i].sh_offset + sec_size > n_dimage ) { \
sewardj7eb7c582005-06-23 01:02:53 +00001532 ML_(symerr)(" section beyond image end?!"); \
thughesc035bd92004-06-13 09:59:02 +00001533 goto out; \
1534 } \
1535 }
1536
1537 /* Nb: must find where .got and .plt sections will be in the
1538 * executable image, not in the object image transiently loaded. */
1539 FIND(".stab", stab, stab_sz, UChar*)
1540 else FIND(".stabstr", stabstr, stabstr_sz, UChar*)
1541 else FIND(".debug_line", debug_line, debug_line_sz, UChar*)
tome36cb5a2005-06-15 10:19:43 +00001542 else FIND(".debug_info", debug_info, debug_info_sz, UChar*)
1543 else FIND(".debug_abbrev", debug_abbv, debug_abbv_sz, UChar*)
1544 else FIND(".debug_str", debug_str, debug_str_sz, UChar*)
thughesc035bd92004-06-13 09:59:02 +00001545 else FIND(".debug", dwarf1d, dwarf1d_sz, UChar*)
1546 else FIND(".line", dwarf1l, dwarf1l_sz, UChar*)
1547
1548# undef FIND
thughesc035bd92004-06-13 09:59:02 +00001549 }
1550 }
1551 }
1552 }
1553
njnd54e4ec2005-05-15 03:38:53 +00001554 /* Read symbols */
1555 read_symtab(si, "symbol table", False,
1556 o_symtab, o_symtab_sz,
1557 o_strtab, o_strtab_sz);
1558
1559 read_symtab(si, "dynamic symbol table", True,
1560 o_dynsym, o_dynsym_sz,
1561 o_dynstr, o_dynstr_sz);
1562
sewardj5c638c22005-04-30 07:55:58 +00001563 /* Read .eh_frame (call-frame-info) if any */
sewardj55022aa2005-05-03 16:05:00 +00001564 if (ehframe) {
sewardj7eb7c582005-06-23 01:02:53 +00001565 ML_(read_callframe_info_dwarf2) ( si, ehframe, ehframe_sz, ehframe_addr );
sewardj5c638c22005-04-30 07:55:58 +00001566 }
1567
sewardje7aa4ae2005-06-09 12:43:42 +00001568 /* Read the stabs and/or dwarf2 debug information, if any. It
1569 appears reading stabs stuff on amd64-linux doesn't work, so
1570 we ignore it. */
1571# if !defined(VGP_amd64_linux)
nethercote80f76782003-11-13 22:34:00 +00001572 if (stab != NULL && stabstr != NULL) {
jseward8b3131a2003-12-13 23:16:26 +00001573 has_debuginfo = True;
sewardj7eb7c582005-06-23 01:02:53 +00001574 ML_(read_debuginfo_stabs) ( si, stab, stab_sz,
jseward8b3131a2003-12-13 23:16:26 +00001575 stabstr, stabstr_sz );
1576 }
sewardje7aa4ae2005-06-09 12:43:42 +00001577# endif
tom6f917fd2005-03-30 15:05:46 +00001578 if (debug_line) {
jseward8b3131a2003-12-13 23:16:26 +00001579 has_debuginfo = True;
sewardj7eb7c582005-06-23 01:02:53 +00001580 ML_(read_debuginfo_dwarf2) ( si,
sewardj022bf2f2005-06-14 21:51:14 +00001581 debug_info, debug_info_sz,
1582 debug_abbv,
1583 debug_line, debug_line_sz,
1584 debug_str );
jseward8b3131a2003-12-13 23:16:26 +00001585 }
1586 if (dwarf1d && dwarf1l) {
1587 has_debuginfo = True;
sewardj7eb7c582005-06-23 01:02:53 +00001588 ML_(read_debuginfo_dwarf1) ( si, dwarf1d, dwarf1d_sz,
jseward8b3131a2003-12-13 23:16:26 +00001589 dwarf1l, dwarf1l_sz );
1590 }
1591 if (!has_debuginfo) {
sewardj7eb7c582005-06-23 01:02:53 +00001592 ML_(symerr)(" object doesn't have any line number info");
nethercote80f76782003-11-13 22:34:00 +00001593 goto out;
sewardjde4a1d02002-03-22 01:27:54 +00001594 }
1595 }
nethercote80f76782003-11-13 22:34:00 +00001596 res = True;
sewardjde4a1d02002-03-22 01:27:54 +00001597
nethercotee567e702004-07-10 17:49:17 +00001598 out: {
1599 Int m_res;
thughesc035bd92004-06-13 09:59:02 +00001600 /* Last, but not least, heave the image(s) back overboard. */
nethercotee567e702004-07-10 17:49:17 +00001601 if (dimage) {
1602 m_res = VG_(munmap) ( (void*)dimage, n_dimage );
1603 vg_assert(0 == m_res);
1604 }
1605 m_res = VG_(munmap) ( (void*)oimage, n_oimage );
1606 vg_assert(0 == m_res);
nethercote80f76782003-11-13 22:34:00 +00001607 return res;
nethercotee567e702004-07-10 17:49:17 +00001608 }
sewardjde4a1d02002-03-22 01:27:54 +00001609}
1610
sewardjde4a1d02002-03-22 01:27:54 +00001611/*------------------------------------------------------------*/
1612/*--- Main entry point for symbols table reading. ---*/
1613/*------------------------------------------------------------*/
1614
1615/* The root structure for the entire symbol table system. It is a
1616 linked list of SegInfos. Note that this entire mechanism assumes
1617 that what we read from /proc/self/maps doesn't contain overlapping
1618 address ranges, and as a result the SegInfos in this list describe
1619 disjoint address ranges.
1620*/
fitzhardinge98abfc72003-12-16 02:05:15 +00001621SegInfo *VG_(read_seg_symbols) ( Segment *seg )
sewardjde4a1d02002-03-22 01:27:54 +00001622{
1623 SegInfo* si;
1624
njn36ef6ba2005-05-14 18:42:26 +00001625 vg_assert(seg->seginfo == NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001626
njnfa1016e2003-09-25 17:54:11 +00001627 VGP_PUSHCC(VgpReadSyms);
1628
sewardjde4a1d02002-03-22 01:27:54 +00001629 /* Get the record initialised right. */
njn25e49d8e72002-09-23 09:36:25 +00001630 si = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(SegInfo));
sewardjde4a1d02002-03-22 01:27:54 +00001631
sewardj8fe15a32002-10-20 19:29:21 +00001632 VG_(memset)(si, 0, sizeof(*si));
fitzhardinge98abfc72003-12-16 02:05:15 +00001633 si->start = seg->addr;
1634 si->size = seg->len;
1635 si->foffset = seg->offset;
fitzhardinge1a4adf02003-12-22 10:42:59 +00001636 si->filename = VG_(arena_strdup)(VG_AR_SYMTAB, seg->filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00001637
1638 si->ref = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001639
1640 si->symtab = NULL;
1641 si->symtab_size = si->symtab_used = 0;
1642 si->loctab = NULL;
1643 si->loctab_size = si->loctab_used = 0;
jsgfcb1d1c02003-10-14 21:55:10 +00001644 si->strchunks = NULL;
1645 si->scopetab = NULL;
1646 si->scopetab_size = si->scopetab_used = 0;
sewardj5c638c22005-04-30 07:55:58 +00001647 si->cfisi = NULL;
1648 si->cfisi_size = si->cfisi_used = 0;
sewardjbf603752005-05-02 00:36:27 +00001649 si->cfisi_minaddr = si->cfisi_maxaddr = 0;
jsgfcb1d1c02003-10-14 21:55:10 +00001650
fitzhardinge98abfc72003-12-16 02:05:15 +00001651 si->seg = seg;
1652
jsgfcb1d1c02003-10-14 21:55:10 +00001653 si->stab_typetab = NULL;
sewardjde4a1d02002-03-22 01:27:54 +00001654
nethercote80f76782003-11-13 22:34:00 +00001655 si->plt_start = si->plt_size = 0;
1656 si->got_start = si->got_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001657 si->data_start = si->data_size = 0;
nethercote80f76782003-11-13 22:34:00 +00001658 si->bss_start = si->bss_size = 0;
sewardj8a77ffb2003-07-10 23:31:27 +00001659
sewardjde4a1d02002-03-22 01:27:54 +00001660 /* And actually fill it up. */
njn695c16e2005-03-27 03:40:28 +00001661 if (!read_lib_symbols ( si ) && 0) {
sewardj8fe15a32002-10-20 19:29:21 +00001662 /* XXX this interacts badly with the prevN optimization in
1663 addStr(). Since this frees the si, the si pointer value can
1664 be recycled, which confuses the curr_si == si test. For now,
1665 this code is disabled, and everything is included in the
1666 segment list, even if it is a bad ELF file. Ironically,
1667 running this under valgrind itself hides the problem, because
1668 it doesn't recycle pointers... */
njn16eeb4e2005-06-16 03:56:58 +00001669 // [Nb: the prevN optimization has now been removed from addStr().
1670 // However, when I try reactivating this path of the branch I get
1671 // seg faults... --njn 13-Jun-2005]
sewardj8fe15a32002-10-20 19:29:21 +00001672 freeSegInfo( si );
1673 } else {
njn16eeb4e2005-06-16 03:56:58 +00001674 // Prepend si to segInfo_list
1675 si->next = segInfo_list;
1676 segInfo_list = si;
sewardj8fe15a32002-10-20 19:29:21 +00001677
njn16eeb4e2005-06-16 03:56:58 +00001678 canonicaliseSymtab ( si );
1679 canonicaliseLoctab ( si );
jsgfcb1d1c02003-10-14 21:55:10 +00001680 canonicaliseScopetab ( si );
njn16eeb4e2005-06-16 03:56:58 +00001681 canonicaliseCfiSI ( si );
fitzhardinge98abfc72003-12-16 02:05:15 +00001682
1683 /* do redirects */
sewardjb5f6f512005-03-10 23:59:00 +00001684 VG_(resolve_seg_redirs)( si );
sewardj8fe15a32002-10-20 19:29:21 +00001685 }
njnfa1016e2003-09-25 17:54:11 +00001686 VGP_POPCC(VgpReadSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001687
1688 return si;
sewardjde4a1d02002-03-22 01:27:54 +00001689}
1690
1691
sewardjde4a1d02002-03-22 01:27:54 +00001692/* When an munmap() call happens, check to see whether it corresponds
1693 to a segment for a .so, and if so discard the relevant SegInfo.
1694 This might not be a very clever idea from the point of view of
1695 accuracy of error messages, but we need to do it in order to
sewardj18d75132002-05-16 11:06:21 +00001696 maintain the no-overlapping invariant.
sewardjde4a1d02002-03-22 01:27:54 +00001697*/
nethercote928a5f72004-11-03 18:10:37 +00001698static void unload_symbols ( Addr start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +00001699{
1700 SegInfo *prev, *curr;
1701
sewardjde4a1d02002-03-22 01:27:54 +00001702 prev = NULL;
njn16eeb4e2005-06-16 03:56:58 +00001703 curr = segInfo_list;
sewardjde4a1d02002-03-22 01:27:54 +00001704 while (True) {
1705 if (curr == NULL) break;
1706 if (start == curr->start) break;
1707 prev = curr;
1708 curr = curr->next;
1709 }
njnfa1016e2003-09-25 17:54:11 +00001710 if (curr == NULL) {
1711 VGP_POPCC(VgpReadSyms);
njn25e49d8e72002-09-23 09:36:25 +00001712 return;
njnfa1016e2003-09-25 17:54:11 +00001713 }
sewardjde4a1d02002-03-22 01:27:54 +00001714
mueller75c0ed62003-11-19 00:47:00 +00001715 if (VG_(clo_verbosity) > 1)
njn1fd5eb22005-03-13 05:43:23 +00001716 VG_(message)(Vg_DebugMsg,
fitzhardinge98abfc72003-12-16 02:05:15 +00001717 "discard syms at %p-%p in %s due to munmap()",
1718 start, start+length, curr->filename ? curr->filename : (Char *)"???");
sewardjde4a1d02002-03-22 01:27:54 +00001719
1720 vg_assert(prev == NULL || prev->next == curr);
1721
1722 if (prev == NULL) {
njn16eeb4e2005-06-16 03:56:58 +00001723 segInfo_list = curr->next;
sewardjde4a1d02002-03-22 01:27:54 +00001724 } else {
1725 prev->next = curr->next;
1726 }
1727
1728 freeSegInfo(curr);
njn25e49d8e72002-09-23 09:36:25 +00001729 return;
sewardjde4a1d02002-03-22 01:27:54 +00001730}
1731
njn36ef6ba2005-05-14 18:42:26 +00001732void VG_(seginfo_decref)(SegInfo *si, Addr start)
fitzhardinge98abfc72003-12-16 02:05:15 +00001733{
1734 vg_assert(si->ref >= 1);
1735 if (--si->ref == 0)
nethercote85cdd342004-08-01 22:36:40 +00001736 unload_symbols(si->start, si->size);
fitzhardinge98abfc72003-12-16 02:05:15 +00001737}
1738
njn36ef6ba2005-05-14 18:42:26 +00001739void VG_(seginfo_incref)(SegInfo *si)
fitzhardinge98abfc72003-12-16 02:05:15 +00001740{
1741 vg_assert(si->ref > 0);
1742 si->ref++;
1743}
sewardjde4a1d02002-03-22 01:27:54 +00001744
1745/*------------------------------------------------------------*/
1746/*--- Use of symbol table & location info to create ---*/
1747/*--- plausible-looking stack dumps. ---*/
1748/*------------------------------------------------------------*/
1749
1750/* Find a symbol-table index containing the specified pointer, or -1
1751 if not found. Binary search. */
1752
njn25e49d8e72002-09-23 09:36:25 +00001753static Int search_one_symtab ( SegInfo* si, Addr ptr,
1754 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001755{
1756 Addr a_mid_lo, a_mid_hi;
njn25e49d8e72002-09-23 09:36:25 +00001757 Int mid, size,
sewardjde4a1d02002-03-22 01:27:54 +00001758 lo = 0,
1759 hi = si->symtab_used-1;
1760 while (True) {
1761 /* current unsearched space is from lo to hi, inclusive. */
1762 if (lo > hi) return -1; /* not found */
1763 mid = (lo + hi) / 2;
1764 a_mid_lo = si->symtab[mid].addr;
njn25e49d8e72002-09-23 09:36:25 +00001765 size = ( match_anywhere_in_fun
1766 ? si->symtab[mid].size
1767 : 1);
1768 a_mid_hi = ((Addr)si->symtab[mid].addr) + size - 1;
sewardjde4a1d02002-03-22 01:27:54 +00001769
1770 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1771 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1772 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1773 return mid;
1774 }
1775}
1776
1777
sewardj25c7c3a2003-07-10 00:17:58 +00001778/* SLOW (Linear search). Try and map a symbol name to an address.
1779 Since this is searching in the direction opposite to which the
1780 table is designed we have no option but to do a complete linear
1781 scan of the table. Returns NULL if not found. */
1782
sewardjb5f6f512005-03-10 23:59:00 +00001783Addr VG_(reverse_search_one_symtab) ( const SegInfo* si, const Char* name )
sewardj25c7c3a2003-07-10 00:17:58 +00001784{
1785 UInt i;
1786 for (i = 0; i < si->symtab_used; i++) {
sewardjc8bf5fe2003-07-13 00:53:22 +00001787 if (0)
jsgfcb1d1c02003-10-14 21:55:10 +00001788 VG_(printf)("%p %s\n", si->symtab[i].addr, si->symtab[i].name);
1789 if (0 == VG_(strcmp)(name, si->symtab[i].name))
sewardj25c7c3a2003-07-10 00:17:58 +00001790 return si->symtab[i].addr;
1791 }
1792 return (Addr)NULL;
1793}
1794
1795
sewardjde4a1d02002-03-22 01:27:54 +00001796/* Search all symtabs that we know about to locate ptr. If found, set
1797 *psi to the relevant SegInfo, and *symno to the symtab entry number
1798 within that. If not found, *psi is set to NULL. */
njn25e49d8e72002-09-23 09:36:25 +00001799static void search_all_symtabs ( Addr ptr, /*OUT*/SegInfo** psi,
1800 /*OUT*/Int* symno,
1801 Bool match_anywhere_in_fun )
sewardjde4a1d02002-03-22 01:27:54 +00001802{
1803 Int sno;
1804 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001805
njn25e49d8e72002-09-23 09:36:25 +00001806 VGP_PUSHCC(VgpSearchSyms);
fitzhardinge98abfc72003-12-16 02:05:15 +00001807
njn1727cc82005-06-21 23:09:45 +00001808 for (si = segInfo_list; si != NULL; si = si->next) {
1809 if (si->start <= ptr && ptr < si->start+si->size) {
1810 sno = search_one_symtab ( si, ptr, match_anywhere_in_fun );
1811 if (sno == -1) goto not_found;
1812 *symno = sno;
1813 *psi = si;
1814 VGP_POPCC(VgpSearchSyms);
1815 return;
1816 }
1817 }
sewardjde4a1d02002-03-22 01:27:54 +00001818 not_found:
1819 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001820 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001821}
1822
1823
1824/* Find a location-table index containing the specified pointer, or -1
1825 if not found. Binary search. */
1826
1827static Int search_one_loctab ( SegInfo* si, Addr ptr )
1828{
1829 Addr a_mid_lo, a_mid_hi;
1830 Int mid,
1831 lo = 0,
1832 hi = si->loctab_used-1;
1833 while (True) {
1834 /* current unsearched space is from lo to hi, inclusive. */
1835 if (lo > hi) return -1; /* not found */
1836 mid = (lo + hi) / 2;
1837 a_mid_lo = si->loctab[mid].addr;
1838 a_mid_hi = ((Addr)si->loctab[mid].addr) + si->loctab[mid].size - 1;
1839
1840 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1841 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1842 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1843 return mid;
1844 }
1845}
1846
1847
1848/* Search all loctabs that we know about to locate ptr. If found, set
1849 *psi to the relevant SegInfo, and *locno to the loctab entry number
1850 within that. If not found, *psi is set to NULL.
1851*/
njn25e49d8e72002-09-23 09:36:25 +00001852static void search_all_loctabs ( Addr ptr, /*OUT*/SegInfo** psi,
1853 /*OUT*/Int* locno )
sewardjde4a1d02002-03-22 01:27:54 +00001854{
1855 Int lno;
1856 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00001857
1858 VGP_PUSHCC(VgpSearchSyms);
1859
njn16eeb4e2005-06-16 03:56:58 +00001860 for (si = segInfo_list; si != NULL; si = si->next) {
sewardjde4a1d02002-03-22 01:27:54 +00001861 if (si->start <= ptr && ptr < si->start+si->size) {
1862 lno = search_one_loctab ( si, ptr );
1863 if (lno == -1) goto not_found;
1864 *locno = lno;
1865 *psi = si;
njn25e49d8e72002-09-23 09:36:25 +00001866 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001867 return;
1868 }
1869 }
1870 not_found:
1871 *psi = NULL;
njn25e49d8e72002-09-23 09:36:25 +00001872 VGP_POPCC(VgpSearchSyms);
sewardjde4a1d02002-03-22 01:27:54 +00001873}
1874
1875
jsgfcb1d1c02003-10-14 21:55:10 +00001876/* Find a scope-table index containing the specified pointer, or -1
1877 if not found. Binary search. */
1878
1879static Int search_one_scopetab ( SegInfo* si, Addr ptr )
1880{
1881 Addr a_mid_lo, a_mid_hi;
1882 Int mid,
1883 lo = 0,
1884 hi = si->scopetab_used-1;
1885 while (True) {
1886 /* current unsearched space is from lo to hi, inclusive. */
1887 if (lo > hi) return -1; /* not found */
1888 mid = (lo + hi) / 2;
1889 a_mid_lo = si->scopetab[mid].addr;
1890 a_mid_hi = ((Addr)si->scopetab[mid].addr) + si->scopetab[mid].size - 1;
1891
1892 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1893 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1894 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1895 return mid;
1896 }
1897}
1898
1899
1900/* Search all scopetabs that we know about to locate ptr. If found, set
1901 *psi to the relevant SegInfo, and *locno to the scopetab entry number
1902 within that. If not found, *psi is set to NULL.
1903*/
1904static void search_all_scopetabs ( Addr ptr,
1905 /*OUT*/SegInfo** psi,
1906 /*OUT*/Int* scopeno )
1907{
1908 Int scno;
1909 SegInfo* si;
1910
1911 VGP_PUSHCC(VgpSearchSyms);
1912
njn16eeb4e2005-06-16 03:56:58 +00001913 for (si = segInfo_list; si != NULL; si = si->next) {
jsgfcb1d1c02003-10-14 21:55:10 +00001914 if (si->start <= ptr && ptr < si->start+si->size) {
1915 scno = search_one_scopetab ( si, ptr );
1916 if (scno == -1) goto not_found;
1917 *scopeno = scno;
1918 *psi = si;
1919 VGP_POPCC(VgpSearchSyms);
1920 return;
1921 }
1922 }
1923 not_found:
1924 *psi = NULL;
1925 VGP_POPCC(VgpSearchSyms);
1926}
1927
sewardj3a1c7db2005-05-02 09:43:44 +00001928
1929/* Find a CFI-table index containing the specified pointer, or -1
1930 if not found. Binary search. */
1931
1932static Int search_one_cfitab ( SegInfo* si, Addr ptr )
1933{
1934 Addr a_mid_lo, a_mid_hi;
1935 Int mid, size,
1936 lo = 0,
1937 hi = si->cfisi_used-1;
1938 while (True) {
1939 /* current unsearched space is from lo to hi, inclusive. */
1940 if (lo > hi) return -1; /* not found */
1941 mid = (lo + hi) / 2;
1942 a_mid_lo = si->cfisi[mid].base;
1943 size = si->cfisi[mid].len;
1944 a_mid_hi = a_mid_lo + size - 1;
1945 vg_assert(a_mid_hi >= a_mid_lo);
1946 if (ptr < a_mid_lo) { hi = mid-1; continue; }
1947 if (ptr > a_mid_hi) { lo = mid+1; continue; }
1948 vg_assert(ptr >= a_mid_lo && ptr <= a_mid_hi);
1949 return mid;
1950 }
1951}
1952
1953
sewardjde4a1d02002-03-22 01:27:54 +00001954/* The whole point of this whole big deal: map a code address to a
1955 plausible symbol name. Returns False if no idea; otherwise True.
njn25e49d8e72002-09-23 09:36:25 +00001956 Caller supplies buf and nbuf. If demangle is False, don't do
njn695c16e2005-03-27 03:40:28 +00001957 demangling, regardless of VG_(clo_demangle) -- probably because the
1958 call has come from VG_(get_fnname_nodemangle)(). */
njn25e49d8e72002-09-23 09:36:25 +00001959static
1960Bool get_fnname ( Bool demangle, Addr a, Char* buf, Int nbuf,
sewardj1771e172002-11-13 22:06:35 +00001961 Bool match_anywhere_in_fun, Bool show_offset)
sewardjde4a1d02002-03-22 01:27:54 +00001962{
1963 SegInfo* si;
1964 Int sno;
sewardj1771e172002-11-13 22:06:35 +00001965 Int offset;
1966
njn25e49d8e72002-09-23 09:36:25 +00001967 search_all_symtabs ( a, &si, &sno, match_anywhere_in_fun );
sewardjde4a1d02002-03-22 01:27:54 +00001968 if (si == NULL)
1969 return False;
njn25e49d8e72002-09-23 09:36:25 +00001970 if (demangle) {
jsgfcb1d1c02003-10-14 21:55:10 +00001971 VG_(demangle) ( si->symtab[sno].name, buf, nbuf );
njn25e49d8e72002-09-23 09:36:25 +00001972 } else {
njnbe73f432005-03-26 21:34:45 +00001973 VG_(strncpy_safely) ( buf, si->symtab[sno].name, nbuf );
sewardjde4a1d02002-03-22 01:27:54 +00001974 }
sewardj1771e172002-11-13 22:06:35 +00001975
1976 offset = a - si->symtab[sno].addr;
1977 if (show_offset && offset != 0) {
1978 Char buf2[12];
1979 Char* symend = buf + VG_(strlen)(buf);
1980 Char* end = buf + nbuf;
1981 Int len;
1982
1983 len = VG_(sprintf)(buf2, "%c%d",
1984 offset < 0 ? '-' : '+',
1985 offset < 0 ? -offset : offset);
sewardj05bcdcb2003-05-18 10:05:38 +00001986 vg_assert(len < (Int)sizeof(buf2));
sewardj1771e172002-11-13 22:06:35 +00001987
1988 if (len < (end - symend)) {
1989 Char *cp = buf2;
1990 VG_(memcpy)(symend, cp, len+1);
1991 }
1992 }
1993
sewardjde4a1d02002-03-22 01:27:54 +00001994 return True;
1995}
1996
nethercote7cc9c232004-01-21 15:08:04 +00001997/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00001998 match anywhere in function, but don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00001999Bool VG_(get_fnname) ( Addr a, Char* buf, Int nbuf )
2000{
2001 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00002002 /*match_anywhere_in_fun*/True,
2003 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00002004}
sewardjde4a1d02002-03-22 01:27:54 +00002005
nethercote7cc9c232004-01-21 15:08:04 +00002006/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00002007 match anywhere in function, and show offset if nonzero. */
2008Bool VG_(get_fnname_w_offset) ( Addr a, Char* buf, Int nbuf )
2009{
2010 return get_fnname ( /*demangle*/True, a, buf, nbuf,
2011 /*match_anywhere_in_fun*/True,
2012 /*show offset?*/True );
2013}
2014
nethercote7cc9c232004-01-21 15:08:04 +00002015/* This is available to tools... always demangle C++ names,
sewardj6e008cb2002-12-15 13:11:39 +00002016 only succeed if 'a' matches first instruction of function,
2017 and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00002018Bool VG_(get_fnname_if_entry) ( Addr a, Char* buf, Int nbuf )
2019{
2020 return get_fnname ( /*demangle*/True, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00002021 /*match_anywhere_in_fun*/False,
2022 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00002023}
2024
sewardj6e008cb2002-12-15 13:11:39 +00002025/* This is only available to core... don't demangle C++ names,
2026 match anywhere in function, and don't show offsets. */
njn25e49d8e72002-09-23 09:36:25 +00002027Bool VG_(get_fnname_nodemangle) ( Addr a, Char* buf, Int nbuf )
2028{
2029 return get_fnname ( /*demangle*/False, a, buf, nbuf,
sewardj6e008cb2002-12-15 13:11:39 +00002030 /*match_anywhere_in_fun*/True,
2031 /*show offset?*/False );
njn25e49d8e72002-09-23 09:36:25 +00002032}
2033
2034/* Map a code address to the name of a shared object file or the executable.
2035 Returns False if no idea; otherwise True. Doesn't require debug info.
2036 Caller supplies buf and nbuf. */
2037Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
sewardjde4a1d02002-03-22 01:27:54 +00002038{
2039 SegInfo* si;
njn25e49d8e72002-09-23 09:36:25 +00002040
njn16eeb4e2005-06-16 03:56:58 +00002041 for (si = segInfo_list; si != NULL; si = si->next) {
sewardjde4a1d02002-03-22 01:27:54 +00002042 if (si->start <= a && a < si->start+si->size) {
2043 VG_(strncpy_safely)(buf, si->filename, nbuf);
2044 return True;
2045 }
2046 }
2047 return False;
2048}
2049
njnb877d492003-01-28 20:40:57 +00002050/* Map a code address to its SegInfo. Returns NULL if not found. Doesn't
2051 require debug info. */
2052SegInfo* VG_(get_obj) ( Addr a )
2053{
2054 SegInfo* si;
2055
njn16eeb4e2005-06-16 03:56:58 +00002056 for (si = segInfo_list; si != NULL; si = si->next) {
njnb877d492003-01-28 20:40:57 +00002057 if (si->start <= a && a < si->start+si->size) {
2058 return si;
2059 }
2060 }
nethercote80f76782003-11-13 22:34:00 +00002061 return NULL;
njnb877d492003-01-28 20:40:57 +00002062}
2063
njn25e49d8e72002-09-23 09:36:25 +00002064
2065/* Map a code address to a filename. Returns True if successful. */
2066Bool VG_(get_filename)( Addr a, Char* filename, Int n_filename )
sewardjde4a1d02002-03-22 01:27:54 +00002067{
njn25e49d8e72002-09-23 09:36:25 +00002068 SegInfo* si;
2069 Int locno;
2070 search_all_loctabs ( a, &si, &locno );
2071 if (si == NULL)
2072 return False;
njnbe73f432005-03-26 21:34:45 +00002073 VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
njn25e49d8e72002-09-23 09:36:25 +00002074 return True;
sewardjde4a1d02002-03-22 01:27:54 +00002075}
2076
njn25e49d8e72002-09-23 09:36:25 +00002077/* Map a code address to a line number. Returns True if successful. */
2078Bool VG_(get_linenum)( Addr a, UInt* lineno )
2079{
2080 SegInfo* si;
2081 Int locno;
2082 search_all_loctabs ( a, &si, &locno );
2083 if (si == NULL)
2084 return False;
2085 *lineno = si->loctab[locno].lineno;
2086
2087 return True;
2088}
sewardjde4a1d02002-03-22 01:27:54 +00002089
sewardj7cee6f92005-06-13 17:39:06 +00002090/* Map a code address to a filename/line number/dir name info.
2091 See prototype for detailed description of behaviour.
sewardjde4a1d02002-03-22 01:27:54 +00002092*/
sewardj7cee6f92005-06-13 17:39:06 +00002093Bool VG_(get_filename_linenum) ( Addr a,
2094 /*OUT*/Char* filename, Int n_filename,
2095 /*OUT*/Char* dirname, Int n_dirname,
2096 /*OUT*/Bool* dirname_available,
2097 /*OUT*/UInt* lineno )
sewardjde4a1d02002-03-22 01:27:54 +00002098{
2099 SegInfo* si;
2100 Int locno;
sewardj7cee6f92005-06-13 17:39:06 +00002101
2102 vg_assert( (dirname == NULL && dirname_available == NULL)
2103 ||
2104 (dirname != NULL && dirname_available != NULL) );
2105
sewardjde4a1d02002-03-22 01:27:54 +00002106 search_all_loctabs ( a, &si, &locno );
2107 if (si == NULL)
2108 return False;
njnbe73f432005-03-26 21:34:45 +00002109 VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
sewardjde4a1d02002-03-22 01:27:54 +00002110 *lineno = si->loctab[locno].lineno;
njn4f9c9342002-04-29 16:03:24 +00002111
sewardj7cee6f92005-06-13 17:39:06 +00002112 if (dirname) {
2113 /* caller wants directory info too .. */
2114 vg_assert(n_dirname > 0);
2115 if (si->loctab[locno].dirname) {
2116 /* .. and we have some */
2117 *dirname_available = True;
2118 VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
2119 n_dirname);
2120 } else {
2121 /* .. but we don't have any */
2122 *dirname_available = False;
2123 *dirname = 0;
2124 }
2125 }
2126
sewardjde4a1d02002-03-22 01:27:54 +00002127 return True;
2128}
2129
jsgfcb1d1c02003-10-14 21:55:10 +00002130#ifndef TEST
2131
njn6b2b96a2005-05-16 00:01:04 +00002132// Note that R_STACK_PTR and R_FRAME_PTR are used again further below,
2133// which is why they get a named constant.
2134static Addr regaddr_from_tst(Int regno, ThreadArchState *arch)
2135{
2136#if defined(VGA_x86)
sewardj7cee6f92005-06-13 17:39:06 +00002137 /* This is the Intel register encoding -- integer regs. */
njn6b2b96a2005-05-16 00:01:04 +00002138# define R_STACK_PTR 4
2139# define R_FRAME_PTR 5
2140 switch (regno) {
2141 case 0: return (Addr) & arch->vex.guest_EAX;
2142 case 1: return (Addr) & arch->vex.guest_ECX;
2143 case 2: return (Addr) & arch->vex.guest_EDX;
2144 case 3: return (Addr) & arch->vex.guest_EBX;
2145 case R_STACK_PTR: return (Addr) & arch->vex.guest_ESP;
2146 case R_FRAME_PTR: return (Addr) & arch->vex.guest_EBP;
2147 case 6: return (Addr) & arch->vex.guest_ESI;
2148 case 7: return (Addr) & arch->vex.guest_EDI;
2149 default: return 0;
2150 }
2151#elif defined(VGA_amd64)
sewardj7cee6f92005-06-13 17:39:06 +00002152 /* This is the AMD64 register encoding -- integer regs. */
tom7b998562005-05-16 07:31:57 +00002153# define R_STACK_PTR 7
2154# define R_FRAME_PTR 6
2155 switch (regno) {
2156 case 0: return (Addr) & arch->vex.guest_RAX;
2157 case 1: return (Addr) & arch->vex.guest_RDX;
2158 case 2: return (Addr) & arch->vex.guest_RCX;
2159 case 3: return (Addr) & arch->vex.guest_RBX;
2160 case 4: return (Addr) & arch->vex.guest_RSI;
2161 case 5: return (Addr) & arch->vex.guest_RDI;
2162 case R_FRAME_PTR: return (Addr) & arch->vex.guest_RBP;
2163 case R_STACK_PTR: return (Addr) & arch->vex.guest_RSP;
2164 case 8: return (Addr) & arch->vex.guest_R8;
2165 case 9: return (Addr) & arch->vex.guest_R9;
2166 case 10: return (Addr) & arch->vex.guest_R10;
2167 case 11: return (Addr) & arch->vex.guest_R11;
2168 case 12: return (Addr) & arch->vex.guest_R12;
2169 case 13: return (Addr) & arch->vex.guest_R13;
2170 case 14: return (Addr) & arch->vex.guest_R14;
2171 case 15: return (Addr) & arch->vex.guest_R15;
2172 default: return 0;
2173 }
cerion85665ca2005-06-20 15:51:07 +00002174#elif defined(VGA_ppc32)
2175 /* This is the Intel register encoding -- integer regs. */
2176# define R_STACK_PTR 1
2177# define R_FRAME_PTR 1
2178 switch (regno) {
2179 case 0: return (Addr) & arch->vex.guest_GPR0;
2180 case R_STACK_PTR: return (Addr) & arch->vex.guest_GPR1;
2181 case 2: return (Addr) & arch->vex.guest_GPR2;
2182 case 3: return (Addr) & arch->vex.guest_GPR3;
2183 case 4: return (Addr) & arch->vex.guest_GPR4;
2184 case 5: return (Addr) & arch->vex.guest_GPR5;
2185 case 6: return (Addr) & arch->vex.guest_GPR6;
2186 case 7: return (Addr) & arch->vex.guest_GPR7;
2187 case 8: return (Addr) & arch->vex.guest_GPR8;
2188 case 9: return (Addr) & arch->vex.guest_GPR9;
2189 case 10: return (Addr) & arch->vex.guest_GPR10;
2190 case 11: return (Addr) & arch->vex.guest_GPR11;
2191 case 12: return (Addr) & arch->vex.guest_GPR12;
2192 case 13: return (Addr) & arch->vex.guest_GPR13;
2193 case 14: return (Addr) & arch->vex.guest_GPR14;
2194 case 15: return (Addr) & arch->vex.guest_GPR15;
2195 case 16: return (Addr) & arch->vex.guest_GPR16;
2196 case 17: return (Addr) & arch->vex.guest_GPR17;
2197 case 18: return (Addr) & arch->vex.guest_GPR18;
2198 case 19: return (Addr) & arch->vex.guest_GPR19;
2199 case 20: return (Addr) & arch->vex.guest_GPR20;
2200 case 21: return (Addr) & arch->vex.guest_GPR21;
2201 case 22: return (Addr) & arch->vex.guest_GPR22;
2202 case 23: return (Addr) & arch->vex.guest_GPR23;
2203 case 24: return (Addr) & arch->vex.guest_GPR24;
2204 case 25: return (Addr) & arch->vex.guest_GPR25;
2205 case 26: return (Addr) & arch->vex.guest_GPR26;
2206 case 27: return (Addr) & arch->vex.guest_GPR27;
2207 case 28: return (Addr) & arch->vex.guest_GPR28;
2208 case 29: return (Addr) & arch->vex.guest_GPR29;
2209 case 30: return (Addr) & arch->vex.guest_GPR30;
2210 case 31: return (Addr) & arch->vex.guest_GPR31;
2211 default: return 0;
2212 }
njn6b2b96a2005-05-16 00:01:04 +00002213#else
2214# error Unknown platform
2215#endif
2216}
2217
2218
jsgfcb1d1c02003-10-14 21:55:10 +00002219/* return a pointer to a register (now for 5 other impossible things
2220 before breakfast) */
njn6b2b96a2005-05-16 00:01:04 +00002221static Addr regaddr(ThreadId tid, Int regno)
jsgfcb1d1c02003-10-14 21:55:10 +00002222{
njn6b2b96a2005-05-16 00:01:04 +00002223 Addr ret = regaddr_from_tst(regno, &VG_(threads)[tid].arch);
jsgfcb1d1c02003-10-14 21:55:10 +00002224
2225 if (ret == 0) {
njn252ed912005-05-15 03:30:56 +00002226 Char buf[100];
2227 VG_(describe_IP)( VG_(get_IP)(tid), buf, 100 );
2228 VG_(printf)("mysterious register %d used at %s\n", regno, buf);
jsgfcb1d1c02003-10-14 21:55:10 +00002229 }
2230
2231 return ret;
2232}
2233
2234/* Get a list of all variables in scope, working out from the directly
2235 current one */
sewardj7eb7c582005-06-23 01:02:53 +00002236Variable* ML_(get_scope_variables)(ThreadId tid)
jsgfcb1d1c02003-10-14 21:55:10 +00002237{
2238 static const Bool debug = False;
2239 Variable *list, *end;
2240 Addr eip;
2241 SegInfo *si;
2242 Int scopeidx;
2243 Scope *scope;
2244 Int distance;
2245 static const Int maxsyms = 1000;
2246 Int nsyms = maxsyms;
2247
2248 list = end = NULL;
2249
njn67516132005-03-22 04:02:43 +00002250 eip = VG_(get_IP)(tid);
jsgfcb1d1c02003-10-14 21:55:10 +00002251
2252 search_all_scopetabs(eip, &si, &scopeidx);
2253
2254 if (debug)
2255 VG_(printf)("eip=%p si=%p (%s; offset=%p) scopeidx=%d\n",
2256 eip, si, si ? si->filename : (Char *)"???",
2257 si ? si->offset : 0x99999, scopeidx);
2258
2259 if (si == NULL)
2260 return NULL; /* nothing in scope (should use global scope at least) */
2261
2262 if (debug) {
2263 ScopeRange *sr = &si->scopetab[scopeidx];
2264 Char file[100];
2265 Int line;
2266
sewardj7cee6f92005-06-13 17:39:06 +00002267 if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file),
2268 NULL, 0, NULL, &line))
jsgfcb1d1c02003-10-14 21:55:10 +00002269 file[0] = 0;
2270
2271 VG_(printf)("found scope range %p: eip=%p (%s:%d) size=%d scope=%p\n",
2272 sr, sr->addr, file, line, sr->size, sr->scope);
2273 }
2274
2275 distance = 0;
sewardj7cee6f92005-06-13 17:39:06 +00002276 for (scope = si->scopetab[scopeidx].scope;
2277 scope != NULL;
2278 scope = scope->outer, distance++) {
jsgfcb1d1c02003-10-14 21:55:10 +00002279 UInt i;
2280
2281 for(i = 0; i < scope->nsyms; i++) {
2282 Sym *sym = &scope->syms[i];
2283 Variable *v;
2284
2285 if (nsyms-- == 0) {
2286 VG_(printf)("max %d syms reached\n", maxsyms);
2287 return list;
2288 }
2289
2290 v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
2291
2292 v->next = NULL;
2293 v->distance = distance;
sewardj7eb7c582005-06-23 01:02:53 +00002294 v->type = ML_(st_basetype)(sym->type, False);
jsgfcb1d1c02003-10-14 21:55:10 +00002295 v->name = VG_(arena_strdup)(VG_AR_SYMTAB, sym->name);
2296 v->container = NULL;
sewardj7eb7c582005-06-23 01:02:53 +00002297 v->size = ML_(st_sizeof)(sym->type);
jsgfcb1d1c02003-10-14 21:55:10 +00002298
2299 if (debug && 0)
mueller5ed88f22004-01-06 16:02:29 +00002300 VG_(printf)("sym->name=%s sym->kind=%d offset=%d\n", sym->name, sym->kind, sym->u.offset);
jsgfcb1d1c02003-10-14 21:55:10 +00002301 switch(sym->kind) {
jsgfcb1d1c02003-10-14 21:55:10 +00002302
2303 case SyGlobal:
2304 case SyStatic:
mueller5ed88f22004-01-06 16:02:29 +00002305 if (sym->u.addr == 0) {
jsgfcb1d1c02003-10-14 21:55:10 +00002306 /* XXX lookup value */
2307 }
mueller5ed88f22004-01-06 16:02:29 +00002308 v->valuep = sym->u.addr;
jsgfcb1d1c02003-10-14 21:55:10 +00002309 break;
2310
2311 case SyReg:
njn6b2b96a2005-05-16 00:01:04 +00002312 v->valuep = regaddr(tid, sym->u.regno);
jsgfcb1d1c02003-10-14 21:55:10 +00002313 break;
2314
2315 case SyEBPrel:
njn6b2b96a2005-05-16 00:01:04 +00002316 case SyESPrel: {
2317 Addr reg = *(Addr*)regaddr(tid, sym->kind == SyESPrel
2318 ? R_STACK_PTR : R_FRAME_PTR);
jsgfcb1d1c02003-10-14 21:55:10 +00002319 if (debug)
mueller5ed88f22004-01-06 16:02:29 +00002320 VG_(printf)("reg=%p+%d=%p\n", reg, sym->u.offset, reg+sym->u.offset);
njn6b2b96a2005-05-16 00:01:04 +00002321 v->valuep = reg + sym->u.offset;
jsgfcb1d1c02003-10-14 21:55:10 +00002322 break;
njn6b2b96a2005-05-16 00:01:04 +00002323 }
jsgfcb1d1c02003-10-14 21:55:10 +00002324
2325 case SyType:
2326 VG_(core_panic)("unexpected typedef in scope");
2327 }
2328
2329 if (v->valuep == 0) {
2330 /* not interesting or useful */
2331 VG_(arena_free)(VG_AR_SYMTAB, v);
2332 continue;
2333 }
2334
2335 /* append to end of list */
2336 if (list == NULL)
2337 list = end = v;
2338 else {
2339 end->next = v;
2340 end = v;
2341 }
2342 }
2343 }
2344
2345 return list;
2346}
sewardj7cee6f92005-06-13 17:39:06 +00002347
2348# undef R_STACK_PTR
2349# undef R_FRAME_PTR
2350
jsgfcb1d1c02003-10-14 21:55:10 +00002351#endif /* TEST */
2352
njn6c846552003-09-16 07:41:43 +00002353/* Print into buf info on code address, function name and filename */
sewardj948d7612005-06-09 23:58:36 +00002354
2355static Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
2356{
2357 for (; n < n_buf-1 && *str != 0; n++,str++)
2358 buf[n] = *str;
2359 buf[n] = '\0';
2360 return n;
2361}
2362static Int putStrEsc ( Int n, Int n_buf, Char* buf, Char* str )
2363{
2364 Char alt[2];
2365 for (; *str != 0; str++) {
2366 switch (*str) {
2367 case '&': n = putStr( n, n_buf, buf, "&amp;"); break;
2368 case '<': n = putStr( n, n_buf, buf, "&lt;"); break;
2369 case '>': n = putStr( n, n_buf, buf, "&gt;"); break;
2370 default: alt[0] = *str;
2371 alt[1] = 0;
2372 n = putStr( n, n_buf, buf, alt );
2373 break;
2374 }
2375 }
2376 return n;
2377}
2378
njnd01fef72005-03-25 23:35:48 +00002379Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
sewardjde4a1d02002-03-22 01:27:54 +00002380{
sewardj948d7612005-06-09 23:58:36 +00002381# define APPEND(_str) \
2382 n = putStr(n, n_buf, buf, _str);
2383# define APPEND_ESC(_str) \
2384 n = putStrEsc(n, n_buf, buf, _str);
njn83f9e792005-06-11 05:04:09 +00002385# define BUF_LEN 4096
sewardj948d7612005-06-09 23:58:36 +00002386
nethercote80f76782003-11-13 22:34:00 +00002387 UInt lineno;
sewardj71bc3cb2005-05-19 00:25:45 +00002388 UChar ibuf[50];
sewardj948d7612005-06-09 23:58:36 +00002389 Int n = 0;
njn83f9e792005-06-11 05:04:09 +00002390 static UChar buf_fn[BUF_LEN];
2391 static UChar buf_obj[BUF_LEN];
2392 static UChar buf_srcloc[BUF_LEN];
sewardj7cee6f92005-06-13 17:39:06 +00002393 static UChar buf_dirname[BUF_LEN];
2394 Bool know_dirinfo = False;
njn83f9e792005-06-11 05:04:09 +00002395 Bool know_fnname = VG_(get_fnname) (eip, buf_fn, BUF_LEN);
2396 Bool know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
sewardj7cee6f92005-06-13 17:39:06 +00002397 Bool know_srcloc = VG_(get_filename_linenum)(
2398 eip,
2399 buf_srcloc, BUF_LEN,
2400 buf_dirname, BUF_LEN, &know_dirinfo,
2401 &lineno
2402 );
sewardj71bc3cb2005-05-19 00:25:45 +00002403 if (VG_(clo_xml)) {
2404
sewardj8665d8e2005-06-01 17:35:23 +00002405 Bool human_readable = True;
2406 HChar* maybe_newline = human_readable ? "\n " : "";
2407 HChar* maybe_newline2 = human_readable ? "\n " : "";
2408
sewardj71bc3cb2005-05-19 00:25:45 +00002409 /* Print in XML format, dumping in as much info as we know. */
2410 APPEND("<frame>");
2411 VG_(sprintf)(ibuf,"<ip>0x%llx</ip>", (ULong)eip);
sewardj8665d8e2005-06-01 17:35:23 +00002412 APPEND(maybe_newline);
sewardj71bc3cb2005-05-19 00:25:45 +00002413 APPEND(ibuf);
2414 if (know_objname) {
sewardj8665d8e2005-06-01 17:35:23 +00002415 APPEND(maybe_newline);
sewardj71bc3cb2005-05-19 00:25:45 +00002416 APPEND("<obj>");
sewardj948d7612005-06-09 23:58:36 +00002417 APPEND_ESC(buf_obj);
sewardj71bc3cb2005-05-19 00:25:45 +00002418 APPEND("</obj>");
2419 }
2420 if (know_fnname) {
sewardj8665d8e2005-06-01 17:35:23 +00002421 APPEND(maybe_newline);
sewardj71bc3cb2005-05-19 00:25:45 +00002422 APPEND("<fn>");
sewardj948d7612005-06-09 23:58:36 +00002423 APPEND_ESC(buf_fn);
sewardj71bc3cb2005-05-19 00:25:45 +00002424 APPEND("</fn>");
2425 }
2426 if (know_srcloc) {
sewardj7cee6f92005-06-13 17:39:06 +00002427 if (know_dirinfo) {
2428 APPEND(maybe_newline);
2429 APPEND("<dir>");
2430 APPEND(buf_dirname);
2431 APPEND("</dir>");
2432 }
sewardj8665d8e2005-06-01 17:35:23 +00002433 APPEND(maybe_newline);
sewardj71bc3cb2005-05-19 00:25:45 +00002434 APPEND("<file>");
sewardj948d7612005-06-09 23:58:36 +00002435 APPEND_ESC(buf_srcloc);
sewardj71bc3cb2005-05-19 00:25:45 +00002436 APPEND("</file>");
sewardj8665d8e2005-06-01 17:35:23 +00002437 APPEND(maybe_newline);
sewardj71bc3cb2005-05-19 00:25:45 +00002438 APPEND("<line>");
2439 VG_(sprintf)(ibuf,"%d",lineno);
2440 APPEND(ibuf);
2441 APPEND("</line>");
2442 }
sewardj8665d8e2005-06-01 17:35:23 +00002443 APPEND(maybe_newline2);
sewardj71bc3cb2005-05-19 00:25:45 +00002444 APPEND("</frame>");
2445
2446 } else {
2447
2448 /* Print for humans to read */
2449 VG_(sprintf)(ibuf,"0x%llx: ", (ULong)eip);
2450 APPEND(ibuf);
2451 if (know_fnname) {
2452 APPEND(buf_fn);
2453 if (!know_srcloc && know_objname) {
2454 APPEND(" (in ");
2455 APPEND(buf_obj);
2456 APPEND(")");
2457 }
2458 } else if (know_objname && !know_srcloc) {
2459 APPEND("(within ");
njn6c846552003-09-16 07:41:43 +00002460 APPEND(buf_obj);
2461 APPEND(")");
sewardj71bc3cb2005-05-19 00:25:45 +00002462 } else {
2463 APPEND("???");
njn6c846552003-09-16 07:41:43 +00002464 }
sewardj71bc3cb2005-05-19 00:25:45 +00002465 if (know_srcloc) {
2466 APPEND(" (");
2467 APPEND(buf_srcloc);
2468 APPEND(":");
2469 VG_(sprintf)(ibuf,"%d",lineno);
2470 APPEND(ibuf);
2471 APPEND(")");
2472 }
2473
njn6c846552003-09-16 07:41:43 +00002474 }
2475 return buf;
2476
sewardj948d7612005-06-09 23:58:36 +00002477# undef APPEND
2478# undef APPEND_ESC
sewardj7cee6f92005-06-13 17:39:06 +00002479# undef BUF_LEN
njn6c846552003-09-16 07:41:43 +00002480}
2481
sewardj35165532005-04-30 18:47:48 +00002482/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
2483
2484Bool VG_(use_CFI_info) ( /*MOD*/Addr* ipP,
2485 /*MOD*/Addr* spP,
2486 /*MOD*/Addr* fpP,
2487 Addr min_accessible,
2488 Addr max_accessible )
2489{
2490 Int i;
2491 SegInfo* si;
2492 CfiSI* cfisi = NULL;
2493 Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
2494
sewardjbf603752005-05-02 00:36:27 +00002495
sewardj35165532005-04-30 18:47:48 +00002496 if (0) VG_(printf)("search for %p\n", *ipP);
2497
njn16eeb4e2005-06-16 03:56:58 +00002498 for (si = segInfo_list; si != NULL; si = si->next) {
sewardjbf603752005-05-02 00:36:27 +00002499 /* Use the per-SegInfo summary address ranges to skip
2500 inapplicable SegInfos quickly. */
2501 if (si->cfisi_used == 0)
2502 continue;
2503 if (*ipP < si->cfisi_minaddr || *ipP > si->cfisi_maxaddr)
2504 continue;
2505
sewardj3a1c7db2005-05-02 09:43:44 +00002506 i = search_one_cfitab( si, *ipP );
2507 if (i != -1) {
2508 vg_assert(i >= 0 && i < si->cfisi_used);
2509 cfisi = &si->cfisi[i];
2510 break;
sewardj35165532005-04-30 18:47:48 +00002511 }
2512 }
2513
sewardj35165532005-04-30 18:47:48 +00002514 if (cfisi == NULL)
2515 return False;
2516
2517 if (0) {
2518 VG_(printf)("found cfisi: ");
sewardj7eb7c582005-06-23 01:02:53 +00002519 ML_(ppCfiSI)(cfisi);
sewardj35165532005-04-30 18:47:48 +00002520 }
2521
2522 ipPrev = spPrev = fpPrev = 0;
2523
2524 ipHere = *ipP;
2525 spHere = *spP;
2526 fpHere = *fpP;
2527
2528 cfa = cfisi->cfa_off + (cfisi->cfa_sprel ? spHere : fpHere);
2529
2530# define COMPUTE(_prev, _here, _how, _off) \
2531 do { \
2532 switch (_how) { \
2533 case CFIR_UNKNOWN: \
2534 return False; \
2535 case CFIR_SAME: \
2536 _prev = _here; break; \
2537 case CFIR_MEMCFAREL: { \
2538 Addr a = cfa + (Word)_off; \
2539 if (a < min_accessible \
2540 || a+sizeof(Addr) > max_accessible) \
2541 return False; \
2542 _prev = *(Addr*)a; \
2543 break; \
2544 } \
2545 case CFIR_CFAREL: \
2546 _prev = cfa + (Word)_off; \
2547 break; \
2548 } \
2549 } while (0)
2550
2551 COMPUTE(ipPrev, ipHere, cfisi->ra_how, cfisi->ra_off);
2552 COMPUTE(spPrev, spHere, cfisi->sp_how, cfisi->sp_off);
2553 COMPUTE(fpPrev, fpHere, cfisi->fp_how, cfisi->fp_off);
2554
2555# undef COMPUTE
2556
2557 *ipP = ipPrev;
2558 *spP = spPrev;
2559 *fpP = fpPrev;
2560 return True;
2561}
2562
2563
sewardj25c7c3a2003-07-10 00:17:58 +00002564/*------------------------------------------------------------*/
sewardj47104382002-10-20 18:35:48 +00002565/*--- SegInfo accessor functions ---*/
2566/*------------------------------------------------------------*/
2567
njn36ef6ba2005-05-14 18:42:26 +00002568const SegInfo* VG_(next_seginfo)(const SegInfo* si)
sewardj47104382002-10-20 18:35:48 +00002569{
njn36ef6ba2005-05-14 18:42:26 +00002570 if (si == NULL)
njn16eeb4e2005-06-16 03:56:58 +00002571 return segInfo_list;
njn36ef6ba2005-05-14 18:42:26 +00002572 return si->next;
sewardj47104382002-10-20 18:35:48 +00002573}
2574
njn36ef6ba2005-05-14 18:42:26 +00002575Addr VG_(seg_start)(const SegInfo* si)
sewardj47104382002-10-20 18:35:48 +00002576{
njn36ef6ba2005-05-14 18:42:26 +00002577 return si->start;
sewardj47104382002-10-20 18:35:48 +00002578}
2579
njn36ef6ba2005-05-14 18:42:26 +00002580SizeT VG_(seg_size)(const SegInfo* si)
sewardj47104382002-10-20 18:35:48 +00002581{
njn36ef6ba2005-05-14 18:42:26 +00002582 return si->size;
sewardj47104382002-10-20 18:35:48 +00002583}
2584
njn36ef6ba2005-05-14 18:42:26 +00002585const UChar* VG_(seg_filename)(const SegInfo* si)
sewardj47104382002-10-20 18:35:48 +00002586{
njn36ef6ba2005-05-14 18:42:26 +00002587 return si->filename;
sewardj47104382002-10-20 18:35:48 +00002588}
2589
njn36ef6ba2005-05-14 18:42:26 +00002590ULong VG_(seg_sym_offset)(const SegInfo* si)
sewardj47104382002-10-20 18:35:48 +00002591{
njn36ef6ba2005-05-14 18:42:26 +00002592 return si->offset;
sewardj47104382002-10-20 18:35:48 +00002593}
2594
2595VgSectKind VG_(seg_sect_kind)(Addr a)
2596{
njn36ef6ba2005-05-14 18:42:26 +00002597 SegInfo* si;
sewardj47104382002-10-20 18:35:48 +00002598 VgSectKind ret = Vg_SectUnknown;
2599
njn16eeb4e2005-06-16 03:56:58 +00002600 for(si = segInfo_list; si != NULL; si = si->next) {
njn36ef6ba2005-05-14 18:42:26 +00002601 if (a >= si->start && a < (si->start + si->size)) {
sewardj47104382002-10-20 18:35:48 +00002602 if (0)
njn36ef6ba2005-05-14 18:42:26 +00002603 VG_(printf)("addr=%p si=%p %s got=%p %d plt=%p %d data=%p %d bss=%p %d\n",
2604 a, si, si->filename,
2605 si->got_start, si->got_size,
2606 si->plt_start, si->plt_size,
2607 si->data_start, si->data_size,
2608 si->bss_start, si->bss_size);
sewardj47104382002-10-20 18:35:48 +00002609 ret = Vg_SectText;
2610
njn36ef6ba2005-05-14 18:42:26 +00002611 if (a >= si->data_start && a < (si->data_start + si->data_size))
sewardj8fe15a32002-10-20 19:29:21 +00002612 ret = Vg_SectData;
njn36ef6ba2005-05-14 18:42:26 +00002613 else if (a >= si->bss_start && a < (si->bss_start + si->bss_size))
sewardj8fe15a32002-10-20 19:29:21 +00002614 ret = Vg_SectBSS;
njn36ef6ba2005-05-14 18:42:26 +00002615 else if (a >= si->plt_start && a < (si->plt_start + si->plt_size))
sewardj47104382002-10-20 18:35:48 +00002616 ret = Vg_SectPLT;
njn36ef6ba2005-05-14 18:42:26 +00002617 else if (a >= si->got_start && a < (si->got_start + si->got_size))
sewardj47104382002-10-20 18:35:48 +00002618 ret = Vg_SectGOT;
2619 }
2620 }
2621
2622 return ret;
2623}
2624
sewardjde4a1d02002-03-22 01:27:54 +00002625/*--------------------------------------------------------------------*/
njnea27e462005-05-31 02:38:09 +00002626/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002627/*--------------------------------------------------------------------*/