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