blob: f5a94b4ca41af6b7a539fb4a0962596e1157aeb2 [file] [log] [blame]
Jeff Browned07e002011-02-03 17:46:23 -08001
2/*--------------------------------------------------------------------*/
3/*--- Reading of syms & debug info from ELF .so/executable files. ---*/
4/*--- readelf.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
Ben Cheng663860b2013-01-31 15:38:14 -080011 Copyright (C) 2000-2012 Julian Seward
Jeff Browned07e002011-02-03 17:46:23 -080012 jseward@acm.org
13
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
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#if defined(VGO_linux)
33
34#include "pub_core_basics.h"
35#include "pub_core_vki.h"
36#include "pub_core_debuginfo.h"
37#include "pub_core_libcbase.h"
38#include "pub_core_libcprint.h"
39#include "pub_core_libcassert.h"
40#include "pub_core_libcfile.h"
41#include "pub_core_aspacemgr.h" /* for mmaping debuginfo files */
42#include "pub_core_machine.h" /* VG_ELF_CLASS */
43#include "pub_core_options.h"
44#include "pub_core_oset.h"
45#include "pub_core_tooliface.h" /* VG_(needs) */
46#include "pub_core_xarray.h"
47#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
48#include "priv_d3basics.h"
49#include "priv_tytypes.h"
50#include "priv_storage.h"
51#include "priv_readelf.h" /* self */
52#include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
53#include "priv_readdwarf3.h"
54#include "priv_readstabs.h" /* and stabs, if we're unlucky */
55
56/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
57#include <elf.h>
58/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
59
60/*------------------------------------------------------------*/
61/*--- 32/64-bit parameterisation ---*/
62/*------------------------------------------------------------*/
63
64/* For all the ELF macros and types which specify '32' or '64',
65 select the correct variant for this platform and give it
66 an 'XX' name. Then use the 'XX' variant consistently in
67 the rest of this file.
68*/
69#if VG_WORDSIZE == 4
70# define ElfXX_Ehdr Elf32_Ehdr
71# define ElfXX_Shdr Elf32_Shdr
72# define ElfXX_Phdr Elf32_Phdr
73# define ElfXX_Nhdr Elf32_Nhdr
74# define ElfXX_Sym Elf32_Sym
75# define ElfXX_Off Elf32_Off
76# define ElfXX_Word Elf32_Word
77# define ElfXX_Addr Elf32_Addr
78# define ElfXX_Dyn Elf32_Dyn
79# define ELFXX_ST_BIND ELF32_ST_BIND
80# define ELFXX_ST_TYPE ELF32_ST_TYPE
81
82#elif VG_WORDSIZE == 8
83# define ElfXX_Ehdr Elf64_Ehdr
84# define ElfXX_Shdr Elf64_Shdr
85# define ElfXX_Phdr Elf64_Phdr
86# define ElfXX_Nhdr Elf64_Nhdr
87# define ElfXX_Sym Elf64_Sym
88# define ElfXX_Off Elf64_Off
89# define ElfXX_Word Elf64_Word
90# define ElfXX_Addr Elf64_Addr
91# define ElfXX_Dyn Elf64_Dyn
92# define ELFXX_ST_BIND ELF64_ST_BIND
93# define ELFXX_ST_TYPE ELF64_ST_TYPE
94
95#else
96# error "VG_WORDSIZE should be 4 or 8"
97#endif
98
99
100/*------------------------------------------------------------*/
101/*--- ---*/
102/*--- Read symbol table and line info from ELF files. ---*/
103/*--- ---*/
104/*------------------------------------------------------------*/
105
106/* readelf.c parses ELF files and acquires symbol table info from
107 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
108 and call frame info found. */
109
110
111/* Identify an ELF object file by peering at the first few bytes of
112 it. */
113
Ben Cheng663860b2013-01-31 15:38:14 -0800114Bool ML_(is_elf_object_file)( void* image, SizeT n_image, Bool rel_ok )
Jeff Browned07e002011-02-03 17:46:23 -0800115{
116 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
117 Int ok = 1;
118
119 if (n_image < sizeof(ElfXX_Ehdr))
120 return False;
121
122 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
123 && ehdr->e_ident[EI_MAG1] == 'E'
124 && ehdr->e_ident[EI_MAG2] == 'L'
125 && ehdr->e_ident[EI_MAG3] == 'F');
126 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
127 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
128 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
Ben Cheng663860b2013-01-31 15:38:14 -0800129 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN
130 || (rel_ok && ehdr->e_type == ET_REL));
Jeff Browned07e002011-02-03 17:46:23 -0800131 ok &= (ehdr->e_machine == VG_ELF_MACHINE);
132 ok &= (ehdr->e_version == EV_CURRENT);
133 ok &= (ehdr->e_shstrndx != SHN_UNDEF);
134 ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
Ben Cheng663860b2013-01-31 15:38:14 -0800135 ok &= ((ehdr->e_phoff != 0 && ehdr->e_phnum != 0)
136 || ehdr->e_type == ET_REL);
Jeff Browned07e002011-02-03 17:46:23 -0800137
138 if (ok)
139 return True;
140 else
141 return False;
142}
143
144
145/* Show a raw ELF symbol, given its in-image address and name. */
146
147static
148void show_raw_elf_symbol ( Int i,
149 ElfXX_Sym* sym, Char* sym_name, Addr sym_svma,
150 Bool ppc64_linux_format )
151{
152 HChar* space = ppc64_linux_format ? " " : "";
153 VG_(printf)("raw symbol [%4d]: ", i);
154 switch (ELFXX_ST_BIND(sym->st_info)) {
155 case STB_LOCAL: VG_(printf)("LOC "); break;
156 case STB_GLOBAL: VG_(printf)("GLO "); break;
157 case STB_WEAK: VG_(printf)("WEA "); break;
158 case STB_LOPROC: VG_(printf)("lop "); break;
159 case STB_HIPROC: VG_(printf)("hip "); break;
160 default: VG_(printf)("??? "); break;
161 }
162 switch (ELFXX_ST_TYPE(sym->st_info)) {
163 case STT_NOTYPE: VG_(printf)("NOT "); break;
164 case STT_OBJECT: VG_(printf)("OBJ "); break;
165 case STT_FUNC: VG_(printf)("FUN "); break;
166 case STT_SECTION: VG_(printf)("SEC "); break;
167 case STT_FILE: VG_(printf)("FIL "); break;
168 case STT_LOPROC: VG_(printf)("lop "); break;
169 case STT_HIPROC: VG_(printf)("hip "); break;
170 default: VG_(printf)("??? "); break;
171 }
172 VG_(printf)(": svma %#010lx, %ssz %4ld %s\n",
173 sym_svma, space, sym->st_size + 0UL,
174 ( sym->st_name ? sym_name : (Char*)"NONAME" ) );
175}
176
177
178/* Decide whether SYM is something we should collect, and if so, copy
179 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
180 this is straightforward - the name, address, size are copied out
181 unchanged.
182
183 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
184 below): we assume that the .bss is mapped immediately after .data,
185 and so accept any data symbol which exists in the range [start of
186 .data, size of .data + size of .bss). I don't know if this is
187 really correct/justifiable, or not.
188
189 For ppc64-linux it's more complex. If the symbol is seen to be in
190 the .opd section, it is taken to be a function descriptor, and so
191 a dereference is attempted, in order to get hold of the real entry
192 point address. Also as part of the dereference, there is an attempt
193 to calculate the TOC pointer (R2 value) associated with the symbol.
194
195 To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0),
196 if the symbol is seen to be outside the .opd section and its name
197 starts with a dot, an .opd deference is not attempted, and no TOC
198 pointer is calculated, but the the leading dot is removed from the
199 name.
200
201 As a result, on ppc64-linux, the caller of this function may have
202 to piece together the real size, address, name of the symbol from
203 multiple calls to this function. Ugly and confusing.
204*/
205static
206Bool get_elf_symbol_info (
207 /* INPUTS */
208 struct _DebugInfo* di, /* containing DebugInfo */
209 ElfXX_Sym* sym, /* ELF symbol */
210 Char* sym_name, /* name */
211 Addr sym_svma, /* address as stated in the object file */
212 Bool symtab_in_debug, /* symbol table is in the debug file */
213 UChar* opd_img, /* oimage of .opd sec (ppc64-linux only) */
214 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
215 /* OUTPUTS */
216 Char** sym_name_out, /* name we should record */
217 Addr* sym_avma_out, /* addr we should record */
218 Int* sym_size_out, /* symbol size */
219 Addr* sym_tocptr_out, /* ppc64-linux only: R2 value to be
220 used on entry */
221 Bool* from_opd_out, /* ppc64-linux only: did we deref an
222 .opd entry? */
223 Bool* is_text_out, /* is this a text symbol? */
224 Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/
225 )
226{
227 Bool plausible;
228# if defined(VGP_ppc64_linux)
229 Bool is_in_opd;
230# endif
231 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
232 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
233 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
234
235 /* Set defaults */
236 *sym_name_out = sym_name;
237 *sym_avma_out = sym_svma; /* we will bias this shortly */
238 *is_text_out = True;
Jeff Browned07e002011-02-03 17:46:23 -0800239 *sym_tocptr_out = 0; /* unknown/inapplicable */
240 *from_opd_out = False;
241 *is_ifunc = False;
Ben Cheng663860b2013-01-31 15:38:14 -0800242 /* Get the symbol size, but restrict it to fit in a signed 32 bit
243 int. Also, deal with the stupid case of negative size by making
244 the size be 1. Note that sym->st_size has type UWord,
245 effectively. */
246 { Word size_tmp = (Word)sym->st_size;
247 Word max_Int = (1LL << 31) - 1;
248 if (size_tmp < 0) size_tmp = 1;
249 if (size_tmp > max_Int) size_tmp = max_Int;
250 *sym_size_out = (Int)size_tmp;
251 }
252 /* After this point refer only to *sym_size_out and not to
253 sym->st_size. */
Jeff Browned07e002011-02-03 17:46:23 -0800254
255 /* Figure out if we're interested in the symbol. Firstly, is it of
256 the right flavour? */
257 plausible
258 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
259 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
260 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
261 )
262 &&
263 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
264 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
Ben Cheng663860b2013-01-31 15:38:14 -0800265# ifdef STT_GNU_IFUNC
Jeff Browned07e002011-02-03 17:46:23 -0800266 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
Ben Cheng663860b2013-01-31 15:38:14 -0800267# endif
Jeff Browned07e002011-02-03 17:46:23 -0800268 );
269
270 /* Work out the svma and bias for each section as it will appear in
271 addresses in the symbol table. */
272 if (symtab_in_debug) {
273 text_svma = di->text_debug_svma;
274 text_bias = di->text_debug_bias;
275 data_svma = di->data_debug_svma;
276 data_bias = di->data_debug_bias;
277 sdata_svma = di->sdata_debug_svma;
278 sdata_bias = di->sdata_debug_bias;
279 rodata_svma = di->rodata_debug_svma;
280 rodata_bias = di->rodata_debug_bias;
281 bss_svma = di->bss_debug_svma;
282 bss_bias = di->bss_debug_bias;
283 sbss_svma = di->sbss_debug_svma;
284 sbss_bias = di->sbss_debug_bias;
285 } else {
286 text_svma = di->text_svma;
287 text_bias = di->text_bias;
288 data_svma = di->data_svma;
289 data_bias = di->data_bias;
290 sdata_svma = di->sdata_svma;
291 sdata_bias = di->sdata_bias;
292 rodata_svma = di->rodata_svma;
293 rodata_bias = di->rodata_bias;
294 bss_svma = di->bss_svma;
295 bss_bias = di->bss_bias;
296 sbss_svma = di->sbss_svma;
297 sbss_bias = di->sbss_bias;
298 }
299
300 /* Now bias sym_avma_out accordingly by figuring out exactly which
301 section the symbol is from and bias accordingly. Screws up if
302 the previously deduced section svma address ranges are wrong. */
303 if (di->text_present
304 && di->text_size > 0
305 && sym_svma >= text_svma
306 && sym_svma < text_svma + di->text_size) {
307 *is_text_out = True;
308 *sym_avma_out += text_bias;
309 } else
310 if (di->data_present
311 && di->data_size > 0
312 && sym_svma >= data_svma
313 && sym_svma < data_svma + di->data_size) {
314 *is_text_out = False;
315 *sym_avma_out += data_bias;
316 } else
317 if (di->sdata_present
318 && di->sdata_size > 0
319 && sym_svma >= sdata_svma
320 && sym_svma < sdata_svma + di->sdata_size) {
321 *is_text_out = False;
322 *sym_avma_out += sdata_bias;
323 } else
324 if (di->rodata_present
325 && di->rodata_size > 0
326 && sym_svma >= rodata_svma
327 && sym_svma < rodata_svma + di->rodata_size) {
328 *is_text_out = False;
329 *sym_avma_out += rodata_bias;
330 } else
331 if (di->bss_present
332 && di->bss_size > 0
333 && sym_svma >= bss_svma
334 && sym_svma < bss_svma + di->bss_size) {
335 *is_text_out = False;
336 *sym_avma_out += bss_bias;
337 } else
338 if (di->sbss_present
339 && di->sbss_size > 0
340 && sym_svma >= sbss_svma
341 && sym_svma < sbss_svma + di->sbss_size) {
342 *is_text_out = False;
343 *sym_avma_out += sbss_bias;
344 } else {
345 /* Assume it's in .text. Is this a good idea? */
346 *is_text_out = True;
347 *sym_avma_out += text_bias;
348 }
349
350# ifdef STT_GNU_IFUNC
351 /* Check for indirect functions. */
352 if (*is_text_out
353 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
354 *is_ifunc = True;
355 }
356# endif
357
358# if defined(VGP_ppc64_linux)
359 /* Allow STT_NOTYPE in the very special case where we're running on
360 ppc64-linux and the symbol is one which the .opd-chasing hack
361 below will chase. */
362 if (!plausible
363 && *is_text_out
364 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
Ben Cheng663860b2013-01-31 15:38:14 -0800365 && *sym_size_out > 0
Jeff Browned07e002011-02-03 17:46:23 -0800366 && di->opd_present
367 && di->opd_size > 0
368 && *sym_avma_out >= di->opd_avma
369 && *sym_avma_out < di->opd_avma + di->opd_size)
370 plausible = True;
371# endif
372
373 if (!plausible)
374 return False;
375
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400376 /* Ignore if nameless. */
377 if (sym_name == (ElfXX_Word)0
Jeff Browned07e002011-02-03 17:46:23 -0800378 || /* VG_(strlen)(sym_name) == 0 */
379 /* equivalent but cheaper ... */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400380 sym_name[0] == 0) {
381 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
382 return False;
383 }
384
385 /* Ignore if zero-sized. Except on Android:
386
387 On Android 2.3.5, some of the symbols that Memcheck needs to
388 intercept (for noise reduction purposes) have zero size, due to
389 lack of .size directives in handwritten assembly sources. So we
390 can't reject them out of hand -- instead give them a bogusly
391 large size and let canonicaliseSymtab trim them so they don't
392 overlap any following symbols. At least the following symbols
393 are known to be affected:
394
395 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
396 in /system/bin/linker: __dl_strcmp __dl_strlen
397 */
Ben Cheng663860b2013-01-31 15:38:14 -0800398 if (*sym_size_out == 0) {
399# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
400 *sym_size_out = 2048;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400401# else
Jeff Browned07e002011-02-03 17:46:23 -0800402 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
403 return False;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400404# endif
Jeff Browned07e002011-02-03 17:46:23 -0800405 }
406
407 /* This seems to significantly reduce the number of junk
408 symbols, and particularly reduces the number of
409 overlapping address ranges. Don't ask me why ... */
410 if ((Int)sym->st_value == 0) {
411 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
412 return False;
413 }
414
415 /* If it's apparently in a GOT or PLT, it's really a reference to a
416 symbol defined elsewhere, so ignore it. */
417 if (di->got_present
418 && di->got_size > 0
419 && *sym_avma_out >= di->got_avma
420 && *sym_avma_out < di->got_avma + di->got_size) {
421 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
422 return False;
423 }
424 if (di->plt_present
425 && di->plt_size > 0
426 && *sym_avma_out >= di->plt_avma
427 && *sym_avma_out < di->plt_avma + di->plt_size) {
428 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
429 return False;
430 }
431
432 /* ppc64-linux nasty hack: if the symbol is in an .opd section,
433 then really what we have is the address of a function
434 descriptor. So use the first word of that as the function's
435 text.
436
437 See thread starting at
438 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
439 */
440# if defined(VGP_ppc64_linux)
441 is_in_opd = False;
442# endif
443
444 if (di->opd_present
445 && di->opd_size > 0
446 && *sym_avma_out >= di->opd_avma
447 && *sym_avma_out < di->opd_avma + di->opd_size) {
448# if !defined(VGP_ppc64_linux)
449 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
450 return False;
451# else
452 Int offset_in_opd;
453 ULong* fn_descr;
454 Bool details = 1||False;
455
456 if (details)
457 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
458 (void*)(opd_bias), (void*)*sym_avma_out);
459
460 if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
461 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
462 return False;
463 }
464
465 /* *sym_avma_out is a vma pointing into the .opd section. We
466 know the vma of the opd section start, so we can figure out
467 how far into the opd section this is. */
468
469 offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
470 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
471 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
472 return False;
473 }
474
475 /* Now we want to know what's at that offset in the .opd
476 section. We can't look in the running image since it won't
477 necessarily have been mapped. But we can consult the oimage.
478 opd_img is the start address of the .opd in the oimage.
479 Hence: */
480
481 fn_descr = (ULong*)(opd_img + offset_in_opd);
482
483 if (details)
484 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
485 offset_in_opd, fn_descr);
486 if (details)
487 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
488
489 /* opd_bias is the what we have to add to SVMAs found in .opd to
490 get plausible .text AVMAs for the entry point, and .data
491 AVMAs (presumably) for the TOC locations. We use the caller
492 supplied value (which is di->text_bias) for both of these.
493 Not sure why that is correct - it seems to work, and sounds
494 OK for fn_descr[0], but surely we need to use the data bias
495 and not the text bias for fn_descr[1] ? Oh Well.
496 */
497 *sym_avma_out = fn_descr[0] + opd_bias;
498 *sym_tocptr_out = fn_descr[1] + opd_bias;
499 *from_opd_out = True;
500 is_in_opd = True;
501
502 /* Do a final sanity check: if the symbol falls outside the
503 DebugInfo's mapped range, ignore it. Since *sym_avma_out has
504 been updated, that can be achieved simply by falling through
505 to the test below. */
506
507# endif /* ppc64-linux nasty hack */
508 }
509
510 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
511 the symbol is outside .opd. */
512# if defined(VGP_ppc64_linux)
513 if (di->opd_size > 0
514 && !is_in_opd
515 && sym_name[0] == '.') {
516 vg_assert(!(*from_opd_out));
517 *sym_name_out = &sym_name[1];
518 }
519# endif
520
521 /* If no part of the symbol falls within the mapped range,
522 ignore it. */
523
524 in_text
525 = di->text_present
526 && di->text_size > 0
527 && !(*sym_avma_out + *sym_size_out <= di->text_avma
528 || *sym_avma_out >= di->text_avma + di->text_size);
529
530 in_data
531 = di->data_present
532 && di->data_size > 0
533 && !(*sym_avma_out + *sym_size_out <= di->data_avma
534 || *sym_avma_out >= di->data_avma + di->data_size);
535
536 in_sdata
537 = di->sdata_present
538 && di->sdata_size > 0
539 && !(*sym_avma_out + *sym_size_out <= di->sdata_avma
540 || *sym_avma_out >= di->sdata_avma + di->sdata_size);
541
542 in_rodata
543 = di->rodata_present
544 && di->rodata_size > 0
545 && !(*sym_avma_out + *sym_size_out <= di->rodata_avma
546 || *sym_avma_out >= di->rodata_avma + di->rodata_size);
547
548 in_bss
549 = di->bss_present
550 && di->bss_size > 0
551 && !(*sym_avma_out + *sym_size_out <= di->bss_avma
552 || *sym_avma_out >= di->bss_avma + di->bss_size);
553
554 in_sbss
555 = di->sbss_present
556 && di->sbss_size > 0
557 && !(*sym_avma_out + *sym_size_out <= di->sbss_avma
558 || *sym_avma_out >= di->sbss_avma + di->sbss_size);
559
560
561 if (*is_text_out) {
562 /* This used to reject any symbol falling outside the text
563 segment ("if (!in_text) ..."). Now it is relaxed slightly,
564 to reject only symbols which fall outside the area mapped
565 r-x. This is in accordance with r7427. See
566 "Comment_Regarding_Text_Range_Checks" in storage.c for
567 background. */
568 Bool in_rx;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400569 vg_assert(di->fsm.have_rx_map);
Ben Cheng663860b2013-01-31 15:38:14 -0800570 /* This could actually wrap around and cause
571 ML_(find_rx_mapping) to assert. But that seems so unlikely,
572 let's wait for it to happen before fixing it. */
573 in_rx = (ML_(find_rx_mapping)(di, *sym_avma_out,
574 *sym_avma_out + *sym_size_out) != NULL);
Jeff Browned07e002011-02-03 17:46:23 -0800575 if (in_text)
576 vg_assert(in_rx);
577 if (!in_rx) {
578 TRACE_SYMTAB(
579 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
580 *sym_avma_out, *sym_avma_out + *sym_size_out,
581 di->text_avma,
582 di->text_avma + di->text_size);
583 return False;
584 }
585 } else {
586 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
587 TRACE_SYMTAB(
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400588 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
589 "/ .bss / .sbss svma ranges\n",
Jeff Browned07e002011-02-03 17:46:23 -0800590 *sym_avma_out, *sym_avma_out + *sym_size_out);
591 return False;
592 }
593 }
594
595# if defined(VGP_ppc64_linux)
596 /* It's crucial that we never add symbol addresses in the .opd
597 section. This would completely mess up function redirection and
598 intercepting. This assert ensures that anysymbols that make it
599 into the symbol table on ppc64-linux don't point into .opd. */
600 if (di->opd_present && di->opd_size > 0) {
601 vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
602 || *sym_avma_out >= di->opd_avma + di->opd_size);
603 }
604# endif
605
606 /* Acquire! */
607 return True;
608}
609
610
611/* Read an ELF symbol table (normal or dynamic). This one is for the
612 "normal" case ({x86,amd64,ppc32}-linux). */
613static
614__attribute__((unused)) /* not referred to on all targets */
615void read_elf_symtab__normal(
616 struct _DebugInfo* di, UChar* tab_name,
617 ElfXX_Sym* symtab_img, SizeT symtab_szB,
618 UChar* strtab_img, SizeT strtab_szB,
619 Bool symtab_in_debug,
620 UChar* opd_img /* ppc64-linux only */
621 )
622{
623 Word i;
624 Addr sym_svma, sym_avma_really;
625 Char *sym_name, *sym_name_really;
626 Int sym_size;
627 Addr sym_tocptr;
628 Bool from_opd, is_text, is_ifunc;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400629 DiSym disym;
Jeff Browned07e002011-02-03 17:46:23 -0800630 ElfXX_Sym *sym;
631
632 if (strtab_img == NULL || symtab_img == NULL) {
633 Char buf[80];
634 vg_assert(VG_(strlen)(tab_name) < 40);
635 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
636 ML_(symerr)(di, False, buf);
637 return;
638 }
639
640 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n",
641 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
642
643 /* Perhaps should start at i = 1; ELF docs suggest that entry
644 0 always denotes 'unknown symbol'. */
645 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
646 sym = & symtab_img[i];
647 sym_name = (UChar*)(strtab_img + sym->st_name);
648 sym_svma = sym->st_value;
649
650 if (di->trace_symtab)
651 show_raw_elf_symbol(i, sym, sym_name, sym_svma, False);
652
653 if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
654 symtab_in_debug,
655 opd_img, di->text_bias,
656 &sym_name_really,
657 &sym_avma_really,
658 &sym_size,
659 &sym_tocptr,
660 &from_opd, &is_text, &is_ifunc)) {
661
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400662 disym.addr = sym_avma_really;
663 disym.tocptr = sym_tocptr;
664 disym.pri_name = ML_(addStr) ( di, sym_name_really, -1 );
665 disym.sec_names = NULL;
666 disym.size = sym_size;
667 disym.isText = is_text;
668 disym.isIFunc = is_ifunc;
669 vg_assert(disym.pri_name);
670 vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */
671 ML_(addSym) ( di, &disym );
Jeff Browned07e002011-02-03 17:46:23 -0800672
673 if (di->trace_symtab) {
674 VG_(printf)(" rec(%c) [%4ld]: "
675 " val %#010lx, sz %4d %s\n",
676 is_text ? 't' : 'd',
677 i,
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400678 disym.addr,
679 (Int)disym.size,
680 (HChar*)disym.pri_name
Jeff Browned07e002011-02-03 17:46:23 -0800681 );
682 }
683
684 }
685 }
686}
687
688
689/* Read an ELF symbol table (normal or dynamic). This one is for
690 ppc64-linux, which requires special treatment. */
691
692typedef
693 struct {
694 Addr addr;
695 UChar* name;
696 }
697 TempSymKey;
698
699typedef
700 struct {
701 TempSymKey key;
702 Addr tocptr;
703 Int size;
704 Bool from_opd;
705 Bool is_text;
706 Bool is_ifunc;
707 }
708 TempSym;
709
710static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
711 if (key1->addr < elem2->key.addr) return -1;
712 if (key1->addr > elem2->key.addr) return 1;
713 return (Word)VG_(strcmp)(key1->name, elem2->key.name);
714}
715
716static
717__attribute__((unused)) /* not referred to on all targets */
718void read_elf_symtab__ppc64_linux(
719 struct _DebugInfo* di, UChar* tab_name,
720 ElfXX_Sym* symtab_img, SizeT symtab_szB,
721 UChar* strtab_img, SizeT strtab_szB,
722 Bool symtab_in_debug,
723 UChar* opd_img /* ppc64-linux only */
724 )
725{
726 Word i;
727 Int old_size;
728 Addr sym_svma, sym_avma_really;
729 Char *sym_name, *sym_name_really;
730 Int sym_size;
731 Addr sym_tocptr;
732 Bool from_opd, modify_size, modify_tocptr, is_text, is_ifunc;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400733 DiSym disym;
Jeff Browned07e002011-02-03 17:46:23 -0800734 ElfXX_Sym *sym;
735 OSet *oset;
736 TempSymKey key;
737 TempSym *elem;
738 TempSym *prev;
739
740 if (strtab_img == NULL || symtab_img == NULL) {
741 Char buf[80];
742 vg_assert(VG_(strlen)(tab_name) < 40);
743 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
744 ML_(symerr)(di, False, buf);
745 return;
746 }
747
748 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n",
749 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
750
751 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
752 (OSetCmp_t)cmp_TempSymKey,
753 ML_(dinfo_zalloc), "di.respl.1",
754 ML_(dinfo_free) );
755 vg_assert(oset);
756
757 /* Perhaps should start at i = 1; ELF docs suggest that entry
758 0 always denotes 'unknown symbol'. */
759 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
760 sym = & symtab_img[i];
761 sym_name = (Char*)(strtab_img + sym->st_name);
762 sym_svma = sym->st_value;
763
764 if (di->trace_symtab)
765 show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
766
767 if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
768 symtab_in_debug,
769 opd_img, di->text_bias,
770 &sym_name_really,
771 &sym_avma_really,
772 &sym_size,
773 &sym_tocptr,
774 &from_opd, &is_text, &is_ifunc)) {
775
776 /* Check if we've seen this (name,addr) key before. */
777 key.addr = sym_avma_really;
778 key.name = sym_name_really;
779 prev = VG_(OSetGen_Lookup)( oset, &key );
780
781 if (prev) {
782
783 /* Seen it before. Fold in whatever new info we can. */
784 modify_size = False;
785 modify_tocptr = False;
786 old_size = 0;
787
788 if (prev->from_opd && !from_opd
789 && (prev->size == 24 || prev->size == 16)
790 && sym_size != prev->size) {
791 /* Existing one is an opd-redirect, with a bogus size,
792 so the only useful new fact we have is the real size
793 of the symbol. */
794 modify_size = True;
795 old_size = prev->size;
796 prev->size = sym_size;
797 }
798 else
799 if (!prev->from_opd && from_opd
800 && (sym_size == 24 || sym_size == 16)) {
801 /* Existing one is non-opd, new one is opd. What we
802 can acquire from the new one is the TOC ptr to be
803 used. Since the existing sym is non-toc, it
804 shouldn't currently have an known TOC ptr. */
805 vg_assert(prev->tocptr == 0);
806 modify_tocptr = True;
807 prev->tocptr = sym_tocptr;
808 }
809 else {
810 /* ignore. can we do better here? */
811 }
812
813 /* Only one or the other is possible (I think) */
814 vg_assert(!(modify_size && modify_tocptr));
815
816 if (modify_size && di->trace_symtab) {
817 VG_(printf)(" modify (old sz %4d) "
818 " val %#010lx, toc %#010lx, sz %4d %s\n",
819 old_size,
820 prev->key.addr,
821 prev->tocptr,
822 (Int) prev->size,
823 (HChar*)prev->key.name
824 );
825 }
826 if (modify_tocptr && di->trace_symtab) {
827 VG_(printf)(" modify (upd tocptr) "
828 " val %#010lx, toc %#010lx, sz %4d %s\n",
829 prev->key.addr,
830 prev->tocptr,
831 (Int) prev->size,
832 (HChar*)prev->key.name
833 );
834 }
835
836 } else {
837
838 /* A new (name,addr) key. Add and continue. */
839 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
840 vg_assert(elem);
841 elem->key = key;
842 elem->tocptr = sym_tocptr;
843 elem->size = sym_size;
844 elem->from_opd = from_opd;
845 elem->is_text = is_text;
846 elem->is_ifunc = is_ifunc;
847 VG_(OSetGen_Insert)(oset, elem);
848 if (di->trace_symtab) {
849 VG_(printf)(" to-oset [%4ld]: "
850 " val %#010lx, toc %#010lx, sz %4d %s\n",
851 i,
852 elem->key.addr,
853 elem->tocptr,
854 (Int) elem->size,
855 (HChar*)elem->key.name
856 );
857 }
858
859 }
860 }
861 }
862
863 /* All the syms that matter are in the oset. Now pull them out,
864 build a "standard" symbol table, and nuke the oset. */
865
866 i = 0;
867 VG_(OSetGen_ResetIter)( oset );
868
869 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400870 disym.addr = elem->key.addr;
871 disym.tocptr = elem->tocptr;
872 disym.pri_name = ML_(addStr) ( di, elem->key.name, -1 );
873 disym.sec_names = NULL;
874 disym.size = elem->size;
875 disym.isText = elem->is_text;
876 disym.isIFunc = elem->is_ifunc;
877 vg_assert(disym.pri_name != NULL);
Jeff Browned07e002011-02-03 17:46:23 -0800878
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400879 ML_(addSym) ( di, &disym );
Jeff Browned07e002011-02-03 17:46:23 -0800880 if (di->trace_symtab) {
881 VG_(printf)(" rec(%c) [%4ld]: "
882 " val %#010lx, toc %#010lx, sz %4d %s\n",
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400883 disym.isText ? 't' : 'd',
Jeff Browned07e002011-02-03 17:46:23 -0800884 i,
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400885 disym.addr,
886 disym.tocptr,
887 (Int) disym.size,
888 (HChar*)disym.pri_name
Jeff Browned07e002011-02-03 17:46:23 -0800889 );
890 }
891 i++;
892 }
893
894 VG_(OSetGen_Destroy)( oset );
895}
896
897
898/*
899 * Look for a build-id in an ELF image. The build-id specification
900 * can be found here:
901 *
902 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
903 */
904static
Ben Cheng663860b2013-01-31 15:38:14 -0800905Char *find_buildid(Addr image, UWord n_image, Bool rel_ok)
Jeff Browned07e002011-02-03 17:46:23 -0800906{
907 Char* buildid = NULL;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400908 __attribute__((unused)) /* on Android, at least */
Jeff Browned07e002011-02-03 17:46:23 -0800909 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
910
911#ifdef NT_GNU_BUILD_ID
912 if (n_image >= sizeof(ElfXX_Ehdr) &&
Ben Cheng663860b2013-01-31 15:38:14 -0800913 ML_(is_elf_object_file)(ehdr, n_image, rel_ok)) {
Jeff Browned07e002011-02-03 17:46:23 -0800914 Word i;
915
916 for (i = 0; i < ehdr->e_phnum; i++) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400917 ElfXX_Phdr* phdr
918 = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize);
Jeff Browned07e002011-02-03 17:46:23 -0800919
920 if (phdr->p_type == PT_NOTE) {
921 ElfXX_Off offset = phdr->p_offset;
922
923 while (offset < phdr->p_offset + phdr->p_filesz) {
924 ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
925 Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
926 UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
927 Word j;
928
929 if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
930 note->n_type == NT_GNU_BUILD_ID) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400931 buildid = ML_(dinfo_zalloc)("di.fbi.1",
932 note->n_descsz * 2 + 1);
Jeff Browned07e002011-02-03 17:46:23 -0800933
934 for (j = 0; j < note->n_descsz; j++) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +0400935 VG_(sprintf)(buildid + VG_(strlen)(buildid),
936 "%02x", desc[j]);
Jeff Browned07e002011-02-03 17:46:23 -0800937 }
938 }
939
940 offset = offset + sizeof(ElfXX_Nhdr)
941 + ((note->n_namesz + 3) & ~3)
942 + ((note->n_descsz + 3) & ~3);
943 }
944 }
Ben Cheng663860b2013-01-31 15:38:14 -0800945 }
946
947 if (buildid || !rel_ok)
948 return buildid;
949
950 for (i = 0; i < ehdr->e_shnum; i++) {
951 ElfXX_Shdr* shdr
952 = (ElfXX_Shdr*)(image + ehdr->e_shoff + i * ehdr->e_shentsize);
953
954 if (shdr->sh_type == SHT_NOTE) {
955 ElfXX_Off offset = shdr->sh_offset;
956
957 while (offset < shdr->sh_offset + shdr->sh_size) {
958 ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
959 Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
960 UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
961 Word j;
962
963 if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
964 note->n_type == NT_GNU_BUILD_ID) {
965 buildid = ML_(dinfo_zalloc)("di.fbi.1",
966 note->n_descsz * 2 + 1);
967
968 for (j = 0; j < note->n_descsz; j++) {
969 VG_(sprintf)(buildid + VG_(strlen)(buildid),
970 "%02x", desc[j]);
971 }
972 }
973
974 offset = offset + sizeof(ElfXX_Nhdr)
975 + ((note->n_namesz + 3) & ~3)
976 + ((note->n_descsz + 3) & ~3);
977 }
978 }
979 }
Jeff Browned07e002011-02-03 17:46:23 -0800980 }
981#endif
982
983 return buildid;
984}
985
986/*
987 * This routine for calculating the CRC for a separate debug file
988 * is GPLed code borrowed from GNU binutils.
989 */
990static UInt
991calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
992{
993 static const UInt crc32_table[256] =
994 {
995 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
996 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
997 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
998 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
999 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
1000 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1001 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
1002 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
1003 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
1004 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
1005 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
1006 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1007 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
1008 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
1009 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
1010 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
1011 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
1012 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1013 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
1014 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
1015 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
1016 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
1017 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
1018 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1019 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
1020 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
1021 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
1022 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
1023 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
1024 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1025 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
1026 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
1027 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
1028 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
1029 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
1030 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1031 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
1032 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
1033 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
1034 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
1035 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
1036 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1037 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
1038 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
1039 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
1040 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
1041 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
1042 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1043 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
1044 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
1045 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
1046 0x2d02ef8d
1047 };
1048 const UChar *end;
1049
1050 crc = ~crc & 0xffffffff;
1051 for (end = buf + len; buf < end; ++ buf)
1052 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1053 return ~crc & 0xffffffff;;
1054}
1055
1056/*
1057 * Try and open a separate debug file, ignoring any where the CRC does
1058 * not match the value from the main object file.
1059 */
1060static
Ben Cheng663860b2013-01-31 15:38:14 -08001061Addr open_debug_file( Char* name, Char* buildid, UInt crc, Bool rel_ok,
1062 /*OUT*/UWord* size )
Jeff Browned07e002011-02-03 17:46:23 -08001063{
1064 SysRes fd, sres;
1065 struct vg_stat stat_buf;
1066 UInt calccrc;
1067
1068 fd = VG_(open)(name, VKI_O_RDONLY, 0);
1069 if (sr_isError(fd))
1070 return 0;
1071
1072 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1073 VG_(close)(sr_Res(fd));
1074 return 0;
1075 }
1076
1077 if (VG_(clo_verbosity) > 1)
1078 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1079
1080 *size = stat_buf.size;
1081
1082 sres = VG_(am_mmap_file_float_valgrind)
1083 ( *size, VKI_PROT_READ, sr_Res(fd), 0 );
1084
1085 VG_(close)(sr_Res(fd));
1086
1087 if (sr_isError(sres))
1088 return 0;
1089
1090 if (buildid) {
Ben Cheng663860b2013-01-31 15:38:14 -08001091 Char* debug_buildid = find_buildid(sr_Res(sres), *size, rel_ok);
Jeff Browned07e002011-02-03 17:46:23 -08001092 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1093 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1094 vg_assert(!sr_isError(res));
1095 if (VG_(clo_verbosity) > 1)
1096 VG_(message)(Vg_DebugMsg,
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001097 " .. build-id mismatch (found %s wanted %s)\n",
1098 debug_buildid, buildid);
Jeff Browned07e002011-02-03 17:46:23 -08001099 ML_(dinfo_free)(debug_buildid);
1100 return 0;
1101 }
1102 ML_(dinfo_free)(debug_buildid);
1103
1104 if (VG_(clo_verbosity) > 1)
1105 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1106 } else {
1107 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
1108 if (calccrc != crc) {
1109 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1110 vg_assert(!sr_isError(res));
1111 if (VG_(clo_verbosity) > 1)
1112 VG_(message)(Vg_DebugMsg,
1113 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1114 return 0;
1115 }
1116
1117 if (VG_(clo_verbosity) > 1)
1118 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1119 }
1120
1121 return sr_Res(sres);
1122}
1123
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001124
1125/* Try to find and map in a debuginfo file by some totally ad-hoc
1126 scheme. If successful, set *dimage and *n_dimage to point to the
1127 image, and return True, else return False. A temporary hack for
1128 Android; does nothing on any other platform. */
Jeff Browned07e002011-02-03 17:46:23 -08001129static
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001130Bool find_ad_hoc_debug_image( struct _DebugInfo* di,
1131 Char* filename,
1132 /*OUT*/Addr* dimage,
1133 /*OUT*/SizeT* n_dimage )
1134{
1135 vg_assert(*dimage == 0 && *n_dimage == 0);
1136
Ben Cheng663860b2013-01-31 15:38:14 -08001137# if !defined(VGPV_arm_linux_android) && !defined(VGPV_x86_linux_android)
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001138 return False; /* we don't know narfink */
1139
1140# else /* android specific hacks; look away now. */
1141
1142 /* The deal is: if we're looking for for a debuginfo file for some
Ben Cheng663860b2013-01-31 15:38:14 -08001143 object /path/to/object (which can be any path), see if we can
1144 find the file /sdcard/symbols/path/to/object. So for example it
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001145 produces the following mappings, both of which are important for
1146 Memcheck:
1147
1148 /system/bin/linker --> /sdcard/symbols/system/bin/linker
1149 /system/lib/libc.so --> /sdcard/symbols/system/lib/libc.so
1150
1151 These /symbols files come from the AOSP build tree for your
1152 device, for example out/target/product/crespo/symbols/system
1153 (for a Nexus S), so one simple thing you can do is take the tree
1154 rooted at out/target/product/crespo/symbols/system on the host
1155 and park it at /sdcard/symbols/system on the device. Then,
1156 assuming it matches what's actually running on the device,
1157 you'll have full debuginfo for all the libraries on the device.
1158
1159 But beware: there is no checking that the debuginfo file, if
1160 found, matches the main file in any way.
1161 */
Ben Cheng663860b2013-01-31 15:38:14 -08001162 if (!filename || *filename != '/')
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001163 return False;
1164
1165 HChar* nm = ML_(dinfo_zalloc)("di.fahdi.1",
1166 50 + VG_(strlen)(filename));
1167 VG_(sprintf)(nm, "/sdcard/symbols%s", filename);
1168
1169 SysRes fd = VG_(open)(nm, VKI_O_RDONLY, 0);
1170 if (sr_isError(fd)) goto fail;
1171
1172 struct vg_stat stat_buf;
1173 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1174 VG_(close)(sr_Res(fd));
1175 goto fail;
1176 }
1177
1178 *n_dimage = stat_buf.size;
1179
1180 SysRes sres = VG_(am_mmap_file_float_valgrind)
1181 ( *n_dimage, VKI_PROT_READ, sr_Res(fd), 0 );
1182
1183 VG_(close)(sr_Res(fd));
1184 if (sr_isError(sres))
1185 goto fail;
1186
1187 *dimage = sr_Res(sres);
1188
1189 if (VG_(clo_verbosity) > 1)
1190 VG_(dmsg)(" Using debuginfo from %s\n", nm);
1191
1192 ML_(dinfo_free)(nm);
1193 return True;
1194
1195 fail:
1196 if (nm) ML_(dinfo_free)(nm);
1197 return False;
1198
1199# endif
1200}
1201
1202
1203/* Try to find a separate debug file for a given object file. If
1204 found, it will be mapped in and the address and size returned in
1205 *dimage and *n_dimage. If not, *dimage and *n_dimage will be
1206 unchanged. The caller should set them to zero before the call. */
1207static
1208void find_debug_file( struct _DebugInfo* di,
Jeff Browned07e002011-02-03 17:46:23 -08001209 Char* objpath, Char* buildid,
Ben Cheng663860b2013-01-31 15:38:14 -08001210 Char* debugname, UInt crc, Bool rel_ok,
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001211 /*OUT*/Addr* dimage,
1212 /*OUT*/SizeT* n_dimage )
Jeff Browned07e002011-02-03 17:46:23 -08001213{
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001214 Char* debugpath = NULL;
1215 Addr addr = 0;
1216 UWord size = 0;
1217
1218 vg_assert(*dimage == 0 && *n_dimage == 0);
Jeff Browned07e002011-02-03 17:46:23 -08001219
1220 if (buildid != NULL) {
1221 debugpath = ML_(dinfo_zalloc)(
1222 "di.fdf.1",
1223 VG_(strlen)(buildid) + 33);
1224
1225 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1226 buildid[0], buildid[1], buildid + 2);
1227
Ben Cheng663860b2013-01-31 15:38:14 -08001228 if ((addr = open_debug_file(debugpath, buildid, 0,
1229 rel_ok, &size)) == 0) {
Jeff Browned07e002011-02-03 17:46:23 -08001230 ML_(dinfo_free)(debugpath);
1231 debugpath = NULL;
1232 }
1233 }
1234
Ben Cheng663860b2013-01-31 15:38:14 -08001235 if (addr == 0 && debugname != NULL && !rel_ok) {
Jeff Browned07e002011-02-03 17:46:23 -08001236 Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1237 Char *objdirptr;
1238
1239 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1240 *objdirptr = '\0';
1241
1242 debugpath = ML_(dinfo_zalloc)(
1243 "di.fdf.3",
1244 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
1245
1246 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1247
Ben Cheng663860b2013-01-31 15:38:14 -08001248 if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
Jeff Browned07e002011-02-03 17:46:23 -08001249 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
Ben Cheng663860b2013-01-31 15:38:14 -08001250 if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
Jeff Browned07e002011-02-03 17:46:23 -08001251 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
Ben Cheng753e0692013-02-01 11:28:22 -08001252 if ((addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size)) == 0) {
1253#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
1254 VG_(sprintf)(debugpath, "/data/local/symbols%s/%s", objdir,
1255 debugname);
1256 addr = open_debug_file(debugpath, NULL, crc, rel_ok, &size);
1257#endif
1258 }
Jeff Browned07e002011-02-03 17:46:23 -08001259 }
1260 }
1261
1262 ML_(dinfo_free)(objdir);
1263 }
1264
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001265 if (addr > 0 && size > 0) {
Jeff Browned07e002011-02-03 17:46:23 -08001266 TRACE_SYMTAB("\n");
1267 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001268 *dimage = addr;
1269 *n_dimage = size;
Jeff Browned07e002011-02-03 17:46:23 -08001270 }
1271
1272 ML_(dinfo_free)(debugpath);
Jeff Browned07e002011-02-03 17:46:23 -08001273}
1274
1275
1276static Bool contained_within ( Addr outer, UWord n_outer,
1277 Addr inner, UWord n_inner )
1278{
1279 if (n_outer == 0 || n_inner == 0)
1280 return False;
1281 /* Simplistic .. assumes no wraparound (reasonably enough) */
1282 if (inner >= outer && inner+n_inner <= outer+n_outer)
1283 return True;
1284 return False;
1285}
1286
1287static void* INDEX_BIS ( void* base, Word idx, Word scale ) {
1288 return (void*)( ((UChar*)base) + idx * scale );
1289}
1290
1291
1292/* Find the file offset corresponding to SVMA by using the program
1293 headers. This is taken from binutils-2.17/binutils/readelf.c
1294 offset_from_vma(). */
1295static
1296Word file_offset_from_svma ( /*OUT*/Bool* ok,
1297 Addr svma,
1298 ElfXX_Phdr* phdr_img,
1299 Word phdr_nent,
1300 Word phdr_ent_szB )
1301{
1302 Word i;
1303 ElfXX_Phdr* seg;
1304 for (i = 0; i < phdr_nent; i++) {
1305 seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1306 if (seg->p_type != PT_LOAD)
1307 continue;
1308 if (svma >= (seg->p_vaddr & -seg->p_align)
1309 && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
1310 *ok = True;
1311 return svma - seg->p_vaddr + seg->p_offset;
1312 }
1313 }
1314 *ok = False;
1315 return 0;
1316}
1317
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001318
Jeff Browned07e002011-02-03 17:46:23 -08001319/* The central function for reading ELF debug info. For the
1320 object/exe specified by the DebugInfo, find ELF sections, then read
1321 the symbols, line number info, file name info, CFA (stack-unwind
1322 info) and anything else we want, into the tables within the
1323 supplied DebugInfo.
1324*/
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001325
Jeff Browned07e002011-02-03 17:46:23 -08001326Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1327{
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001328 /* This function is long and complex. That, and the presence of
1329 nested scopes, means it's not always easy to see which parts are
1330 in loops/conditionals and which aren't. To make it easier to
1331 follow, points executed exactly once -- that is, those which are
1332 the top level of the function -- are marked TOPLEVEL.
1333 */
1334 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08001335 Bool res, ok;
1336 SysRes fd, sres;
Ben Cheng663860b2013-01-31 15:38:14 -08001337 Word i, j;
Jeff Browned07e002011-02-03 17:46:23 -08001338 Bool dynbss_present = False;
1339 Bool sdynbss_present = False;
1340
1341 /* Image addresses for the ELF file we're working with. */
1342 Addr oimage = 0;
1343 UWord n_oimage = 0;
1344
1345 /* Ditto for any ELF debuginfo file that we might happen to load. */
1346 Addr dimage = 0;
1347 UWord n_dimage = 0;
1348
Ben Cheng663860b2013-01-31 15:38:14 -08001349 /* Ditto for alternate ELF debuginfo file that we might happen to load. */
1350 Addr aimage = 0;
1351 UWord n_aimage = 0;
1352
Jeff Browned07e002011-02-03 17:46:23 -08001353 /* ELF header for the main file. Should == oimage since is at
1354 start of file. */
1355 ElfXX_Ehdr* ehdr_img = NULL;
1356
1357 /* Program header table image addr, # entries, entry size */
1358 ElfXX_Phdr* phdr_img = NULL;
1359 UWord phdr_nent = 0;
1360 UWord phdr_ent_szB = 0;
1361
1362 /* Section header image addr, # entries, entry size. Also the
1363 associated string table. */
1364 ElfXX_Shdr* shdr_img = NULL;
1365 UWord shdr_nent = 0;
1366 UWord shdr_ent_szB = 0;
1367 UChar* shdr_strtab_img = NULL;
1368
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001369 /* SVMAs covered by rx and rw segments and corresponding biases.
Ben Cheng663860b2013-01-31 15:38:14 -08001370 Normally each object would provide just one rx and one rw area,
1371 but various ELF mangling tools create objects with multiple
1372 such entries, hence the generality. */
1373 typedef
1374 struct {
1375 Addr svma_base;
1376 Addr svma_limit;
1377 PtrdiffT bias;
1378 Bool exec;
1379 }
1380 RangeAndBias;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001381
Ben Cheng663860b2013-01-31 15:38:14 -08001382 XArray* /* of RangeAndBias */ svma_ranges = NULL;
Jeff Browned07e002011-02-03 17:46:23 -08001383
1384 /* Build ID */
1385 Char* buildid = NULL;
1386
1387 vg_assert(di);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001388 vg_assert(di->fsm.have_rx_map == True);
1389 vg_assert(di->fsm.have_rw_map == True);
Jeff Browned07e002011-02-03 17:46:23 -08001390 vg_assert(di->have_dinfo == False);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001391 vg_assert(di->fsm.filename);
Jeff Browned07e002011-02-03 17:46:23 -08001392 vg_assert(!di->symtab);
1393 vg_assert(!di->loctab);
1394 vg_assert(!di->cfsi);
1395 vg_assert(!di->cfsi_exprs);
1396 vg_assert(!di->strchunks);
1397 vg_assert(!di->soname);
1398
Ben Cheng663860b2013-01-31 15:38:14 -08001399 {
1400 Bool has_nonempty_rx = False;
1401 Bool has_nonempty_rw = False;
1402 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1403 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1404 if (!map->rx && !map->rw)
1405 continue;
1406 if (map->rx && map->size > 0)
1407 has_nonempty_rx = True;
1408 if (map->rw && map->size > 0)
1409 has_nonempty_rw = True;
1410 /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr
1411 managed to do a mapping where the start isn't page aligned.
1412 Which sounds pretty bogus to me. */
1413 vg_assert(VG_IS_PAGE_ALIGNED(map->avma));
1414 }
1415 vg_assert(has_nonempty_rx);
1416 vg_assert(has_nonempty_rw);
1417 }
Jeff Browned07e002011-02-03 17:46:23 -08001418
1419 /* ----------------------------------------------------------
1420 At this point, there is very little information in the
1421 DebugInfo. We only know that something that looks like an ELF
Ben Cheng663860b2013-01-31 15:38:14 -08001422 file has been mapped rx-ishly and rw-ishly as recorded in the
1423 di->fsm.maps array items. First we examine the file's ELF
1424 Program Header, and, by comparing that against the di->fsm.maps
Jeff Browned07e002011-02-03 17:46:23 -08001425 info, try to figure out the AVMAs for the sections we care
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001426 about, that should have been mapped: text, data, sdata, bss,
1427 got, plt, and toc.
Jeff Browned07e002011-02-03 17:46:23 -08001428 ---------------------------------------------------------- */
1429
1430 res = False;
1431
1432 oimage = (Addr)NULL;
1433 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
Ben Cheng663860b2013-01-31 15:38:14 -08001434 VG_(message)(Vg_DebugMsg, "Reading syms from %s\n",
1435 di->fsm.filename );
Jeff Browned07e002011-02-03 17:46:23 -08001436
1437 /* mmap the object image aboard, so that we can read symbols and
1438 line number info out of it. It will be munmapped immediately
1439 thereafter; it is only aboard transiently. */
1440
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001441 fd = VG_(open)(di->fsm.filename, VKI_O_RDONLY, 0);
Jeff Browned07e002011-02-03 17:46:23 -08001442 if (sr_isError(fd)) {
1443 ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
1444 return False;
1445 }
1446
1447 { Long n_oimageLL = VG_(fsize)(sr_Res(fd));
1448 if (n_oimageLL <= 0) {
1449 ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
1450 VG_(close)(sr_Res(fd));
1451 return False;
1452 }
1453 n_oimage = (UWord)(ULong)n_oimageLL;
1454 }
1455
1456 sres = VG_(am_mmap_file_float_valgrind)
1457 ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 );
1458
1459 VG_(close)(sr_Res(fd));
1460
1461 if (sr_isError(sres)) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001462 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s\n",
1463 di->fsm.filename );
Jeff Browned07e002011-02-03 17:46:23 -08001464 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
1465 return False;
1466 }
1467
1468 oimage = sr_Res(sres);
1469 /* Check against wraparound. am_mmap_file_float_valgrind should
1470 not produce a wrapped-around mapping. */
1471 vg_assert(n_oimage > 0);
1472 vg_assert(oimage + n_oimage > oimage);
1473
1474 if (0) {
1475 VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n",
1476 (void*)oimage, (void*)(oimage + (UWord)n_oimage));
1477 }
1478
1479 /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now
1480 verify that it is a valid ELF .so or executable image. */
1481 res = False;
1482 ok = (n_oimage >= sizeof(ElfXX_Ehdr));
1483 ehdr_img = (ElfXX_Ehdr*)oimage;
1484
1485 if (ok)
Ben Cheng663860b2013-01-31 15:38:14 -08001486 ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage, False);
Jeff Browned07e002011-02-03 17:46:23 -08001487
1488 if (!ok) {
1489 ML_(symerr)(di, True, "Invalid ELF Header");
1490 goto out;
1491 }
1492
1493 /* Find where the program and section header tables are, and give
1494 up if either is missing or outside the image (bogus). */
1495 phdr_img = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
1496 phdr_nent = ehdr_img->e_phnum;
1497 phdr_ent_szB = ehdr_img->e_phentsize;
1498
1499 shdr_img = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
1500 shdr_nent = ehdr_img->e_shnum;
1501 shdr_ent_szB = ehdr_img->e_shentsize;
1502
1503 TRACE_SYMTAB("------ Basic facts about the object ------\n");
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001504 TRACE_SYMTAB("object: img %p n_oimage %ld\n",
Jeff Browned07e002011-02-03 17:46:23 -08001505 (void*)oimage, n_oimage);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001506 TRACE_SYMTAB("phdr: img %p nent %ld ent_szB %ld\n",
Jeff Browned07e002011-02-03 17:46:23 -08001507 phdr_img, phdr_nent, phdr_ent_szB);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001508 TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n",
Jeff Browned07e002011-02-03 17:46:23 -08001509 shdr_img, shdr_nent, shdr_ent_szB);
Ben Cheng663860b2013-01-31 15:38:14 -08001510 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1511 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1512 if (map->rx)
1513 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n",
1514 map->avma, map->size, map->foff);
1515 }
1516 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1517 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1518 if (map->rw)
1519 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n",
1520 map->avma, map->size, map->foff);
1521 }
Jeff Browned07e002011-02-03 17:46:23 -08001522
1523 if (phdr_nent == 0
1524 || !contained_within(
1525 oimage, n_oimage,
1526 (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
1527 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1528 goto out;
1529 }
1530
1531 if (shdr_nent == 0
1532 || !contained_within(
1533 oimage, n_oimage,
1534 (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
1535 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1536 goto out;
1537 }
1538
1539 /* Also find the section header's string table, and validate. */
1540 /* checked previously by is_elf_object_file: */
1541 vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
1542
1543 shdr_strtab_img
1544 = (UChar*)( ((UChar*)ehdr_img)
1545 + shdr_img[ehdr_img->e_shstrndx].sh_offset);
1546 if (!contained_within( oimage, n_oimage,
1547 (Addr)shdr_strtab_img,
1548 1/*bogus, but we don't know the real size*/ )) {
1549 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1550 goto out;
1551 }
1552
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001553 TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img );
Jeff Browned07e002011-02-03 17:46:23 -08001554
Ben Cheng663860b2013-01-31 15:38:14 -08001555 svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1",
1556 ML_(dinfo_free), sizeof(RangeAndBias));
1557
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001558 /* TOPLEVEL */
1559 /* Look through the program header table, and:
Ben Cheng663860b2013-01-31 15:38:14 -08001560 - copy information from suitable PT_LOAD entries into svma_ranges
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001561 - find (or fake up) the .soname for this object.
1562 */
Jeff Browned07e002011-02-03 17:46:23 -08001563 TRACE_SYMTAB("\n");
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001564 TRACE_SYMTAB("------ Examining the program headers ------\n");
Jeff Browned07e002011-02-03 17:46:23 -08001565 vg_assert(di->soname == NULL);
1566 {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001567 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08001568 ElfXX_Addr prev_svma = 0;
1569
1570 for (i = 0; i < phdr_nent; i++) {
1571 ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1572
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001573 /* Make sure the PT_LOADable entries are in order and
1574 non-overlapping. This in turn means the address ranges
Ben Cheng663860b2013-01-31 15:38:14 -08001575 slurped into svma_ranges are in order and
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001576 non-overlapping. */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001577
Jeff Browned07e002011-02-03 17:46:23 -08001578 if (phdr->p_type == PT_LOAD) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001579 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
1580 i, (UWord)phdr->p_vaddr, (UWord)prev_svma);
1581 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
1582 " perms %c%c%c\n",
1583 i, (UWord)phdr->p_offset, (UWord)phdr->p_filesz,
1584 phdr->p_flags & PF_R ? 'r' : '-',
1585 phdr->p_flags & PF_W ? 'w' : '-',
1586 phdr->p_flags & PF_X ? 'x' : '-');
Jeff Browned07e002011-02-03 17:46:23 -08001587 if (phdr->p_vaddr < prev_svma) {
1588 ML_(symerr)(di, True,
1589 "ELF Program Headers are not in ascending order");
1590 goto out;
1591 }
1592 prev_svma = phdr->p_vaddr;
Ben Cheng663860b2013-01-31 15:38:14 -08001593 if (phdr->p_memsz > 0) {
1594 Bool loaded = False;
1595 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
1596 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
1597 if ( (map->rx || map->rw)
1598 && phdr->p_offset >= map->foff
1599 && phdr->p_offset < map->foff + map->size
1600 && phdr->p_offset + phdr->p_filesz <= map->foff
1601 + map->size) {
1602 RangeAndBias item;
1603 item.svma_base = phdr->p_vaddr;
1604 item.svma_limit = phdr->p_vaddr + phdr->p_memsz;
1605 item.bias = map->avma - map->foff
1606 + phdr->p_offset - phdr->p_vaddr;
1607 if ( map->rw
1608 && (phdr->p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) {
1609 item.exec = False;
1610 VG_(addToXA)(svma_ranges, &item);
1611 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i);
1612 loaded = True;
1613 }
1614 if ( map->rx
1615 && (phdr->p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) {
1616 item.exec = True;
1617 VG_(addToXA)(svma_ranges, &item);
1618 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i);
1619 loaded = True;
1620 }
1621 }
1622 }
1623 if (!loaded) {
1624 ML_(symerr)(di, False,
1625 "ELF section outside all mapped regions");
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001626 goto out;
1627 }
Jeff Browned07e002011-02-03 17:46:23 -08001628 }
1629 }
1630
1631 /* Try to get the soname. If there isn't one, use "NONE".
1632 The seginfo needs to have some kind of soname in order to
1633 facilitate writing redirect functions, since all redirect
1634 specifications require a soname (pattern). */
1635 if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
1636 ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
1637 + phdr->p_offset);
1638 Word stroff = -1;
1639 UChar* strtab = NULL;
Jeff Browned07e002011-02-03 17:46:23 -08001640 for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
1641 switch (dyn_img[j].d_tag) {
1642 case DT_SONAME: {
1643 stroff = dyn_img[j].d_un.d_val;
1644 break;
1645 }
1646 case DT_STRTAB: {
1647 Bool ok2 = False;
1648 Word offset = file_offset_from_svma(
1649 &ok2,
1650 dyn_img[j].d_un.d_ptr,
1651 phdr_img,
1652 phdr_nent, phdr_ent_szB
1653 );
1654 if (ok2 && strtab == NULL) {
1655 vg_assert(offset >= 0 && offset <= n_oimage);
1656 strtab = ((UChar*)ehdr_img) + offset;
1657 }
1658 break;
1659 }
1660 default:
1661 break;
1662 }
1663 }
1664 if (stroff != -1 && strtab != NULL) {
1665 TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
1666 di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff);
1667 }
1668 }
1669 } /* for (i = 0; i < phdr_nent; i++) ... */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001670 /* TOPLEVEL */
1671
1672 } /* examine the program headers (local scope) */
1673
1674 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08001675
1676 /* If, after looking at all the program headers, we still didn't
1677 find a soname, add a fake one. */
1678 if (di->soname == NULL) {
1679 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
Ben Cheng663860b2013-01-31 15:38:14 -08001680 di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE");
Jeff Browned07e002011-02-03 17:46:23 -08001681 }
1682
Ben Cheng663860b2013-01-31 15:38:14 -08001683 vg_assert(VG_(sizeXA)(svma_ranges) != 0);
Jeff Browned07e002011-02-03 17:46:23 -08001684
1685 /* Now read the section table. */
1686 TRACE_SYMTAB("\n");
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001687 TRACE_SYMTAB("------ Examining the section headers ------\n");
Ben Cheng663860b2013-01-31 15:38:14 -08001688 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1689 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1690 if (map->rx)
1691 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1692 map->avma, map->foff, map->foff + map->size - 1 );
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001693 }
Ben Cheng663860b2013-01-31 15:38:14 -08001694 TRACE_SYMTAB("rx: contains these svma regions:\n");
1695 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1696 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1697 if (reg->exec)
1698 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
1699 reg->svma_base, reg->svma_limit - 1, reg->bias );
1700 }
1701 for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
1702 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
1703 if (map->rw)
1704 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1705 map->avma, map->foff, map->foff + map->size - 1 );
1706 }
1707 TRACE_SYMTAB("rw: contains these svma regions:\n");
1708 for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
1709 RangeAndBias* reg = VG_(indexXA)(svma_ranges, i);
1710 if (!reg->exec)
1711 TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n",
1712 reg->svma_base, reg->svma_limit - 1, reg->bias );
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001713 }
Jeff Browned07e002011-02-03 17:46:23 -08001714
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001715 /* TOPLEVEL */
1716 /* Iterate over section headers */
Jeff Browned07e002011-02-03 17:46:23 -08001717 for (i = 0; i < shdr_nent; i++) {
1718 ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
1719 UChar* name = shdr_strtab_img + shdr->sh_name;
1720 Addr svma = shdr->sh_addr;
1721 OffT foff = shdr->sh_offset;
1722 UWord size = shdr->sh_size;
1723 UInt alyn = shdr->sh_addralign;
1724 Bool bits = !(shdr->sh_type == SHT_NOBITS);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001725 /* Look through our collection of info obtained from the PT_LOAD
1726 headers, and make 'inrx' and 'inrw' point to the first entry
1727 in each that intersects 'avma'. If in each case none is found,
1728 leave the relevant pointer at NULL. */
1729 RangeAndBias* inrx = NULL;
1730 RangeAndBias* inrw = NULL;
Ben Cheng663860b2013-01-31 15:38:14 -08001731 for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) {
1732 RangeAndBias* rng = VG_(indexXA)(svma_ranges, j);
1733 if (svma >= rng->svma_base && svma < rng->svma_limit) {
1734 if (!inrx && rng->exec) {
1735 inrx = rng;
1736 } else if (!inrw && !rng->exec) {
1737 inrw = rng;
1738 }
1739 if (inrx && inrw)
1740 break;
1741 }
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001742 }
Jeff Browned07e002011-02-03 17:46:23 -08001743
1744 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld "
1745 " svma %p name \"%s\"\n",
1746 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn,
1747 foff, foff+size-1, (void*)svma, name );
1748
1749 /* Check for sane-sized segments. SHT_NOBITS sections have zero
1750 size in the file. */
Ben Cheng663860b2013-01-31 15:38:14 -08001751 if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) {
Jeff Browned07e002011-02-03 17:46:23 -08001752 ML_(symerr)(di, True, "ELF Section extends beyond image end");
1753 goto out;
1754 }
1755
1756 /* Check for a sane alignment value. */
1757 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1758 ML_(symerr)(di, True, "ELF Section contains invalid "
1759 ".sh_addralign value");
1760 goto out;
1761 }
1762
1763# define BAD(_secname) \
1764 do { ML_(symerr)(di, True, \
1765 "Can't make sense of " _secname \
1766 " section mapping"); \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001767 /* make sure we don't assert if we find */ \
1768 /* ourselves back in this routine later, */ \
1769 /* with the same di */ \
1770 di->soname = NULL; \
Jeff Browned07e002011-02-03 17:46:23 -08001771 goto out; \
1772 } while (0)
1773
1774 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
1775 and .eh_frame */
1776
1777 /* Accept .text where mapped as rx (code), even if zero-sized */
1778 if (0 == VG_(strcmp)(name, ".text")) {
1779 if (inrx && size >= 0 && !di->text_present) {
1780 di->text_present = True;
1781 di->text_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001782 di->text_avma = svma + inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001783 di->text_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001784 di->text_bias = inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001785 di->text_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001786 di->text_debug_bias = inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001787 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
1788 di->text_svma,
1789 di->text_svma + di->text_size - 1);
1790 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
1791 di->text_avma,
1792 di->text_avma + di->text_size - 1);
1793 TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
1794 } else {
1795 BAD(".text");
1796 }
1797 }
1798
1799 /* Accept .data where mapped as rw (data), even if zero-sized */
1800 if (0 == VG_(strcmp)(name, ".data")) {
1801 if (inrw && size >= 0 && !di->data_present) {
1802 di->data_present = True;
1803 di->data_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001804 di->data_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001805 di->data_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001806 di->data_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001807 di->data_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001808 di->data_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001809 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
1810 di->data_svma,
1811 di->data_svma + di->data_size - 1);
1812 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
1813 di->data_avma,
1814 di->data_avma + di->data_size - 1);
1815 TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
1816 } else {
1817 BAD(".data");
1818 }
1819 }
1820
1821 /* Accept .sdata where mapped as rw (data) */
1822 if (0 == VG_(strcmp)(name, ".sdata")) {
1823 if (inrw && size > 0 && !di->sdata_present) {
1824 di->sdata_present = True;
1825 di->sdata_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001826 di->sdata_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001827 di->sdata_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001828 di->sdata_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001829 di->sdata_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001830 di->sdata_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001831 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
1832 di->sdata_svma,
1833 di->sdata_svma + di->sdata_size - 1);
1834 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
1835 di->sdata_avma,
1836 di->sdata_avma + di->sdata_size - 1);
1837 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
1838 } else {
1839 BAD(".sdata");
1840 }
1841 }
1842
1843 /* Accept .rodata where mapped as rx (data), even if zero-sized */
1844 if (0 == VG_(strcmp)(name, ".rodata")) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001845 if (inrx && size >= 0 && !di->rodata_present) {
Jeff Browned07e002011-02-03 17:46:23 -08001846 di->rodata_present = True;
1847 di->rodata_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001848 di->rodata_avma = svma + inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001849 di->rodata_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001850 di->rodata_bias = inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001851 di->rodata_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001852 di->rodata_debug_bias = inrx->bias;
1853 /* NB was 'inrw' prior to r11794 */
Jeff Browned07e002011-02-03 17:46:23 -08001854 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
1855 di->rodata_svma,
1856 di->rodata_svma + di->rodata_size - 1);
1857 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
1858 di->rodata_avma,
1859 di->rodata_avma + di->rodata_size - 1);
1860 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias);
1861 } else {
1862 BAD(".rodata");
1863 }
1864 }
1865
1866 if (0 == VG_(strcmp)(name, ".dynbss")) {
1867 if (inrw && size > 0 && !di->bss_present) {
1868 dynbss_present = True;
1869 di->bss_present = True;
1870 di->bss_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001871 di->bss_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001872 di->bss_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001873 di->bss_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001874 di->bss_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001875 di->bss_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001876 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
1877 di->bss_svma,
1878 di->bss_svma + di->bss_size - 1);
1879 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
1880 di->bss_avma,
1881 di->bss_avma + di->bss_size - 1);
1882 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias);
1883 }
1884 }
1885
1886 /* Accept .bss where mapped as rw (data), even if zero-sized */
1887 if (0 == VG_(strcmp)(name, ".bss")) {
1888 if (inrw && size > 0 && dynbss_present) {
1889 vg_assert(di->bss_present);
1890 dynbss_present = False;
1891 vg_assert(di->bss_svma + di->bss_size == svma);
1892 di->bss_size += size;
1893 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1894 svma, svma + size - 1);
1895 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001896 svma + inrw->bias, svma + inrw->bias + size - 1);
Jeff Browned07e002011-02-03 17:46:23 -08001897 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1898 } else
1899
1900 if (inrw && size >= 0 && !di->bss_present) {
1901 di->bss_present = True;
1902 di->bss_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001903 di->bss_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001904 di->bss_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001905 di->bss_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001906 di->bss_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001907 di->bss_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001908 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1909 di->bss_svma,
1910 di->bss_svma + di->bss_size - 1);
1911 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1912 di->bss_avma,
1913 di->bss_avma + di->bss_size - 1);
1914 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1915 } else
1916
1917 /* Now one from the wtf?! department ... */
1918 if (inrx && (!inrw) && size >= 0 && !di->bss_present) {
1919 /* File contains a .bss, but it got mapped as rx only.
1920 This is very strange. For now, just pretend we didn't
1921 see it :-) */
1922 di->bss_present = False;
1923 di->bss_svma = 0;
1924 di->bss_avma = 0;
1925 di->bss_size = 0;
1926 di->bss_bias = 0;
1927 di->bss_debug_svma = 0;
1928 di->bss_debug_bias = 0;
1929 if (!VG_(clo_xml)) {
1930 VG_(message)(Vg_UserMsg,
1931 "Warning: the following file's .bss is "
1932 "mapped r-x only - ignoring .bss syms\n");
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001933 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
1934 ? di->fsm.filename
Jeff Browned07e002011-02-03 17:46:23 -08001935 : (UChar*)"(null?!)" );
1936 }
1937 } else
1938
1939 if ((!inrw) && (!inrx) && size >= 0 && !di->bss_present) {
1940 /* File contains a .bss, but it didn't get mapped. Ignore. */
1941 di->bss_present = False;
1942 di->bss_svma = 0;
1943 di->bss_avma = 0;
1944 di->bss_size = 0;
1945 di->bss_bias = 0;
1946 } else {
1947 BAD(".bss");
1948 }
1949 }
1950
1951 if (0 == VG_(strcmp)(name, ".sdynbss")) {
1952 if (inrw && size >= 0 && !di->sbss_present) {
1953 sdynbss_present = True;
1954 di->sbss_present = True;
1955 di->sbss_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001956 di->sbss_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001957 di->sbss_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001958 di->sbss_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001959 di->sbss_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001960 di->sbss_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001961 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
1962 di->sbss_svma,
1963 di->sbss_svma + di->sbss_size - 1);
1964 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
1965 di->sbss_avma,
1966 di->sbss_avma + di->sbss_size - 1);
1967 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias);
1968 }
1969 }
1970
1971 /* Accept .sbss where mapped as rw (data) */
1972 if (0 == VG_(strcmp)(name, ".sbss")) {
1973 if (inrw && size > 0 && sdynbss_present) {
1974 vg_assert(di->sbss_present);
1975 sdynbss_present = False;
1976 vg_assert(di->sbss_svma + di->sbss_size == svma);
1977 di->sbss_size += size;
1978 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1979 svma, svma + size - 1);
1980 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001981 svma + inrw->bias, svma + inrw->bias + size - 1);
Jeff Browned07e002011-02-03 17:46:23 -08001982 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
1983 } else
1984
1985 if (inrw && size > 0 && !di->sbss_present) {
1986 di->sbss_present = True;
1987 di->sbss_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001988 di->sbss_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001989 di->sbss_size = size;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001990 di->sbss_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001991 di->sbss_debug_svma = svma;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04001992 di->sbss_debug_bias = inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08001993 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1994 di->sbss_svma,
1995 di->sbss_svma + di->sbss_size - 1);
1996 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
1997 di->sbss_avma,
1998 di->sbss_avma + di->sbss_size - 1);
1999 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
2000 } else {
2001 BAD(".sbss");
2002 }
2003 }
2004
2005 /* Accept .got where mapped as rw (data) */
2006 if (0 == VG_(strcmp)(name, ".got")) {
2007 if (inrw && size > 0 && !di->got_present) {
2008 di->got_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002009 di->got_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002010 di->got_size = size;
2011 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
2012 } else {
2013 BAD(".got");
2014 }
2015 }
2016
2017 /* Accept .got.plt where mapped as rw (data) */
2018 if (0 == VG_(strcmp)(name, ".got.plt")) {
2019 if (inrw && size > 0 && !di->gotplt_present) {
2020 di->gotplt_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002021 di->gotplt_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002022 di->gotplt_size = size;
2023 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
2024 } else if (size != 0) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002025 BAD(".got.plt");
Jeff Browned07e002011-02-03 17:46:23 -08002026 }
2027 }
2028
2029 /* PLT is different on different platforms, it seems. */
2030# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
Ben Cheng663860b2013-01-31 15:38:14 -08002031 || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
2032 || defined(VGP_mips32_linux)
Jeff Browned07e002011-02-03 17:46:23 -08002033 /* Accept .plt where mapped as rx (code) */
2034 if (0 == VG_(strcmp)(name, ".plt")) {
2035 if (inrx && size > 0 && !di->plt_present) {
2036 di->plt_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002037 di->plt_avma = svma + inrx->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002038 di->plt_size = size;
2039 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2040 } else {
2041 BAD(".plt");
2042 }
2043 }
2044# elif defined(VGP_ppc32_linux)
2045 /* Accept .plt where mapped as rw (data) */
2046 if (0 == VG_(strcmp)(name, ".plt")) {
2047 if (inrw && size > 0 && !di->plt_present) {
2048 di->plt_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002049 di->plt_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002050 di->plt_size = size;
2051 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2052 } else {
2053 BAD(".plt");
2054 }
2055 }
2056# elif defined(VGP_ppc64_linux)
2057 /* Accept .plt where mapped as rw (data), or unmapped */
2058 if (0 == VG_(strcmp)(name, ".plt")) {
2059 if (inrw && size > 0 && !di->plt_present) {
2060 di->plt_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002061 di->plt_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002062 di->plt_size = size;
2063 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2064 } else
2065 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2066 /* File contains a .plt, but it didn't get mapped.
2067 Presumably it is not required on this platform. At
2068 least don't reject the situation as invalid. */
2069 di->plt_present = True;
2070 di->plt_avma = 0;
2071 di->plt_size = 0;
2072 } else {
2073 BAD(".plt");
2074 }
2075 }
2076# else
2077# error "Unsupported platform"
2078# endif
2079
2080 /* Accept .opd where mapped as rw (data) */
2081 if (0 == VG_(strcmp)(name, ".opd")) {
2082 if (inrw && size > 0 && !di->opd_present) {
2083 di->opd_present = True;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002084 di->opd_avma = svma + inrw->bias;
Jeff Browned07e002011-02-03 17:46:23 -08002085 di->opd_size = size;
2086 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2087 } else {
2088 BAD(".opd");
2089 }
2090 }
2091
2092 /* Accept .eh_frame where mapped as rx (code). This seems to be
2093 the common case. However, if that doesn't pan out, try for
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002094 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2095 ELF object. */
Jeff Browned07e002011-02-03 17:46:23 -08002096 if (0 == VG_(strcmp)(name, ".eh_frame")) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002097 if (inrx && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2098 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2099 di->ehframe_size[di->n_ehframe] = size;
2100 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2101 di->ehframe_avma[di->n_ehframe]);
2102 di->n_ehframe++;
Jeff Browned07e002011-02-03 17:46:23 -08002103 } else
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002104 if (inrw && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2105 di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
2106 di->ehframe_size[di->n_ehframe] = size;
2107 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2108 di->ehframe_avma[di->n_ehframe]);
2109 di->n_ehframe++;
Jeff Browned07e002011-02-03 17:46:23 -08002110 } else {
2111 BAD(".eh_frame");
2112 }
2113 }
2114
2115# undef BAD
2116
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002117 } /* iterate over the section headers */
Jeff Browned07e002011-02-03 17:46:23 -08002118
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002119 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08002120 if (0) VG_(printf)("YYYY text_: avma %#lx size %ld bias %#lx\n",
2121 di->text_avma, di->text_size, di->text_bias);
2122
2123 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2124 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2125 di->text_avma - di->text_bias,
2126 di->text_avma );
2127
2128 TRACE_SYMTAB("\n");
2129 TRACE_SYMTAB("------ Finding image addresses "
2130 "for debug-info sections ------\n");
2131
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002132 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08002133 /* Find interesting sections, read the symbol table(s), read any debug
2134 information */
2135 {
2136 /* IMAGE addresses: pointers to start of sections in the
2137 transiently loaded oimage, not in the fragments of the file
2138 mapped in by the guest's dynamic linker. */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002139 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08002140 UChar* strtab_img = NULL; /* .strtab */
2141 ElfXX_Sym* symtab_img = NULL; /* .symtab */
2142 UChar* dynstr_img = NULL; /* .dynstr */
2143 ElfXX_Sym* dynsym_img = NULL; /* .dynsym */
2144 UChar* debuglink_img = NULL; /* .gnu_debuglink */
Ben Cheng663860b2013-01-31 15:38:14 -08002145 UChar* debugaltlink_img = NULL; /* .gnu_debugaltlink */
Jeff Browned07e002011-02-03 17:46:23 -08002146 UChar* stab_img = NULL; /* .stab (stabs) */
2147 UChar* stabstr_img = NULL; /* .stabstr (stabs) */
2148 UChar* debug_line_img = NULL; /* .debug_line (dwarf2) */
2149 UChar* debug_info_img = NULL; /* .debug_info (dwarf2) */
Ben Cheng663860b2013-01-31 15:38:14 -08002150 UChar* debug_types_img = NULL; /* .debug_types (dwarf4) */
Jeff Browned07e002011-02-03 17:46:23 -08002151 UChar* debug_abbv_img = NULL; /* .debug_abbrev (dwarf2) */
2152 UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */
2153 UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
2154 UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */
2155 UChar* debug_frame_img = NULL; /* .debug_frame (dwarf2) */
Ben Cheng663860b2013-01-31 15:38:14 -08002156 UChar* debug_line_alt_img = NULL; /* .debug_line (alternate) */
2157 UChar* debug_info_alt_img = NULL; /* .debug_info (alternate) */
2158 UChar* debug_abbv_alt_img = NULL; /* .debug_abbrev (alternate) */
2159 UChar* debug_str_alt_img = NULL; /* .debug_str (alternate) */
Jeff Browned07e002011-02-03 17:46:23 -08002160 UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */
2161 UChar* dwarf1l_img = NULL; /* .line (dwarf1) */
Jeff Browned07e002011-02-03 17:46:23 -08002162 UChar* opd_img = NULL; /* .opd (dwarf2,
2163 ppc64-linux) */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002164 UChar* ehframe_img[N_EHFRAME_SECTS]; /* .eh_frame (dwarf2) */
2165
Jeff Browned07e002011-02-03 17:46:23 -08002166 /* Section sizes, in bytes */
2167 SizeT strtab_sz = 0;
2168 SizeT symtab_sz = 0;
2169 SizeT dynstr_sz = 0;
2170 SizeT dynsym_sz = 0;
2171 SizeT debuglink_sz = 0;
Ben Cheng663860b2013-01-31 15:38:14 -08002172 SizeT debugaltlink_sz = 0;
Jeff Browned07e002011-02-03 17:46:23 -08002173 SizeT stab_sz = 0;
2174 SizeT stabstr_sz = 0;
2175 SizeT debug_line_sz = 0;
2176 SizeT debug_info_sz = 0;
Ben Cheng663860b2013-01-31 15:38:14 -08002177 SizeT debug_types_sz = 0;
Jeff Browned07e002011-02-03 17:46:23 -08002178 SizeT debug_abbv_sz = 0;
2179 SizeT debug_str_sz = 0;
2180 SizeT debug_ranges_sz = 0;
2181 SizeT debug_loc_sz = 0;
2182 SizeT debug_frame_sz = 0;
Ben Cheng663860b2013-01-31 15:38:14 -08002183 SizeT debug_line_alt_sz = 0;
2184 SizeT debug_info_alt_sz = 0;
2185 SizeT debug_abbv_alt_sz = 0;
2186 SizeT debug_str_alt_sz = 0;
Jeff Browned07e002011-02-03 17:46:23 -08002187 SizeT dwarf1d_sz = 0;
2188 SizeT dwarf1l_sz = 0;
Jeff Browned07e002011-02-03 17:46:23 -08002189 SizeT opd_sz_unused = 0;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002190 SizeT ehframe_sz[N_EHFRAME_SECTS];
2191
2192 for (i = 0; i < N_EHFRAME_SECTS; i++) {
2193 ehframe_img[i] = NULL;
2194 ehframe_sz[i] = 0;
2195 }
Jeff Browned07e002011-02-03 17:46:23 -08002196
2197 /* Find all interesting sections */
2198
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002199 UInt ehframe_ix = 0;
Evgeniy Stepanov8f943af2011-12-06 18:30:06 +04002200
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002201 /* What FIND does: it finds the section called _SEC_NAME. The
2202 size of it is assigned to _SEC_SIZE. The address of the
2203 section in the transiently loaded oimage is assigned to
2204 _SEC_IMG. If the section is found, _POST_FX is executed
2205 after _SEC_NAME and _SEC_SIZE have been assigned to.
2206
2207 Even for sections which are marked loadable, the client's
2208 ld.so may not have loaded them yet, so there is no guarantee
2209 that we can safely prod around in any such area). Because
2210 the entire object file is transiently mapped aboard for
2211 inspection, it's always safe to inspect that area. */
2212
2213 /* TOPLEVEL */
2214 /* Iterate over section headers (again) */
Jeff Browned07e002011-02-03 17:46:23 -08002215 for (i = 0; i < ehdr_img->e_shnum; i++) {
2216
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002217# define FINDX(_sec_name, _sec_size, _sec_img, _post_fx) \
Jeff Browned07e002011-02-03 17:46:23 -08002218 do { ElfXX_Shdr* shdr \
2219 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002220 if (0 == VG_(strcmp)(_sec_name, shdr_strtab_img \
2221 + shdr->sh_name)) { \
Jeff Browned07e002011-02-03 17:46:23 -08002222 Bool nobits; \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002223 _sec_img = (void*)(oimage + shdr->sh_offset); \
2224 _sec_size = shdr->sh_size; \
2225 nobits = shdr->sh_type == SHT_NOBITS; \
Jeff Browned07e002011-02-03 17:46:23 -08002226 TRACE_SYMTAB( "%18s: img %p .. %p\n", \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002227 _sec_name, (UChar*)_sec_img, \
2228 ((UChar*)_sec_img) + _sec_size - 1); \
Jeff Browned07e002011-02-03 17:46:23 -08002229 /* SHT_NOBITS sections have zero size in the file. */ \
2230 if ( shdr->sh_offset \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002231 + (nobits ? 0 : _sec_size) > n_oimage ) { \
Jeff Browned07e002011-02-03 17:46:23 -08002232 ML_(symerr)(di, True, \
2233 " section beyond image end?!"); \
2234 goto out; \
2235 } \
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002236 _post_fx; \
Jeff Browned07e002011-02-03 17:46:23 -08002237 } \
2238 } while (0);
2239
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002240 /* Version with no post-effects */
2241# define FIND(_sec_name, _sec_size, _sec_img) \
2242 FINDX(_sec_name, _sec_size, _sec_img, /**/)
2243
Jeff Browned07e002011-02-03 17:46:23 -08002244 /* NAME SIZE IMAGE addr */
2245 FIND(".dynsym", dynsym_sz, dynsym_img)
2246 FIND(".dynstr", dynstr_sz, dynstr_img)
2247 FIND(".symtab", symtab_sz, symtab_img)
2248 FIND(".strtab", strtab_sz, strtab_img)
2249
2250 FIND(".gnu_debuglink", debuglink_sz, debuglink_img)
Ben Cheng663860b2013-01-31 15:38:14 -08002251 FIND(".gnu_debugaltlink", debugaltlink_sz, debugaltlink_img)
Jeff Browned07e002011-02-03 17:46:23 -08002252
2253 FIND(".stab", stab_sz, stab_img)
2254 FIND(".stabstr", stabstr_sz, stabstr_img)
2255
2256 FIND(".debug_line", debug_line_sz, debug_line_img)
2257 FIND(".debug_info", debug_info_sz, debug_info_img)
Ben Cheng663860b2013-01-31 15:38:14 -08002258 FIND(".debug_types", debug_types_sz, debug_types_img)
Jeff Browned07e002011-02-03 17:46:23 -08002259 FIND(".debug_abbrev", debug_abbv_sz, debug_abbv_img)
2260 FIND(".debug_str", debug_str_sz, debug_str_img)
2261 FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img)
2262 FIND(".debug_loc", debug_loc_sz, debug_loc_img)
2263 FIND(".debug_frame", debug_frame_sz, debug_frame_img)
2264
2265 FIND(".debug", dwarf1d_sz, dwarf1d_img)
2266 FIND(".line", dwarf1l_sz, dwarf1l_img)
Jeff Browned07e002011-02-03 17:46:23 -08002267
2268 FIND(".opd", opd_sz_unused, opd_img)
2269
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002270 FINDX(".eh_frame", ehframe_sz[ehframe_ix],
2271 ehframe_img[ehframe_ix],
2272 do { ehframe_ix++; vg_assert(ehframe_ix <= N_EHFRAME_SECTS); }
2273 while (0)
2274 )
2275 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2276 multi-instance kludgery, how are we assured that the order
2277 in which we fill in ehframe_sz[] and ehframe_img[] is
2278 consistent with the order in which we previously filled in
2279 di->ehframe_avma[] and di->ehframe_size[] ? By the fact
2280 that in both cases, these arrays were filled in by
2281 iterating over the section headers top-to-bottom. So both
2282 loops (this one and the previous one) encounter the
2283 .eh_frame entries in the same order and so fill in these
2284 arrays in a consistent order.
2285 */
2286
2287# undef FINDX
Jeff Browned07e002011-02-03 17:46:23 -08002288# undef FIND
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002289 } /* Iterate over section headers (again) */
2290
2291 /* TOPLEVEL */
2292 /* Now, see if we can find a debuginfo object, and if so map it in, and
2293 put the mapping address and size in dimage and n_dimage. */
2294 vg_assert(dimage == 0 && n_dimage == 0);
Jeff Browned07e002011-02-03 17:46:23 -08002295
2296 /* Look for a build-id */
Ben Cheng663860b2013-01-31 15:38:14 -08002297 buildid = find_buildid(oimage, n_oimage, False);
Jeff Browned07e002011-02-03 17:46:23 -08002298
2299 /* Look for a debug image */
2300 if (buildid != NULL || debuglink_img != NULL) {
2301 /* Do have a debuglink section? */
2302 if (debuglink_img != NULL) {
2303 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
2304 UInt crc;
2305
2306 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
2307
2308 /* Extract the CRC from the debuglink section */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002309 crc = ML_(read_UInt)(debuglink_img + crc_offset);
Jeff Browned07e002011-02-03 17:46:23 -08002310
2311 /* See if we can find a matching debug file */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002312 find_debug_file( di, di->fsm.filename, buildid,
Ben Cheng663860b2013-01-31 15:38:14 -08002313 debuglink_img, crc, False, &dimage, &n_dimage );
Jeff Browned07e002011-02-03 17:46:23 -08002314 } else {
2315 /* See if we can find a matching debug file */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002316 find_debug_file( di, di->fsm.filename, buildid,
Ben Cheng663860b2013-01-31 15:38:14 -08002317 NULL, 0, False, &dimage, &n_dimage );
Kenny Root9bea4c12011-12-09 15:14:13 -08002318 }
2319 }
2320
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002321 if (buildid) {
2322 ML_(dinfo_free)(buildid);
2323 buildid = NULL; /* paranoia */
2324 }
2325
2326 /* Still no luck? Let's have one last roll of the dice. */
2327 if (dimage == 0) {
2328 vg_assert(n_dimage == 0);
2329 Bool found = find_ad_hoc_debug_image( di, di->fsm.filename,
2330 &dimage, &n_dimage );
2331 if (found)
2332 vg_assert(dimage != 0);
2333 }
2334
2335 /* TOPLEVEL */
2336 /* If we were successful in finding a debug image, pull various
2337 SVMA/bias/size and image addresses out of it. */
2338 if (dimage != 0
2339 && n_dimage >= sizeof(ElfXX_Ehdr)
Ben Cheng663860b2013-01-31 15:38:14 -08002340 && ML_(is_elf_object_file)((void*)dimage, n_dimage, False)) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002341
2342 /* Pull out and validate program header and section header info */
2343 ElfXX_Ehdr* ehdr_dimg = (ElfXX_Ehdr*)dimage;
2344 ElfXX_Phdr* phdr_dimg = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
2345 + ehdr_dimg->e_phoff );
2346 UWord phdr_dnent = ehdr_dimg->e_phnum;
2347 UWord phdr_dent_szB = ehdr_dimg->e_phentsize;
2348 ElfXX_Shdr* shdr_dimg = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
2349 + ehdr_dimg->e_shoff );
2350 UWord shdr_dnent = ehdr_dimg->e_shnum;
2351 UWord shdr_dent_szB = ehdr_dimg->e_shentsize;
2352 UChar* shdr_strtab_dimg = NULL;
2353
2354 /* SVMAs covered by rx and rw segments and corresponding bias. */
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002355 Addr rx_dsvma_limit = 0;
2356 PtrdiffT rx_dbias = 0;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002357 Addr rw_dsvma_limit = 0;
2358 PtrdiffT rw_dbias = 0;
2359
2360 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
2361
2362 if (phdr_dnent == 0
2363 || !contained_within(
2364 dimage, n_dimage,
2365 (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
2366 ML_(symerr)(di, True,
2367 "Missing or invalid ELF Program Header Table"
2368 " (debuginfo file)");
2369 goto out;
2370 }
2371
2372 if (shdr_dnent == 0
2373 || !contained_within(
2374 dimage, n_dimage,
2375 (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
2376 ML_(symerr)(di, True,
2377 "Missing or invalid ELF Section Header Table"
2378 " (debuginfo file)");
2379 goto out;
2380 }
2381
2382 /* Also find the section header's string table, and validate. */
2383 /* checked previously by is_elf_object_file: */
2384 vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
2385
2386 shdr_strtab_dimg
2387 = (UChar*)( ((UChar*)ehdr_dimg)
2388 + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
2389 if (!contained_within(
2390 dimage, n_dimage,
2391 (Addr)shdr_strtab_dimg,
2392 1/*bogus, but we don't know the real size*/ )) {
2393 ML_(symerr)(di, True,
2394 "Invalid ELF Section Header String Table"
2395 " (debuginfo file)");
2396 goto out;
2397 }
2398
2399 need_symtab = (NULL == symtab_img);
2400 need_stabs = (NULL == stab_img);
2401 need_dwarf2 = (NULL == debug_info_img);
2402 need_dwarf1 = (NULL == dwarf1d_img);
2403
2404 for (i = 0; i < ehdr_dimg->e_phnum; i++) {
2405 ElfXX_Phdr* phdr
2406 = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
2407 i, phdr_ent_szB );
2408 if (phdr->p_type == PT_LOAD) {
Ben Cheng663860b2013-01-31 15:38:14 -08002409 for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) {
2410 struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j);
2411 if ( phdr->p_offset >= map->foff
2412 && phdr->p_offset < map->foff + map->size
2413 && phdr->p_offset + phdr->p_filesz < map->foff
2414 + map->size) {
2415 if (map->rx && rx_dsvma_limit == 0) {
2416 rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2417 rx_dbias = map->avma - map->foff + phdr->p_offset
2418 - phdr->p_vaddr;
2419 }
2420 if (map->rw && rw_dsvma_limit == 0) {
2421 rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2422 rw_dbias = map->avma - map->foff + phdr->p_offset
2423 - phdr->p_vaddr;
2424 }
2425 break;
2426 }
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002427 }
2428 }
2429 }
2430
2431 /* Find all interesting sections */
2432 for (i = 0; i < ehdr_dimg->e_shnum; i++) {
2433
2434 /* Find debug svma and bias information for sections
2435 we found in the main file. */
2436
2437# define FIND(sec, seg) \
2438 do { ElfXX_Shdr* shdr \
2439 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2440 if (di->sec##_present \
2441 && 0 == VG_(strcmp)("." #sec, \
2442 shdr_strtab_dimg + shdr->sh_name)) { \
2443 vg_assert(di->sec##_size == shdr->sh_size); \
2444 vg_assert(di->sec##_avma + shdr->sh_addr + seg##_dbias); \
2445 /* Assume we have a correct value for the main */ \
2446 /* object's bias. Use that to derive the debuginfo */ \
2447 /* object's bias, by adding the difference in SVMAs */ \
2448 /* for the corresponding sections in the two files. */ \
2449 /* That should take care of all prelinking effects. */ \
2450 di->sec##_debug_svma = shdr->sh_addr; \
2451 di->sec##_debug_bias \
2452 = di->sec##_bias + \
2453 di->sec##_svma - di->sec##_debug_svma; \
2454 TRACE_SYMTAB("acquiring ." #sec \
2455 " debug svma = %#lx .. %#lx\n", \
2456 di->sec##_debug_svma, \
2457 di->sec##_debug_svma + di->sec##_size - 1); \
2458 TRACE_SYMTAB("acquiring ." #sec " debug bias = %#lx\n", \
2459 di->sec##_debug_bias); \
2460 } \
2461 } while (0);
2462
2463 /* SECTION SEGMENT */
2464 FIND(text, rx)
2465 FIND(data, rw)
2466 FIND(sdata, rw)
2467 FIND(rodata, rw)
2468 FIND(bss, rw)
2469 FIND(sbss, rw)
2470
2471# undef FIND
2472
2473 /* Same deal as previous FIND, except only do it for those
2474 sections for which we didn't find anything useful in
2475 the main file. */
2476
2477# define FIND(condition, sec_name, sec_size, sec_img) \
2478 do { ElfXX_Shdr* shdr \
2479 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2480 if (condition \
2481 && 0 == VG_(strcmp)(sec_name, \
2482 shdr_strtab_dimg + shdr->sh_name)) { \
2483 Bool nobits; \
2484 if (0 != sec_img) \
2485 VG_(core_panic)("repeated section!\n"); \
2486 sec_img = (void*)(dimage + shdr->sh_offset); \
2487 sec_size = shdr->sh_size; \
2488 nobits = shdr->sh_type == SHT_NOBITS; \
2489 TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
2490 sec_name, \
2491 (UChar*)sec_img, \
2492 ((UChar*)sec_img) + sec_size - 1); \
2493 /* SHT_NOBITS sections have zero size in the file. */ \
2494 if ( shdr->sh_offset \
2495 + (nobits ? 0 : sec_size) > n_dimage ) { \
2496 ML_(symerr)(di, True, \
2497 " section beyond image end?!"); \
2498 goto out; \
2499 } \
2500 } \
2501 } while (0);
2502
2503 /* NEEDED? NAME SIZE IMAGE addr */
2504 FIND(need_symtab, ".symtab", symtab_sz, symtab_img)
2505 FIND(need_symtab, ".strtab", strtab_sz, strtab_img)
2506 FIND(need_stabs, ".stab", stab_sz, stab_img)
2507 FIND(need_stabs, ".stabstr", stabstr_sz, stabstr_img)
2508 FIND(need_dwarf2, ".debug_line", debug_line_sz, debug_line_img)
2509 FIND(need_dwarf2, ".debug_info", debug_info_sz, debug_info_img)
Ben Cheng663860b2013-01-31 15:38:14 -08002510 FIND(need_dwarf2, ".debug_types", debug_types_sz,
2511 debug_types_img)
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002512 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
2513 FIND(need_dwarf2, ".debug_str", debug_str_sz, debug_str_img)
2514 FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
2515 debug_ranges_img)
2516 FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img)
2517 FIND(need_dwarf2, ".debug_frame", debug_frame_sz,
2518 debug_frame_img)
Ben Cheng663860b2013-01-31 15:38:14 -08002519 FIND(need_dwarf2, ".gnu_debugaltlink", debugaltlink_sz,
2520 debugaltlink_img)
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002521 FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img)
2522 FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img)
2523
2524# undef FIND
2525 } /* Find all interesting sections */
2526 } /* do we have a debug image? */
2527
Ben Cheng663860b2013-01-31 15:38:14 -08002528 /* Look for alternate debug image */
2529 if (debugaltlink_img != NULL) {
2530 UInt buildid_offset = VG_(strlen)(debugaltlink_img)+1;
2531
2532 vg_assert(buildid_offset < debugaltlink_sz);
2533
2534 Char *altbuildid
2535 = ML_(dinfo_zalloc)("di.fbi.4",
2536 (debugaltlink_sz - buildid_offset)
2537 * 2 + 1);
2538
2539 for (j = 0; j < debugaltlink_sz - buildid_offset; j++)
2540 VG_(sprintf)(altbuildid + 2 * j,
2541 "%02x", debugaltlink_img[buildid_offset + j]);
2542
2543 /* See if we can find a matching debug file */
2544 find_debug_file( di, di->fsm.filename, altbuildid,
2545 NULL, 0, True, &aimage, &n_aimage );
2546
2547 ML_(dinfo_free)(altbuildid);
2548 }
2549
2550 /* TOPLEVEL */
2551 /* If we were successful in finding alternate debug image, pull various
2552 size and image addresses out of it. */
2553 if (aimage != 0
2554 && n_aimage >= sizeof(ElfXX_Ehdr)
2555 && ML_(is_elf_object_file)((void*)aimage, n_aimage, True)) {
2556
2557 /* Pull out and validate program header and section header info */
2558 ElfXX_Ehdr* ehdr_aimg = (ElfXX_Ehdr*)aimage;
2559 ElfXX_Shdr* shdr_aimg = (ElfXX_Shdr*)( ((UChar*)ehdr_aimg)
2560 + ehdr_aimg->e_shoff );
2561 UWord shdr_dnent = ehdr_aimg->e_shnum;
2562 UWord shdr_dent_szB = ehdr_aimg->e_shentsize;
2563 UChar* shdr_strtab_aimg = NULL;
2564
2565 if (shdr_dnent == 0
2566 || !contained_within(
2567 aimage, n_aimage,
2568 (Addr)shdr_aimg, shdr_dnent * shdr_dent_szB)) {
2569 ML_(symerr)(di, True,
2570 "Missing or invalid ELF Section Header Table"
2571 " (alternate debuginfo file)");
2572 goto out;
2573 }
2574
2575 /* Also find the section header's string table, and validate. */
2576 /* checked previously by is_elf_object_file: */
2577 vg_assert( ehdr_aimg->e_shstrndx != SHN_UNDEF );
2578
2579 shdr_strtab_aimg
2580 = (UChar*)( ((UChar*)ehdr_aimg)
2581 + shdr_aimg[ehdr_aimg->e_shstrndx].sh_offset);
2582 if (!contained_within(
2583 aimage, n_aimage,
2584 (Addr)shdr_strtab_aimg,
2585 1/*bogus, but we don't know the real size*/ )) {
2586 ML_(symerr)(di, True,
2587 "Invalid ELF Section Header String Table"
2588 " (alternate debuginfo file)");
2589 goto out;
2590 }
2591
2592 /* Find all interesting sections */
2593 for (i = 0; i < ehdr_aimg->e_shnum; i++) {
2594
2595# define FIND(sec_name, sec_size, sec_img) \
2596 do { ElfXX_Shdr* shdr \
2597 = INDEX_BIS( shdr_aimg, i, shdr_dent_szB ); \
2598 if (0 == VG_(strcmp)(sec_name, \
2599 shdr_strtab_aimg + shdr->sh_name)) { \
2600 if (0 != sec_img) \
2601 VG_(core_panic)("repeated section!\n"); \
2602 sec_img = (void*)(aimage + shdr->sh_offset); \
2603 sec_size = shdr->sh_size; \
2604 TRACE_SYMTAB( "%18s: aimg %p .. %p\n", \
2605 sec_name, \
2606 (UChar*)sec_img, \
2607 ((UChar*)sec_img) + sec_size - 1); \
2608 } \
2609 } while (0);
2610
2611 /* NAME SIZE IMAGE addr */
2612 FIND(".debug_line", debug_line_alt_sz, debug_line_alt_img)
2613 FIND(".debug_info", debug_info_alt_sz, debug_info_alt_img)
2614 FIND(".debug_abbrev", debug_abbv_alt_sz, debug_abbv_alt_img)
2615 FIND(".debug_str", debug_str_alt_sz, debug_str_alt_img)
2616
2617# undef FIND
2618 } /* Find all interesting sections */
2619 } /* do we have a debug image? */
2620
2621
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002622 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08002623 /* Check some sizes */
2624 vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
2625 vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
2626
2627 /* Read symbols */
2628 {
2629 void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
2630 ElfXX_Sym*,SizeT,
2631 UChar*,SizeT,
2632 Bool,UChar*);
2633 Bool symtab_in_debug;
2634# if defined(VGP_ppc64_linux)
2635 read_elf_symtab = read_elf_symtab__ppc64_linux;
2636# else
2637 read_elf_symtab = read_elf_symtab__normal;
2638# endif
2639 symtab_in_debug = (Addr)symtab_img >= dimage
2640 && (Addr)symtab_img < dimage + n_dimage;
2641 read_elf_symtab(di, "symbol table",
2642 symtab_img, symtab_sz,
2643 strtab_img, strtab_sz,
2644 symtab_in_debug, opd_img);
2645
2646 read_elf_symtab(di, "dynamic symbol table",
2647 dynsym_img, dynsym_sz,
2648 dynstr_img, dynstr_sz,
2649 False, opd_img);
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002650 } /* Read symbols */
Jeff Browned07e002011-02-03 17:46:23 -08002651
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002652 /* TOPLEVEL */
2653 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
2654 the .eh_frame section(s) first. */
2655 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
2656 for (i = 0; i < di->n_ehframe; i++) {
2657 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2658 this next assertion should hold. */
2659 vg_assert(ehframe_sz[i] == di->ehframe_size[i]);
2660 ML_(read_callframe_info_dwarf3)( di,
2661 ehframe_img[i],
2662 ehframe_sz[i],
2663 di->ehframe_avma[i],
2664 True/*is_ehframe*/ );
Jeff Browned07e002011-02-03 17:46:23 -08002665 }
2666 if (debug_frame_sz) {
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002667 ML_(read_callframe_info_dwarf3)( di,
2668 debug_frame_img, debug_frame_sz,
2669 0/*assume zero avma*/,
2670 False/*!is_ehframe*/ );
Jeff Browned07e002011-02-03 17:46:23 -08002671 }
2672
2673 /* Read the stabs and/or dwarf2 debug information, if any. It
2674 appears reading stabs stuff on amd64-linux doesn't work, so
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002675 we ignore it. On s390x stabs also doesnt work and we always
2676 have the dwarf info in the eh_frame. We also segfault on
2677 ppc64-linux when reading stabs, so skip that. ppc32-linux
2678 seems OK though. Also skip on Android. */
2679# if !defined(VGP_amd64_linux) \
2680 && !defined(VGP_s390x_linux) \
2681 && !defined(VGP_ppc64_linux) \
2682 && !defined(VGPV_arm_linux_android) \
2683 && !defined(VGPV_x86_linux_android)
Jeff Browned07e002011-02-03 17:46:23 -08002684 if (stab_img && stabstr_img) {
2685 ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz,
2686 stabstr_img, stabstr_sz );
2687 }
2688# endif
2689 /* jrs 2006-01-01: icc-8.1 has been observed to generate
2690 binaries without debug_str sections. Don't preclude
2691 debuginfo reading for that reason, but, in
2692 read_unitinfo_dwarf2, do check that debugstr is non-NULL
2693 before using it. */
2694 if (debug_info_img && debug_abbv_img && debug_line_img
2695 /* && debug_str_img */) {
2696
2697 /* The old reader: line numbers and unwind info only */
2698 ML_(read_debuginfo_dwarf3) ( di,
2699 debug_info_img, debug_info_sz,
Ben Cheng663860b2013-01-31 15:38:14 -08002700 debug_types_img, debug_types_sz,
Jeff Browned07e002011-02-03 17:46:23 -08002701 debug_abbv_img, debug_abbv_sz,
2702 debug_line_img, debug_line_sz,
Ben Cheng663860b2013-01-31 15:38:14 -08002703 debug_str_img, debug_str_sz,
2704 debug_str_alt_img, debug_str_alt_sz );
Jeff Browned07e002011-02-03 17:46:23 -08002705
2706 /* The new reader: read the DIEs in .debug_info to acquire
2707 information on variable types and locations. But only if
2708 the tool asks for it, or the user requests it on the
2709 command line. */
2710 if (VG_(needs).var_info /* the tool requires it */
2711 || VG_(clo_read_var_info) /* the user asked for it */) {
2712 ML_(new_dwarf3_reader)(
2713 di, debug_info_img, debug_info_sz,
Ben Cheng663860b2013-01-31 15:38:14 -08002714 debug_types_img, debug_types_sz,
Jeff Browned07e002011-02-03 17:46:23 -08002715 debug_abbv_img, debug_abbv_sz,
2716 debug_line_img, debug_line_sz,
2717 debug_str_img, debug_str_sz,
2718 debug_ranges_img, debug_ranges_sz,
Ben Cheng663860b2013-01-31 15:38:14 -08002719 debug_loc_img, debug_loc_sz,
2720 debug_info_alt_img, debug_info_alt_sz,
2721 debug_abbv_alt_img, debug_abbv_alt_sz,
2722 debug_line_alt_img, debug_line_alt_sz,
2723 debug_str_alt_img, debug_str_alt_sz
Jeff Browned07e002011-02-03 17:46:23 -08002724 );
2725 }
2726 }
2727 if (dwarf1d_img && dwarf1l_img) {
2728 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
2729 dwarf1l_img, dwarf1l_sz );
2730 }
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002731 /* TOPLEVEL */
2732
2733 } /* "Find interesting sections, read the symbol table(s), read any debug
2734 information" (a local scope) */
2735
2736 /* TOPLEVEL */
Jeff Browned07e002011-02-03 17:46:23 -08002737 res = True;
2738
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002739 /* If reading Dwarf3 variable type/location info, print a line
2740 showing the number of variables read for each object.
2741 (Currently disabled -- is a sanity-check mechanism for
2742 exp-sgcheck.) */
2743 if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) {
2744 UWord nVars = 0;
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002745 if (di->varinfo) {
2746 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
2747 OSet* /* of DiAddrRange */ scope
2748 = *(OSet**)VG_(indexXA)(di->varinfo, j);
2749 vg_assert(scope);
2750 VG_(OSetGen_ResetIter)( scope );
2751 while (True) {
2752 DiAddrRange* range = VG_(OSetGen_Next)( scope );
2753 if (!range) break;
2754 vg_assert(range->vars);
2755 Word w = VG_(sizeXA)(range->vars);
2756 vg_assert(w >= 0);
2757 if (0) VG_(printf)("range %#lx %#lx %ld\n",
2758 range->aMin, range->aMax, w);
2759 nVars += (UWord)w;
2760 }
2761 }
2762 }
2763 VG_(umsg)("VARINFO: %7lu vars %7ld text_size %s\n",
2764 nVars, di->text_size, di->fsm.filename);
Kenny Root9bea4c12011-12-09 15:14:13 -08002765 }
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002766 /* TOPLEVEL */
2767
2768 out:
2769 {
2770 SysRes m_res;
2771 /* Last, but not least, heave the image(s) back overboard. */
2772 if (dimage) {
2773 m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
2774 vg_assert(!sr_isError(m_res));
2775 }
2776 m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
2777 vg_assert(!sr_isError(m_res));
Ben Cheng663860b2013-01-31 15:38:14 -08002778
2779 if (svma_ranges)
2780 VG_(deleteXA)(svma_ranges);
2781
Evgeniy Stepanovb32f5802011-12-20 11:21:56 +04002782 return res;
2783 } /* out: */
2784
2785 /* NOTREACHED */
Jeff Browned07e002011-02-03 17:46:23 -08002786}
2787
2788#endif // defined(VGO_linux)
2789
2790/*--------------------------------------------------------------------*/
2791/*--- end ---*/
2792/*--------------------------------------------------------------------*/