1
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
11 Copyright (C) 2000-2011 Julian Seward
12 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_mallocfree.h"
44 #include "pub_core_options.h"
45 #include "pub_core_oset.h"
46 #include "pub_core_tooliface.h" /* VG_(needs) */
47 #include "pub_core_xarray.h"
48 #include "priv_misc.h" /* dinfo_zalloc/free/strdup */
49 #include "priv_d3basics.h"
50 #include "priv_tytypes.h"
51 #include "priv_storage.h"
52 #include "priv_readelf.h" /* self */
53 #include "priv_readdwarf.h" /* 'cos ELF contains DWARF */
54 #include "priv_readdwarf3.h"
55 #include "priv_readstabs.h" /* and stabs, if we're unlucky */
56
57 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
58 #include <elf.h>
59 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
60
61 /*------------------------------------------------------------*/
62 /*--- 32/64-bit parameterisation ---*/
63 /*------------------------------------------------------------*/
64
65 /* For all the ELF macros and types which specify '32' or '64',
66 select the correct variant for this platform and give it
67 an 'XX' name. Then use the 'XX' variant consistently in
68 the rest of this file.
69 */
70 #if VG_WORDSIZE == 4
71 # define ElfXX_Ehdr Elf32_Ehdr
72 # define ElfXX_Shdr Elf32_Shdr
73 # define ElfXX_Phdr Elf32_Phdr
74 # define ElfXX_Nhdr Elf32_Nhdr
75 # define ElfXX_Sym Elf32_Sym
76 # define ElfXX_Off Elf32_Off
77 # define ElfXX_Word Elf32_Word
78 # define ElfXX_Addr Elf32_Addr
79 # define ElfXX_Dyn Elf32_Dyn
80 # define ELFXX_ST_BIND ELF32_ST_BIND
81 # define ELFXX_ST_TYPE ELF32_ST_TYPE
82
83 #elif VG_WORDSIZE == 8
84 # define ElfXX_Ehdr Elf64_Ehdr
85 # define ElfXX_Shdr Elf64_Shdr
86 # define ElfXX_Phdr Elf64_Phdr
87 # define ElfXX_Nhdr Elf64_Nhdr
88 # define ElfXX_Sym Elf64_Sym
89 # define ElfXX_Off Elf64_Off
90 # define ElfXX_Word Elf64_Word
91 # define ElfXX_Addr Elf64_Addr
92 # define ElfXX_Dyn Elf64_Dyn
93 # define ELFXX_ST_BIND ELF64_ST_BIND
94 # define ELFXX_ST_TYPE ELF64_ST_TYPE
95
96 #else
97 # error "VG_WORDSIZE should be 4 or 8"
98 #endif
99
100
101 /*------------------------------------------------------------*/
102 /*--- ---*/
103 /*--- Read symbol table and line info from ELF files. ---*/
104 /*--- ---*/
105 /*------------------------------------------------------------*/
106
107 /* readelf.c parses ELF files and acquires symbol table info from
108 them. It calls onwards to readdwarf.c to read DWARF2/3 line number
109 and call frame info found. */
110
111
112 /* Identify an ELF object file by peering at the first few bytes of
113 it. */
114
ML_(is_elf_object_file)115 Bool ML_(is_elf_object_file)( void* image, SizeT n_image )
116 {
117 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
118 Int ok = 1;
119
120 if (n_image < sizeof(ElfXX_Ehdr))
121 return False;
122
123 ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
124 && ehdr->e_ident[EI_MAG1] == 'E'
125 && ehdr->e_ident[EI_MAG2] == 'L'
126 && ehdr->e_ident[EI_MAG3] == 'F');
127 ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
128 && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
129 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
130 ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
131 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);
135 ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
136
137 if (ok)
138 return True;
139 else
140 return False;
141 }
142
143
144 /* Show a raw ELF symbol, given its in-image address and name. */
145
146 static
show_raw_elf_symbol(Int i,ElfXX_Sym * sym,Char * sym_name,Addr sym_svma,Bool ppc64_linux_format)147 void show_raw_elf_symbol ( Int i,
148 ElfXX_Sym* sym, Char* sym_name, Addr sym_svma,
149 Bool ppc64_linux_format )
150 {
151 HChar* space = ppc64_linux_format ? " " : "";
152 VG_(printf)("raw symbol [%4d]: ", i);
153 switch (ELFXX_ST_BIND(sym->st_info)) {
154 case STB_LOCAL: VG_(printf)("LOC "); break;
155 case STB_GLOBAL: VG_(printf)("GLO "); break;
156 case STB_WEAK: VG_(printf)("WEA "); break;
157 case STB_LOPROC: VG_(printf)("lop "); break;
158 case STB_HIPROC: VG_(printf)("hip "); break;
159 default: VG_(printf)("??? "); break;
160 }
161 switch (ELFXX_ST_TYPE(sym->st_info)) {
162 case STT_NOTYPE: VG_(printf)("NOT "); break;
163 case STT_OBJECT: VG_(printf)("OBJ "); break;
164 case STT_FUNC: VG_(printf)("FUN "); break;
165 case STT_SECTION: VG_(printf)("SEC "); break;
166 case STT_FILE: VG_(printf)("FIL "); break;
167 case STT_LOPROC: VG_(printf)("lop "); break;
168 case STT_HIPROC: VG_(printf)("hip "); break;
169 default: VG_(printf)("??? "); break;
170 }
171 VG_(printf)(": svma %#010lx, %ssz %4ld %s\n",
172 sym_svma, space, sym->st_size + 0UL,
173 ( sym->st_name ? sym_name : (Char*)"NONAME" ) );
174 }
175
176
177 /* Decide whether SYM is something we should collect, and if so, copy
178 relevant info to the _OUT arguments. For {x86,amd64,ppc32}-linux
179 this is straightforward - the name, address, size are copied out
180 unchanged.
181
182 There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
183 below): we assume that the .bss is mapped immediately after .data,
184 and so accept any data symbol which exists in the range [start of
185 .data, size of .data + size of .bss). I don't know if this is
186 really correct/justifiable, or not.
187
188 For ppc64-linux it's more complex. If the symbol is seen to be in
189 the .opd section, it is taken to be a function descriptor, and so
190 a dereference is attempted, in order to get hold of the real entry
191 point address. Also as part of the dereference, there is an attempt
192 to calculate the TOC pointer (R2 value) associated with the symbol.
193
194 To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0),
195 if the symbol is seen to be outside the .opd section and its name
196 starts with a dot, an .opd deference is not attempted, and no TOC
197 pointer is calculated, but the the leading dot is removed from the
198 name.
199
200 As a result, on ppc64-linux, the caller of this function may have
201 to piece together the real size, address, name of the symbol from
202 multiple calls to this function. Ugly and confusing.
203 */
204 static
get_elf_symbol_info(struct _DebugInfo * di,ElfXX_Sym * sym,Char * sym_name,Addr sym_svma,Bool symtab_in_debug,UChar * opd_img,PtrdiffT opd_bias,Char ** sym_name_out,Addr * sym_avma_out,Int * sym_size_out,Addr * sym_tocptr_out,Bool * from_opd_out,Bool * is_text_out,Bool * is_ifunc)205 Bool get_elf_symbol_info (
206 /* INPUTS */
207 struct _DebugInfo* di, /* containing DebugInfo */
208 ElfXX_Sym* sym, /* ELF symbol */
209 Char* sym_name, /* name */
210 Addr sym_svma, /* address as stated in the object file */
211 Bool symtab_in_debug, /* symbol table is in the debug file */
212 UChar* opd_img, /* oimage of .opd sec (ppc64-linux only) */
213 PtrdiffT opd_bias, /* for biasing AVMAs found in .opd */
214 /* OUTPUTS */
215 Char** sym_name_out, /* name we should record */
216 Addr* sym_avma_out, /* addr we should record */
217 Int* sym_size_out, /* symbol size */
218 Addr* sym_tocptr_out, /* ppc64-linux only: R2 value to be
219 used on entry */
220 Bool* from_opd_out, /* ppc64-linux only: did we deref an
221 .opd entry? */
222 Bool* is_text_out, /* is this a text symbol? */
223 Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/
224 )
225 {
226 Bool plausible;
227 # if defined(VGP_ppc64_linux)
228 Bool is_in_opd;
229 # endif
230 Bool in_text, in_data, in_sdata, in_rodata, in_bss, in_sbss;
231 Addr text_svma, data_svma, sdata_svma, rodata_svma, bss_svma, sbss_svma;
232 PtrdiffT text_bias, data_bias, sdata_bias, rodata_bias, bss_bias, sbss_bias;
233
234 /* Set defaults */
235 *sym_name_out = sym_name;
236 *sym_avma_out = sym_svma; /* we will bias this shortly */
237 *is_text_out = True;
238 *sym_size_out = (Int)sym->st_size;
239 *sym_tocptr_out = 0; /* unknown/inapplicable */
240 *from_opd_out = False;
241 *is_ifunc = False;
242
243 /* Figure out if we're interested in the symbol. Firstly, is it of
244 the right flavour? */
245 plausible
246 = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
247 || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
248 || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
249 )
250 &&
251 (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
252 || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
253 #ifdef STT_GNU_IFUNC
254 || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
255 #endif
256 );
257
258 /* Work out the svma and bias for each section as it will appear in
259 addresses in the symbol table. */
260 if (symtab_in_debug) {
261 text_svma = di->text_debug_svma;
262 text_bias = di->text_debug_bias;
263 data_svma = di->data_debug_svma;
264 data_bias = di->data_debug_bias;
265 sdata_svma = di->sdata_debug_svma;
266 sdata_bias = di->sdata_debug_bias;
267 rodata_svma = di->rodata_debug_svma;
268 rodata_bias = di->rodata_debug_bias;
269 bss_svma = di->bss_debug_svma;
270 bss_bias = di->bss_debug_bias;
271 sbss_svma = di->sbss_debug_svma;
272 sbss_bias = di->sbss_debug_bias;
273 } else {
274 text_svma = di->text_svma;
275 text_bias = di->text_bias;
276 data_svma = di->data_svma;
277 data_bias = di->data_bias;
278 sdata_svma = di->sdata_svma;
279 sdata_bias = di->sdata_bias;
280 rodata_svma = di->rodata_svma;
281 rodata_bias = di->rodata_bias;
282 bss_svma = di->bss_svma;
283 bss_bias = di->bss_bias;
284 sbss_svma = di->sbss_svma;
285 sbss_bias = di->sbss_bias;
286 }
287
288 /* Now bias sym_avma_out accordingly by figuring out exactly which
289 section the symbol is from and bias accordingly. Screws up if
290 the previously deduced section svma address ranges are wrong. */
291 if (di->text_present
292 && di->text_size > 0
293 && sym_svma >= text_svma
294 && sym_svma < text_svma + di->text_size) {
295 *is_text_out = True;
296 *sym_avma_out += text_bias;
297 } else
298 if (di->data_present
299 && di->data_size > 0
300 && sym_svma >= data_svma
301 && sym_svma < data_svma + di->data_size) {
302 *is_text_out = False;
303 *sym_avma_out += data_bias;
304 } else
305 if (di->sdata_present
306 && di->sdata_size > 0
307 && sym_svma >= sdata_svma
308 && sym_svma < sdata_svma + di->sdata_size) {
309 *is_text_out = False;
310 *sym_avma_out += sdata_bias;
311 } else
312 if (di->rodata_present
313 && di->rodata_size > 0
314 && sym_svma >= rodata_svma
315 && sym_svma < rodata_svma + di->rodata_size) {
316 *is_text_out = False;
317 *sym_avma_out += rodata_bias;
318 } else
319 if (di->bss_present
320 && di->bss_size > 0
321 && sym_svma >= bss_svma
322 && sym_svma < bss_svma + di->bss_size) {
323 *is_text_out = False;
324 *sym_avma_out += bss_bias;
325 } else
326 if (di->sbss_present
327 && di->sbss_size > 0
328 && sym_svma >= sbss_svma
329 && sym_svma < sbss_svma + di->sbss_size) {
330 *is_text_out = False;
331 *sym_avma_out += sbss_bias;
332 } else {
333 /* Assume it's in .text. Is this a good idea? */
334 *is_text_out = True;
335 *sym_avma_out += text_bias;
336 }
337
338 # ifdef STT_GNU_IFUNC
339 /* Check for indirect functions. */
340 if (*is_text_out
341 && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
342 *is_ifunc = True;
343 }
344 # endif
345
346 # if defined(VGP_ppc64_linux)
347 /* Allow STT_NOTYPE in the very special case where we're running on
348 ppc64-linux and the symbol is one which the .opd-chasing hack
349 below will chase. */
350 if (!plausible
351 && *is_text_out
352 && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
353 && sym->st_size > 0
354 && di->opd_present
355 && di->opd_size > 0
356 && *sym_avma_out >= di->opd_avma
357 && *sym_avma_out < di->opd_avma + di->opd_size)
358 plausible = True;
359 # endif
360
361 if (!plausible)
362 return False;
363
364 /* Ignore if nameless. */
365 if (sym_name == (ElfXX_Word)0
366 || /* VG_(strlen)(sym_name) == 0 */
367 /* equivalent but cheaper ... */
368 sym_name[0] == 0) {
369 TRACE_SYMTAB(" ignore -- nameless: %s\n", sym_name);
370 return False;
371 }
372
373 /* Ignore if zero-sized. Except on Android:
374
375 On Android 2.3.5, some of the symbols that Memcheck needs to
376 intercept (for noise reduction purposes) have zero size, due to
377 lack of .size directives in handwritten assembly sources. So we
378 can't reject them out of hand -- instead give them a bogusly
379 large size and let canonicaliseSymtab trim them so they don't
380 overlap any following symbols. At least the following symbols
381 are known to be affected:
382
383 in /system/lib/libc.so: strlen strcmp strcpy memcmp memcpy
384 in /system/bin/linker: __dl_strcmp __dl_strlen
385 */
386 if (sym->st_size == 0) {
387 # if defined(VGPV_arm_linux_android)
388 *sym_size_out = 1024;
389 # else
390 TRACE_SYMTAB(" ignore -- size=0: %s\n", sym_name);
391 return False;
392 # endif
393 }
394
395 /* This seems to significantly reduce the number of junk
396 symbols, and particularly reduces the number of
397 overlapping address ranges. Don't ask me why ... */
398 if ((Int)sym->st_value == 0) {
399 TRACE_SYMTAB( " ignore -- valu=0: %s\n", sym_name);
400 return False;
401 }
402
403 /* If it's apparently in a GOT or PLT, it's really a reference to a
404 symbol defined elsewhere, so ignore it. */
405 if (di->got_present
406 && di->got_size > 0
407 && *sym_avma_out >= di->got_avma
408 && *sym_avma_out < di->got_avma + di->got_size) {
409 TRACE_SYMTAB(" ignore -- in GOT: %s\n", sym_name);
410 return False;
411 }
412 if (di->plt_present
413 && di->plt_size > 0
414 && *sym_avma_out >= di->plt_avma
415 && *sym_avma_out < di->plt_avma + di->plt_size) {
416 TRACE_SYMTAB(" ignore -- in PLT: %s\n", sym_name);
417 return False;
418 }
419
420 /* ppc64-linux nasty hack: if the symbol is in an .opd section,
421 then really what we have is the address of a function
422 descriptor. So use the first word of that as the function's
423 text.
424
425 See thread starting at
426 http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
427 */
428 # if defined(VGP_ppc64_linux)
429 is_in_opd = False;
430 # endif
431
432 if (di->opd_present
433 && di->opd_size > 0
434 && *sym_avma_out >= di->opd_avma
435 && *sym_avma_out < di->opd_avma + di->opd_size) {
436 # if !defined(VGP_ppc64_linux)
437 TRACE_SYMTAB(" ignore -- in OPD: %s\n", sym_name);
438 return False;
439 # else
440 Int offset_in_opd;
441 ULong* fn_descr;
442 Bool details = 1||False;
443
444 if (details)
445 TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
446 (void*)(opd_bias), (void*)*sym_avma_out);
447
448 if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
449 TRACE_SYMTAB(" ignore -- not 8-aligned: %s\n", sym_name);
450 return False;
451 }
452
453 /* *sym_avma_out is a vma pointing into the .opd section. We
454 know the vma of the opd section start, so we can figure out
455 how far into the opd section this is. */
456
457 offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
458 if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
459 TRACE_SYMTAB(" ignore -- invalid OPD offset: %s\n", sym_name);
460 return False;
461 }
462
463 /* Now we want to know what's at that offset in the .opd
464 section. We can't look in the running image since it won't
465 necessarily have been mapped. But we can consult the oimage.
466 opd_img is the start address of the .opd in the oimage.
467 Hence: */
468
469 fn_descr = (ULong*)(opd_img + offset_in_opd);
470
471 if (details)
472 TRACE_SYMTAB("opdXXY: offset %d, fn_descr %p\n",
473 offset_in_opd, fn_descr);
474 if (details)
475 TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
476
477 /* opd_bias is the what we have to add to SVMAs found in .opd to
478 get plausible .text AVMAs for the entry point, and .data
479 AVMAs (presumably) for the TOC locations. We use the caller
480 supplied value (which is di->text_bias) for both of these.
481 Not sure why that is correct - it seems to work, and sounds
482 OK for fn_descr[0], but surely we need to use the data bias
483 and not the text bias for fn_descr[1] ? Oh Well.
484 */
485 *sym_avma_out = fn_descr[0] + opd_bias;
486 *sym_tocptr_out = fn_descr[1] + opd_bias;
487 *from_opd_out = True;
488 is_in_opd = True;
489
490 /* Do a final sanity check: if the symbol falls outside the
491 DebugInfo's mapped range, ignore it. Since *sym_avma_out has
492 been updated, that can be achieved simply by falling through
493 to the test below. */
494
495 # endif /* ppc64-linux nasty hack */
496 }
497
498 /* Here's yet another ppc64-linux hack. Get rid of leading dot if
499 the symbol is outside .opd. */
500 # if defined(VGP_ppc64_linux)
501 if (di->opd_size > 0
502 && !is_in_opd
503 && sym_name[0] == '.') {
504 vg_assert(!(*from_opd_out));
505 *sym_name_out = &sym_name[1];
506 }
507 # endif
508
509 /* If no part of the symbol falls within the mapped range,
510 ignore it. */
511
512 in_text
513 = di->text_present
514 && di->text_size > 0
515 && !(*sym_avma_out + *sym_size_out <= di->text_avma
516 || *sym_avma_out >= di->text_avma + di->text_size);
517
518 in_data
519 = di->data_present
520 && di->data_size > 0
521 && !(*sym_avma_out + *sym_size_out <= di->data_avma
522 || *sym_avma_out >= di->data_avma + di->data_size);
523
524 in_sdata
525 = di->sdata_present
526 && di->sdata_size > 0
527 && !(*sym_avma_out + *sym_size_out <= di->sdata_avma
528 || *sym_avma_out >= di->sdata_avma + di->sdata_size);
529
530 in_rodata
531 = di->rodata_present
532 && di->rodata_size > 0
533 && !(*sym_avma_out + *sym_size_out <= di->rodata_avma
534 || *sym_avma_out >= di->rodata_avma + di->rodata_size);
535
536 in_bss
537 = di->bss_present
538 && di->bss_size > 0
539 && !(*sym_avma_out + *sym_size_out <= di->bss_avma
540 || *sym_avma_out >= di->bss_avma + di->bss_size);
541
542 in_sbss
543 = di->sbss_present
544 && di->sbss_size > 0
545 && !(*sym_avma_out + *sym_size_out <= di->sbss_avma
546 || *sym_avma_out >= di->sbss_avma + di->sbss_size);
547
548
549 if (*is_text_out) {
550 /* This used to reject any symbol falling outside the text
551 segment ("if (!in_text) ..."). Now it is relaxed slightly,
552 to reject only symbols which fall outside the area mapped
553 r-x. This is in accordance with r7427. See
554 "Comment_Regarding_Text_Range_Checks" in storage.c for
555 background. */
556 Bool in_rx;
557 vg_assert(di->fsm.have_rx_map);
558 in_rx = (!(*sym_avma_out + *sym_size_out <= di->fsm.rx_map_avma
559 || *sym_avma_out >= di->fsm.rx_map_avma
560 + di->fsm.rx_map_size));
561 if (in_text)
562 vg_assert(in_rx);
563 if (!in_rx) {
564 TRACE_SYMTAB(
565 "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
566 *sym_avma_out, *sym_avma_out + *sym_size_out,
567 di->text_avma,
568 di->text_avma + di->text_size);
569 return False;
570 }
571 } else {
572 if (!(in_data || in_sdata || in_rodata || in_bss || in_sbss)) {
573 TRACE_SYMTAB(
574 "ignore -- %#lx .. %#lx outside .data / .sdata / .rodata "
575 "/ .bss / .sbss svma ranges\n",
576 *sym_avma_out, *sym_avma_out + *sym_size_out);
577 return False;
578 }
579 }
580
581 # if defined(VGP_ppc64_linux)
582 /* It's crucial that we never add symbol addresses in the .opd
583 section. This would completely mess up function redirection and
584 intercepting. This assert ensures that anysymbols that make it
585 into the symbol table on ppc64-linux don't point into .opd. */
586 if (di->opd_present && di->opd_size > 0) {
587 vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
588 || *sym_avma_out >= di->opd_avma + di->opd_size);
589 }
590 # endif
591
592 /* Acquire! */
593 return True;
594 }
595
596
597 /* Read an ELF symbol table (normal or dynamic). This one is for the
598 "normal" case ({x86,amd64,ppc32}-linux). */
599 static
600 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__normal(struct _DebugInfo * di,UChar * tab_name,ElfXX_Sym * symtab_img,SizeT symtab_szB,UChar * strtab_img,SizeT strtab_szB,Bool symtab_in_debug,UChar * opd_img)601 void read_elf_symtab__normal(
602 struct _DebugInfo* di, UChar* tab_name,
603 ElfXX_Sym* symtab_img, SizeT symtab_szB,
604 UChar* strtab_img, SizeT strtab_szB,
605 Bool symtab_in_debug,
606 UChar* opd_img /* ppc64-linux only */
607 )
608 {
609 Word i;
610 Addr sym_svma, sym_avma_really;
611 Char *sym_name, *sym_name_really;
612 Int sym_size;
613 Addr sym_tocptr;
614 Bool from_opd, is_text, is_ifunc;
615 DiSym disym;
616 ElfXX_Sym *sym;
617
618 if (strtab_img == NULL || symtab_img == NULL) {
619 Char buf[80];
620 vg_assert(VG_(strlen)(tab_name) < 40);
621 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
622 ML_(symerr)(di, False, buf);
623 return;
624 }
625
626 TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n",
627 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
628
629 /* Perhaps should start at i = 1; ELF docs suggest that entry
630 0 always denotes 'unknown symbol'. */
631 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
632 sym = & symtab_img[i];
633 sym_name = (UChar*)(strtab_img + sym->st_name);
634 sym_svma = sym->st_value;
635
636 if (di->trace_symtab)
637 show_raw_elf_symbol(i, sym, sym_name, sym_svma, False);
638
639 if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
640 symtab_in_debug,
641 opd_img, di->text_bias,
642 &sym_name_really,
643 &sym_avma_really,
644 &sym_size,
645 &sym_tocptr,
646 &from_opd, &is_text, &is_ifunc)) {
647
648 disym.addr = sym_avma_really;
649 disym.tocptr = sym_tocptr;
650 disym.pri_name = ML_(addStr) ( di, sym_name_really, -1 );
651 disym.sec_names = NULL;
652 disym.size = sym_size;
653 disym.isText = is_text;
654 disym.isIFunc = is_ifunc;
655 vg_assert(disym.pri_name);
656 vg_assert(disym.tocptr == 0); /* has no role except on ppc64-linux */
657 ML_(addSym) ( di, &disym );
658
659 if (di->trace_symtab) {
660 VG_(printf)(" rec(%c) [%4ld]: "
661 " val %#010lx, sz %4d %s\n",
662 is_text ? 't' : 'd',
663 i,
664 disym.addr,
665 (Int)disym.size,
666 (HChar*)disym.pri_name
667 );
668 }
669
670 }
671 }
672 }
673
674
675 /* Read an ELF symbol table (normal or dynamic). This one is for
676 ppc64-linux, which requires special treatment. */
677
678 typedef
679 struct {
680 Addr addr;
681 UChar* name;
682 }
683 TempSymKey;
684
685 typedef
686 struct {
687 TempSymKey key;
688 Addr tocptr;
689 Int size;
690 Bool from_opd;
691 Bool is_text;
692 Bool is_ifunc;
693 }
694 TempSym;
695
cmp_TempSymKey(TempSymKey * key1,TempSym * elem2)696 static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
697 if (key1->addr < elem2->key.addr) return -1;
698 if (key1->addr > elem2->key.addr) return 1;
699 return (Word)VG_(strcmp)(key1->name, elem2->key.name);
700 }
701
702 static
703 __attribute__((unused)) /* not referred to on all targets */
read_elf_symtab__ppc64_linux(struct _DebugInfo * di,UChar * tab_name,ElfXX_Sym * symtab_img,SizeT symtab_szB,UChar * strtab_img,SizeT strtab_szB,Bool symtab_in_debug,UChar * opd_img)704 void read_elf_symtab__ppc64_linux(
705 struct _DebugInfo* di, UChar* tab_name,
706 ElfXX_Sym* symtab_img, SizeT symtab_szB,
707 UChar* strtab_img, SizeT strtab_szB,
708 Bool symtab_in_debug,
709 UChar* opd_img /* ppc64-linux only */
710 )
711 {
712 Word i;
713 Int old_size;
714 Addr sym_svma, sym_avma_really;
715 Char *sym_name, *sym_name_really;
716 Int sym_size;
717 Addr sym_tocptr;
718 Bool from_opd, modify_size, modify_tocptr, is_text, is_ifunc;
719 DiSym disym;
720 ElfXX_Sym *sym;
721 OSet *oset;
722 TempSymKey key;
723 TempSym *elem;
724 TempSym *prev;
725
726 if (strtab_img == NULL || symtab_img == NULL) {
727 Char buf[80];
728 vg_assert(VG_(strlen)(tab_name) < 40);
729 VG_(sprintf)(buf, " object doesn't have a %s", tab_name);
730 ML_(symerr)(di, False, buf);
731 return;
732 }
733
734 TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n",
735 tab_name, symtab_szB/sizeof(ElfXX_Sym) );
736
737 oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
738 (OSetCmp_t)cmp_TempSymKey,
739 ML_(dinfo_zalloc), "di.respl.1",
740 ML_(dinfo_free) );
741 vg_assert(oset);
742
743 /* Perhaps should start at i = 1; ELF docs suggest that entry
744 0 always denotes 'unknown symbol'. */
745 for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
746 sym = & symtab_img[i];
747 sym_name = (Char*)(strtab_img + sym->st_name);
748 sym_svma = sym->st_value;
749
750 if (di->trace_symtab)
751 show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
752
753 if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
754 symtab_in_debug,
755 opd_img, di->text_bias,
756 &sym_name_really,
757 &sym_avma_really,
758 &sym_size,
759 &sym_tocptr,
760 &from_opd, &is_text, &is_ifunc)) {
761
762 /* Check if we've seen this (name,addr) key before. */
763 key.addr = sym_avma_really;
764 key.name = sym_name_really;
765 prev = VG_(OSetGen_Lookup)( oset, &key );
766
767 if (prev) {
768
769 /* Seen it before. Fold in whatever new info we can. */
770 modify_size = False;
771 modify_tocptr = False;
772 old_size = 0;
773
774 if (prev->from_opd && !from_opd
775 && (prev->size == 24 || prev->size == 16)
776 && sym_size != prev->size) {
777 /* Existing one is an opd-redirect, with a bogus size,
778 so the only useful new fact we have is the real size
779 of the symbol. */
780 modify_size = True;
781 old_size = prev->size;
782 prev->size = sym_size;
783 }
784 else
785 if (!prev->from_opd && from_opd
786 && (sym_size == 24 || sym_size == 16)) {
787 /* Existing one is non-opd, new one is opd. What we
788 can acquire from the new one is the TOC ptr to be
789 used. Since the existing sym is non-toc, it
790 shouldn't currently have an known TOC ptr. */
791 vg_assert(prev->tocptr == 0);
792 modify_tocptr = True;
793 prev->tocptr = sym_tocptr;
794 }
795 else {
796 /* ignore. can we do better here? */
797 }
798
799 /* Only one or the other is possible (I think) */
800 vg_assert(!(modify_size && modify_tocptr));
801
802 if (modify_size && di->trace_symtab) {
803 VG_(printf)(" modify (old sz %4d) "
804 " val %#010lx, toc %#010lx, sz %4d %s\n",
805 old_size,
806 prev->key.addr,
807 prev->tocptr,
808 (Int) prev->size,
809 (HChar*)prev->key.name
810 );
811 }
812 if (modify_tocptr && di->trace_symtab) {
813 VG_(printf)(" modify (upd tocptr) "
814 " val %#010lx, toc %#010lx, sz %4d %s\n",
815 prev->key.addr,
816 prev->tocptr,
817 (Int) prev->size,
818 (HChar*)prev->key.name
819 );
820 }
821
822 } else {
823
824 /* A new (name,addr) key. Add and continue. */
825 elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
826 vg_assert(elem);
827 elem->key = key;
828 elem->tocptr = sym_tocptr;
829 elem->size = sym_size;
830 elem->from_opd = from_opd;
831 elem->is_text = is_text;
832 elem->is_ifunc = is_ifunc;
833 VG_(OSetGen_Insert)(oset, elem);
834 if (di->trace_symtab) {
835 VG_(printf)(" to-oset [%4ld]: "
836 " val %#010lx, toc %#010lx, sz %4d %s\n",
837 i,
838 elem->key.addr,
839 elem->tocptr,
840 (Int) elem->size,
841 (HChar*)elem->key.name
842 );
843 }
844
845 }
846 }
847 }
848
849 /* All the syms that matter are in the oset. Now pull them out,
850 build a "standard" symbol table, and nuke the oset. */
851
852 i = 0;
853 VG_(OSetGen_ResetIter)( oset );
854
855 while ( (elem = VG_(OSetGen_Next)(oset)) ) {
856 disym.addr = elem->key.addr;
857 disym.tocptr = elem->tocptr;
858 disym.pri_name = ML_(addStr) ( di, elem->key.name, -1 );
859 disym.sec_names = NULL;
860 disym.size = elem->size;
861 disym.isText = elem->is_text;
862 disym.isIFunc = elem->is_ifunc;
863 vg_assert(disym.pri_name != NULL);
864
865 ML_(addSym) ( di, &disym );
866 if (di->trace_symtab) {
867 VG_(printf)(" rec(%c) [%4ld]: "
868 " val %#010lx, toc %#010lx, sz %4d %s\n",
869 disym.isText ? 't' : 'd',
870 i,
871 disym.addr,
872 disym.tocptr,
873 (Int) disym.size,
874 (HChar*)disym.pri_name
875 );
876 }
877 i++;
878 }
879
880 VG_(OSetGen_Destroy)( oset );
881 }
882
883
884 /*
885 * Look for a build-id in an ELF image. The build-id specification
886 * can be found here:
887 *
888 * http://fedoraproject.org/wiki/RolandMcGrath/BuildID
889 */
890 static
find_buildid(Addr image,UWord n_image)891 Char *find_buildid(Addr image, UWord n_image)
892 {
893 Char* buildid = NULL;
894 __attribute__((unused)) /* on Android, at least */
895 ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
896
897 #ifdef NT_GNU_BUILD_ID
898 if (n_image >= sizeof(ElfXX_Ehdr) &&
899 ML_(is_elf_object_file)(ehdr, n_image)) {
900 Word i;
901
902 for (i = 0; i < ehdr->e_phnum; i++) {
903 ElfXX_Phdr* phdr
904 = (ElfXX_Phdr*)(image + ehdr->e_phoff + i * ehdr->e_phentsize);
905
906 if (phdr->p_type == PT_NOTE) {
907 ElfXX_Off offset = phdr->p_offset;
908
909 while (offset < phdr->p_offset + phdr->p_filesz) {
910 ElfXX_Nhdr* note = (ElfXX_Nhdr*)(image + offset);
911 Char* name = (Char *)note + sizeof(ElfXX_Nhdr);
912 UChar *desc = (UChar *)name + ((note->n_namesz + 3) & ~3);
913 Word j;
914
915 if (VG_(strcmp)(name, ELF_NOTE_GNU) == 0 &&
916 note->n_type == NT_GNU_BUILD_ID) {
917 buildid = ML_(dinfo_zalloc)("di.fbi.1",
918 note->n_descsz * 2 + 1);
919
920 for (j = 0; j < note->n_descsz; j++) {
921 VG_(sprintf)(buildid + VG_(strlen)(buildid),
922 "%02x", desc[j]);
923 }
924 }
925
926 offset = offset + sizeof(ElfXX_Nhdr)
927 + ((note->n_namesz + 3) & ~3)
928 + ((note->n_descsz + 3) & ~3);
929 }
930 }
931 }
932 }
933 #endif
934
935 return buildid;
936 }
937
938 /*
939 * This routine for calculating the CRC for a separate debug file
940 * is GPLed code borrowed from GNU binutils.
941 */
942 static UInt
calc_gnu_debuglink_crc32(UInt crc,const UChar * buf,Int len)943 calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
944 {
945 static const UInt crc32_table[256] =
946 {
947 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
948 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
949 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
950 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
951 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
952 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
953 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
954 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
955 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
956 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
957 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
958 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
959 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
960 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
961 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
962 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
963 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
964 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
965 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
966 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
967 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
968 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
969 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
970 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
971 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
972 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
973 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
974 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
975 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
976 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
977 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
978 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
979 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
980 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
981 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
982 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
983 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
984 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
985 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
986 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
987 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
988 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
989 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
990 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
991 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
992 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
993 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
994 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
995 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
996 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
997 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
998 0x2d02ef8d
999 };
1000 const UChar *end;
1001
1002 crc = ~crc & 0xffffffff;
1003 for (end = buf + len; buf < end; ++ buf)
1004 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
1005 return ~crc & 0xffffffff;;
1006 }
1007
1008 /*
1009 * Try and open a separate debug file, ignoring any where the CRC does
1010 * not match the value from the main object file.
1011 */
1012 static
open_debug_file(Char * name,Char * buildid,UInt crc,UWord * size)1013 Addr open_debug_file( Char* name, Char* buildid, UInt crc, /*OUT*/UWord* size )
1014 {
1015 SysRes fd, sres;
1016 struct vg_stat stat_buf;
1017 UInt calccrc;
1018
1019 fd = VG_(open)(name, VKI_O_RDONLY, 0);
1020 if (sr_isError(fd))
1021 return 0;
1022
1023 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1024 VG_(close)(sr_Res(fd));
1025 return 0;
1026 }
1027
1028 if (VG_(clo_verbosity) > 1)
1029 VG_(message)(Vg_DebugMsg, " Considering %s ..\n", name);
1030
1031 *size = stat_buf.size;
1032
1033 sres = VG_(am_mmap_file_float_valgrind)
1034 ( *size, VKI_PROT_READ, sr_Res(fd), 0 );
1035
1036 VG_(close)(sr_Res(fd));
1037
1038 if (sr_isError(sres))
1039 return 0;
1040
1041 if (buildid) {
1042 Char* debug_buildid = find_buildid(sr_Res(sres), *size);
1043 if (debug_buildid == NULL || VG_(strcmp)(buildid, debug_buildid) != 0) {
1044 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1045 vg_assert(!sr_isError(res));
1046 if (VG_(clo_verbosity) > 1)
1047 VG_(message)(Vg_DebugMsg,
1048 " .. build-id mismatch (found %s wanted %s)\n",
1049 debug_buildid, buildid);
1050 ML_(dinfo_free)(debug_buildid);
1051 return 0;
1052 }
1053 ML_(dinfo_free)(debug_buildid);
1054
1055 if (VG_(clo_verbosity) > 1)
1056 VG_(message)(Vg_DebugMsg, " .. build-id is valid\n");
1057 } else {
1058 calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size);
1059 if (calccrc != crc) {
1060 SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size);
1061 vg_assert(!sr_isError(res));
1062 if (VG_(clo_verbosity) > 1)
1063 VG_(message)(Vg_DebugMsg,
1064 " .. CRC mismatch (computed %08x wanted %08x)\n", calccrc, crc);
1065 return 0;
1066 }
1067
1068 if (VG_(clo_verbosity) > 1)
1069 VG_(message)(Vg_DebugMsg, " .. CRC is valid\n");
1070 }
1071
1072 return sr_Res(sres);
1073 }
1074
1075
1076 /* Try to find and map in a debuginfo file by some totally ad-hoc
1077 scheme. If successful, set *dimage and *n_dimage to point to the
1078 image, and return True, else return False. A temporary hack for
1079 Android; does nothing on any other platform. */
1080 static
find_ad_hoc_debug_image(struct _DebugInfo * di,Char * filename,Addr * dimage,SizeT * n_dimage)1081 Bool find_ad_hoc_debug_image( struct _DebugInfo* di,
1082 Char* filename,
1083 /*OUT*/Addr* dimage,
1084 /*OUT*/SizeT* n_dimage )
1085 {
1086 vg_assert(*dimage == 0 && *n_dimage == 0);
1087
1088 # if !defined(VGPV_arm_linux_android)
1089 return False; /* we don't know narfink */
1090
1091 # else /* android specific hacks; look away now. */
1092
1093 /* The deal is: if we're looking for for a debuginfo file for some
1094 object /system/blah (where blah can be any path), see if we can
1095 find the file /sdcard/symbols/system/blah. So for example it
1096 produces the following mappings, both of which are important for
1097 Memcheck:
1098
1099 /system/bin/linker --> /sdcard/symbols/system/bin/linker
1100 /system/lib/libc.so --> /sdcard/symbols/system/lib/libc.so
1101
1102 These /symbols files come from the AOSP build tree for your
1103 device, for example out/target/product/crespo/symbols/system
1104 (for a Nexus S), so one simple thing you can do is take the tree
1105 rooted at out/target/product/crespo/symbols/system on the host
1106 and park it at /sdcard/symbols/system on the device. Then,
1107 assuming it matches what's actually running on the device,
1108 you'll have full debuginfo for all the libraries on the device.
1109
1110 But beware: there is no checking that the debuginfo file, if
1111 found, matches the main file in any way.
1112 */
1113 if (0 != VG_(strncmp)(filename, "/system/", 8))
1114 return False;
1115
1116 HChar* nm = ML_(dinfo_zalloc)("di.fahdi.1",
1117 50 + VG_(strlen)(filename));
1118 VG_(sprintf)(nm, "/sdcard/symbols%s", filename);
1119
1120 SysRes fd = VG_(open)(nm, VKI_O_RDONLY, 0);
1121 if (sr_isError(fd)) goto fail;
1122
1123 struct vg_stat stat_buf;
1124 if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) {
1125 VG_(close)(sr_Res(fd));
1126 goto fail;
1127 }
1128
1129 *n_dimage = stat_buf.size;
1130
1131 SysRes sres = VG_(am_mmap_file_float_valgrind)
1132 ( *n_dimage, VKI_PROT_READ, sr_Res(fd), 0 );
1133
1134 VG_(close)(sr_Res(fd));
1135 if (sr_isError(sres))
1136 goto fail;
1137
1138 *dimage = sr_Res(sres);
1139
1140 if (VG_(clo_verbosity) > 1)
1141 VG_(dmsg)(" Using debuginfo from %s\n", nm);
1142
1143 ML_(dinfo_free)(nm);
1144 return True;
1145
1146 fail:
1147 if (nm) ML_(dinfo_free)(nm);
1148 return False;
1149
1150 # endif
1151 }
1152
1153
1154 /* Try to find a separate debug file for a given object file. If
1155 found, it will be mapped in and the address and size returned in
1156 *dimage and *n_dimage. If not, *dimage and *n_dimage will be
1157 unchanged. The caller should set them to zero before the call. */
1158 static
find_debug_file(struct _DebugInfo * di,Char * objpath,Char * buildid,Char * debugname,UInt crc,Addr * dimage,SizeT * n_dimage)1159 void find_debug_file( struct _DebugInfo* di,
1160 Char* objpath, Char* buildid,
1161 Char* debugname, UInt crc,
1162 /*OUT*/Addr* dimage,
1163 /*OUT*/SizeT* n_dimage )
1164 {
1165 Char* debugpath = NULL;
1166 Addr addr = 0;
1167 UWord size = 0;
1168
1169 vg_assert(*dimage == 0 && *n_dimage == 0);
1170
1171 if (buildid != NULL) {
1172 debugpath = ML_(dinfo_zalloc)(
1173 "di.fdf.1",
1174 VG_(strlen)(buildid) + 33);
1175
1176 VG_(sprintf)(debugpath, "/usr/lib/debug/.build-id/%c%c/%s.debug",
1177 buildid[0], buildid[1], buildid + 2);
1178
1179 if ((addr = open_debug_file(debugpath, buildid, 0, &size)) == 0) {
1180 ML_(dinfo_free)(debugpath);
1181 debugpath = NULL;
1182 }
1183 }
1184
1185 if (addr == 0 && debugname != NULL) {
1186 Char *objdir = ML_(dinfo_strdup)("di.fdf.2", objpath);
1187 Char *objdirptr;
1188
1189 if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
1190 *objdirptr = '\0';
1191
1192 debugpath = ML_(dinfo_zalloc)(
1193 "di.fdf.3",
1194 VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
1195
1196 VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
1197
1198 if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1199 VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
1200 if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1201 VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
1202 if ((addr = open_debug_file(debugpath, NULL, crc, &size)) == 0) {
1203 #ifdef ANDROID
1204 VG_(sprintf)(debugpath, "/data/local/symbols%s/%s", objdir, debugname);
1205 addr = open_debug_file(debugpath, NULL, crc, &size);
1206 #endif
1207 }
1208
1209 }
1210 }
1211
1212 ML_(dinfo_free)(objdir);
1213 }
1214
1215 if (addr > 0 && size > 0) {
1216 TRACE_SYMTAB("\n");
1217 TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
1218 *dimage = addr;
1219 *n_dimage = size;
1220 }
1221
1222 ML_(dinfo_free)(debugpath);
1223 }
1224
1225
contained_within(Addr outer,UWord n_outer,Addr inner,UWord n_inner)1226 static Bool contained_within ( Addr outer, UWord n_outer,
1227 Addr inner, UWord n_inner )
1228 {
1229 if (n_outer == 0 || n_inner == 0)
1230 return False;
1231 /* Simplistic .. assumes no wraparound (reasonably enough) */
1232 if (inner >= outer && inner+n_inner <= outer+n_outer)
1233 return True;
1234 return False;
1235 }
1236
INDEX_BIS(void * base,Word idx,Word scale)1237 static void* INDEX_BIS ( void* base, Word idx, Word scale ) {
1238 return (void*)( ((UChar*)base) + idx * scale );
1239 }
1240
1241
1242 /* Find the file offset corresponding to SVMA by using the program
1243 headers. This is taken from binutils-2.17/binutils/readelf.c
1244 offset_from_vma(). */
1245 static
file_offset_from_svma(Bool * ok,Addr svma,ElfXX_Phdr * phdr_img,Word phdr_nent,Word phdr_ent_szB)1246 Word file_offset_from_svma ( /*OUT*/Bool* ok,
1247 Addr svma,
1248 ElfXX_Phdr* phdr_img,
1249 Word phdr_nent,
1250 Word phdr_ent_szB )
1251 {
1252 Word i;
1253 ElfXX_Phdr* seg;
1254 for (i = 0; i < phdr_nent; i++) {
1255 seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1256 if (seg->p_type != PT_LOAD)
1257 continue;
1258 if (svma >= (seg->p_vaddr & -seg->p_align)
1259 && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
1260 *ok = True;
1261 return svma - seg->p_vaddr + seg->p_offset;
1262 }
1263 }
1264 *ok = False;
1265 return 0;
1266 }
1267
1268
1269 /* The central function for reading ELF debug info. For the
1270 object/exe specified by the DebugInfo, find ELF sections, then read
1271 the symbols, line number info, file name info, CFA (stack-unwind
1272 info) and anything else we want, into the tables within the
1273 supplied DebugInfo.
1274 */
1275
1276 /* Temporarily holds information copied out of PT_LOAD entries
1277 in ML_(read_elf_debug_info. */
1278 typedef
1279 struct { Addr svma_base; Addr svma_limit; PtrdiffT bias; }
1280 RangeAndBias;
1281
ML_(read_elf_debug_info)1282 Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
1283 {
1284 /* This function is long and complex. That, and the presence of
1285 nested scopes, means it's not always easy to see which parts are
1286 in loops/conditionals and which aren't. To make it easier to
1287 follow, points executed exactly once -- that is, those which are
1288 the top level of the function -- are marked TOPLEVEL.
1289 */
1290 /* TOPLEVEL */
1291 Bool res, ok;
1292 SysRes fd, sres;
1293 Word i;
1294 Bool dynbss_present = False;
1295 Bool sdynbss_present = False;
1296
1297 /* Image addresses for the ELF file we're working with. */
1298 Addr oimage = 0;
1299 UWord n_oimage = 0;
1300
1301 /* Ditto for any ELF debuginfo file that we might happen to load. */
1302 Addr dimage = 0;
1303 UWord n_dimage = 0;
1304
1305 /* ELF header for the main file. Should == oimage since is at
1306 start of file. */
1307 ElfXX_Ehdr* ehdr_img = NULL;
1308
1309 /* Program header table image addr, # entries, entry size */
1310 ElfXX_Phdr* phdr_img = NULL;
1311 UWord phdr_nent = 0;
1312 UWord phdr_ent_szB = 0;
1313
1314 /* Section header image addr, # entries, entry size. Also the
1315 associated string table. */
1316 ElfXX_Shdr* shdr_img = NULL;
1317 UWord shdr_nent = 0;
1318 UWord shdr_ent_szB = 0;
1319 UChar* shdr_strtab_img = NULL;
1320
1321 /* SVMAs covered by rx and rw segments and corresponding biases.
1322 We keep separate lists of rx and rw areas. Each can have up to
1323 N_RX_RW_AREAS entries. Normally each object would provide just
1324 one rx and one rw area, but Mike Hommey's elfhack creates
1325 objects with two rx PT_LOAD entries, hence the generality. */
1326 const Int N_RX_RW_AREAS = 2;
1327
1328 RangeAndBias rx[N_RX_RW_AREAS];
1329 RangeAndBias rw[N_RX_RW_AREAS];
1330 Word n_rx = 0; /* 0 .. N_RX_RW_AREAS */
1331 Word n_rw = 0; /* 0 .. N_RX_RW_AREAS */
1332 /* Pointless paranoia: */
1333 VG_(memset)( rx, 0, sizeof(rx) );
1334 VG_(memset)( rw, 0, sizeof(rw) );
1335
1336 /* Build ID */
1337 Char* buildid = NULL;
1338
1339 vg_assert(di);
1340 vg_assert(di->fsm.have_rx_map == True);
1341 vg_assert(di->fsm.have_rw_map == True);
1342 vg_assert(di->fsm.rx_map_size > 0);
1343 vg_assert(di->fsm.rw_map_size > 0);
1344 vg_assert(di->have_dinfo == False);
1345 vg_assert(di->fsm.filename);
1346 vg_assert(!di->symtab);
1347 vg_assert(!di->loctab);
1348 vg_assert(!di->cfsi);
1349 vg_assert(!di->cfsi_exprs);
1350 vg_assert(!di->strchunks);
1351 vg_assert(!di->soname);
1352
1353 /* If these don't hold true, it means that m_syswrap/m_aspacemgr
1354 managed to do a mapping where the start isn't page aligned.
1355 Which sounds pretty bogus to me. */
1356 vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rx_map_avma));
1357 vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rw_map_avma));
1358
1359 /* ----------------------------------------------------------
1360 At this point, there is very little information in the
1361 DebugInfo. We only know that something that looks like an ELF
1362 file has been mapped rx-ishly as recorded with the di->*rx_map*
1363 fields and has also been mapped rw-ishly as recorded with the
1364 di->*rw_map* fields. First we examine the file's ELF Program
1365 Header, and, by comparing that against the di->*r{w,x}_map*
1366 info, try to figure out the AVMAs for the sections we care
1367 about, that should have been mapped: text, data, sdata, bss,
1368 got, plt, and toc.
1369 ---------------------------------------------------------- */
1370
1371 res = False;
1372
1373 oimage = (Addr)NULL;
1374 if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1375 VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)\n",
1376 di->fsm.filename, di->fsm.rx_map_avma );
1377
1378 /* mmap the object image aboard, so that we can read symbols and
1379 line number info out of it. It will be munmapped immediately
1380 thereafter; it is only aboard transiently. */
1381
1382 fd = VG_(open)(di->fsm.filename, VKI_O_RDONLY, 0);
1383 if (sr_isError(fd)) {
1384 ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
1385 return False;
1386 }
1387
1388 { Long n_oimageLL = VG_(fsize)(sr_Res(fd));
1389 if (n_oimageLL <= 0) {
1390 ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
1391 VG_(close)(sr_Res(fd));
1392 return False;
1393 }
1394 n_oimage = (UWord)(ULong)n_oimageLL;
1395 }
1396
1397 sres = VG_(am_mmap_file_float_valgrind)
1398 ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 );
1399
1400 VG_(close)(sr_Res(fd));
1401
1402 if (sr_isError(sres)) {
1403 VG_(message)(Vg_UserMsg, "warning: mmap failed on %s\n",
1404 di->fsm.filename );
1405 VG_(message)(Vg_UserMsg, " no symbols or debug info loaded\n" );
1406 return False;
1407 }
1408
1409 oimage = sr_Res(sres);
1410 /* Check against wraparound. am_mmap_file_float_valgrind should
1411 not produce a wrapped-around mapping. */
1412 vg_assert(n_oimage > 0);
1413 vg_assert(oimage + n_oimage > oimage);
1414
1415 if (0) {
1416 VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n",
1417 (void*)oimage, (void*)(oimage + (UWord)n_oimage));
1418 }
1419
1420 /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. Now
1421 verify that it is a valid ELF .so or executable image. */
1422 res = False;
1423 ok = (n_oimage >= sizeof(ElfXX_Ehdr));
1424 ehdr_img = (ElfXX_Ehdr*)oimage;
1425
1426 if (ok)
1427 ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage);
1428
1429 if (!ok) {
1430 ML_(symerr)(di, True, "Invalid ELF Header");
1431 goto out;
1432 }
1433
1434 /* Find where the program and section header tables are, and give
1435 up if either is missing or outside the image (bogus). */
1436 phdr_img = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
1437 phdr_nent = ehdr_img->e_phnum;
1438 phdr_ent_szB = ehdr_img->e_phentsize;
1439
1440 shdr_img = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
1441 shdr_nent = ehdr_img->e_shnum;
1442 shdr_ent_szB = ehdr_img->e_shentsize;
1443
1444 TRACE_SYMTAB("------ Basic facts about the object ------\n");
1445 TRACE_SYMTAB("object: img %p n_oimage %ld\n",
1446 (void*)oimage, n_oimage);
1447 TRACE_SYMTAB("phdr: img %p nent %ld ent_szB %ld\n",
1448 phdr_img, phdr_nent, phdr_ent_szB);
1449 TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n",
1450 shdr_img, shdr_nent, shdr_ent_szB);
1451 TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n",
1452 di->fsm.rx_map_avma, di->fsm.rx_map_size, di->fsm.rx_map_foff);
1453 TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n",
1454 di->fsm.rw_map_avma, di->fsm.rw_map_size, di->fsm.rw_map_foff);
1455
1456 if (phdr_nent == 0
1457 || !contained_within(
1458 oimage, n_oimage,
1459 (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
1460 ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1461 goto out;
1462 }
1463
1464 if (shdr_nent == 0
1465 || !contained_within(
1466 oimage, n_oimage,
1467 (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
1468 ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1469 goto out;
1470 }
1471
1472 /* Also find the section header's string table, and validate. */
1473 /* checked previously by is_elf_object_file: */
1474 vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
1475
1476 shdr_strtab_img
1477 = (UChar*)( ((UChar*)ehdr_img)
1478 + shdr_img[ehdr_img->e_shstrndx].sh_offset);
1479 if (!contained_within( oimage, n_oimage,
1480 (Addr)shdr_strtab_img,
1481 1/*bogus, but we don't know the real size*/ )) {
1482 ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1483 goto out;
1484 }
1485
1486 TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img );
1487
1488 /* TOPLEVEL */
1489 /* Look through the program header table, and:
1490 - copy information from suitable PT_LOAD entries into rx[] or
1491 rw[]
1492 - find (or fake up) the .soname for this object.
1493 */
1494 TRACE_SYMTAB("\n");
1495 TRACE_SYMTAB("------ Examining the program headers ------\n");
1496 vg_assert(di->soname == NULL);
1497 {
1498 /* TOPLEVEL */
1499 ElfXX_Addr prev_svma = 0;
1500
1501 for (i = 0; i < phdr_nent; i++) {
1502 ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1503
1504 /* Make sure the PT_LOADable entries are in order and
1505 non-overlapping. This in turn means the address ranges
1506 slurped into rx[] and rw[] are in order and
1507 non-overlapping. */
1508 vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS);
1509 vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS);
1510
1511 if (phdr->p_type == PT_LOAD) {
1512 TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n",
1513 i, (UWord)phdr->p_vaddr, (UWord)prev_svma);
1514 TRACE_SYMTAB("PT_LOAD[%ld]: p_offset %lu, p_filesz %lu,"
1515 " perms %c%c%c\n",
1516 i, (UWord)phdr->p_offset, (UWord)phdr->p_filesz,
1517 phdr->p_flags & PF_R ? 'r' : '-',
1518 phdr->p_flags & PF_W ? 'w' : '-',
1519 phdr->p_flags & PF_X ? 'x' : '-');
1520 if (phdr->p_vaddr < prev_svma) {
1521 ML_(symerr)(di, True,
1522 "ELF Program Headers are not in ascending order");
1523 goto out;
1524 }
1525 prev_svma = phdr->p_vaddr;
1526 if (phdr->p_offset >= di->fsm.rx_map_foff
1527 && phdr->p_offset < di->fsm.rx_map_foff + di->fsm.rx_map_size
1528 && phdr->p_offset + phdr->p_filesz
1529 <= di->fsm.rx_map_foff + di->fsm.rx_map_size
1530 && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_X)) {
1531 if (n_rx == N_RX_RW_AREAS) {
1532 ML_(symerr)(di, True,
1533 "N_RX_RW_AREAS is too low; "
1534 "increase and recompile.");
1535 goto out;
1536 }
1537 rx[n_rx].svma_base = phdr->p_vaddr;
1538 rx[n_rx].svma_limit = phdr->p_vaddr + phdr->p_memsz;
1539 rx[n_rx].bias = di->fsm.rx_map_avma - di->fsm.rx_map_foff
1540 + phdr->p_offset - phdr->p_vaddr;
1541 n_rx++;
1542 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i);
1543 }
1544 else
1545 if (phdr->p_offset >= di->fsm.rw_map_foff
1546 && phdr->p_offset < di->fsm.rw_map_foff + di->fsm.rw_map_size
1547 && phdr->p_offset + phdr->p_filesz
1548 <= di->fsm.rw_map_foff + di->fsm.rw_map_size
1549 && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_W)) {
1550 if (n_rw == N_RX_RW_AREAS) {
1551 ML_(symerr)(di, True,
1552 "N_RX_RW_AREAS is too low; "
1553 "increase and recompile.");
1554 goto out;
1555 }
1556 rw[n_rw].svma_base = phdr->p_vaddr;
1557 rw[n_rw].svma_limit = phdr->p_vaddr + phdr->p_memsz;
1558 rw[n_rw].bias = di->fsm.rw_map_avma - di->fsm.rw_map_foff
1559 + phdr->p_offset - phdr->p_vaddr;
1560 n_rw++;
1561 TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i);
1562 }
1563 }
1564
1565 /* Try to get the soname. If there isn't one, use "NONE".
1566 The seginfo needs to have some kind of soname in order to
1567 facilitate writing redirect functions, since all redirect
1568 specifications require a soname (pattern). */
1569 if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
1570 ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
1571 + phdr->p_offset);
1572 Word stroff = -1;
1573 UChar* strtab = NULL;
1574 Word j;
1575 for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
1576 switch (dyn_img[j].d_tag) {
1577 case DT_SONAME: {
1578 stroff = dyn_img[j].d_un.d_val;
1579 break;
1580 }
1581 case DT_STRTAB: {
1582 Bool ok2 = False;
1583 Word offset = file_offset_from_svma(
1584 &ok2,
1585 dyn_img[j].d_un.d_ptr,
1586 phdr_img,
1587 phdr_nent, phdr_ent_szB
1588 );
1589 if (ok2 && strtab == NULL) {
1590 vg_assert(offset >= 0 && offset <= n_oimage);
1591 strtab = ((UChar*)ehdr_img) + offset;
1592 }
1593 break;
1594 }
1595 default:
1596 break;
1597 }
1598 }
1599 if (stroff != -1 && strtab != NULL) {
1600 TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
1601 di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff);
1602 }
1603 }
1604 } /* for (i = 0; i < phdr_nent; i++) ... */
1605 /* TOPLEVEL */
1606
1607 } /* examine the program headers (local scope) */
1608
1609 /* TOPLEVEL */
1610
1611 /* If, after looking at all the program headers, we still didn't
1612 find a soname, add a fake one. */
1613 if (di->soname == NULL) {
1614 TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
1615 di->soname = "NONE";
1616 }
1617
1618 // NaCl nexe
1619 if (ehdr_img->e_ident[EI_OSABI] == 0x7b) {
1620 HChar* s = VG_(arena_malloc)(VG_AR_DINFO, "di.redi.1", 6 + VG_(strlen)(di->soname));
1621 VG_(strcpy)(s, "NaCl_");
1622 VG_(strcpy)(s + 5, di->soname);
1623 di->soname = s;
1624 TRACE_SYMTAB("Fixed soname = %s\n", di->soname);
1625 }
1626
1627
1628 vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS);
1629 vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS);
1630 for (i = 0; i < n_rx; i++) {
1631 vg_assert(rx[i].svma_limit != 0);
1632 }
1633 for (i = 0; i < n_rw; i++) {
1634 vg_assert(rw[i].svma_limit != 0);
1635 }
1636
1637 /* Now read the section table. */
1638 TRACE_SYMTAB("\n");
1639 TRACE_SYMTAB("------ Examining the section headers ------\n");
1640 TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1641 di->fsm.rx_map_avma,
1642 di->fsm.rx_map_foff,
1643 di->fsm.rx_map_foff + di->fsm.rx_map_size - 1 );
1644 for (i = 0; i < n_rx; i++) {
1645 TRACE_SYMTAB("rx[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n",
1646 i, rx[i].svma_base, rx[i].svma_limit - 1, rx[i].bias );
1647 }
1648 TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1649 di->fsm.rw_map_avma,
1650 di->fsm.rw_map_foff,
1651 di->fsm.rw_map_foff + di->fsm.rw_map_size - 1 );
1652 for (i = 0; i < n_rw; i++) {
1653 TRACE_SYMTAB("rw[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n",
1654 i, rw[i].svma_base, rw[i].svma_limit - 1, rw[i].bias );
1655 }
1656
1657 /* TOPLEVEL */
1658 /* Iterate over section headers */
1659 for (i = 0; i < shdr_nent; i++) {
1660 ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
1661 UChar* name = shdr_strtab_img + shdr->sh_name;
1662 Addr svma = shdr->sh_addr;
1663 OffT foff = shdr->sh_offset;
1664 UWord size = shdr->sh_size;
1665 UInt alyn = shdr->sh_addralign;
1666 Bool bits = !(shdr->sh_type == SHT_NOBITS);
1667 /* Look through our collection of info obtained from the PT_LOAD
1668 headers, and make 'inrx' and 'inrw' point to the first entry
1669 in each that intersects 'avma'. If in each case none is found,
1670 leave the relevant pointer at NULL. */
1671 RangeAndBias* inrx = NULL;
1672 RangeAndBias* inrw = NULL;
1673 { Word j;
1674 for (j = 0; j < n_rx; j++) {
1675 if (svma >= rx[j].svma_base && svma < rx[j].svma_limit) {
1676 inrx = &rx[j];
1677 break;
1678 }
1679 }
1680 for (j = 0; j < n_rw; j++) {
1681 if (svma >= rw[j].svma_base && svma < rw[j].svma_limit) {
1682 inrw = &rw[j];
1683 break;
1684 }
1685 }
1686 }
1687
1688 TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld "
1689 " svma %p name \"%s\"\n",
1690 i, inrx ? "rx" : " ", inrw ? "rw" : " ", alyn,
1691 foff, foff+size-1, (void*)svma, name );
1692
1693 /* Check for sane-sized segments. SHT_NOBITS sections have zero
1694 size in the file. */
1695 if (bits &&
1696 ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage))) {
1697 ML_(symerr)(di, True, "ELF Section extends beyond image end");
1698 goto out;
1699 }
1700
1701 /* Check for a sane alignment value. */
1702 if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1703 ML_(symerr)(di, True, "ELF Section contains invalid "
1704 ".sh_addralign value");
1705 goto out;
1706 }
1707
1708 # define BAD(_secname) \
1709 do { ML_(symerr)(di, True, \
1710 "Can't make sense of " _secname \
1711 " section mapping"); \
1712 /* make sure we don't assert if we find */ \
1713 /* ourselves back in this routine later, */ \
1714 /* with the same di */ \
1715 di->soname = NULL; \
1716 goto out; \
1717 } while (0)
1718
1719 /* Find avma-s for: .text .data .sdata .rodata .bss .sbss .plt .got .opd
1720 and .eh_frame */
1721
1722 /* Accept .text where mapped as rx (code), even if zero-sized */
1723 if (0 == VG_(strcmp)(name, ".text")) {
1724 if (inrx && size >= 0 && !di->text_present) {
1725 di->text_present = True;
1726 di->text_svma = svma;
1727 di->text_avma = svma + inrx->bias;
1728 di->text_size = size;
1729 di->text_bias = inrx->bias;
1730 di->text_debug_svma = svma;
1731 di->text_debug_bias = inrx->bias;
1732 TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
1733 di->text_svma,
1734 di->text_svma + di->text_size - 1);
1735 TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
1736 di->text_avma,
1737 di->text_avma + di->text_size - 1);
1738 TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
1739 } else {
1740 BAD(".text");
1741 }
1742 }
1743
1744 /* Accept .data where mapped as rw (data), even if zero-sized */
1745 if (0 == VG_(strcmp)(name, ".data")) {
1746 if (inrw && size >= 0 && !di->data_present) {
1747 di->data_present = True;
1748 di->data_svma = svma;
1749 di->data_avma = svma + inrw->bias;
1750 di->data_size = size;
1751 di->data_bias = inrw->bias;
1752 di->data_debug_svma = svma;
1753 di->data_debug_bias = inrw->bias;
1754 TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
1755 di->data_svma,
1756 di->data_svma + di->data_size - 1);
1757 TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
1758 di->data_avma,
1759 di->data_avma + di->data_size - 1);
1760 TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
1761 } else {
1762 BAD(".data");
1763 }
1764 }
1765
1766 /* Accept .sdata where mapped as rw (data) */
1767 if (0 == VG_(strcmp)(name, ".sdata")) {
1768 if (inrw && size > 0 && !di->sdata_present) {
1769 di->sdata_present = True;
1770 di->sdata_svma = svma;
1771 di->sdata_avma = svma + inrw->bias;
1772 di->sdata_size = size;
1773 di->sdata_bias = inrw->bias;
1774 di->sdata_debug_svma = svma;
1775 di->sdata_debug_bias = inrw->bias;
1776 TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
1777 di->sdata_svma,
1778 di->sdata_svma + di->sdata_size - 1);
1779 TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
1780 di->sdata_avma,
1781 di->sdata_avma + di->sdata_size - 1);
1782 TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
1783 } else {
1784 BAD(".sdata");
1785 }
1786 }
1787
1788 /* Accept .rodata where mapped as rx (data), even if zero-sized */
1789 if (0 == VG_(strcmp)(name, ".rodata")) {
1790 if (inrx && size >= 0 && !di->rodata_present) {
1791 di->rodata_present = True;
1792 di->rodata_svma = svma;
1793 di->rodata_avma = svma + inrx->bias;
1794 di->rodata_size = size;
1795 di->rodata_bias = inrx->bias;
1796 di->rodata_debug_svma = svma;
1797 di->rodata_debug_bias = inrx->bias;
1798 /* NB was 'inrw' prior to r11794 */
1799 TRACE_SYMTAB("acquiring .rodata svma = %#lx .. %#lx\n",
1800 di->rodata_svma,
1801 di->rodata_svma + di->rodata_size - 1);
1802 TRACE_SYMTAB("acquiring .rodata avma = %#lx .. %#lx\n",
1803 di->rodata_avma,
1804 di->rodata_avma + di->rodata_size - 1);
1805 TRACE_SYMTAB("acquiring .rodata bias = %#lx\n", di->rodata_bias);
1806 } else {
1807 BAD(".rodata");
1808 }
1809 }
1810
1811 if (0 == VG_(strcmp)(name, ".dynbss")) {
1812 if (inrw && size > 0 && !di->bss_present) {
1813 dynbss_present = True;
1814 di->bss_present = True;
1815 di->bss_svma = svma;
1816 di->bss_avma = svma + inrw->bias;
1817 di->bss_size = size;
1818 di->bss_bias = inrw->bias;
1819 di->bss_debug_svma = svma;
1820 di->bss_debug_bias = inrw->bias;
1821 TRACE_SYMTAB("acquiring .dynbss svma = %#lx .. %#lx\n",
1822 di->bss_svma,
1823 di->bss_svma + di->bss_size - 1);
1824 TRACE_SYMTAB("acquiring .dynbss avma = %#lx .. %#lx\n",
1825 di->bss_avma,
1826 di->bss_avma + di->bss_size - 1);
1827 TRACE_SYMTAB("acquiring .dynbss bias = %#lx\n", di->bss_bias);
1828 }
1829 }
1830
1831 /* Accept .bss where mapped as rw (data), even if zero-sized */
1832 if (0 == VG_(strcmp)(name, ".bss")) {
1833 if (inrw && size > 0 && dynbss_present) {
1834 vg_assert(di->bss_present);
1835 dynbss_present = False;
1836 vg_assert(di->bss_svma + di->bss_size == svma);
1837 di->bss_size += size;
1838 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1839 svma, svma + size - 1);
1840 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1841 svma + inrw->bias, svma + inrw->bias + size - 1);
1842 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1843 } else
1844
1845 if (inrw && size >= 0 && !di->bss_present) {
1846 di->bss_present = True;
1847 di->bss_svma = svma;
1848 di->bss_avma = svma + inrw->bias;
1849 di->bss_size = size;
1850 di->bss_bias = inrw->bias;
1851 di->bss_debug_svma = svma;
1852 di->bss_debug_bias = inrw->bias;
1853 TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1854 di->bss_svma,
1855 di->bss_svma + di->bss_size - 1);
1856 TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1857 di->bss_avma,
1858 di->bss_avma + di->bss_size - 1);
1859 TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1860 } else
1861
1862 /* Now one from the wtf?! department ... */
1863 if (inrx && (!inrw) && size >= 0 && !di->bss_present) {
1864 /* File contains a .bss, but it got mapped as rx only.
1865 This is very strange. For now, just pretend we didn't
1866 see it :-) */
1867 di->bss_present = False;
1868 di->bss_svma = 0;
1869 di->bss_avma = 0;
1870 di->bss_size = 0;
1871 di->bss_bias = 0;
1872 di->bss_debug_svma = 0;
1873 di->bss_debug_bias = 0;
1874 if (!VG_(clo_xml)) {
1875 VG_(message)(Vg_UserMsg,
1876 "Warning: the following file's .bss is "
1877 "mapped r-x only - ignoring .bss syms\n");
1878 VG_(message)(Vg_UserMsg, " %s\n", di->fsm.filename
1879 ? di->fsm.filename
1880 : (UChar*)"(null?!)" );
1881 }
1882 } else
1883
1884 if ((!inrw) && (!inrx) && size >= 0 && !di->bss_present) {
1885 /* File contains a .bss, but it didn't get mapped. Ignore. */
1886 di->bss_present = False;
1887 di->bss_svma = 0;
1888 di->bss_avma = 0;
1889 di->bss_size = 0;
1890 di->bss_bias = 0;
1891 } else {
1892 BAD(".bss");
1893 }
1894 }
1895
1896 if (0 == VG_(strcmp)(name, ".sdynbss")) {
1897 if (inrw && size >= 0 && !di->sbss_present) {
1898 sdynbss_present = True;
1899 di->sbss_present = True;
1900 di->sbss_svma = svma;
1901 di->sbss_avma = svma + inrw->bias;
1902 di->sbss_size = size;
1903 di->sbss_bias = inrw->bias;
1904 di->sbss_debug_svma = svma;
1905 di->sbss_debug_bias = inrw->bias;
1906 TRACE_SYMTAB("acquiring .sdynbss svma = %#lx .. %#lx\n",
1907 di->sbss_svma,
1908 di->sbss_svma + di->sbss_size - 1);
1909 TRACE_SYMTAB("acquiring .sdynbss avma = %#lx .. %#lx\n",
1910 di->sbss_avma,
1911 di->sbss_avma + di->sbss_size - 1);
1912 TRACE_SYMTAB("acquiring .sdynbss bias = %#lx\n", di->sbss_bias);
1913 }
1914 }
1915
1916 /* Accept .sbss where mapped as rw (data) */
1917 if (0 == VG_(strcmp)(name, ".sbss")) {
1918 if (inrw && size > 0 && sdynbss_present) {
1919 vg_assert(di->sbss_present);
1920 sdynbss_present = False;
1921 vg_assert(di->sbss_svma + di->sbss_size == svma);
1922 di->sbss_size += size;
1923 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1924 svma, svma + size - 1);
1925 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
1926 svma + inrw->bias, svma + inrw->bias + size - 1);
1927 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
1928 } else
1929
1930 if (inrw && size > 0 && !di->sbss_present) {
1931 di->sbss_present = True;
1932 di->sbss_svma = svma;
1933 di->sbss_avma = svma + inrw->bias;
1934 di->sbss_size = size;
1935 di->sbss_bias = inrw->bias;
1936 di->sbss_debug_svma = svma;
1937 di->sbss_debug_bias = inrw->bias;
1938 TRACE_SYMTAB("acquiring .sbss svma = %#lx .. %#lx\n",
1939 di->sbss_svma,
1940 di->sbss_svma + di->sbss_size - 1);
1941 TRACE_SYMTAB("acquiring .sbss avma = %#lx .. %#lx\n",
1942 di->sbss_avma,
1943 di->sbss_avma + di->sbss_size - 1);
1944 TRACE_SYMTAB("acquiring .sbss bias = %#lx\n", di->sbss_bias);
1945 } else {
1946 BAD(".sbss");
1947 }
1948 }
1949
1950 /* Accept .got where mapped as rw (data) */
1951 if (0 == VG_(strcmp)(name, ".got")) {
1952 if (inrw && size > 0 && !di->got_present) {
1953 di->got_present = True;
1954 di->got_avma = svma + inrw->bias;
1955 di->got_size = size;
1956 TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
1957 } else {
1958 BAD(".got");
1959 }
1960 }
1961
1962 /* Accept .got.plt where mapped as rw (data) */
1963 if (0 == VG_(strcmp)(name, ".got.plt")) {
1964 if (inrw && size > 0 && !di->gotplt_present) {
1965 di->gotplt_present = True;
1966 di->gotplt_avma = svma + inrw->bias;
1967 di->gotplt_size = size;
1968 TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
1969 } else if (size != 0) {
1970 BAD(".got.plt");
1971 }
1972 }
1973
1974 /* PLT is different on different platforms, it seems. */
1975 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1976 || defined(VGP_arm_linux) || defined (VGP_s390x_linux)
1977 /* Accept .plt where mapped as rx (code) */
1978 if (0 == VG_(strcmp)(name, ".plt")) {
1979 if (inrx && size > 0 && !di->plt_present) {
1980 di->plt_present = True;
1981 di->plt_avma = svma + inrx->bias;
1982 di->plt_size = size;
1983 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1984 } else {
1985 BAD(".plt");
1986 }
1987 }
1988 # elif defined(VGP_ppc32_linux)
1989 /* Accept .plt where mapped as rw (data) */
1990 if (0 == VG_(strcmp)(name, ".plt")) {
1991 if (inrw && size > 0 && !di->plt_present) {
1992 di->plt_present = True;
1993 di->plt_avma = svma + inrw->bias;
1994 di->plt_size = size;
1995 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1996 } else {
1997 BAD(".plt");
1998 }
1999 }
2000 # elif defined(VGP_ppc64_linux)
2001 /* Accept .plt where mapped as rw (data), or unmapped */
2002 if (0 == VG_(strcmp)(name, ".plt")) {
2003 if (inrw && size > 0 && !di->plt_present) {
2004 di->plt_present = True;
2005 di->plt_avma = svma + inrw->bias;
2006 di->plt_size = size;
2007 TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
2008 } else
2009 if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
2010 /* File contains a .plt, but it didn't get mapped.
2011 Presumably it is not required on this platform. At
2012 least don't reject the situation as invalid. */
2013 di->plt_present = True;
2014 di->plt_avma = 0;
2015 di->plt_size = 0;
2016 } else {
2017 BAD(".plt");
2018 }
2019 }
2020 # else
2021 # error "Unsupported platform"
2022 # endif
2023
2024 /* Accept .opd where mapped as rw (data) */
2025 if (0 == VG_(strcmp)(name, ".opd")) {
2026 if (inrw && size > 0 && !di->opd_present) {
2027 di->opd_present = True;
2028 di->opd_avma = svma + inrw->bias;
2029 di->opd_size = size;
2030 TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
2031 } else {
2032 BAD(".opd");
2033 }
2034 }
2035
2036 /* Accept .eh_frame where mapped as rx (code). This seems to be
2037 the common case. However, if that doesn't pan out, try for
2038 rw (data) instead. We can handle up to N_EHFRAME_SECTS per
2039 ELF object. */
2040 if (0 == VG_(strcmp)(name, ".eh_frame")) {
2041 if (inrx && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2042 di->ehframe_avma[di->n_ehframe] = svma + inrx->bias;
2043 di->ehframe_size[di->n_ehframe] = size;
2044 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2045 di->ehframe_avma[di->n_ehframe]);
2046 di->n_ehframe++;
2047 } else
2048 if (inrw && size > 0 && di->n_ehframe < N_EHFRAME_SECTS) {
2049 di->ehframe_avma[di->n_ehframe] = svma + inrw->bias;
2050 di->ehframe_size[di->n_ehframe] = size;
2051 TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n",
2052 di->ehframe_avma[di->n_ehframe]);
2053 di->n_ehframe++;
2054 } else {
2055 BAD(".eh_frame");
2056 }
2057 }
2058
2059 # undef BAD
2060
2061 } /* iterate over the section headers */
2062
2063 /* TOPLEVEL */
2064 if (0) VG_(printf)("YYYY text_: avma %#lx size %ld bias %#lx\n",
2065 di->text_avma, di->text_size, di->text_bias);
2066
2067 if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
2068 VG_(message)(Vg_DebugMsg, " svma %#010lx, avma %#010lx\n",
2069 di->text_avma - di->text_bias,
2070 di->text_avma );
2071
2072 TRACE_SYMTAB("\n");
2073 TRACE_SYMTAB("------ Finding image addresses "
2074 "for debug-info sections ------\n");
2075
2076 /* TOPLEVEL */
2077 /* Find interesting sections, read the symbol table(s), read any debug
2078 information */
2079 {
2080 /* IMAGE addresses: pointers to start of sections in the
2081 transiently loaded oimage, not in the fragments of the file
2082 mapped in by the guest's dynamic linker. */
2083 /* TOPLEVEL */
2084 UChar* strtab_img = NULL; /* .strtab */
2085 ElfXX_Sym* symtab_img = NULL; /* .symtab */
2086 UChar* dynstr_img = NULL; /* .dynstr */
2087 ElfXX_Sym* dynsym_img = NULL; /* .dynsym */
2088 UChar* debuglink_img = NULL; /* .gnu_debuglink */
2089 UChar* stab_img = NULL; /* .stab (stabs) */
2090 UChar* stabstr_img = NULL; /* .stabstr (stabs) */
2091 UChar* debug_line_img = NULL; /* .debug_line (dwarf2) */
2092 UChar* debug_info_img = NULL; /* .debug_info (dwarf2) */
2093 UChar* debug_abbv_img = NULL; /* .debug_abbrev (dwarf2) */
2094 UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */
2095 UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
2096 UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */
2097 UChar* debug_frame_img = NULL; /* .debug_frame (dwarf2) */
2098 UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */
2099 UChar* dwarf1l_img = NULL; /* .line (dwarf1) */
2100 UChar* opd_img = NULL; /* .opd (dwarf2,
2101 ppc64-linux) */
2102 UChar* ehframe_img[N_EHFRAME_SECTS]; /* .eh_frame (dwarf2) */
2103
2104 /* Section sizes, in bytes */
2105 SizeT strtab_sz = 0;
2106 SizeT symtab_sz = 0;
2107 SizeT dynstr_sz = 0;
2108 SizeT dynsym_sz = 0;
2109 SizeT debuglink_sz = 0;
2110 SizeT stab_sz = 0;
2111 SizeT stabstr_sz = 0;
2112 SizeT debug_line_sz = 0;
2113 SizeT debug_info_sz = 0;
2114 SizeT debug_abbv_sz = 0;
2115 SizeT debug_str_sz = 0;
2116 SizeT debug_ranges_sz = 0;
2117 SizeT debug_loc_sz = 0;
2118 SizeT debug_frame_sz = 0;
2119 SizeT dwarf1d_sz = 0;
2120 SizeT dwarf1l_sz = 0;
2121 SizeT opd_sz_unused = 0;
2122 SizeT ehframe_sz[N_EHFRAME_SECTS];
2123
2124 for (i = 0; i < N_EHFRAME_SECTS; i++) {
2125 ehframe_img[i] = NULL;
2126 ehframe_sz[i] = 0;
2127 }
2128
2129 /* Find all interesting sections */
2130
2131 UInt ehframe_ix = 0;
2132
2133 /* What FIND does: it finds the section called _SEC_NAME. The
2134 size of it is assigned to _SEC_SIZE. The address of the
2135 section in the transiently loaded oimage is assigned to
2136 _SEC_IMG. If the section is found, _POST_FX is executed
2137 after _SEC_NAME and _SEC_SIZE have been assigned to.
2138
2139 Even for sections which are marked loadable, the client's
2140 ld.so may not have loaded them yet, so there is no guarantee
2141 that we can safely prod around in any such area). Because
2142 the entire object file is transiently mapped aboard for
2143 inspection, it's always safe to inspect that area. */
2144
2145 /* TOPLEVEL */
2146 /* Iterate over section headers (again) */
2147 for (i = 0; i < ehdr_img->e_shnum; i++) {
2148
2149 # define FINDX(_sec_name, _sec_size, _sec_img, _post_fx) \
2150 do { ElfXX_Shdr* shdr \
2151 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
2152 if (0 == VG_(strcmp)(_sec_name, shdr_strtab_img \
2153 + shdr->sh_name)) { \
2154 Bool nobits; \
2155 _sec_img = (void*)(oimage + shdr->sh_offset); \
2156 _sec_size = shdr->sh_size; \
2157 nobits = shdr->sh_type == SHT_NOBITS; \
2158 TRACE_SYMTAB( "%18s: img %p .. %p\n", \
2159 _sec_name, (UChar*)_sec_img, \
2160 ((UChar*)_sec_img) + _sec_size - 1); \
2161 /* SHT_NOBITS sections have zero size in the file. */ \
2162 if ( shdr->sh_offset \
2163 + (nobits ? 0 : _sec_size) > n_oimage ) { \
2164 ML_(symerr)(di, True, \
2165 " section beyond image end?!"); \
2166 goto out; \
2167 } \
2168 _post_fx; \
2169 } \
2170 } while (0);
2171
2172 /* Version with no post-effects */
2173 # define FIND(_sec_name, _sec_size, _sec_img) \
2174 FINDX(_sec_name, _sec_size, _sec_img, /**/)
2175
2176 /* NAME SIZE IMAGE addr */
2177 FIND(".dynsym", dynsym_sz, dynsym_img)
2178 FIND(".dynstr", dynstr_sz, dynstr_img)
2179 FIND(".symtab", symtab_sz, symtab_img)
2180 FIND(".strtab", strtab_sz, strtab_img)
2181
2182 FIND(".gnu_debuglink", debuglink_sz, debuglink_img)
2183
2184 FIND(".stab", stab_sz, stab_img)
2185 FIND(".stabstr", stabstr_sz, stabstr_img)
2186
2187 FIND(".debug_line", debug_line_sz, debug_line_img)
2188 FIND(".debug_info", debug_info_sz, debug_info_img)
2189 FIND(".debug_abbrev", debug_abbv_sz, debug_abbv_img)
2190 FIND(".debug_str", debug_str_sz, debug_str_img)
2191 FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img)
2192 FIND(".debug_loc", debug_loc_sz, debug_loc_img)
2193 FIND(".debug_frame", debug_frame_sz, debug_frame_img)
2194
2195 FIND(".debug", dwarf1d_sz, dwarf1d_img)
2196 FIND(".line", dwarf1l_sz, dwarf1l_img)
2197
2198 FIND(".opd", opd_sz_unused, opd_img)
2199
2200 FINDX(".eh_frame", ehframe_sz[ehframe_ix],
2201 ehframe_img[ehframe_ix],
2202 do { ehframe_ix++; vg_assert(ehframe_ix <= N_EHFRAME_SECTS); }
2203 while (0)
2204 )
2205 /* Comment_on_EH_FRAME_MULTIPLE_INSTANCES: w.r.t. .eh_frame
2206 multi-instance kludgery, how are we assured that the order
2207 in which we fill in ehframe_sz[] and ehframe_img[] is
2208 consistent with the order in which we previously filled in
2209 di->ehframe_avma[] and di->ehframe_size[] ? By the fact
2210 that in both cases, these arrays were filled in by
2211 iterating over the section headers top-to-bottom. So both
2212 loops (this one and the previous one) encounter the
2213 .eh_frame entries in the same order and so fill in these
2214 arrays in a consistent order.
2215 */
2216
2217 # undef FINDX
2218 # undef FIND
2219 } /* Iterate over section headers (again) */
2220
2221 /* TOPLEVEL */
2222 /* Now, see if we can find a debuginfo object, and if so map it in, and
2223 put the mapping address and size in dimage and n_dimage. */
2224 vg_assert(dimage == 0 && n_dimage == 0);
2225
2226 /* Look for a build-id */
2227 buildid = find_buildid(oimage, n_oimage);
2228
2229 /* Look for a debug image */
2230 if (buildid != NULL || debuglink_img != NULL) {
2231 /* Do have a debuglink section? */
2232 if (debuglink_img != NULL) {
2233 UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
2234 UInt crc;
2235
2236 vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
2237
2238 /* Extract the CRC from the debuglink section */
2239 crc = ML_(read_UInt)(debuglink_img + crc_offset);
2240
2241 /* See if we can find a matching debug file */
2242 find_debug_file( di, di->fsm.filename, buildid,
2243 debuglink_img, crc, &dimage, &n_dimage );
2244 } else {
2245 /* See if we can find a matching debug file */
2246 find_debug_file( di, di->fsm.filename, buildid,
2247 NULL, 0, &dimage, &n_dimage );
2248 }
2249 }
2250
2251 if (buildid) {
2252 ML_(dinfo_free)(buildid);
2253 buildid = NULL; /* paranoia */
2254 }
2255
2256 /* Still no luck? Let's have one last roll of the dice. */
2257 if (dimage == 0) {
2258 vg_assert(n_dimage == 0);
2259 Bool found = find_ad_hoc_debug_image( di, di->fsm.filename,
2260 &dimage, &n_dimage );
2261 if (found)
2262 vg_assert(dimage != 0);
2263 }
2264
2265 /* TOPLEVEL */
2266 /* If we were successful in finding a debug image, pull various
2267 SVMA/bias/size and image addresses out of it. */
2268 if (dimage != 0
2269 && n_dimage >= sizeof(ElfXX_Ehdr)
2270 && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
2271
2272 /* Pull out and validate program header and section header info */
2273 ElfXX_Ehdr* ehdr_dimg = (ElfXX_Ehdr*)dimage;
2274 ElfXX_Phdr* phdr_dimg = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
2275 + ehdr_dimg->e_phoff );
2276 UWord phdr_dnent = ehdr_dimg->e_phnum;
2277 UWord phdr_dent_szB = ehdr_dimg->e_phentsize;
2278 ElfXX_Shdr* shdr_dimg = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
2279 + ehdr_dimg->e_shoff );
2280 UWord shdr_dnent = ehdr_dimg->e_shnum;
2281 UWord shdr_dent_szB = ehdr_dimg->e_shentsize;
2282 UChar* shdr_strtab_dimg = NULL;
2283
2284 /* SVMAs covered by rx and rw segments and corresponding bias. */
2285 /* Addr rx_dsvma_base = 0; */ /* UNUSED */
2286 Addr rx_dsvma_limit = 0;
2287 PtrdiffT rx_dbias = 0;
2288 /* Addr rw_dsvma_base = 0; */ /* UNUSED */
2289 Addr rw_dsvma_limit = 0;
2290 PtrdiffT rw_dbias = 0;
2291
2292 Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
2293
2294 if (phdr_dnent == 0
2295 || !contained_within(
2296 dimage, n_dimage,
2297 (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
2298 ML_(symerr)(di, True,
2299 "Missing or invalid ELF Program Header Table"
2300 " (debuginfo file)");
2301 goto out;
2302 }
2303
2304 if (shdr_dnent == 0
2305 || !contained_within(
2306 dimage, n_dimage,
2307 (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
2308 ML_(symerr)(di, True,
2309 "Missing or invalid ELF Section Header Table"
2310 " (debuginfo file)");
2311 goto out;
2312 }
2313
2314 /* Also find the section header's string table, and validate. */
2315 /* checked previously by is_elf_object_file: */
2316 vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
2317
2318 shdr_strtab_dimg
2319 = (UChar*)( ((UChar*)ehdr_dimg)
2320 + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
2321 if (!contained_within(
2322 dimage, n_dimage,
2323 (Addr)shdr_strtab_dimg,
2324 1/*bogus, but we don't know the real size*/ )) {
2325 ML_(symerr)(di, True,
2326 "Invalid ELF Section Header String Table"
2327 " (debuginfo file)");
2328 goto out;
2329 }
2330
2331 need_symtab = (NULL == symtab_img);
2332 need_stabs = (NULL == stab_img);
2333 need_dwarf2 = (NULL == debug_info_img);
2334 need_dwarf1 = (NULL == dwarf1d_img);
2335
2336 for (i = 0; i < ehdr_dimg->e_phnum; i++) {
2337 ElfXX_Phdr* phdr
2338 = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
2339 i, phdr_ent_szB );
2340 if (phdr->p_type == PT_LOAD) {
2341 if (rx_dsvma_limit == 0
2342 && phdr->p_offset >= di->fsm.rx_map_foff
2343 && phdr->p_offset
2344 < di->fsm.rx_map_foff + di->fsm.rx_map_size
2345 && phdr->p_offset + phdr->p_filesz
2346 <= di->fsm.rx_map_foff + di->fsm.rx_map_size) {
2347 /* rx_dsvma_base = phdr->p_vaddr; */ /* UNUSED */
2348 rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2349 rx_dbias = di->fsm.rx_map_avma - di->fsm.rx_map_foff
2350 + phdr->p_offset - phdr->p_vaddr;
2351 }
2352 else
2353 if (rw_dsvma_limit == 0
2354 && phdr->p_offset >= di->fsm.rw_map_foff
2355 && phdr->p_offset
2356 < di->fsm.rw_map_foff + di->fsm.rw_map_size
2357 && phdr->p_offset + phdr->p_filesz
2358 <= di->fsm.rw_map_foff + di->fsm.rw_map_size) {
2359 /* rw_dsvma_base = phdr->p_vaddr; */ /* UNUSED */
2360 rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz;
2361 rw_dbias = di->fsm.rw_map_avma - di->fsm.rw_map_foff
2362 + phdr->p_offset - phdr->p_vaddr;
2363 }
2364 }
2365 }
2366
2367 /* Find all interesting sections */
2368 for (i = 0; i < ehdr_dimg->e_shnum; i++) {
2369
2370 /* Find debug svma and bias information for sections
2371 we found in the main file. */
2372
2373 # define FIND(sec, seg) \
2374 do { ElfXX_Shdr* shdr \
2375 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2376 if (di->sec##_present \
2377 && 0 == VG_(strcmp)("." #sec, \
2378 shdr_strtab_dimg + shdr->sh_name)) { \
2379 vg_assert(di->sec##_size == shdr->sh_size); \
2380 vg_assert(di->sec##_avma + shdr->sh_addr + seg##_dbias); \
2381 /* Assume we have a correct value for the main */ \
2382 /* object's bias. Use that to derive the debuginfo */ \
2383 /* object's bias, by adding the difference in SVMAs */ \
2384 /* for the corresponding sections in the two files. */ \
2385 /* That should take care of all prelinking effects. */ \
2386 di->sec##_debug_svma = shdr->sh_addr; \
2387 di->sec##_debug_bias \
2388 = di->sec##_bias + \
2389 di->sec##_svma - di->sec##_debug_svma; \
2390 TRACE_SYMTAB("acquiring ." #sec \
2391 " debug svma = %#lx .. %#lx\n", \
2392 di->sec##_debug_svma, \
2393 di->sec##_debug_svma + di->sec##_size - 1); \
2394 TRACE_SYMTAB("acquiring ." #sec " debug bias = %#lx\n", \
2395 di->sec##_debug_bias); \
2396 } \
2397 } while (0);
2398
2399 /* SECTION SEGMENT */
2400 FIND(text, rx)
2401 FIND(data, rw)
2402 FIND(sdata, rw)
2403 FIND(rodata, rw)
2404 FIND(bss, rw)
2405 FIND(sbss, rw)
2406
2407 # undef FIND
2408
2409 /* Same deal as previous FIND, except only do it for those
2410 sections for which we didn't find anything useful in
2411 the main file. */
2412
2413 # define FIND(condition, sec_name, sec_size, sec_img) \
2414 do { ElfXX_Shdr* shdr \
2415 = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
2416 if (condition \
2417 && 0 == VG_(strcmp)(sec_name, \
2418 shdr_strtab_dimg + shdr->sh_name)) { \
2419 Bool nobits; \
2420 if (0 != sec_img) \
2421 VG_(core_panic)("repeated section!\n"); \
2422 sec_img = (void*)(dimage + shdr->sh_offset); \
2423 sec_size = shdr->sh_size; \
2424 nobits = shdr->sh_type == SHT_NOBITS; \
2425 TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
2426 sec_name, \
2427 (UChar*)sec_img, \
2428 ((UChar*)sec_img) + sec_size - 1); \
2429 /* SHT_NOBITS sections have zero size in the file. */ \
2430 if ( shdr->sh_offset \
2431 + (nobits ? 0 : sec_size) > n_dimage ) { \
2432 ML_(symerr)(di, True, \
2433 " section beyond image end?!"); \
2434 goto out; \
2435 } \
2436 } \
2437 } while (0);
2438
2439 /* NEEDED? NAME SIZE IMAGE addr */
2440 FIND(need_symtab, ".symtab", symtab_sz, symtab_img)
2441 FIND(need_symtab, ".strtab", strtab_sz, strtab_img)
2442 FIND(need_stabs, ".stab", stab_sz, stab_img)
2443 FIND(need_stabs, ".stabstr", stabstr_sz, stabstr_img)
2444 FIND(need_dwarf2, ".debug_line", debug_line_sz, debug_line_img)
2445 FIND(need_dwarf2, ".debug_info", debug_info_sz, debug_info_img)
2446 FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
2447 FIND(need_dwarf2, ".debug_str", debug_str_sz, debug_str_img)
2448 FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
2449 debug_ranges_img)
2450 FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img)
2451 FIND(need_dwarf2, ".debug_frame", debug_frame_sz,
2452 debug_frame_img)
2453 FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img)
2454 FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img)
2455
2456 # undef FIND
2457 } /* Find all interesting sections */
2458 } /* do we have a debug image? */
2459
2460 /* TOPLEVEL */
2461 /* Check some sizes */
2462 vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
2463 vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
2464
2465 /* Read symbols */
2466 {
2467 void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
2468 ElfXX_Sym*,SizeT,
2469 UChar*,SizeT,
2470 Bool,UChar*);
2471 Bool symtab_in_debug;
2472 # if defined(VGP_ppc64_linux)
2473 read_elf_symtab = read_elf_symtab__ppc64_linux;
2474 # else
2475 read_elf_symtab = read_elf_symtab__normal;
2476 # endif
2477 symtab_in_debug = (Addr)symtab_img >= dimage
2478 && (Addr)symtab_img < dimage + n_dimage;
2479 read_elf_symtab(di, "symbol table",
2480 symtab_img, symtab_sz,
2481 strtab_img, strtab_sz,
2482 symtab_in_debug, opd_img);
2483
2484 read_elf_symtab(di, "dynamic symbol table",
2485 dynsym_img, dynsym_sz,
2486 dynstr_img, dynstr_sz,
2487 False, opd_img);
2488 } /* Read symbols */
2489
2490 /* TOPLEVEL */
2491 /* Read .eh_frame and .debug_frame (call-frame-info) if any. Do
2492 the .eh_frame section(s) first. */
2493 vg_assert(di->n_ehframe >= 0 && di->n_ehframe <= N_EHFRAME_SECTS);
2494 for (i = 0; i < di->n_ehframe; i++) {
2495 /* see Comment_on_EH_FRAME_MULTIPLE_INSTANCES above for why
2496 this next assertion should hold. */
2497 vg_assert(ehframe_sz[i] == di->ehframe_size[i]);
2498 ML_(read_callframe_info_dwarf3)( di,
2499 ehframe_img[i],
2500 ehframe_sz[i],
2501 di->ehframe_avma[i],
2502 True/*is_ehframe*/ );
2503 }
2504 if (debug_frame_sz) {
2505 ML_(read_callframe_info_dwarf3)( di,
2506 debug_frame_img, debug_frame_sz,
2507 0/*assume zero avma*/,
2508 False/*!is_ehframe*/ );
2509 }
2510
2511 /* Read the stabs and/or dwarf2 debug information, if any. It
2512 appears reading stabs stuff on amd64-linux doesn't work, so
2513 we ignore it. On s390x stabs also doesnt work and we always
2514 have the dwarf info in the eh_frame. We also segfault on
2515 ppc64-linux when reading stabs, so skip that. ppc32-linux
2516 seems OK though. Also skip on Android. */
2517 # if !defined(VGP_amd64_linux) \
2518 && !defined(VGP_s390x_linux) \
2519 && !defined(VGP_ppc64_linux) \
2520 && !defined(VGPV_arm_linux_android) \
2521 && !defined(VGPV_x86_linux_android)
2522 if (stab_img && stabstr_img) {
2523 ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz,
2524 stabstr_img, stabstr_sz );
2525 }
2526 # endif
2527 /* jrs 2006-01-01: icc-8.1 has been observed to generate
2528 binaries without debug_str sections. Don't preclude
2529 debuginfo reading for that reason, but, in
2530 read_unitinfo_dwarf2, do check that debugstr is non-NULL
2531 before using it. */
2532 if (debug_info_img && debug_abbv_img && debug_line_img
2533 /* && debug_str_img */) {
2534
2535 /* The old reader: line numbers and unwind info only */
2536 ML_(read_debuginfo_dwarf3) ( di,
2537 debug_info_img, debug_info_sz,
2538 debug_abbv_img, debug_abbv_sz,
2539 debug_line_img, debug_line_sz,
2540 debug_str_img, debug_str_sz );
2541
2542 /* The new reader: read the DIEs in .debug_info to acquire
2543 information on variable types and locations. But only if
2544 the tool asks for it, or the user requests it on the
2545 command line. */
2546 if (VG_(needs).var_info /* the tool requires it */
2547 || VG_(clo_read_var_info) /* the user asked for it */) {
2548 ML_(new_dwarf3_reader)(
2549 di, debug_info_img, debug_info_sz,
2550 debug_abbv_img, debug_abbv_sz,
2551 debug_line_img, debug_line_sz,
2552 debug_str_img, debug_str_sz,
2553 debug_ranges_img, debug_ranges_sz,
2554 debug_loc_img, debug_loc_sz
2555 );
2556 }
2557 }
2558 if (dwarf1d_img && dwarf1l_img) {
2559 ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
2560 dwarf1l_img, dwarf1l_sz );
2561 }
2562 /* TOPLEVEL */
2563
2564 } /* "Find interesting sections, read the symbol table(s), read any debug
2565 information" (a local scope) */
2566
2567 /* TOPLEVEL */
2568 res = True;
2569
2570 /* If reading Dwarf3 variable type/location info, print a line
2571 showing the number of variables read for each object.
2572 (Currently disabled -- is a sanity-check mechanism for
2573 exp-sgcheck.) */
2574 if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) {
2575 UWord nVars = 0;
2576 Word j;
2577 if (di->varinfo) {
2578 for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) {
2579 OSet* /* of DiAddrRange */ scope
2580 = *(OSet**)VG_(indexXA)(di->varinfo, j);
2581 vg_assert(scope);
2582 VG_(OSetGen_ResetIter)( scope );
2583 while (True) {
2584 DiAddrRange* range = VG_(OSetGen_Next)( scope );
2585 if (!range) break;
2586 vg_assert(range->vars);
2587 Word w = VG_(sizeXA)(range->vars);
2588 vg_assert(w >= 0);
2589 if (0) VG_(printf)("range %#lx %#lx %ld\n",
2590 range->aMin, range->aMax, w);
2591 nVars += (UWord)w;
2592 }
2593 }
2594 }
2595 VG_(umsg)("VARINFO: %7lu vars %7ld text_size %s\n",
2596 nVars, di->text_size, di->fsm.filename);
2597 }
2598 /* TOPLEVEL */
2599
2600 out:
2601 {
2602 SysRes m_res;
2603 /* Last, but not least, heave the image(s) back overboard. */
2604 if (dimage) {
2605 m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
2606 vg_assert(!sr_isError(m_res));
2607 }
2608 m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
2609 vg_assert(!sr_isError(m_res));
2610 return res;
2611 } /* out: */
2612
2613 /* NOTREACHED */
2614 }
2615
2616 #endif // defined(VGO_linux)
2617
2618 /*--------------------------------------------------------------------*/
2619 /*--- end ---*/
2620 /*--------------------------------------------------------------------*/
2621